Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
50 changes: 35 additions & 15 deletions pkg/mcp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/mcp/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down