Operator
Production Kubernetes operator for deploying and validating MCP servers
Installation
npx mcp-operatorAsk AI about Operator
Powered by Claude · Grounded in docs
I know everything about Operator. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
MCP Operator
⚠️ Alpha Software
This 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.
Why use this?
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.
What this doesn't do
- 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.
Quick Start
See the Getting Started Guide for a complete walkthrough.
Installation
Two options:
Option 1: Install via Helm (Recommended)
# 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
Option 2: Install via kubectl
# 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.yaml
Helm is easier to configure. kubectl has fewer dependencies.
Your First MCPServer
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.yaml
Watch the status:
kubectl get mcpservers -w
Output:
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.
What Gets Created
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.
Examples
With Auto-Scaling
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"
Protocol Validation
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: true
For detailed validation behavior, see the Validation Behavior Guide.
Monitoring
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=true
With 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.yaml
This creates a ServiceMonitor (so Prometheus scrapes the operator metrics) and a ConfigMap with a Grafana dashboard.
See the Monitoring Guide for details.
MCP Server Metrics
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.
Transport Configuration
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: auto
Explicit SSE:
transport:
type: http
protocol: sse
Explicit Streamable HTTP:
transport:
type: http
protocol: streamable-http
Auto-detection works by trying to connect with each protocol. If you know which protocol your server uses, specifying it explicitly is faster.
Documentation
Getting Started
- Getting Started Guide - 5-minute walkthrough
- Installation Guide - Detailed installation options
Configuration
- Configuration Guide - Complete configuration patterns and examples
- Environment Variables - Configuring environment variables
- Configuration Examples - Real-world YAML examples
Reference
- API Reference - Complete CRD field documentation
- Validation Behavior - Protocol validation deep dive
Operations
- 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
Advanced Topics
- Release Process - For maintainers
- Contributing - Development and contribution guidelines
Examples and Samples
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/
Contributing
See CONTRIBUTING.md for guidelines on bug reports, feature requests, and code contributions.
Support
- Found a bug? Open an issue
- Have questions? Start a discussion
License
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.
