Thank you for your interest in contributing to the Rancher AI MCP Server! This guide will help you get started with development and understand our contribution process.
- Go 1.24 or later
- Access to a Kubernetes cluster (for testing)
- Basic understanding of Kubernetes and the Model Context Protocol (MCP)
- Fork and Clone the Repository
git clone https://github.com/<your-username>/rancher-ai-mcp.git
cd rancher-ai-mcp- Install Dependencies
go mod download- Run Tests
go test -v -cover ./...- Build the Project
go build -o mcp-server .pkg/
├── client/ # Kubernetes client wrapper - use it to fetch/update/create resources in Kubernetes clusters
├── toolsets/ # Tool collections
│ ├── core/ # Core Kubernetes tools
│ ├── security/ # Security-related tools (example)
│ └── ... # Other domain-specific toolsets
├── response/ # Response formatting utilities
└── converter/ # Data transformation utilities
To add a new tool to an existing toolset (e.g., adding a new tool to the core toolset):
- Create a new handler file in the toolset directory (e.g.,
pkg/toolsets/core/your_tool.go):
package core
import (
"github.com/rancher/rancher-ai-mcp/pkg/response"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
// handleYourNewTool handles the yourNewTool tool invocation
func (t *Tools) handleYourNewTool(ctx context.Context, toolReq *mcp.CallToolRequest, params YourParams) (*mcp.CallToolResult, any, error) {
// Use the client to interact with Kubernetes if needed
result, err := t.client.GetResource(/* parameters */)
if err != nil {
return nil, nil, err
}
return &mcp.CallToolResult{
Content: []mcp.Content{&mcp.TextContent{Text: stringResult}},
}, nil, nil
}- Register the tool in the toolset's
tools.gofile by adding it to theAddTools()method:
func (t *Tools) AddTools(mcpServer *mcp.Server) {
// ... existing tools ...
mcp.AddTool(mcpServer, &mcp.Tool{
Name: "yourNewTool",
Description: "Clear description of what the tool does",
Meta: map[string]any{"toolset": "your-toolset"},
Handler: t.handleYourNewTool,
})
}- Create a test file (e.g.,
pkg/toolsets/core/your_tool_test.go) following the existing test patterns:
package core
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestHandleYourNewTool(t *testing.T) {
// Add unit tests here
}- Run tests to ensure everything works:
go test -v ./pkg/toolsets/core- Update documentation in README.md to list the new tool in the Available Tools table
- Create a new directory under
pkg/toolsets/(e.g.,pkg/toolsets/security/) - Implement the
toolsAdderinterface:
type toolsAdder interface {
AddTools(mcpServer *mcp.Server)
}- Create a
tools.gofile with your tool implementations:
package security
import (
"github.com/rancher/rancher-ai-mcp/pkg/client"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
type Tools struct {
client *client.Client
}
func NewTools(client *client.Client) *Tools {
return &Tools{client: client}
}
func (t *Tools) AddTools(mcpServer *mcp.Server) {
mcp.AddTool(mcpServer, &mcp.Tool{
Name: "scanForVulnerabilities",
Description: "Scan cluster for security vulnerabilities",
Meta: map[string]any{"toolset": "security"}, // make sure this is unique for this toolset
Handler: t.handleVulnerabilityScan,
})
// Add more tools here...
}- Make sure the toolset annotation is unique
- Add comprehensive tests in
tools_test.go - Update
pkg/toolsets/toolsets.goto include your new toolset - Update documentation in README.md
The pkg/response package provides utilities for formatting tool responses. There are two main ways to return data:
For basic responses without UI integration, use mcp.TextContent:
return &mcp.CallToolResult{
Content: []mcp.Content{&mcp.TextContent{Text: "your response in string here"}},
}, nil, nilThis returns plain text or formatted data that the AI agent can process.
When you want to enable the Rancher UI to display clickable links to Kubernetes resources, use response.CreateMcpResponse():
mcpResponse, err := response.CreateMcpResponse([]*unstructured.Unstructured{obj}, params.Cluster)
if err != nil {
zap.L().Error("failed to create mcp response", zap.String("tool", "updateKubernetesResource"), zap.Error(err))
return nil, nil, err
}
return &mcp.CallToolResult{
Content: []mcp.Content{&mcp.TextContent{Text: mcpResponse}},
}, nil, nilKey Benefits of CreateMcpResponse():
- Automatically extracts resource metadata (namespace, kind, name, cluster)
- Generates UI context that the Rancher UI uses to create clickable resource links
- Removes
managedFieldsto reduce payload size
When to use each:
- Use
mcp.TextContentfor: Simple text responses, status messages, errors, or non-resource data - Use
CreateMcpResponse()for: Any response containing Kubernetes resources that users might want to view in the UI
When reporting bugs or requesting features:
- Search Existing Issues - Check if it's already reported
- Use Issue Templates - Follow the provided templates
- Provide Details:
- Clear description of the issue or feature
- Steps to reproduce (for bugs)
- Expected vs actual behavior
- Environment details (Go version, Rancher version, Kubernetes version, etc.)
- Relevant logs or error messages