# MCP Server Kubernetes Deployment # Model Context Protocol server for AI integration # Provides tools, resources, and prompts to Claude and other LLMs # # Usage: # nickel eval --format json mcp-server-deployment.yaml.ncl | yq -P > mcp-server-deployment.yaml # kubectl apply -f mcp-server-deployment.yaml { apiVersion = "apps/v1", kind = "Deployment", metadata = { name = "mcp-server", labels = { app = "mcp-server", component = "provisioning-platform", }, }, spec = { # Solo: 1 replica # MultiUser: 1 replica # CI/CD: 1 replica (optional, stateless) # Enterprise: 2 replicas (HA) replicas = 1, # Override per mode selector = { matchLabels = { app = "mcp-server", }, }, template = { metadata = { labels = { app = "mcp-server", component = "provisioning-platform", }, annotations = { "prometheus.io/scrape" = "true", "prometheus.io/port" = "8888", "prometheus.io/path" = "/metrics", }, }, spec = { serviceAccountName = "mcp-server", # Init container: wait for orchestrator and control-center initContainers = [ { name = "wait-for-orchestrator", image = "busybox:1.35", command = ["sh", "-c", "until wget -q http://orchestrator:9090/health || true; do echo waiting; sleep 2; done"], imagePullPolicy = "IfNotPresent", }, ], containers = [ { name = "mcp-server", image = "provisioning-mcp-server:latest", imagePullPolicy = "Always", ports = [ { name = "http", containerPort = 8888, protocol = "TCP", }, { name = "metrics", containerPort = 8889, protocol = "TCP", }, ], env = [ { name = "MCP_SERVER_MODE", value = "kubernetes", }, { name = "MCP_SERVER_HOST", value = "0.0.0.0", }, { name = "MCP_SERVER_PORT", value = "8888", }, { name = "MCP_SERVER_PROTOCOL", valueFrom = { configMapKeyRef = { name = "mcp-server-config", key = "protocol", }, }, }, # Orchestrator integration { name = "MCP_SERVER_ORCHESTRATOR_URL", valueFrom = { configMapKeyRef = { name = "mcp-server-config", key = "orchestrator_url", }, }, }, # Control Center integration { name = "MCP_SERVER_CONTROL_CENTER_URL", valueFrom = { configMapKeyRef = { name = "mcp-server-config", key = "control_center_url", }, }, }, # MCP capabilities { name = "MCP_SERVER_ENABLE_TOOLS", valueFrom = { configMapKeyRef = { name = "mcp-server-config", key = "enable_tools", }, }, }, { name = "MCP_SERVER_ENABLE_RESOURCES", valueFrom = { configMapKeyRef = { name = "mcp-server-config", key = "enable_resources", }, }, }, { name = "MCP_SERVER_ENABLE_PROMPTS", valueFrom = { configMapKeyRef = { name = "mcp-server-config", key = "enable_prompts", }, }, }, # Tool configuration { name = "MCP_SERVER_MAX_CONCURRENT_TOOLS", valueFrom = { configMapKeyRef = { name = "mcp-server-config", key = "max_concurrent_tools", }, }, }, # Resource limits { name = "MCP_SERVER_MAX_RESOURCE_SIZE", valueFrom = { configMapKeyRef = { name = "mcp-server-config", key = "max_resource_size", }, }, }, # Logging { name = "MCP_SERVER_LOG_LEVEL", valueFrom = { configMapKeyRef = { name = "mcp-server-config", key = "log_level", }, }, }, # Pod metadata { name = "POD_NAME", valueFrom = { fieldRef = { fieldPath = "metadata.name", }, }, }, { name = "POD_NAMESPACE", valueFrom = { fieldRef = { fieldPath = "metadata.namespace", }, }, }, ], # Health checks livenessProbe = { httpGet = { path = "/health", port = 8888, }, initialDelaySeconds = 30, periodSeconds = 15, timeoutSeconds = 5, failureThreshold = 3, }, readinessProbe = { httpGet = { path = "/ready", port = 8888, }, initialDelaySeconds = 20, periodSeconds = 5, timeoutSeconds = 3, failureThreshold = 3, }, # Resource limits (lighter than orchestrator/control-center) resources = { requests = { cpu = "100m", memory = "128Mi", }, limits = { cpu = "500m", memory = "512Mi", }, }, # Volume mounts volumeMounts = [ { name = "mcp-server-config", mountPath = "/etc/provisioning/mcp-server", readOnly = true, }, { name = "mcp-server-logs", mountPath = "/var/log/provisioning/mcp-server", }, ], # Security context securityContext = { allowPrivilegeEscalation = false, runAsNonRoot = true, runAsUser = 1000, capabilities = { drop = ["ALL"], }, readOnlyRootFilesystem = true, }, }, ], # Volumes volumes = [ { name = "mcp-server-config", configMap = { name = "mcp-server-config", defaultMode = 420, }, }, { name = "mcp-server-logs", persistentVolumeClaim = { claimName = "mcp-server-logs", }, }, ], # Pod affinity affinity = { podAffinity = { preferredDuringSchedulingIgnoredDuringExecution = [ { weight = 50, podAffinityTerm = { labelSelector = { matchExpressions = [ { key = "app", operator = "In", values = ["orchestrator"], }, ], }, topologyKey = "kubernetes.io/hostname", }, }, ], }, }, # Tolerations tolerations = [ { key = "node.kubernetes.io/not-ready", operator = "Exists", effect = "NoExecute", tolerationSeconds = 300, }, { key = "node.kubernetes.io/unreachable", operator = "Exists", effect = "NoExecute", tolerationSeconds = 300, }, ], restartPolicy = "Always", terminationGracePeriodSeconds = 20, }, }, strategy = { type = "RollingUpdate", rollingUpdate = { maxSurge = 1, maxUnavailable = 0, }, }, revisionHistoryLimit = 5, }, }