Skip to main content
Glama

mcp-server-kubernetes

by Flux159
index.ts15 kB
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { installHelmChart, installHelmChartSchema, upgradeHelmChart, upgradeHelmChartSchema, uninstallHelmChart, uninstallHelmChartSchema, } from "./tools/helm-operations.js"; import { nodeManagement, nodeManagementSchema, } from "./tools/node-management.js"; import { explainResource, explainResourceSchema, listApiResources, listApiResourcesSchema, } from "./tools/kubectl-operations.js"; import { execInPod, execInPodSchema } from "./tools/exec_in_pod.js"; import { getResourceHandlers } from "./resources/handlers.js"; import { ListResourcesRequestSchema, ReadResourceRequestSchema, ListToolsRequestSchema, CallToolRequestSchema, ErrorCode, McpError, } from "@modelcontextprotocol/sdk/types.js"; import { KubernetesManager } from "./types.js"; import { serverConfig } from "./config/server-config.js"; import { cleanupSchema } from "./config/cleanup-config.js"; import { startSSEServer } from "./utils/sse.js"; import { startPortForward, PortForwardSchema, stopPortForward, StopPortForwardSchema, } from "./tools/port_forward.js"; import { kubectlScale, kubectlScaleSchema } from "./tools/kubectl-scale.js"; import { kubectlContext, kubectlContextSchema, } from "./tools/kubectl-context.js"; import { kubectlGet, kubectlGetSchema } from "./tools/kubectl-get.js"; import { kubectlDescribe, kubectlDescribeSchema, } from "./tools/kubectl-describe.js"; import { kubectlApply, kubectlApplySchema } from "./tools/kubectl-apply.js"; import { kubectlDelete, kubectlDeleteSchema } from "./tools/kubectl-delete.js"; import { kubectlCreate, kubectlCreateSchema } from "./tools/kubectl-create.js"; import { kubectlLogs, kubectlLogsSchema } from "./tools/kubectl-logs.js"; import { kubectlGeneric, kubectlGenericSchema, } from "./tools/kubectl-generic.js"; import { kubectlPatch, kubectlPatchSchema } from "./tools/kubectl-patch.js"; import { kubectlRollout, kubectlRolloutSchema, } from "./tools/kubectl-rollout.js"; import { registerPromptHandlers } from "./prompts/index.js"; import { ping, pingSchema } from "./tools/ping.js"; import { startStreamableHTTPServer } from "./utils/streamable-http.js"; // Check environment variables for tool filtering const allowOnlyReadonlyTools = process.env.ALLOW_ONLY_READONLY_TOOLS === "true"; const allowedToolsEnv = process.env.ALLOWED_TOOLS; const nonDestructiveTools = process.env.ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS === "true"; // Define readonly tools const readonlyTools = [ kubectlGetSchema, kubectlDescribeSchema, kubectlLogsSchema, kubectlContextSchema, explainResourceSchema, listApiResourcesSchema, pingSchema, ]; // Define destructive tools (delete and uninstall operations) const destructiveTools = [ kubectlDeleteSchema, // This replaces all individual delete operations uninstallHelmChartSchema, cleanupSchema, // Cleanup is also destructive as it deletes resources kubectlGenericSchema, // Generic kubectl command can perform destructive operations nodeManagementSchema, // Node management can drain nodes (destructive) ]; // Get all available tools const allTools = [ // Core operation tools cleanupSchema, // Unified kubectl-style tools - these replace many specific tools kubectlGetSchema, kubectlDescribeSchema, kubectlApplySchema, kubectlDeleteSchema, kubectlCreateSchema, kubectlLogsSchema, kubectlScaleSchema, kubectlPatchSchema, kubectlRolloutSchema, // Kubernetes context management kubectlContextSchema, // Special operations that aren't covered by simple kubectl commands explainResourceSchema, // Helm operations installHelmChartSchema, upgradeHelmChartSchema, uninstallHelmChartSchema, nodeManagementSchema, // Port forwarding PortForwardSchema, StopPortForwardSchema, execInPodSchema, // API resource operations listApiResourcesSchema, // Generic kubectl command kubectlGenericSchema, // Ping utility pingSchema, ]; const k8sManager = new KubernetesManager(); const server = new Server( { name: serverConfig.name, version: serverConfig.version, }, { ...serverConfig, capabilities: { prompts: {}, ...serverConfig.capabilities, }, } ); // Resources handlers const resourceHandlers = getResourceHandlers(k8sManager); server.setRequestHandler( ListResourcesRequestSchema, resourceHandlers.listResources ); server.setRequestHandler( ReadResourceRequestSchema, resourceHandlers.readResource ); // Register prompt handlers registerPromptHandlers(server, k8sManager); // Tools handlers server.setRequestHandler(ListToolsRequestSchema, async () => { let tools; if (allowedToolsEnv) { const allowedToolNames = allowedToolsEnv.split(",").map((t) => t.trim()); tools = allTools.filter((tool) => allowedToolNames.includes(tool.name)); } else if (allowOnlyReadonlyTools) { tools = readonlyTools; } else if (nonDestructiveTools) { tools = allTools.filter( (tool) => !destructiveTools.some((dt) => dt.name === tool.name) ); } else { tools = allTools; } return { tools }; }); server.setRequestHandler( CallToolRequestSchema, async (request: { params: { name: string; _meta?: any; arguments?: Record<string, any> }; method: string; }) => { try { const { name, arguments: input = {} } = request.params; // Handle new kubectl-style commands if (name === "kubectl_context") { return await kubectlContext( k8sManager, input as { operation: "list" | "get" | "set"; name?: string; showCurrent?: boolean; detailed?: boolean; output?: string; context?: string; } ); } if (name === "kubectl_get") { return await kubectlGet( k8sManager, input as { resourceType: string; name?: string; namespace?: string; output?: string; allNamespaces?: boolean; labelSelector?: string; fieldSelector?: string; sortBy?: string; context?: string; } ); } if (name === "kubectl_describe") { return await kubectlDescribe( k8sManager, input as { resourceType: string; name: string; namespace?: string; allNamespaces?: boolean; context?: string; } ); } if (name === "kubectl_apply") { return await kubectlApply( k8sManager, input as { manifest?: string; filename?: string; namespace?: string; dryRun?: boolean; force?: boolean; context?: string; } ); } if (name === "kubectl_delete") { return await kubectlDelete( k8sManager, input as { resourceType?: string; name?: string; namespace?: string; labelSelector?: string; manifest?: string; filename?: string; allNamespaces?: boolean; force?: boolean; gracePeriodSeconds?: number; context?: string; } ); } if (name === "kubectl_create") { return await kubectlCreate( k8sManager, input as { manifest?: string; filename?: string; namespace?: string; dryRun?: boolean; validate?: boolean; context?: string; } ); } if (name === "kubectl_logs") { return await kubectlLogs( k8sManager, input as { resourceType: string; name: string; namespace: string; container?: string; tail?: number; since?: string; sinceTime?: string; timestamps?: boolean; previous?: boolean; follow?: boolean; labelSelector?: string; context?: string; } ); } if (name === "kubectl_patch") { return await kubectlPatch( k8sManager, input as { resourceType: string; name: string; namespace?: string; patchType?: "strategic" | "merge" | "json"; patchData?: object; patchFile?: string; dryRun?: boolean; context?: string; } ); } if (name === "kubectl_rollout") { return await kubectlRollout( k8sManager, input as { subCommand: | "history" | "pause" | "restart" | "resume" | "status" | "undo"; resourceType: "deployment" | "daemonset" | "statefulset"; name: string; namespace?: string; revision?: number; toRevision?: number; timeout?: string; watch?: boolean; context?: string; } ); } if (name === "kubectl_generic") { return await kubectlGeneric( k8sManager, input as { command: string; subCommand?: string; resourceType?: string; name?: string; namespace?: string; outputFormat?: string; flags?: Record<string, any>; args?: string[]; context?: string; } ); } if (name === "kubectl_events") { return await kubectlGet(k8sManager, { resourceType: "events", namespace: (input as { namespace?: string }).namespace, fieldSelector: (input as { fieldSelector?: string }).fieldSelector, labelSelector: (input as { labelSelector?: string }).labelSelector, sortBy: (input as { sortBy?: string }).sortBy, output: (input as { output?: string }).output, context: (input as { context?: string }).context, }); } // Handle specific non-kubectl operations switch (name) { case "cleanup": { await k8sManager.cleanup(); return { content: [ { type: "text", text: JSON.stringify( { success: true, }, null, 2 ), }, ], }; } case "explain_resource": { return await explainResource( input as { context?: string; resource: string; apiVersion?: string; recursive?: boolean; output?: "plaintext" | "plaintext-openapiv2"; } ); } case "install_helm_chart": { return await installHelmChart( input as { name: string; chart: string; repo: string; namespace: string; values?: Record<string, any>; context?: string; } ); } case "uninstall_helm_chart": { return await uninstallHelmChart( input as { name: string; namespace: string; context?: string; } ); } case "upgrade_helm_chart": { return await upgradeHelmChart( input as { name: string; chart: string; repo: string; namespace: string; values?: Record<string, any>; context?: string; } ); } case "node_management": { return await nodeManagement( input as { operation: "cordon" | "drain" | "uncordon"; nodeName?: string; force?: boolean; gracePeriod?: number; deleteLocalData?: boolean; ignoreDaemonsets?: boolean; timeout?: string; dryRun?: boolean; confirmDrain?: boolean; } ); } case "list_api_resources": { return await listApiResources( input as { apiGroup?: string; namespaced?: boolean; verbs?: string[]; output?: "wide" | "name" | "no-headers"; context?: string; } ); } case "port_forward": { return await startPortForward( k8sManager, input as { resourceType: string; resourceName: string; localPort: number; targetPort: number; context?: string; } ); } case "stop_port_forward": { return await stopPortForward( k8sManager, input as { id: string; } ); } case "kubectl_scale": { return await kubectlScale( k8sManager, input as { name: string; namespace?: string; replicas: number; resourceType?: string; context?: string; } ); } case "ping": { return await ping(); } case "exec_in_pod": { return await execInPod( k8sManager, input as { name: string; namespace?: string; command: string | string[]; container?: string; context?: string; } ); } default: throw new McpError(ErrorCode.InvalidRequest, `Unknown tool: ${name}`); } } catch (error) { if (error instanceof McpError) throw error; throw new McpError( ErrorCode.InternalError, `Tool execution failed: ${error}` ); } } ); // Start the server if (process.env.ENABLE_UNSAFE_SSE_TRANSPORT) { startSSEServer(server); console.log(`SSE server started`); } else if (process.env.ENABLE_UNSAFE_STREAMABLE_HTTP_TRANSPORT) { startStreamableHTTPServer(server); console.log(`Streamable HTTP server started`); } else { const transport = new StdioServerTransport(); console.error( `Starting Kubernetes MCP server v${serverConfig.version}, handling commands...` ); server.connect(transport); } ["SIGINT", "SIGTERM"].forEach((signal) => { process.on(signal, async () => { console.log(`Received ${signal}, shutting down...`); await server.close(); process.exit(0); }); }); export { allTools, destructiveTools };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Flux159/mcp-server-kubernetes'

If you have feedback or need assistance with the MCP directory API, please join our Discord server