vthapar/subm-mcp-server
If you are the rightful owner of subm-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
A Model Context Protocol (MCP) server for managing multiple Kubernetes clusters.
Kubernetes Multi-Cluster MCP Server
A Model Context Protocol (MCP) server for managing multiple Kubernetes clusters. This server provides generic operations for any Kubernetes resource type, plus specialized operations for ServiceExports across multiple configured clusters.
Features
- Multi-cluster support with a single server instance
- Generic Resource Operations: Get and List any Kubernetes resource (pods, deployments, services, CRDs, etc.)
- Supports both namespaced and cluster-scoped resources
- Works with any API version (v1, apps/v1, custom CRDs, etc.)
- Label selector support for filtering
- ServiceExports (multicluster.x-k8s.io/v1alpha1): Get, List, Create, Delete
- Simplified creation with just name (manifest optional)
- Full MCS API compatibility
- Namespace Operations: List namespaces across clusters
- Multiple transport modes:
- Stdio: JSON-RPC 2.0 over stdin/stdout (default)
- HTTP: RESTful HTTP server with JSON-RPC 2.0
- Easy configuration via YAML file
- CORS support for HTTP mode
Prerequisites
- Go 1.21 or later
- Access to one or more Kubernetes clusters
- Valid kubeconfig files for each cluster
Installation
Build from source
git clone https://github.com/vthapar/subm-mcp-server.git
cd subm-mcp-server
make build
The binary will be created at bin/subm-mcp-server.
Install
make install
Configuration
Create a configuration file config.yaml:
clusters:
- name: cluster1
kubeconfig: /path/to/cluster1/kubeconfig
context: cluster1-context # optional
- name: cluster2
kubeconfig: /path/to/cluster2/kubeconfig
context: cluster2-context # optional
- name: local
kubeconfig: ~/.kube/config
# Server configuration (optional)
server:
transport: stdio # "stdio" or "http", defaults to "stdio"
http:
host: localhost # defaults to "localhost"
port: 8080 # defaults to 8080
See config.yaml.example for a complete example.
Usage
Running the server
Stdio Mode (Default)
# Using -config flag
./bin/subm-mcp-server -config config.yaml
# Using environment variable
export MCP_K8S_CONFIG=config.yaml
./bin/subm-mcp-server
# Override transport mode via command line
./bin/subm-mcp-server -config config.yaml -transport stdio
The server reads JSON-RPC 2.0 requests from stdin and writes responses to stdout.
HTTP Mode
# Using config file with HTTP transport
./bin/subm-mcp-server -config config.yaml
# Override via command line flags
./bin/subm-mcp-server -config config.yaml -transport http
# Custom host and port
./bin/subm-mcp-server -config config.yaml -transport http -http-host 0.0.0.0 -http-port 9000
The HTTP server exposes the following endpoints:
POST /mcp- MCP JSON-RPC 2.0 endpointGET /health- Health check endpoint
Available Tools
Cluster Management
list_clusters- List all configured clusterslist_namespaces- List all namespaces in a cluster
Generic Resource Operations
get_resource- Get any Kubernetes resource by API version and typelist_resources- List any Kubernetes resources by API version and type
ServiceExports (Specialized Operations)
get_serviceexport- Get a specific ServiceExportlist_serviceexports- List ServiceExports in a namespacecreate_serviceexport- Create a new ServiceExport (simple name-based or full manifest)delete_serviceexport- Delete a ServiceExport
Tool Details
Generic Resource Operations
The get_resource and list_resources tools work with any Kubernetes resource type:
Supported Resource Types:
- Core resources:
pods,services,configmaps,secrets,nodes,namespaces, etc. (useapi_version: "v1") - Apps resources:
deployments,statefulsets,daemonsets,replicasets(useapi_version: "apps/v1") - Custom Resources: Any CRD installed in your cluster (e.g.,
api_version: "submariner.io/v1alpha1",resource: "submariners")
Parameters:
cluster(required): Name of the cluster from configapi_version(required): API version (e.g., "v1", "apps/v1", "submariner.io/v1alpha1")resource(required): Resource type in plural form (e.g., "pods", "deployments", "submariners")name(required for get_resource): Resource namenamespace(optional): Namespace (omit for cluster-scoped resources like nodes)labels(optional for list_resources): Label selector for filtering
ServiceExport Operations
ServiceExports follow the Kubernetes Multi-Cluster Services API (MCS).
Simple Creation: Just provide a name - the server creates a minimal ServiceExport that declares the service should be exported.
Advanced Creation:
Provide a full manifest to specify additional fields like exportedLabels or exportedAnnotations.
Example Requests
Stdio Mode Examples
These examples show raw JSON-RPC requests/responses for stdio mode:
Initialize
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
List Tools
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
List Clusters
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "list_clusters",
"arguments": {}
}
}
List Namespaces
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "list_namespaces",
"arguments": {
"cluster": "cluster1"
}
}
}
Get a Resource (Pod Example)
{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "get_resource",
"arguments": {
"cluster": "cluster1",
"api_version": "v1",
"resource": "pods",
"namespace": "default",
"name": "my-pod"
}
}
}
List Resources (Pods with Label Selector)
{
"jsonrpc": "2.0",
"id": 6,
"method": "tools/call",
"params": {
"name": "list_resources",
"arguments": {
"cluster": "cluster1",
"api_version": "v1",
"resource": "pods",
"namespace": "default",
"labels": "app=myapp"
}
}
}
Get a Custom Resource (Submariner Example)
{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/call",
"params": {
"name": "get_resource",
"arguments": {
"cluster": "cluster1",
"api_version": "submariner.io/v1alpha1",
"resource": "submariners",
"name": "submariner"
}
}
}
List Cluster-Scoped Resources (Nodes with Labels)
{
"jsonrpc": "2.0",
"id": 8,
"method": "tools/call",
"params": {
"name": "list_resources",
"arguments": {
"cluster": "cluster1",
"api_version": "v1",
"resource": "nodes",
"labels": "submariner.io/gateway=true"
}
}
}
Create a ServiceExport (Simple)
{
"jsonrpc": "2.0",
"id": 9,
"method": "tools/call",
"params": {
"name": "create_serviceexport",
"arguments": {
"cluster": "cluster1",
"namespace": "default",
"name": "my-service"
}
}
}
Create a ServiceExport (With Manifest)
{
"jsonrpc": "2.0",
"id": 10,
"method": "tools/call",
"params": {
"name": "create_serviceexport",
"arguments": {
"cluster": "cluster1",
"namespace": "default",
"name": "my-service",
"manifest": "{\"apiVersion\":\"multicluster.x-k8s.io/v1alpha1\",\"kind\":\"ServiceExport\",\"metadata\":{\"name\":\"my-service\",\"namespace\":\"default\"},\"spec\":{\"exportedLabels\":{\"env\":\"prod\"}}}"
}
}
}
HTTP Mode Examples
These examples show how to make requests using curl when running in HTTP mode:
Health Check
curl http://localhost:8080/health
Response:
{
"status": "healthy",
"server": "kubernetes-mcp-server"
}
List Clusters
curl -s -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_clusters",
"arguments": {}
}
}'
List Namespaces
curl -s -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "list_namespaces",
"arguments": {
"cluster": "cluster1"
}
}
}'
Get a Resource (Pod)
curl -s -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "get_resource",
"arguments": {
"cluster": "cluster1",
"api_version": "v1",
"resource": "pods",
"namespace": "default",
"name": "my-pod"
}
}
}'
List Resources (Submariner CRs)
curl -s -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "list_resources",
"arguments": {
"cluster": "cluster1",
"api_version": "submariner.io/v1alpha1",
"resource": "submariners"
}
}
}'
Create a ServiceExport
curl -s -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "create_serviceexport",
"arguments": {
"cluster": "cluster1",
"namespace": "default",
"name": "my-service"
}
}
}'
Project Structure
.
├── cmd/
│ └── server/
│ └── main.go # Application entry point
├── config/
│ └── config.go # Configuration loading and validation
├── pkg/
│ ├── cluster/
│ │ └── manager.go # Multi-cluster client manager
│ ├── handlers/
│ │ ├── resources.go # Generic resource operations (Get, List, ListNamespaces)
│ │ ├── serviceexports.go # ServiceExport CRUD operations
│ │ └── utils.go # Shared utilities
│ ├── mcp/
│ │ ├── server.go # MCP server implementation
│ │ ├── tools.go # Tool definitions
│ │ └── types.go # MCP protocol types
│ └── transport/
│ ├── http.go # HTTP transport implementation
│ └── stdio.go # Stdio transport implementation
├── .gitignore # Git ignore rules
├── Makefile # Build automation
├── README.md # This file
├── config.yaml.example # Example configuration file
├── go.mod # Go module definition
└── go.sum # Go module checksums
Development
Build
make build
Format code
make fmt
Run tests
make test
Clean build artifacts
make clean
License
MIT License
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.