| Filename | Latest commit message | Latest commit date |
|---|---|---|
The Always pull policy is needed for the latest tag to force Kubernetes to pull the newest image on every pod creation, even if an image with that tag already exists locally. Without this, pods might use outdated cached versions since the latest tag is mutable and can point to different images over time. |
||
| .. | ||
| pkg | ||
| .gitignore | ||
| go.mod | ||
| go.sum | ||
| main.go | ||
| Makefile | ||
| Pulumi.aksProd.yaml | ||
| Pulumi.gcpProd.yaml | ||
| Pulumi.gcpStaging.yaml | ||
| Pulumi.local.yaml | ||
| Pulumi.yaml | ||
| README.md | ||
MCP Registry Kubernetes Deployment
This directory contains Pulumi infrastructure code to deploy the MCP Registry service to a Kubernetes cluster. It supports deploying the infrastructure locally (using an existing kubeconfig, e.g. with minikube) or to Google Cloud Platform (GCP).
Quick Start
Local Development
Pre-requisites:
- Pulumi CLI installed
- Access to a Kubernetes cluster via kubeconfig. You can run a cluster locally with minikube.
- Set Pulumi's backend to local:
pulumi login --local - Init the local stack:
pulumi stack init local(fine to leavepasswordblank) - Set your config:
# General environment pulumi config set mcp-registry:environment local # To use your local kubeconfig (default) pulumi config set mcp-registry:provider local # GitHub OAuth pulumi config set mcp-registry:githubClientId <your-github-client-id> pulumi config set --secret mcp-registry:githubClientSecret <your-github-client-secret> - Deploy:
make local-up - Access the repository via the ingress load balancer. You can find its external IP with
kubectl get svc ingress-nginx-controller -n ingress-nginx(with minikube, if it's 'pending' you might needminikube tunnel). Then runcurl -H "Host: local.registry.modelcontextprotocol.io" -k https://<EXTERNAL-IP>/v0/pingto check that the service is up.
Production Deployment (GCP)
Note: The production deployment is automatically handled by GitHub Actions. All merges to the main branch trigger an automatic deployment to GCP via the configured GitHub Actions workflow. The steps below are preserved as a log of what we did, or if a manual override is needed.
Pre-requisites:
- Pulumi CLI installed
- A Google Cloud Platform (GCP) account
- A GCP Service Account with appropriate permissions
- Create a project:
gcloud projects create mcp-registry-prod - Set the project:
gcloud config set project mcp-registry-prod - Enable required APIs:
gcloud services enable storage.googleapis.com && gcloud services enable container.googleapis.com - Create a service account with necessary permissions, and get the key:
gcloud iam service-accounts create pulumi-svc sleep 10 gcloud projects add-iam-policy-binding mcp-registry-prod --member="serviceAccount:pulumi-svc@mcp-registry-prod.iam.gserviceaccount.com" --role="roles/container.admin" gcloud projects add-iam-policy-binding mcp-registry-prod --member="serviceAccount:pulumi-svc@mcp-registry-prod.iam.gserviceaccount.com" --role="roles/compute.admin" gcloud projects add-iam-policy-binding mcp-registry-prod --member="serviceAccount:pulumi-svc@mcp-registry-prod.iam.gserviceaccount.com" --role="roles/storage.admin" gcloud iam service-accounts add-iam-policy-binding $(gcloud projects describe mcp-registry-prod --format="value(projectNumber)")-compute@developer.gserviceaccount.com --member="serviceAccount:pulumi-svc@mcp-registry-prod.iam.gserviceaccount.com" --role="roles/iam.serviceAccountUser" gcloud iam service-accounts keys create sa-key.json --iam-account=pulumi-svc@mcp-registry-prod.iam.gserviceaccount.com - Create a GCS bucket for Pulumi state:
gsutil mb gs://mcp-registry-prod-pulumi-state - Set Pulumi's backend to GCS:
pulumi login gs://mcp-registry-prod-pulumi-state - Get the passphrase file
passphrase.prod.txtfrom the registry maintainers - Init the GCP stack:
PULUMI_CONFIG_PASSPHRASE_FILE=passphrase.prod.txt pulumi stack init gcpProd - Set the GCP credentials in Pulumi config:
# Base64 encode the service account key and set it pulumi config set --secret gcp:credentials "$(base64 < sa-key.json)" - Deploy:
make prod-up - Access the repository via the ingress load balancer. You can find its external IP with:
kubectl get svc ingress-nginx-controller -n ingress-nginx. Then runcurl -H "Host: prod.registry.modelcontextprotocol.io" -k https://<EXTERNAL-IP>/v0/pingto check that the service is up.
Structure
├── main.go # Pulumi program entry point
├── Pulumi.yaml # Project configuration
├── Pulumi.local.yaml # Local stack configuration
├── Pulumi.prod.yaml # Production stack configuration (Azure)
├── Pulumi.gcp.yaml # Production stack configuration (GCP)
├── Makefile # Build and deployment targets
├── go.mod # Go module dependencies
├── go.sum # Go module checksums
└── pkg/ # Infrastructure packages
├── k8s/ # Kubernetes deployment components
│ ├── cert_manager.go # SSL certificate management
│ ├── deploy.go # Deployment orchestration
│ ├── ingress.go # Ingress controller setup
│ ├── mongodb.go # MongoDB deployment
│ └── registry.go # MCP Registry deployment
└── providers/ # Kubernetes cluster providers
├── types.go # Provider interface definitions
├── aks/ # Azure Kubernetes Service provider
├── gcp/ # Google Kubernetes Engine provider
└── local/ # Local kubeconfig provider
Architecture Overview
Deployment Flow
- Pulumi program starts in
main.go - Configuration is loaded from Pulumi config files
- Provider factory creates appropriate cluster provider (AKS or local)
- Cluster provider sets up Kubernetes access
k8s.DeployAll()orchestrates complete deployment:- Certificate manager for SSL/TLS
- Ingress controller for external access
- MongoDB for data persistence
- MCP Registry application
Configuration
| Parameter | Description | Required |
|---|---|---|
environment |
Deployment environment (dev/prod) | Yes |
provider |
Kubernetes provider (local/aks/gcp) | No (default: local) |
githubClientId |
GitHub OAuth Client ID | Yes |
githubClientSecret |
GitHub OAuth Client Secret | Yes |
gcpProjectId |
GCP Project ID (required when provider=gcp) | No |
gcpRegion |
GCP Region (default: us-central1) | No |
Troubleshooting
Check Status
kubectl get pods
kubectl get deployment
kubectl get svc
kubectl get ingress
kubectl get svc -n ingress-nginx
View Logs
kubectl logs -l app=mcp-registry
kubectl logs -l app=mongodb