Skip to main content
Glama

mcp-server-kubernetes

by Flux159
port_forward.ts4.22 kB
import { spawn } from "child_process"; import { z } from "zod"; import { KubernetesManager } from "../utils/kubernetes-manager.js"; // Use spawn instead of exec because port-forward is a long-running process async function executeKubectlCommandAsync( command: string ): Promise<{ success: boolean; message: string; pid: number }> { return new Promise((resolve, reject) => { const [cmd, ...args] = command.split(" "); const process = spawn(cmd, args); let output = ""; let errorOutput = ""; process.stdout.on("data", (data) => { output += data.toString(); if (output.includes("Forwarding from")) { resolve({ success: true, message: "port-forwarding was successful", pid: process.pid!, }); } }); process.stderr.on("data", (data) => { errorOutput += data.toString(); }); process.on("error", (error) => { reject(new Error(`Failed to execute port-forward: ${error.message}`)); }); process.on("close", (code) => { if (code !== 0) { reject( new Error( `Port-forward process exited with code ${code}. Error: ${errorOutput}` ) ); } }); // Set a timeout to reject if we don't see the success message setTimeout(() => { if (!output.includes("Forwarding from")) { reject( new Error("port-forwarding failed - no success message received") ); } }, 5000); }); } export const PortForwardSchema = { name: "port_forward", description: "Forward a local port to a port on a Kubernetes resource", inputSchema: { type: "object", properties: { resourceType: { type: "string" }, resourceName: { type: "string" }, localPort: { type: "number" }, targetPort: { type: "number" }, namespace: { type: "string" }, }, required: ["resourceType", "resourceName", "localPort", "targetPort"], }, }; export async function startPortForward( k8sManager: KubernetesManager, input: { resourceType: string; resourceName: string; localPort: number; targetPort: number; namespace?: string; } ): Promise<{ content: { success: boolean; message: string }[] }> { let command = `kubectl port-forward`; if (input.namespace) { command += ` -n ${input.namespace}`; } command += ` ${input.resourceType}/${input.resourceName} ${input.localPort}:${input.targetPort}`; try { const result = await executeKubectlCommandAsync(command); // Track the port-forward process k8sManager.trackPortForward({ id: `${input.resourceType}-${input.resourceName}-${input.localPort}`, server: { stop: async () => { try { process.kill(result.pid); } catch (error) { console.error( `Failed to stop port-forward process ${result.pid}:`, error ); } }, }, resourceType: input.resourceType, name: input.resourceName, namespace: input.namespace || "default", ports: [{ local: input.localPort, remote: input.targetPort }], }); return { content: [{ success: result.success, message: result.message }], }; } catch (error: any) { throw new Error(`Failed to execute port-forward: ${error.message}`); } } export const StopPortForwardSchema = { name: "stop_port_forward", description: "Stop a port-forward process", inputSchema: { type: "object", properties: { id: { type: "string" }, }, required: ["id"], }, }; export async function stopPortForward( k8sManager: KubernetesManager, input: { id: string; } ): Promise<{ content: { success: boolean; message: string }[] }> { const portForward = k8sManager.getPortForward(input.id); if (!portForward) { throw new Error(`Port-forward with id ${input.id} not found`); } try { await portForward.server.stop(); k8sManager.removePortForward(input.id); return { content: [ { success: true, message: "port-forward stopped successfully" }, ], }; } catch (error: any) { throw new Error(`Failed to stop port-forward: ${error.message}`); } }

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