| name | mcp-tool-registration |
| description | Use when defining or registering MCP tools with the Go SDK. Shows how to define tool schemas using Go structs, register handlers, and wire tool groups into the server. |
| allowed-tools | Read, Write, Edit, Grep |
MCP Tool Registration Pattern
Tools are registered with the MCP SDK using typed Go structs that auto-generate JSON Schema.
Defining a Tool
type HelmInstallInput struct {
Release string `json:"release" jsonschema:"required,description=Release name"`
Chart string `json:"chart" jsonschema:"required,description=Chart reference (repo/name or local path)"`
Namespace *string `json:"namespace" jsonschema:"description=Target namespace"`
ValuesFile *string `json:"values_file" jsonschema:"description=Path to values.yaml override"`
Set []string `json:"set" jsonschema:"description=Individual value overrides (key=value)"`
CreateNamespace bool `json:"create_namespace" jsonschema:"description=Create namespace if it doesn't exist"`
Wait bool `json:"wait" jsonschema:"description=Wait until all resources are ready"`
DryRun *string `json:"dry_run" jsonschema:"enum=client,enum=server,enum=none,description=Dry-run mode (default: none for helm)"`
}
type HelmInstallOutput struct {
Release string `json:"release"`
Namespace string `json:"namespace"`
Status string `json:"status"`
Revision int `json:"revision"`
}
Handler Function
func handleHelmInstall(
ctx context.Context,
req *mcp.CallToolRequest,
input HelmInstallInput,
) (*mcp.CallToolResult, HelmInstallOutput, error) {
if err := safety.CheckContext(ctx); err != nil {
return nil, HelmInstallOutput{}, err
}
args := []string{"install", input.Release, input.Chart, "-o", "json"}
result, err := executor.Run(ctx, "helm", args...)
if err != nil {
return nil, HelmInstallOutput{}, fmt.Errorf("helm_install: %w", err)
}
var output HelmInstallOutput
if err := json.Unmarshal(result.Stdout, &output); err != nil {
return nil, HelmInstallOutput{}, fmt.Errorf("helm_install: parse: %w", err)
}
return &mcp.CallToolResult{}, output, nil
}
Registration
func RegisterHelmTools(server *mcp.Server, exec *executor.Executor) {
mcp.AddTool(server, &mcp.Tool{
Name: "helm_install",
Description: "Install a Helm chart into the cluster",
}, handleHelmInstall)
mcp.AddTool(server, &mcp.Tool{
Name: "helm_upgrade",
Description: "Upgrade an existing Helm release",
}, handleHelmUpgrade)
}
Wiring in main.go
func main() {
server := mcp.NewServer(...)
exec := executor.New(cfg)
tools.RegisterK3dTools(server, exec)
tools.RegisterKubectlTools(server, exec)
tools.RegisterKustomizeTools(server, exec)
tools.RegisterTiltTools(server, exec)
tools.RegisterHelmTools(server, exec)
tools.RegisterArtifactHubTools(server, ahClient)
tools.RegisterDocSearchTools(server, index)
tools.RegisterCITools(server, exec)
mcp.ServeStdio(server)
}
Key Rules
- Tool name:
{group}_{verb} in snake_case
- Description: imperative mood, one line, no period
- Required fields: use
jsonschema:"required" tag
- Optional fields: use pointer types (
*string, *int)
- Enums: use
jsonschema:"enum=a,enum=b" tag