package k8s
import (
"os/exec"
"strings"
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apiextensions"
v1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apps/v1"
corev1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1"
"github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/helm/v3"
metav1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1"
networkingv1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/networking/v1"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
"github.com/modelcontextprotocol/registry/deploy/infra/pkg/providers"
)
func getGitCommitHash() string {
cmd := exec.Command("git", "rev-parse", "HEAD")
output, err := cmd.Output()
if err != nil {
return "unknown"
}
return strings.TrimSpace(string(output))
}
func DeployMCPRegistry(ctx *pulumi.Context, cluster *providers.ProviderInfo, environment string, ingressNginx *helm.Chart, pgCluster *apiextensions.CustomResource) (*corev1.Service, error) {
conf := config.New(ctx, "mcp-registry")
githubClientId := conf.Require("githubClientId")
imageTag := "main"
if environment == "prod" {
imageTag = conf.Require("imageTag")
}
secret, err := corev1.NewSecret(ctx, "mcp-registry-secrets", &corev1.SecretArgs{
Metadata: &metav1.ObjectMetaArgs{
Name: pulumi.String("mcp-registry-secrets"),
Namespace: pulumi.String("default"),
Labels: pulumi.StringMap{
"app": pulumi.String("mcp-registry"),
"environment": pulumi.String(environment),
},
},
StringData: pulumi.StringMap{
"GITHUB_CLIENT_SECRET": conf.RequireSecret("githubClientSecret"),
"JWT_PRIVATE_KEY": conf.RequireSecret("jwtPrivateKey"),
},
Type: pulumi.String("Opaque"),
}, pulumi.Provider(cluster.Provider))
if err != nil {
return nil, err
}
_, err = v1.NewDeployment(ctx, "mcp-registry", &v1.DeploymentArgs{
Metadata: &metav1.ObjectMetaArgs{
Name: pulumi.String("mcp-registry"),
Namespace: pulumi.String("default"),
Labels: pulumi.StringMap{
"app": pulumi.String("mcp-registry"),
"environment": pulumi.String(environment),
},
},
Spec: &v1.DeploymentSpecArgs{
Replicas: pulumi.Int(2),
Strategy: &v1.DeploymentStrategyArgs{
Type: pulumi.String("RollingUpdate"),
RollingUpdate: &v1.RollingUpdateDeploymentArgs{
MaxUnavailable: pulumi.IntPtr(0),
MaxSurge: pulumi.IntPtr(1),
},
},
Selector: &metav1.LabelSelectorArgs{
MatchLabels: pulumi.StringMap{
"app": pulumi.String("mcp-registry"),
},
},
Template: &corev1.PodTemplateSpecArgs{
Metadata: &metav1.ObjectMetaArgs{
Labels: pulumi.StringMap{
"app": pulumi.String("mcp-registry"),
},
Annotations: pulumi.StringMap{
"registry.modelcontextprotocol.io/deployCommit": pulumi.String(getGitCommitHash()),
},
},
Spec: &corev1.PodSpecArgs{
Containers: corev1.ContainerArray{
&corev1.ContainerArgs{
Name: pulumi.String("mcp-registry"),
Image: pulumi.Sprintf("ghcr.io/modelcontextprotocol/registry:%s", imageTag),
ImagePullPolicy: pulumi.String("Always"),
Ports: corev1.ContainerPortArray{
&corev1.ContainerPortArgs{
ContainerPort: pulumi.Int(8080),
Name: pulumi.String("http"),
},
},
Env: corev1.EnvVarArray{
&corev1.EnvVarArgs{
Name: pulumi.String("MCP_REGISTRY_DATABASE_URL"),
ValueFrom: &corev1.EnvVarSourceArgs{
SecretKeyRef: &corev1.SecretKeySelectorArgs{
Name: pgCluster.Metadata.Name().ApplyT(func(name *string) string {
if name == nil {
return "registry-pg-app"
}
return *name + "-app"
}).(pulumi.StringOutput),
Key: pulumi.String("uri"),
},
},
},
&corev1.EnvVarArgs{
Name: pulumi.String("MCP_REGISTRY_GITHUB_CLIENT_ID"),
Value: pulumi.String(githubClientId),
},
&corev1.EnvVarArgs{
Name: pulumi.String("MCP_REGISTRY_GITHUB_CLIENT_SECRET"),
ValueFrom: &corev1.EnvVarSourceArgs{
SecretKeyRef: &corev1.SecretKeySelectorArgs{
Name: secret.Metadata.Name(),
Key: pulumi.String("GITHUB_CLIENT_SECRET"),
},
},
},
&corev1.EnvVarArgs{
Name: pulumi.String("MCP_REGISTRY_JWT_PRIVATE_KEY"),
ValueFrom: &corev1.EnvVarSourceArgs{
SecretKeyRef: &corev1.SecretKeySelectorArgs{
Name: secret.Metadata.Name(),
Key: pulumi.String("JWT_PRIVATE_KEY"),
},
},
},
&corev1.EnvVarArgs{
Name: pulumi.String("MCP_REGISTRY_OIDC_ENABLED"),
Value: pulumi.String("true"),
},
&corev1.EnvVarArgs{
Name: pulumi.String("MCP_REGISTRY_OIDC_ISSUER"),
Value: pulumi.String("https://accounts.google.com"),
},
&corev1.EnvVarArgs{
Name: pulumi.String("MCP_REGISTRY_OIDC_CLIENT_ID"),
Value: pulumi.String("32555940559.apps.googleusercontent.com"),
},
&corev1.EnvVarArgs{
Name: pulumi.String("MCP_REGISTRY_OIDC_EXTRA_CLAIMS"),
Value: pulumi.String(`[{"hd":"modelcontextprotocol.io"}]`),
},
&corev1.EnvVarArgs{
Name: pulumi.String("MCP_REGISTRY_OIDC_EDIT_PERMISSIONS"),
Value: pulumi.String("*"),
},
&corev1.EnvVarArgs{
Name: pulumi.String("MCP_REGISTRY_OIDC_PUBLISH_PERMISSIONS"),
Value: pulumi.String("*"),
},
},
LivenessProbe: &corev1.ProbeArgs{
HttpGet: &corev1.HTTPGetActionArgs{
Path: pulumi.String("/v0/health"),
Port: pulumi.Int(8080),
},
InitialDelaySeconds: pulumi.Int(30),
TimeoutSeconds: pulumi.Int(5),
},
ReadinessProbe: &corev1.ProbeArgs{
HttpGet: &corev1.HTTPGetActionArgs{
Path: pulumi.String("/v0/health"),
Port: pulumi.Int(8080),
},
InitialDelaySeconds: pulumi.Int(5),
TimeoutSeconds: pulumi.Int(3),
},
Resources: &corev1.ResourceRequirementsArgs{
Requests: pulumi.StringMap{
"memory": pulumi.String("128Mi"),
"cpu": pulumi.String("100m"),
},
Limits: pulumi.StringMap{
"memory": pulumi.String("256Mi"),
},
},
},
},
},
},
},
}, pulumi.Provider(cluster.Provider))
if err != nil {
return nil, err
}
service, err := corev1.NewService(ctx, "mcp-registry", &corev1.ServiceArgs{
Metadata: &metav1.ObjectMetaArgs{
Name: pulumi.String("mcp-registry"),
Namespace: pulumi.String("default"),
Labels: pulumi.StringMap{
"app": pulumi.String("mcp-registry"),
"environment": pulumi.String(environment),
},
},
Spec: &corev1.ServiceSpecArgs{
Selector: pulumi.StringMap{
"app": pulumi.String("mcp-registry"),
},
Ports: corev1.ServicePortArray{
&corev1.ServicePortArgs{
Port: pulumi.Int(80),
TargetPort: pulumi.Int(8080),
Name: pulumi.String("http"),
},
},
Type: pulumi.String("ClusterIP"),
},
}, pulumi.Provider(cluster.Provider))
if err != nil {
return nil, err
}
hosts := []string{
environment + ".registry.modelcontextprotocol.io",
}
if environment == "prod" {
hosts = append(hosts, "registry.modelcontextprotocol.io")
}
ingress, err := networkingv1.NewIngress(ctx, "mcp-registry", &networkingv1.IngressArgs{
Metadata: &metav1.ObjectMetaArgs{
Name: pulumi.String("mcp-registry"),
Namespace: pulumi.String("default"),
Labels: pulumi.StringMap{
"app": pulumi.String("mcp-registry"),
"environment": pulumi.String(environment),
},
Annotations: pulumi.StringMap{
"cert-manager.io/cluster-issuer": pulumi.String("letsencrypt-prod"),
"kubernetes.io/ingress.class": pulumi.String("nginx"),
"nginx.ingress.kubernetes.io/limit-rpm": pulumi.String("180"),
"nginx.ingress.kubernetes.io/limit-burst-multiplier": pulumi.String("3"),
},
},
Spec: &networkingv1.IngressSpecArgs{
Tls: networkingv1.IngressTLSArray{
&networkingv1.IngressTLSArgs{
Hosts: pulumi.ToStringArray(hosts),
SecretName: pulumi.Sprintf("mcp-registry-%s-tls", environment),
},
},
Rules: pulumi.ToStringArray(hosts).ToStringArrayOutput().ApplyT(func(hosts []string) networkingv1.IngressRuleArray {
rules := make(networkingv1.IngressRuleArray, 0, len(hosts))
for _, host := range hosts {
rules = append(rules, &networkingv1.IngressRuleArgs{
Host: pulumi.String(host),
Http: &networkingv1.HTTPIngressRuleValueArgs{
Paths: networkingv1.HTTPIngressPathArray{
&networkingv1.HTTPIngressPathArgs{
Path: pulumi.String("/"),
PathType: pulumi.String("Prefix"),
Backend: &networkingv1.IngressBackendArgs{
Service: &networkingv1.IngressServiceBackendArgs{
Name: service.Metadata.Name().Elem(),
Port: &networkingv1.ServiceBackendPortArgs{
Number: pulumi.Int(80),
},
},
},
},
},
},
})
}
return rules
}).(networkingv1.IngressRuleArrayOutput),
},
}, pulumi.Provider(cluster.Provider), pulumi.DependsOnInputs(ingressNginx.Ready))
if err != nil {
return nil, err
}
ctx.Export("ingressHosts", ingress.Spec.Rules().ApplyT(func(rules []networkingv1.IngressRule) []string {
hosts := make([]string, 0, len(rules))
for _, rule := range rules {
hosts = append(hosts, *rule.Host)
}
return hosts
}))
return service, nil
}