kubestellar-mcp ships two Go binaries that expose Kubernetes operations as MCP tools over stdio:
kubestellar-ops: diagnostics, RBAC analysis, security checks, and upgrade helperskubestellar-deploy: app-centric multi-cluster deployment, GitOps, Helm, kubectl, kustomize, and labeling workflows
Both binaries follow the same high-level pattern:
- a Cobra root command parses flags
--mcp-serverswitches the process into MCP server mode- the MCP server reads JSON-RPC requests from stdin
- a tool handler performs Kubernetes work through
client-go - the server writes a JSON-RPC response to stdout
cmd/ contains the compiled entrypoints.
cmd/kubestellar-ops/main.gostarts the diagnostics binarycmd/kubestellar-deploy/main.gostarts the deployment binary
The main packages stay intentionally thin and delegate almost immediately into pkg/.
pkg/ contains the application logic.
pkg/cmd/: Cobra command tree forkubestellar-opsroot.gowires global flags, natural-language query mode, and MCP modeclusters/,ai/, andupgrade/provide subcommands
pkg/mcp/server/: thekubestellar-opsMCP serverserver.godefines MCP request/response types, the stdio loop, tool schemas, and dispatchtools.go,diagnostics.go,multicluster.go, andupgrades.goimplement tool behavior
pkg/cluster/: kubeconfig-based cluster discovery and health checkspkg/gitops/: manifest reading, drift detection, and sync logic reused by MCP handlerspkg/ai/claude/: optional natural-language CLI query support forkubestellar-ops querypkg/progress/: CLI progress helpers
pkg/deploy/cmd/: Cobra root command forkubestellar-deploypkg/deploy/mcp/: thekubestellar-deployMCP server and its handlersserver.goowns the MCP loop, tool catalog, and dispatchtools_app.go,tools_deploy.go,tools_gitops.go,tools_helm.go,tools_kubectl.go,tools_kustomize.go, andtools_labels.gogroup handlers by domain
pkg/multicluster/: kubeconfig-backed client management, cluster selection, and parallel execution across clusters
commands/ contains markdown command descriptions used by the Claude Code plugin/marketplace experience. These files explain user-facing workflows such as deploy, delete, app status, and GitOps operations. They are not compiled into the Go binaries, but they should stay aligned with the MCP tools exposed by the servers.
go build -o ./bin/kubestellar-ops ./cmd/kubestellar-ops
go build -o ./bin/kubestellar-deploy ./cmd/kubestellar-deployThe servers speak newline-delimited JSON-RPC over stdio, so they can be launched directly from a terminal:
./bin/kubestellar-ops --mcp-server
./bin/kubestellar-deploy --mcp-serverThey will wait for MCP requests on stdin and write responses to stdout.
The README documents the supported plugin workflow. For local development, the easiest path is:
- build the binary into
./bin - prepend that directory to your
PATH - install or update the
kubestellar/claude-pluginsmarketplace in Claude Code - install the
kubestellar-opsand/orkubestellar-deployplugins - run
/mcpin Claude Code and verify the plugin connects
Example shell setup:
export PATH="$PWD/bin:$PATH"Because the plugin launches the named binary from PATH, putting your local build first lets Claude Code exercise your in-repo changes without publishing a release.
If you want a quick manual smoke test before opening Claude Code, send an initialize request yourself:
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | ./bin/kubestellar-ops --mcp-serverThe two binaries implement the same lifecycle, with slightly different internal helper packages.
cmd/kubestellar-ops/main.gocallspkg/cmd.Execute()cmd/kubestellar-deploy/main.gocallspkg/deploy/cmd.Execute()- the root Cobra command checks
--mcp-server - MCP mode creates a server instance (
pkg/mcp/server.NewServerorpkg/deploy/mcp.NewServer)
Once started, the server reads JSON-RPC messages from stdin.
initializereturns protocol version, server name/version, and tool capability metadatatools/listreturns the tool catalog and JSON schema for each toolinitialized/notifications/initializedis accepted as a notification without a response
In kubestellar-ops, the stdio loop lives in pkg/mcp/server/server.go and uses bufio.Reader.ReadBytes('\n').
In kubestellar-deploy, the loop is in pkg/deploy/mcp/server.go and uses a bufio.Scanner with a larger buffer for larger payloads.
When Claude Code invokes tools/call:
- the server unmarshals the tool name and arguments
handleToolsCall/handleToolCallswitches on the tool name- the selected handler validates input and performs the operation
Examples:
- ops handlers commonly call
getClientForCluster()orcluster.Discoverer - deploy handlers commonly use
multicluster.ClientManager,Executor, andSelector - GitOps handlers call into
pkg/gitops
Handlers then execute the real operation:
- read-only diagnostics call Kubernetes list/get APIs
- multi-cluster operations fan out across all discovered contexts
- deploy workflows aggregate per-cluster results
- GitOps workflows load manifests, compare desired state, and optionally apply changes
Finally the server wraps the result into an MCP tools/call response and writes one JSON line to stdout.
There is one important implementation difference:
kubestellar-opshandlers usually return(string, bool)where the string is preformatted human-readable output and the boolean marks error statekubestellar-deployhandlers usually return structured Go values thatserver.gomarshals into formatted JSON text for the MCP response body
Start by deciding which MCP server owns the capability:
- add diagnostics, RBAC, security, and upgrade tools to
pkg/mcp/server/ - add deployment and app-operation tools to
pkg/deploy/mcp/
Keep handlers grouped by domain.
- add diagnostics logic to
diagnostics.goor a new domain-specific file inpkg/mcp/server/ - add deploy/GitOps/Helm/kubectl logic to the matching
pkg/deploy/mcp/tools_*.gofile
Expose the tool to MCP clients by adding it to the tool catalog in the relevant server file:
pkg/mcp/server/server.go→handleToolsListpkg/deploy/mcp/server.go→handleListTools
At this stage define:
- the tool name
- a clear description
- the JSON input schema
- required fields
Add a new case in the tool dispatch switch:
pkg/mcp/server/server.go→handleToolsCallpkg/deploy/mcp/server.go→handleToolCall
This is what connects the public MCP tool name to your Go handler.
Implementation conventions differ slightly by binary:
- implement a method on
*Server - accept
context.Contextwhen the tool performs Kubernetes I/O - use
getClientForCluster,discoverer, or shared helpers - return a readable text summary and whether the call should be marked as an error
- implement a method on
*Server - unmarshal the raw arguments into a typed request struct
- use
Executor,Selector,ClientManager, andpkg/gitopshelpers as needed - return a structured response object and an
error
Add focused unit tests beside the implementation.
Examples already in the repo:
pkg/mcp/server/tools_test.gopkg/mcp/server/diagnostics_test.gopkg/deploy/mcp/tools_app_test.gopkg/deploy/mcp/tools_gitops_test.go
Favor the existing testing style:
- exercise the handler directly
- inject fakes/stubs for cluster discovery, kube clients, or manifest readers where supported
- assert both success output and error cases
If the tool changes the user experience, update the relevant files:
README.mdordocs/for developer/operator guidance- matching markdown in
commands/if the Claude Code command descriptions should surface the new workflow
The repository is mostly covered by Go unit tests colocated with the implementation.
- Cobra command behavior in
pkg/cmd/...andpkg/deploy/cmd/... - kubeconfig and cluster discovery logic in
pkg/cluster/andpkg/multicluster/ - MCP request handling and tool execution in
pkg/mcp/server/andpkg/deploy/mcp/ - GitOps helpers in
pkg/gitops/ - Claude prompt/client helpers in
pkg/ai/claude/
Run these before sending changes for review:
go test ./...
go vet ./...The GitHub Actions workflow in .github/workflows/build-test.yml also runs:
go build -v ./...go test -v -race -coverprofile=coverage.out ./...golangci-lint
That combination keeps command wiring, MCP protocol handling, and Kubernetes helper logic from drifting out of sync.