registry/deploy
Repository files (latest commit first)
Filename Latest commit message Latest commit date
dependabot[bot] f98e367dd9
build(deps): bump github.com/pulumi/pulumi/sdk/v3 from 3.259.0 to 3.261.0 in /deploy (#1606)
Bumps
[github.com/pulumi/pulumi/sdk/v3](https://github.com/pulumi/pulumi) from
3.259.0 to 3.261.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi/releases">github.com/pulumi/pulumi/sdk/v3's
releases</a>.</em></p>
<blockquote>
<h2>v3.261.0</h2>
<h2>3.261.0 (2026-09-02)</h2>
<h3>Features</h3>
<ul>
<li>[engine] Support state migration callbacks on resource registrations
<a
href="https://redirect.github.com/pulumi/pulumi/pull/24328">#24328</a></li>
<li>[cli/env] Add <code>pulumi env setup {aws,azure,gcp}</code> to
configure cloud OIDC trust and create the ESC environments that use it
<a
href="https://redirect.github.com/pulumi/pulumi/pull/23911">#23911</a></li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>[engine] Report a clear error instead of panicking when the stack's
state contains a custom resource with no ID <a
href="https://redirect.github.com/pulumi/pulumi/pull/24438">#24438</a></li>
<li>[cli] Show the agent account's claim URL instead of an inaccessible
View Live link when running on ephemeral agent credentials <a
href="https://redirect.github.com/pulumi/pulumi/pull/24476">#24476</a></li>
<li>[pcl] Fix a crash when binding a schema property with an integer
constant value <a
href="https://redirect.github.com/pulumi/pulumi/pull/24480">#24480</a></li>
<li>[cli/policy] Avoid hanging when policy pack fails to start up <a
href="https://redirect.github.com/pulumi/pulumi/pull/24492">#24492</a></li>
<li>[pkg/testing] Fix ProgramTest for providers whose Go module or NuGet
package has a double-digit major version <a
href="https://redirect.github.com/pulumi/pulumi/pull/24499">#24499</a></li>
<li>[sdk] Fix serialization of secret unknowns in NodeJS, Python and PCL
<a
href="https://redirect.github.com/pulumi/pulumi/pull/24500">#24500</a></li>
<li>[engine] Ignore internal property keys (those starting with an
underscore) when generating and checking update plans <a
href="https://redirect.github.com/pulumi/pulumi/pull/24532">#24532</a></li>
</ul>
<h3>Improvements</h3>
<ul>
<li>[sdkgen] Generate precise Python output types for discriminated
unions. An array of a union was typed <code>Sequence[Any]</code> and a
scalar union <code>Any</code>, while the matching getters on the
generated Args classes were already typed <a
href="https://redirect.github.com/pulumi/pulumi/pull/24485">#24485</a></li>
<li>[sdk/python] Resolve a union value to its member by matching the
value's wire shape, so unions whose members carry no constant properties
serialize and translate with the right member's property names <a
href="https://redirect.github.com/pulumi/pulumi/pull/24484">#24484</a></li>
<li>[sdkgen/python] Accept a generated output type wherever the
classes-and-dicts input types accept its Args class or TypedDict, so a
resource's output can be passed to another resource's input without a
type error <a
href="https://redirect.github.com/pulumi/pulumi/pull/24507">#24507</a></li>
<li>[engine] Send previously persisted outputs to a provider's Check on
update, gated by a new sends_old_outputs_to_check handshake capability
<a
href="https://redirect.github.com/pulumi/pulumi/pull/24524">#24524</a></li>
<li>[sdk/python] Add helper methods to transform ResourceOptions to
InvokeOptions <a
href="https://redirect.github.com/pulumi/pulumi/pull/24533">#24533</a></li>
</ul>
<h3>Miscellaneous</h3>
<ul>
<li>[java] Upgrade java to v1.36.3 <a
href="https://redirect.github.com/pulumi/pulumi/pull/24509">#24509</a></li>
<li>[yaml] Upgrade yaml to v1.38.5 <a
href="https://redirect.github.com/pulumi/pulumi/pull/24509">#24509</a></li>
<li>[sdk/dotnet] Upgrade dotnet to v3.113.1 <a
href="https://redirect.github.com/pulumi/pulumi/pull/24512">#24512</a></li>
</ul>
<h2>v3.260.0</h2>
<h2>3.260.0 (2026-08-28)</h2>
<h3>Features</h3>
<ul>
<li>[cli/deployment] Make <code>pulumi deployment settings get</code>
render every source kind and show environment variable values, changing
the <code>--output=json</code> shape of
<code>environmentVariables</code> from a list of names to a list of
objects <a
href="https://redirect.github.com/pulumi/pulumi/pull/24284">#24284</a></li>
<li>[sdk/go] Support Go 1.27 <a
href="https://redirect.github.com/pulumi/pulumi/pull/24401">#24401</a></li>
<li>[cli/state] Add <code>pulumi state promote</code> to turn stateful
snippets into Pulumi program code <a
href="https://redirect.github.com/pulumi/pulumi/pull/24453">#24453</a></li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>[engine] Replace resources whose deletedWith target is being
replaced, instead of leaving them orphaned in state <a
href="https://redirect.github.com/pulumi/pulumi/pull/23818">#23818</a></li>
<li>[sdk/python] Serialize typed object stack outputs with their
wire-format (camelCase) property names, matching other language SDKs <a
href="https://redirect.github.com/pulumi/pulumi/pull/24246">#24246</a></li>
<li>[cli/neo] Cancelling a task now interrupts a running local tool call
instead of waiting for it to finish <a
href="https://redirect.github.com/pulumi/pulumi/pull/24268">#24268</a></li>
<li>[programgen/python] Access schema properties whose names contain
hyphens as attributes under their Python names instead of subscripting
<a
href="https://redirect.github.com/pulumi/pulumi/pull/24300">#24300</a></li>
<li>[programgen/go] Generate valid struct field names for properties
whose names contain hyphens <a
href="https://redirect.github.com/pulumi/pulumi/pull/24300">#24300</a></li>
<li>[sdkgen/nodejs] Quote property names that are not legal identifiers
(e.g. kebab-case) in generated declarations and use bracket access for
them <a
href="https://redirect.github.com/pulumi/pulumi/pull/24300">#24300</a></li>
<li>[cli/neo] Cancelling a local tool call no longer leaves the TUI
stuck on &quot;Thinking...&quot; with input blocked <a
href="https://redirect.github.com/pulumi/pulumi/pull/24318">#24318</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pulumi/pulumi/blob/master/CHANGELOG.md">github.com/pulumi/pulumi/sdk/v3's
changelog</a>.</em></p>
<blockquote>
<h2>3.261.0 (2026-09-02)</h2>
<h3>Features</h3>
<ul>
<li>[engine] Support state migration callbacks on resource registrations
<a
href="https://redirect.github.com/pulumi/pulumi/pull/24328">#24328</a></li>
<li>[cli/env] Add <code>pulumi env setup {aws,azure,gcp}</code> to
configure cloud OIDC trust and create the ESC environments that use it
<a
href="https://redirect.github.com/pulumi/pulumi/pull/23911">#23911</a></li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>[engine] Report a clear error instead of panicking when the stack's
state contains a custom resource with no ID <a
href="https://redirect.github.com/pulumi/pulumi/pull/24438">#24438</a></li>
<li>[cli] Show the agent account's claim URL instead of an inaccessible
View Live link when running on ephemeral agent credentials <a
href="https://redirect.github.com/pulumi/pulumi/pull/24476">#24476</a></li>
<li>[pcl] Fix a crash when binding a schema property with an integer
constant value <a
href="https://redirect.github.com/pulumi/pulumi/pull/24480">#24480</a></li>
<li>[cli/policy] Avoid hanging when policy pack fails to start up <a
href="https://redirect.github.com/pulumi/pulumi/pull/24492">#24492</a></li>
<li>[pkg/testing] Fix ProgramTest for providers whose Go module or NuGet
package has a double-digit major version <a
href="https://redirect.github.com/pulumi/pulumi/pull/24499">#24499</a></li>
<li>[sdk] Fix serialization of secret unknowns in NodeJS, Python and PCL
<a
href="https://redirect.github.com/pulumi/pulumi/pull/24500">#24500</a></li>
<li>[engine] Ignore internal property keys (those starting with an
underscore) when generating and checking update plans <a
href="https://redirect.github.com/pulumi/pulumi/pull/24532">#24532</a></li>
</ul>
<h3>Improvements</h3>
<ul>
<li>[sdkgen] Generate precise Python output types for discriminated
unions. An array of a union was typed <code>Sequence[Any]</code> and a
scalar union <code>Any</code>, while the matching getters on the
generated Args classes were already typed <a
href="https://redirect.github.com/pulumi/pulumi/pull/24485">#24485</a></li>
<li>[sdk/python] Resolve a union value to its member by matching the
value's wire shape, so unions whose members carry no constant properties
serialize and translate with the right member's property names <a
href="https://redirect.github.com/pulumi/pulumi/pull/24484">#24484</a></li>
<li>[sdkgen/python] Accept a generated output type wherever the
classes-and-dicts input types accept its Args class or TypedDict, so a
resource's output can be passed to another resource's input without a
type error <a
href="https://redirect.github.com/pulumi/pulumi/pull/24507">#24507</a></li>
<li>[engine] Send previously persisted outputs to a provider's Check on
update, gated by a new sends_old_outputs_to_check handshake capability
<a
href="https://redirect.github.com/pulumi/pulumi/pull/24524">#24524</a></li>
<li>[sdk/python] Add helper methods to transform ResourceOptions to
InvokeOptions <a
href="https://redirect.github.com/pulumi/pulumi/pull/24533">#24533</a></li>
</ul>
<h3>Miscellaneous</h3>
<ul>
<li>[java] Upgrade java to v1.36.3 <a
href="https://redirect.github.com/pulumi/pulumi/pull/24509">#24509</a></li>
<li>[yaml] Upgrade yaml to v1.38.5 <a
href="https://redirect.github.com/pulumi/pulumi/pull/24509">#24509</a></li>
<li>[sdk/dotnet] Upgrade dotnet to v3.113.1 <a
href="https://redirect.github.com/pulumi/pulumi/pull/24512">#24512</a></li>
</ul>
<h2>3.260.0 (2026-08-28)</h2>
<h3>Features</h3>
<ul>
<li>[cli/deployment] Make <code>pulumi deployment settings get</code>
render every source kind and show environment variable values, changing
the <code>--output=json</code> shape of
<code>environmentVariables</code> from a list of names to a list of
objects <a
href="https://redirect.github.com/pulumi/pulumi/pull/24284">#24284</a></li>
<li>[sdk/go] Support Go 1.27 <a
href="https://redirect.github.com/pulumi/pulumi/pull/24401">#24401</a></li>
<li>[cli/state] Add <code>pulumi state promote</code> to turn stateful
snippets into Pulumi program code <a
href="https://redirect.github.com/pulumi/pulumi/pull/24453">#24453</a></li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>[engine] Replace resources whose deletedWith target is being
replaced, instead of leaving them orphaned in state <a
href="https://redirect.github.com/pulumi/pulumi/pull/23818">#23818</a></li>
<li>[sdk/python] Serialize typed object stack outputs with their
wire-format (camelCase) property names, matching other language SDKs <a
href="https://redirect.github.com/pulumi/pulumi/pull/24246">#24246</a></li>
<li>[cli/neo] Cancelling a task now interrupts a running local tool call
instead of waiting for it to finish <a
href="https://redirect.github.com/pulumi/pulumi/pull/24268">#24268</a></li>
<li>[programgen/python] Access schema properties whose names contain
hyphens as attributes under their Python names instead of subscripting
<a
href="https://redirect.github.com/pulumi/pulumi/pull/24300">#24300</a></li>
<li>[programgen/go] Generate valid struct field names for properties
whose names contain hyphens <a
href="https://redirect.github.com/pulumi/pulumi/pull/24300">#24300</a></li>
<li>[sdkgen/nodejs] Quote property names that are not legal identifiers
(e.g. kebab-case) in generated declarations and use bracket access for
them <a
href="https://redirect.github.com/pulumi/pulumi/pull/24300">#24300</a></li>
<li>[cli/neo] Cancelling a local tool call no longer leaves the TUI
stuck on &quot;Thinking...&quot; with input blocked <a
href="https://redirect.github.com/pulumi/pulumi/pull/24318">#24318</a></li>
<li>[sdk/go] Use resolved environment names when evaluating ESC imports
<a
href="https://redirect.github.com/pulumi/pulumi/pull/24375">#24375</a></li>
<li>[codegen/pcl] Allow output-typed values for the id attribute of a
read resource <a
href="https://redirect.github.com/pulumi/pulumi/pull/24386">#24386</a></li>
<li>[sdkgen/nodejs] Register resolvers for output-only properties in
generated Resource.get so they resolve as unknown during preview when
the id is unknown <a
href="https://redirect.github.com/pulumi/pulumi/pull/24386">#24386</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="de0633d6c6"><code>de0633d</code></a>
Fix ProgramTest for double-digit major versions (<a
href="https://redirect.github.com/pulumi/pulumi/issues/24499">#24499</a>)</li>
<li><a
href="1e5b60ad84"><code>1e5b60a</code></a>
Migrate ConstructResult to property.Map (<a
href="https://redirect.github.com/pulumi/pulumi/issues/24463">#24463</a>)</li>
<li><a
href="a2b96b4044"><code>a2b96b4</code></a>
Ignore internal property keys in update plans (<a
href="https://redirect.github.com/pulumi/pulumi/issues/24532">#24532</a>)</li>
<li><a
href="4d41278af7"><code>4d41278</code></a>
python: add helper methods to transform ResourceOptions to InvokeOptions
(<a
href="https://redirect.github.com/pulumi/pulumi/issues/24">#24</a>...</li>
<li><a
href="3081504c7c"><code>3081504</code></a>
Execute component state migrations (<a
href="https://redirect.github.com/pulumi/pulumi/issues/24328">#24328</a>)</li>
<li><a
href="710f0f8a71"><code>710f0f8</code></a>
[Python] Use <code>codegen.IsWireDiscriminatableUnionType</code> in
outputs (<a
href="https://redirect.github.com/pulumi/pulumi/issues/24485">#24485</a>)</li>
<li><a
href="f05eae644e"><code>f05eae6</code></a>
Send OldOutputs to provider Check (<a
href="https://redirect.github.com/pulumi/pulumi/issues/24524">#24524</a>)</li>
<li><a
href="ecabf858ae"><code>ecabf85</code></a>
Preserve secret marker when serializing unknown Outputs (<a
href="https://redirect.github.com/pulumi/pulumi/issues/24500">#24500</a>)</li>
<li><a
href="f0535f9cb9"><code>f0535f9</code></a>
[sdkgen/python] Accept output types in resource and function inputs (<a
href="https://redirect.github.com/pulumi/pulumi/issues/24507">#24507</a>)</li>
<li><a
href="7dc7023287"><code>7dc7023</code></a>
ESC OIDC Onboarding in the CLI (<a
href="https://redirect.github.com/pulumi/pulumi/issues/23911">#23911</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/pulumi/pulumi/compare/v3.259.0...v3.261.0">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-05 21:40:40 +03:00
..
pkg fix(deploy): cache bulk registry reads (#1509) 2026-08-07 02:16:52 +03:00
.gitignore deploy: Deploy the registry to GCP (#255) 2025-08-12 17:44:50 +01:00
go.mod build(deps): bump github.com/pulumi/pulumi/sdk/v3 from 3.259.0 to 3.261.0 in /deploy (#1606) 2026-09-05 21:40:40 +03:00
go.sum build(deps): bump github.com/pulumi/pulumi/sdk/v3 from 3.259.0 to 3.261.0 in /deploy (#1606) 2026-09-05 21:40:40 +03:00
main.go Add database backup functionality with GCS integration (#297) 2025-08-25 17:27:40 +01:00
Makefile infra: Improve local development flow and avoid false positive infra diffs (#267) 2025-08-15 12:13:51 +01:00
Pulumi.gcpProd.yaml chore(deploy): promote production to 1.8.1 (#1510) 2026-08-07 02:43:14 +03:00
Pulumi.gcpStaging.yaml Add monitoring infrastructure: victoriametrics and grafana (#328) 2025-09-02 12:40:43 +00:00
Pulumi.local.yaml Add monitoring infrastructure: victoriametrics and grafana (#328) 2025-09-02 12:40:43 +00:00
Pulumi.yaml feat(infra): Add Pulumi-based Kubernetes deployment infrastructure (#237) 2025-08-11 19:43:49 +01:00
README.md docs(deploy): correct config parameter names in deploy README (#1521) 2026-08-10 16:25:56 +03:00

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:

  1. Ensure your kubeconfig is configured at the cluster you want to use. For minikube, run minikube start && minikube tunnel.
  2. Run make local-up to deploy the stack.
  3. 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 run curl -H "Host: local.registry.modelcontextprotocol.io" -k https://<EXTERNAL-IP>/v0/ping to check that the service is up.

To change config

The stack is configured out of the box for local development. But if you want to make changes, run commands like:

PULUMI_CONFIG_PASSPHRASE="" pulumi config set mcp-registry:environment local
PULUMI_CONFIG_PASSPHRASE="" pulumi config set mcp-registry:githubClientSecret --secret <some-secret-value>

To delete the stack

make local-destroy and deleting the cluster (with minikube: minikube delete) will reset you back to a clean state.

Production Deployment (GCP)

Note: Deployments are automatically handled by GitHub Actions with separate workflows for staging and production:

  • Staging: All merges to the main branch automatically build and deploy the latest code to the staging environment via deploy-staging.yml. Staging always uses the :main Docker image tag.

  • Production: Deployment requires explicit configuration of the Docker image tag in Pulumi.gcpProd.yaml and is triggered automatically via deploy-production.yml when this config file is pushed to main. This GitOps-style approach provides manual control and an audit trail for production versions.

To deploy a specific version to production:

  1. Cut a release (if deploying a new version):

    # Via GitHub UI: https://github.com/modelcontextprotocol/registry/releases
    # Or via gh CLI:
    gh release create v1.2.3 --generate-notes
    

    This builds Docker images tagged as 1.2.3 and latest (note: image tags do not include the 'v' prefix)

  2. Update the production image tag in Pulumi.gcpProd.yaml:

    # Edit deploy/Pulumi.gcpProd.yaml
    # Change line: mcp-registry:imageTag: 1.2.3  (note: no 'v' prefix for Docker image tags)
    git add deploy/Pulumi.gcpProd.yaml
    git commit -m "Deploy version 1.2.3 to production"
    git push
    
  3. The production deployment workflow will automatically trigger and deploy the specified version

Manual Override: The steps below are preserved if a manual deployment override is needed.

Pre-requisites:

  • Pulumi CLI installed
  • A Google Cloud Platform (GCP) account
  • A GCP Service Account with appropriate permissions
  1. Create a project: gcloud projects create mcp-registry-prod
  2. Set the project: gcloud config set project mcp-registry-prod
  3. Enable the bootstrap APIs needed before Pulumi can run. The remaining APIs (cloudresourcemanager, compute, container, logging, monitoring) are adopted as Pulumi-managed projects.Service resources by ensureRequiredAPIs in pkg/providers/gcp/provider.go, so they self-heal against drift but still need to be reachable on the very first deploy:
    gcloud services enable storage.googleapis.com         # for the Pulumi state bucket below
    gcloud services enable cloudresourcemanager.googleapis.com  # for the IAM bindings Pulumi creates
    gcloud services enable container.googleapis.com       # for the GKE cluster
    
  4. Create the Pulumi service account and grant it the roles required to manage the deploy. projectIamAdmin is needed because the deploy creates IAM bindings on the project (for the default compute SA). The other four are general resource management:
    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 projects add-iam-policy-binding mcp-registry-prod --member="serviceAccount:pulumi-svc@mcp-registry-prod.iam.gserviceaccount.com" --role="roles/storage.hmacKeyAdmin"
    gcloud projects add-iam-policy-binding mcp-registry-prod --member="serviceAccount:pulumi-svc@mcp-registry-prod.iam.gserviceaccount.com" --role="roles/resourcemanager.projectIamAdmin"
    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
    
  5. Create a GCS bucket for Pulumi state: gsutil mb gs://mcp-registry-prod-pulumi-state
  6. Set Pulumi's backend to GCS: pulumi login gs://mcp-registry-prod-pulumi-state
  7. Get the passphrase file passphrase.prod.txt from the registry maintainers
  8. Init the GCP stack: PULUMI_CONFIG_PASSPHRASE_FILE=passphrase.prod.txt pulumi stack init gcpProd
  9. 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)"
    
  10. Deploy: make prod-up
  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. Then run curl -H "Host: prod.registry.modelcontextprotocol.io" -k https://<EXTERNAL-IP>/v0/ping to check that the service is up.

Structure

├── main.go                 # Pulumi program entry point
├── Pulumi.yaml             # Project configuration
├── Pulumi.local.yaml       # Local stack configuration
├── Pulumi.gcpProd.yaml     # GCP production stack configuration
├── Pulumi.gcpStaging.yaml  # GCP staging stack configuration
├── Makefile                # Build and deployment targets
├── go.mod                  # Go module dependencies
├── go.sum                  # Go module checksums
└── pkg/                    # Infrastructure packages
    ├── k8s/                # Kubernetes deployment components
    │   ├── backup.go          # Database backup configuration
    │   ├── cert_manager.go    # SSL certificate management
    │   ├── deploy.go          # Deployment orchestration
    │   ├── ingress.go         # Ingress controller setup
    │   ├── monitoring.go      # Metrics and monitoring setup
    │   ├── postgres.go        # PostgreSQL database deployment
    │   └── registry.go        # MCP Registry deployment
    └── providers/          # Kubernetes cluster providers
        ├── types.go           # Provider interface definitions
        ├── gcp/               # Google Kubernetes Engine provider
        └── local/             # Local kubeconfig provider

Architecture Overview

Deployment Flow

  1. Pulumi program starts in main.go
  2. Configuration is loaded from Pulumi config files
  3. Provider factory creates appropriate cluster provider (GCP or local)
  4. Cluster provider sets up Kubernetes access
  5. k8s.DeployAll() orchestrates complete deployment:
    • Certificate manager for SSL/TLS
    • Ingress controller for external access
    • Database for data persistence
    • Backup infrastructure for database
    • Monitoring and metrics collection
    • MCP Registry application

Configuration

Configuration keys are namespaced. Set them with pulumi config set <key> [--secret].

Parameter Description Required
mcp-registry:environment Deployment environment (local/staging/prod) Yes
mcp-registry:provider Kubernetes provider (local/gcp) No (default: local)
mcp-registry:githubClientId GitHub OAuth Client ID Yes
mcp-registry:githubClientSecret GitHub OAuth Client Secret Yes (secret)
mcp-registry:jwtPrivateKey Ed25519 seed used to sign registry JWTs Yes (secret)
mcp-registry:googleOauthClientSecret Google OAuth client secret for Grafana login Yes (secret)
mcp-registry:imageTag Docker image tag for production environment Yes (prod only)
gcp:project GCP Project ID Yes when provider=gcp
gcp:region GCP Region No (default: us-central1)
gcp:credentials GCP service account credentials JSON No (secret; set in staging/prod)

Database Backups

The deployment uses K8up (a Kubernetes backup operator) that uses Restic under the hood.

When running locally they are stored in a Minio bucket. In staging and production, backups are stored in a GCS bucket.

Accessing Backup Files

Local Development (MinIO)

# Expose MinIO web console
kubectl port-forward -n minio svc/minio 9000:9000 9001:9001

Then open localhost:9001, login with username minioadmin and password minioadmin, and navigate to the k8up-backups bucket.

Staging and Production (GCS)

Decrypting and Restoring Backups

Backups are encrypted using Restic. To access the backup data:

  1. Download the backup files from the bucket:
    # Local (MinIO) - ensure port-forward is active: kubectl port-forward -n minio svc/minio 9000:9000 9001:9001
    AWS_ACCESS_KEY_ID=minioadmin AWS_SECRET_ACCESS_KEY=minioadmin \
      aws --endpoint-url http://localhost:9000 s3 sync s3://k8up-backups/ ./backup-files/
    
    # GCS (staging/production)
    gsutil -m cp -r gs://mcp-registry-{staging|prod}-backups/* ./backup-files/
    
  2. Install Restic
  3. Restore the backup:
    RESTIC_PASSWORD=password restic -r ./backup-files restore latest --target ./restored-files
    
    PostgreSQL data will be in ./restored-files/data/registry-pg-1/pgdata/

Troubleshooting

To configure kubectl to access an existing GKE cluster:

# Login
gcloud auth login
gcloud auth application-default login

# For production
gcloud container clusters get-credentials mcp-registry-prod --zone us-central1-b --project mcp-registry-prod

# For staging
gcloud container clusters get-credentials mcp-registry-staging --zone us-central1-b --project mcp-registry-staging

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=postgres

Check Backup Status

kubectl describe schedule.k8up.io 
kubectl get backup