diff --git a/README.md b/README.md index c4d8ae1..123b91b 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,22 @@ The MKP server provides access to Kubernetes resources through MCP resources. Th - Clustered resources: `k8s://clustered/{group}/{version}/{resource}/{name}` - Namespaced resources: `k8s://namespaced/{namespace}/{group}/{version}/{resource}/{name}` +### Controlling Resource Discovery + +By default, MKP serves all Kubernetes resources as MCP resources, which provides useful context for LLMs. However, in large clusters with many resources, this can consume significant context space in the LLM. + +You can disable this behavior by using the `--serve-resources` flag: + +```bash +# Run without serving cluster resources +./build/mkp-server --serve-resources=false + +# Run with a specific kubeconfig without serving cluster resources +./build/mkp-server --kubeconfig=/path/to/kubeconfig --serve-resources=false +``` + +Even with resource discovery disabled, the MCP tools (`get_resource`, `list_resources`, and `apply_resource`) remain fully functional, allowing you to interact with your Kubernetes cluster. + ## Development ### Running tests diff --git a/cmd/server/main.go b/cmd/server/main.go index 041bc36..ac1e245 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -17,6 +17,7 @@ func main() { // Parse command line flags kubeconfig := flag.String("kubeconfig", "", "Path to kubeconfig file. If not provided, in-cluster config will be used") addr := flag.String("addr", ":8080", "Address to listen on") + serveResources := flag.Bool("serve-resources", true, "Whether to serve cluster resources as MCP resources. Setting to false can reduce context size for LLMs when working with large clusters") flag.Parse() // Create a context that can be cancelled @@ -38,8 +39,13 @@ func main() { log.Fatalf("Failed to create Kubernetes client: %v", err) } + // Create MCP server config + config := &mcp.Config{ + ServeResources: *serveResources, + } + // Create MCP server using the helper function - mcpServer := mcp.CreateServer(k8sClient) + mcpServer := mcp.CreateServer(k8sClient, config) // Create SSE server sseServer := mcp.CreateSSEServer(mcpServer) diff --git a/pkg/mcp/server.go b/pkg/mcp/server.go index b18e632..930ce73 100644 --- a/pkg/mcp/server.go +++ b/pkg/mcp/server.go @@ -9,8 +9,26 @@ import ( "github.com/StacklokLabs/mkp/pkg/k8s" ) +// Config holds configuration options for the MCP server +type Config struct { + // ServeResources determines whether to serve cluster resources + // Setting this to false can reduce context size for LLMs when working with large clusters + ServeResources bool +} + +// DefaultConfig returns a Config with default values +func DefaultConfig() *Config { + return &Config{ + ServeResources: true, // Default to serving resources for backward compatibility + } +} + // CreateServer creates a new MCP server for Kubernetes -func CreateServer(k8sClient *k8s.Client) *server.MCPServer { +func CreateServer(k8sClient *k8s.Client, config *Config) *server.MCPServer { + // Use default config if none provided + if config == nil { + config = DefaultConfig() + } // Create MCP implementation impl := NewImplementation(k8sClient) @@ -37,20 +55,22 @@ func CreateServer(k8sClient *k8s.Client) *server.MCPServer { impl.HandleNamespacedResource, ) - // Add resources - go func() { - // List resources in a goroutine to avoid blocking server startup - resources, err := impl.HandleListAllResources(context.Background()) - if err != nil { - log.Printf("Failed to list resources: %v", err) - return - } - - // Add resources to the server - for _, resource := range resources { - mcpServer.AddResource(resource, nil) - } - }() + // Add resources if enabled + if config.ServeResources { + go func() { + // List resources in a goroutine to avoid blocking server startup + resources, err := impl.HandleListAllResources(context.Background()) + if err != nil { + log.Printf("Failed to list resources: %v", err) + return + } + + // Add resources to the server + for _, resource := range resources { + mcpServer.AddResource(resource, nil) + } + }() + } return mcpServer } diff --git a/pkg/mcp/server_test.go b/pkg/mcp/server_test.go index 9f38a77..122a59f 100644 --- a/pkg/mcp/server_test.go +++ b/pkg/mcp/server_test.go @@ -44,8 +44,8 @@ func TestCreateSSEServer(t *testing.T) { // Set the dynamic client mockClient.SetDynamicClient(fakeDynamicClient) - // Create an MCP server - mcpServer := CreateServer(mockClient) + // Create an MCP server with default config + mcpServer := CreateServer(mockClient, nil) assert.NotNil(t, mcpServer, "MCP server should not be nil")