- Remove KCL ecosystem (~220 files deleted) - Migrate all infrastructure to Nickel schema system - Consolidate documentation: legacy docs → provisioning/docs/src/ - Add CI/CD workflows (.github/) and Rust build config (.cargo/) - Update core system for Nickel schema parsing - Update README.md and CHANGES.md for v5.0.0 release - Fix pre-commit hooks: end-of-file, trailing-whitespace - Breaking changes: KCL workspaces require migration - Migration bridge available in docs/src/development/
329 lines
8.8 KiB
Plaintext
329 lines
8.8 KiB
Plaintext
# 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,
|
|
},
|
|
}
|