mirror of
https://github.com/openshift/openshift-mcp-server.git
synced 2025-10-17 14:27:48 +03:00
* feat: add cluster provider for kubeconfig Signed-off-by: Calum Murray <cmurray@redhat.com> * feat: move server to use ClusterProvider interface Signed-off-by: Calum Murray <cmurray@redhat.com> * feat: authentication middleware works with cluster provider Signed-off-by: Calum Murray <cmurray@redhat.com> * fix: unit tests work after cluster provider changes Signed-off-by: Calum Murray <cmurray@redhat.com> * feat: add tool mutator to add cluster parameter Signed-off-by: Calum Murray <cmurray@redhat.com> * test: handle cluster parameter Signed-off-by: Calum Murray <cmurray@redhat.com> * fix: handle lazy init correctly Signed-off-by: Calum Murray <cmurray@redhat.com> * refactor: move to using multi-strategy ManagerProvider Signed-off-by: Calum Murray <cmurray@redhat.com> * feat: add contexts_list tool Signed-off-by: Calum Murray <cmurray@redhat.com> * refactor: make tool mutator generic between cluster/context naming Signed-off-by: Calum Murray <cmurray@redhat.com> * feat: introduce tool filter Signed-off-by: Calum Murray <cmurray@redhat.com> * refactor: use new ManagerProvider/mutator/filter within mcp server Signed-off-by: Calum Murray <cmurray@redhat.com> * fix(test): tests expect context parameter in tool defs Signed-off-by: Calum Murray <cmurray@redhat.com> * feat: auth handles multi-cluster case correctly Signed-off-by: Calum Murray <cmurray@redhat.com> * fix: small changes from local testing Signed-off-by: Calum Murray <cmurray@redhat.com> * chore: fix enum test Signed-off-by: Calum Murray <cmurray@redhat.com> * review: Multi Cluster support (#1) * nit: rename contexts_list to configuration_contexts_list Besides the conventional naming, it helps LLMs understand the context of the tool by providing a certain level of hierarchy. Signed-off-by: Marc Nuri <marc@marcnuri.com> * fix(mcp): ToolMutator doesn't rely on magic strings Signed-off-by: Marc Nuri <marc@marcnuri.com> * refactor(api): don't expose ManagerProvider to toolsets Signed-off-by: Marc Nuri <marc@marcnuri.com> * test(mcp): configuration_contexts_list basic tests Signed-off-by: Marc Nuri <marc@marcnuri.com> * test(toolsets): revert edge-case test This test should not be touched. Signed-off-by: Marc Nuri <marc@marcnuri.com> * test(toolsets): add specific metadata tests for multi-cluster Signed-off-by: Marc Nuri <marc@marcnuri.com> * fix(mcp): ToolFilter doesn't rely on magic strings (partially) Signed-off-by: Marc Nuri <marc@marcnuri.com> * test(api): IsClusterAware and IsTargetListProvider default values Signed-off-by: Marc Nuri <marc@marcnuri.com> * test(mcp): revert unneeded changes in mcp_tools_test.go Signed-off-by: Marc Nuri <marc@marcnuri.com> --------- Signed-off-by: Marc Nuri <marc@marcnuri.com> * fix: always include configuration_contexts_list if contexts > 1 Signed-off-by: Calum Murray <cmurray@redhat.com> * feat: include server urls in configuration_contexts_list Signed-off-by: Calum Murray <cmurray@redhat.com> --------- Signed-off-by: Calum Murray <cmurray@redhat.com> Signed-off-by: Marc Nuri <marc@marcnuri.com> Co-authored-by: Marc Nuri <marc@marcnuri.com>
65 lines
1.6 KiB
Go
65 lines
1.6 KiB
Go
package mcp
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/containers/kubernetes-mcp-server/pkg/api"
|
|
"github.com/google/jsonschema-go/jsonschema"
|
|
)
|
|
|
|
type ToolMutator func(tool api.ServerTool) api.ServerTool
|
|
|
|
const maxTargetsInEnum = 5 // TODO: test and validate that this is a reasonable cutoff
|
|
|
|
// WithTargetParameter adds a target selection parameter to the tool's input schema if the tool is cluster-aware
|
|
func WithTargetParameter(defaultCluster, targetParameterName string, targets []string) ToolMutator {
|
|
return func(tool api.ServerTool) api.ServerTool {
|
|
if !tool.IsClusterAware() {
|
|
return tool
|
|
}
|
|
|
|
if tool.Tool.InputSchema == nil {
|
|
tool.Tool.InputSchema = &jsonschema.Schema{Type: "object"}
|
|
}
|
|
|
|
if tool.Tool.InputSchema.Properties == nil {
|
|
tool.Tool.InputSchema.Properties = make(map[string]*jsonschema.Schema)
|
|
}
|
|
|
|
if len(targets) > 1 {
|
|
tool.Tool.InputSchema.Properties[targetParameterName] = createTargetProperty(
|
|
defaultCluster,
|
|
targetParameterName,
|
|
targets,
|
|
)
|
|
}
|
|
|
|
return tool
|
|
}
|
|
}
|
|
|
|
func createTargetProperty(defaultCluster, targetName string, targets []string) *jsonschema.Schema {
|
|
baseSchema := &jsonschema.Schema{
|
|
Type: "string",
|
|
Description: fmt.Sprintf(
|
|
"Optional parameter selecting which %s to run the tool in. Defaults to %s if not set",
|
|
targetName,
|
|
defaultCluster,
|
|
),
|
|
}
|
|
|
|
if len(targets) <= maxTargetsInEnum {
|
|
// Sort clusters to ensure consistent enum ordering
|
|
sort.Strings(targets)
|
|
|
|
enumValues := make([]any, 0, len(targets))
|
|
for _, c := range targets {
|
|
enumValues = append(enumValues, c)
|
|
}
|
|
baseSchema.Enum = enumValues
|
|
}
|
|
|
|
return baseSchema
|
|
}
|