⚠️ Alpha SoftwareThis project is in early development. APIs may change, features may be incomplete, and bugs are expected. We'd appreciate your feedback via issues.
A Kubernetes operator for deploying MCP servers.
Protocol validation - The operator connects to your MCP server after deployment and verifies it actually speaks MCP. It detects which protocol your server uses (SSE or Streamable HTTP), what capabilities it advertises, and whether it requires authentication. This catches configuration mistakes early - wrong port, wrong path, server not actually running MCP, etc.
Correct transport configuration - SSE and Streamable HTTP have different requirements. The operator handles the transport-specific configuration (paths, session management, keep-alive settings) so you don't have to figure out the right Service annotations or health check paths for each protocol type.
Observability - If you have Prometheus Operator installed, the operator creates ServiceMonitors and Grafana dashboards for your MCP servers. There's also an optional metrics sidecar that can collect MCP-specific metrics (request counts, latencies, etc.)
Standard Kubernetes resources - Under the hood, it creates Deployments, Services, ServiceAccounts, and HPAs. Nothing proprietary.
- Ingress/external exposure - Creates a ClusterIP Service by default. You need to create your own Ingress, Gateway, or change the Service type to LoadBalancer if you want external access.
- Authentication - The operator detects if your server requires auth, but doesn't handle authentication itself. You need to configure auth at your server or ingress layer.
- stdio transport - Only supports HTTP-based transports (SSE and Streamable HTTP). If your MCP server uses stdio, you can wrap it with an adapter like supergateway that exposes it as SSE or Streamable HTTP, then deploy that container with this operator. See the containerizing guide for details.
- MCP client - This deploys servers, not clients. It doesn't help you connect to MCP servers from your applications.
- TLS termination - Doesn't configure TLS by default. You can enable TLS termination via the metrics sidecar (
spec.sidecar.tls) if you're using metrics, or use an ingress controller.
See the Getting Started Guide for a complete walkthrough.
Two options:
# Get latest version
VERSION=$(curl -s https://api.github.com/repos/vitorbari/mcp-operator/releases | jq -r '.[0].tag_name' | sed 's/^v//')
# Install
helm install mcp-operator oci://ghcr.io/vitorbari/mcp-operator \
--version ${VERSION} \
--namespace mcp-operator-system \
--create-namespace# Get latest version
VERSION=$(curl -s https://api.github.com/repos/vitorbari/mcp-operator/releases | jq -r '.[0].tag_name')
# Install from release assets
kubectl apply -f https://github.com/vitorbari/mcp-operator/releases/download/${VERSION}/install.yamlHelm is easier to configure. kubectl has fewer dependencies.
Create my-server.yaml:
apiVersion: mcp.mcp-operator.io/v1
kind: MCPServer
metadata:
name: my-mcp-server
spec:
image: "your-registry/your-mcp-server:v1.0.0"Apply it:
kubectl apply -f my-server.yamlWatch the status:
kubectl get mcpservers -wOutput:
NAME PHASE REPLICAS READY PROTOCOL VALIDATION CAPABILITIES AGE
my-mcp-server Running 1 1 sse Validated ["tools","resources","prompts"] 109s
The operator created a Deployment and Service. It also connected to your server to validate it speaks MCP and detected its capabilities.
When you create an MCPServer, the operator creates:
- Deployment - Runs your server container with configured health checks
- Service - ClusterIP service for in-cluster access (configurable to NodePort or LoadBalancer)
- ServiceAccount - For pod identity
- HPA - If
hpa.enabled: true, creates a HorizontalPodAutoscaler
The operator also runs validation against your server to check protocol compliance.
apiVersion: mcp.mcp-operator.io/v1
kind: MCPServer
metadata:
name: my-mcp-server
spec:
image: "tzolov/mcp-everything-server:v3"
command: ["node", "dist/index.js", "sse"]
transport:
type: http
protocol: auto # Let the operator detect the protocol
config:
http:
port: 3001
path: "/sse"
sessionManagement: true
# Scale between 2-10 pods based on CPU
hpa:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70
# Pod security
security:
runAsUser: 1000
runAsGroup: 1000
runAsNonRoot: true
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "1000m"
memory: "1Gi"The operator automatically validates your MCP servers to ensure they're protocol-compliant. It checks transport connectivity, protocol version, authentication requirements, and available capabilities.
Enable strict mode to fail deployments that don't pass validation:
spec:
validation:
strictMode: trueFor detailed validation behavior, see the Validation Behavior Guide.
Requires Prometheus Operator to be installed in your cluster.
With Helm:
VERSION=$(curl -s https://api.github.com/repos/vitorbari/mcp-operator/releases | jq -r '.[0].tag_name' | sed 's/^v//')
helm install mcp-operator oci://ghcr.io/vitorbari/mcp-operator \
--version ${VERSION} \
--namespace mcp-operator-system \
--create-namespace \
--set prometheus.enable=true \
--set grafana.enabled=trueWith kubectl:
VERSION=$(curl -s https://api.github.com/repos/vitorbari/mcp-operator/releases | jq -r '.[0].tag_name')
kubectl apply -f https://github.com/vitorbari/mcp-operator/releases/download/${VERSION}/monitoring.yamlThis creates a ServiceMonitor (so Prometheus scrapes the operator metrics) and a ConfigMap with a Grafana dashboard.
See the Monitoring Guide for details.
Enable per-server metrics collection with a single line:
apiVersion: mcp.mcp-operator.io/v1
kind: MCPServer
metadata:
name: my-mcp-server
spec:
image: your-registry/your-mcp-server:latest
transport:
type: http
config:
http:
port: 3001
metrics:
enabled: true # That's it!When enabled, the operator injects a metrics sidecar that automatically tracks:
- Request counts, latencies, and sizes
- Tool calls by tool name
- Resource reads by URI
- JSON-RPC errors by method and code
- SSE connection metrics
See the MCP Server Metrics Guide for available metrics, Grafana queries, and alerting examples.
MCP has two HTTP transport protocols: SSE (Server-Sent Events, older) and Streamable HTTP (newer). The operator can auto-detect which one your server uses, or you can specify it explicitly.
Auto-detection:
transport:
type: http
protocol: autoExplicit SSE:
transport:
type: http
protocol: sseExplicit Streamable HTTP:
transport:
type: http
protocol: streamable-httpAuto-detection works by trying to connect with each protocol. If you know which protocol your server uses, specifying it explicitly is faster.
- Getting Started Guide - 5-minute walkthrough
- Installation Guide - Detailed installation options
- Configuration Guide - Complete configuration patterns and examples
- Environment Variables - Configuring environment variables
- Configuration Examples - Real-world YAML examples
- API Reference - Complete CRD field documentation
- Validation Behavior - Protocol validation deep dive
- Troubleshooting Guide - Common issues and solutions
- Monitoring Guide - Operator metrics, dashboards, and alerts
- MCP Server Metrics - Per-server metrics with the sidecar proxy
- Sidecar Architecture - Technical deep-dive into the metrics sidecar
- Release Process - For maintainers
- Contributing - Development and contribution guidelines
Check out the config/samples/ directory for real-world examples:
| # | Sample | Transport | Metrics | Use Case |
|---|---|---|---|---|
| 01 | wikipedia-sse | SSE | No | Minimal example using Wikipedia MCP |
| 02 | streamable-http-basic | Streamable HTTP | No | Modern transport, production-ready |
| 03 | sse-optimized | SSE | No | SSE with session affinity |
| 04 | metrics-basic | Streamable HTTP | Yes | Basic metrics collection |
| 05 | metrics-advanced | Streamable HTTP | Yes | Custom sidecar configuration |
| 06 | metrics-sse | SSE | Yes | SSE with metrics |
| 10 | complete-reference | Auto | Yes | All available options |
Apply all samples:
kubectl apply -k config/samples/See CONTRIBUTING.md for guidelines on bug reports, feature requests, and code contributions.
- Found a bug? Open an issue
- Have questions? Start a discussion
Copyright 2025 Vitor Bari.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
