Skip to content

Commit fe52766

Browse files
authored
deploy: Deploy the registry to GCP (#255)
Adds the Pulumi code to: - Deploy the registry (and associated services e.g. mongodb) to Google Cloud Platform (GCP), on top of Google Kubernetes Engine (GKE) - Sets up proper environments and secrets management - Uses the real container image, now that it's published in #225. At the moment attached to latest, we might want to pin the version later (or perhaps always use `latest` in staging, and pin prod) - Uses real domains (`staging.registry.modelcontextprotocol.io`) rather than examples (``) ## Motivation and Context Setting up infrastructure to deploy it. I set something up in Azure in #227, although not super robust (e.g. no service accounts etc.). Think we will use GCP as: - the maintainers have experience with GCP, but none with Azure - costs are quite low, and Anthropic is happy to cover them in the short term - means we only have to maintain one login system (just Google Cloud Identity), not two (Google Workspace + Azure) ## How Has This Been Tested? Deployed this to a staging and production cluster. Try it yourself at: ```bash curl -H "Host: staging.registry.modelcontextprotocol.io" -k https://35.222.36.75/v0/ping ``` (will be sorting out domains very soon) ## Breaking Changes NA - just adds support for GCP deployment ## Types of changes <!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update ## Checklist <!-- Go over all the following points, and put an `x` in all the boxes that apply. --> - [x] I have read the [MCP Documentation](https://modelcontextprotocol.io) - [x] My code follows the repository's style guidelines - [ ] New and existing tests pass locally - [x] I have added appropriate error handling - [x] I have added or updated documentation as needed ## Additional context <!-- Add any other context, implementation notes, or design decisions --> Expected follow-ups: - GitHub Action setup to deploy things to the cluster from GitHub, to avoid gatekeeping to just the people with the secrets.
1 parent 667e284 commit fe52766

File tree

13 files changed

+395
-144
lines changed

13 files changed

+395
-144
lines changed

deploy/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,7 @@ Thumbs.db
2626

2727
# Build artifacts
2828
infra
29+
30+
# Secrets
31+
passphrase.prod.txt
32+
passphrase.staging.txt

deploy/Makefile

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,31 @@
1-
.PHONY: help init preview deploy destroy clean dev-init prod-init dev-deploy prod-deploy
1+
.PHONY: help build local-preview local-up staging-preview staging-up prod-preview prod-up
22

3+
# Default target
34
help: ## Show this help message
4-
@echo "Usage: make [target]"
5-
@echo ""
6-
@echo "Targets:"
7-
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " %-15s %s\n", $$1, $$2}'
5+
@echo "Available targets:"
6+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " %-20s %s\n", $$1, $$2}'
87

9-
init: ## Initialize Pulumi stack
10-
pulumi stack init
8+
# Build the Go binary
9+
build: ## Build the Pulumi Go program
10+
go build
1111

12-
preview: ## Preview infrastructure changes
13-
pulumi preview
12+
# Local stack commands
13+
local-preview: build ## Preview local infrastructure changes
14+
PULUMI_CONFIG_PASSPHRASE="" pulumi preview --stack local
1415

15-
deploy: ## Deploy infrastructure
16-
pulumi up --yes
16+
local-up: build ## Deploy local infrastructure
17+
PULUMI_CONFIG_PASSPHRASE="" pulumi up --yes --stack local
1718

18-
destroy: ## Destroy infrastructure
19-
pulumi destroy --yes
19+
# Staging stack commands
20+
staging-preview: build ## Preview staging infrastructure changes
21+
PULUMI_CONFIG_PASSPHRASE_FILE=passphrase.staging.txt pulumi preview --stack gcpStaging
2022

21-
clean: ## Clean up temporary files
22-
rm -rf .pulumi/
23-
rm -f Pulumi.*.yaml.bak
23+
staging-up: build ## Deploy staging infrastructure
24+
PULUMI_CONFIG_PASSPHRASE_FILE=passphrase.staging.txt pulumi up --yes --stack gcpStaging
2425

25-
dev-init: ## Initialize development stack
26-
pulumi stack init dev
27-
pulumi stack select dev
26+
# Production stack commands
27+
prod-preview: build ## Preview production infrastructure changes
28+
PULUMI_CONFIG_PASSPHRASE_FILE=passphrase.prod.txt pulumi preview --stack gcpProd
2829

29-
prod-init: ## Initialize production stack
30-
pulumi stack init prod
31-
pulumi stack select prod
32-
33-
dev-deploy: ## Deploy to development environment
34-
pulumi stack select dev
35-
pulumi up --yes
36-
37-
prod-deploy: ## Deploy to production environment
38-
pulumi stack select prod
39-
pulumi up --yes
40-
41-
dev-destroy: ## Destroy development environment
42-
pulumi stack select dev
43-
pulumi destroy --yes
44-
45-
prod-destroy: ## Destroy production environment
46-
pulumi stack select prod
47-
pulumi destroy --yes
30+
prod-up: build ## Deploy production infrastructure
31+
PULUMI_CONFIG_PASSPHRASE_FILE=passphrase.prod.txt pulumi up --yes --stack gcpProd
File renamed without changes.

deploy/Pulumi.gcpProd.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
config:
2+
mcp-registry:environment: prod
3+
mcp-registry:provider: gcp
4+
gcp:project: mcp-registry-prod
5+
mcp-registry:githubClientId: your-github-client-id
6+
mcp-registry:githubClientSecret:
7+
secure: v1:68BmTaKlZ+v77IDj:vVeMsAq/8QoCzkLzgo8MC8F5ALcC5TydWiqZ2NmnnFRpfF3MRPV69Os=
8+
gcp:credentials:
9+
secure: v1:hyZWlpeMTFDnMcz2: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
10+
encryptionsalt: v1:0funtAX4m9k=:v1:yMCnBXyBO+q4+/yy:AqWJTzwwIWXmUK0JGCzqbeg0RUr8Jw==

deploy/Pulumi.gcpStaging.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
config:
2+
mcp-registry:environment: staging
3+
mcp-registry:provider: gcp
4+
gcp:project: mcp-registry-staging
5+
mcp-registry:githubClientId: your-github-client-id
6+
mcp-registry:githubClientSecret:
7+
secure: v1:BpUPXf7aQcG8qHF9:YJxKbhWi5ZQSTdNGrdhzzCGz7sWXKhmNe+yrTls2cKC3/w==
8+
gcp:credentials:
9+
secure: v1:RaHpGsBp37XO/EhJ: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
10+
encryptionsalt: v1:EKBwmTmss1c=:v1:JLd4a7cM0X8Jroh+:z9/q6RSCEFTDzMV6X6h5Tpbw0tnpkA==

deploy/README.md

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# MCP Registry Kubernetes Deployment
22

3-
This directory contains Pulumi infrastructure code to deploy the MCP Registry service to a Kubernetes cluster. It supports multiple Kubernetes providers: Azure Kubernetes Service (AKS) and local (using existing kubeconfig).
3+
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).
44

55
## Quick Start
66

@@ -19,17 +19,53 @@ Pre-requisites:
1919

2020
# To use your local kubeconfig (default)
2121
pulumi config set mcp-registry:provider local
22-
# Alternative: To use AKS
23-
# pulumi config set mcp-registry:provider aks
2422

2523
# GitHub OAuth
2624
pulumi config set mcp-registry:githubClientId <your-github-client-id>
2725
pulumi config set --secret mcp-registry:githubClientSecret <your-github-client-secret>
2826
```
29-
4. Deploy: `go build && PULUMI_CONFIG_PASSPHRASE="" pulumi up --yes`
30-
5. Access the repository via the ingress load balancer. You can find its external IP with `kubectl get svc nginx-ingress-ingress-nginx-controller -n ingress-nginx` (with minikube, if it's 'pending' you might need `minikube tunnel`). Then run `curl -H "Host: mcp-registry-local.example.com" -k https://<EXTERNAL-IP>/v0/ping` to check that the service is up.
27+
4. Deploy: `make local-up`
28+
5. 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 need `minikube tunnel`). Then run `curl -H "Host: local.registry.modelcontextprotocol.io" -k https://<EXTERNAL-IP>/v0/ping` to check that the service is up.
3129
32-
### Production Deployment (AKS)
30+
### Production Deployment (GCP)
31+
32+
**Note:** This is how the production deployment will be set up once. But then the plan will be future updates are effectively a login + `pulumi up` from GitHub Actions.
33+
34+
Pre-requisites:
35+
- [Pulumi CLI installed](https://www.pulumi.com/docs/iac/download-install/)
36+
- A Google Cloud Platform (GCP) account
37+
- A GCP Service Account with appropriate permissions
38+
39+
1. Create a project: `gcloud projects create mcp-registry-prod`
40+
2. Set the project: `gcloud config set project mcp-registry-prod`
41+
3. Enable required APIs: `gcloud services enable storage.googleapis.com && gcloud services enable container.googleapis.com`
42+
4. Create a service account with necessary permissions, and get the key:
43+
```bash
44+
gcloud iam service-accounts create pulumi-svc
45+
sleep 10
46+
gcloud projects add-iam-policy-binding mcp-registry-prod --member="serviceAccount:[email protected]" --role="roles/container.admin"
47+
gcloud projects add-iam-policy-binding mcp-registry-prod --member="serviceAccount:[email protected]" --role="roles/compute.admin"
48+
gcloud projects add-iam-policy-binding mcp-registry-prod --member="serviceAccount:[email protected]" --role="roles/storage.admin"
49+
gcloud iam service-accounts add-iam-policy-binding $(gcloud projects describe mcp-registry-prod --format="value(projectNumber)")[email protected] --member="serviceAccount:[email protected]" --role="roles/iam.serviceAccountUser"
50+
gcloud iam service-accounts keys create sa-key.json --iam-account=pulumi-svc@mcp-registry-prod.iam.gserviceaccount.com
51+
```
52+
5. Create a GCS bucket for Pulumi state: `gsutil mb gs://mcp-registry-prod-pulumi-state`
53+
6. Set Pulumi's backend to GCS: `pulumi login gs://mcp-registry-prod-pulumi-state`
54+
7. Get the passphrase file `passphrase.prod.txt` from @domdomegg
55+
- TODO: avoid dependence on one person! Probably will shift all of this into CI.
56+
8. Init the GCP stack: `PULUMI_CONFIG_PASSPHRASE_FILE=passphrase.prod.txt pulumi stack init gcpProd`
57+
9. Set the GCP credentials in Pulumi config:
58+
```bash
59+
# Base64 encode the service account key and set it
60+
pulumi config set --secret gcp:credentials "$(base64 < sa-key.json)"
61+
```
62+
10. Deploy: `make prod-up`
63+
11. Access the repository via the ingress load balancer. You can find its external IP with: `kubectl get svc ingress-nginx-controller -n ingress-nginx`.
64+
Then run `curl -H "Host: prod.registry.modelcontextprotocol.io" -k https://<EXTERNAL-IP>/v0/ping` to check that the service is up.
65+
66+
<!--
67+
68+
### Production Deployment (Azure)
3369

3470
**Note:** This is how the production deployment will be set up once. But then the plan will be future updates are effectively a login + `pulumi up` from GitHub Actions.
3571

@@ -45,18 +81,21 @@ Pre-requisites:
4581
5. Add the 'Storage Blob Data Contributor' role assignment for yourself on the storage account: `az role assignment create --assignee $(az ad signed-in-user show --query id -o tsv) --role "Storage Blob Data Contributor" --scope "/subscriptions/$(az account show --query id -o tsv)/resourceGroups/official-mcp-registry-prod"`
4682
6. Create a container: `az storage container create --name pulumi-state --account-name officialmcpregistryprod`
4783
7. Set Pulumi's backend to Azure: `pulumi login 'azblob://pulumi-state?storage_account=officialmcpregistryprod'`
48-
8. Init the production stack: `pulumi stack init prod`
84+
8. Init the production stack: `pulumi stack init aksProd`
4985
- TODO: This has a password that maybe needs to be shared with select contributors?
5086
9. Deploy: `go build && PULUMI_CONFIG_PASSPHRASE="" pulumi up --yes`
51-
10. Access the repository via the ingress load balancer. You can find its external IP with `kubectl get svc nginx-ingress-ingress-nginx-controller -n ingress-nginx` or view it in the Pulumi outputs. Then run `curl -H "Host: mcp-registry-prod.example.com" -k https://<EXTERNAL-IP>/v0/ping` to check that the service is up.
87+
10. Access the repository via the ingress load balancer. You can find its external IP with `kubectl get svc ingress-nginx-controller -n ingress-nginx` or view it in the Pulumi outputs. Then run `curl -H "Host: prod.registry.modelcontextprotocol.io" -k https://<EXTERNAL-IP>/v0/ping` to check that the service is up.
88+
89+
-->
5290
5391
## Structure
5492
5593
```
5694
├── main.go # Pulumi program entry point
5795
├── Pulumi.yaml # Project configuration
5896
├── Pulumi.local.yaml # Local stack configuration
59-
├── Pulumi.prod.yaml # Production stack configuration
97+
├── Pulumi.prod.yaml # Production stack configuration (Azure)
98+
├── Pulumi.gcp.yaml # Production stack configuration (GCP)
6099
├── Makefile # Build and deployment targets
61100
├── go.mod # Go module dependencies
62101
├── go.sum # Go module checksums
@@ -70,6 +109,7 @@ Pre-requisites:
70109
└── providers/ # Kubernetes cluster providers
71110
├── types.go # Provider interface definitions
72111
├── aks/ # Azure Kubernetes Service provider
112+
├── gcp/ # Google Kubernetes Engine provider
73113
└── local/ # Local kubeconfig provider
74114
```
75115
@@ -91,9 +131,11 @@ Pre-requisites:
91131
| Parameter | Description | Required |
92132
|-----------|-------------|----------|
93133
| `environment` | Deployment environment (dev/prod) | Yes |
94-
| `provider` | Kubernetes provider (local/aks) | No (default: local) |
134+
| `provider` | Kubernetes provider (local/aks/gcp) | No (default: local) |
95135
| `githubClientId` | GitHub OAuth Client ID | Yes |
96136
| `githubClientSecret` | GitHub OAuth Client Secret | Yes |
137+
| `gcpProjectId` | GCP Project ID (required when provider=gcp) | No |
138+
| `gcpRegion` | GCP Region (default: us-central1) | No |
97139
98140
## Troubleshooting
99141

0 commit comments

Comments
 (0)