mcp-server-kubernetes
Version:
MCP server for interacting with Kubernetes clusters via kubectl
114 lines (113 loc) • 4.56 kB
JavaScript
import { execSync } from "child_process";
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
export const kubectlRolloutSchema = {
name: "kubectl_rollout",
description: "Manage the rollout of a resource (e.g., deployment, daemonset, statefulset)",
inputSchema: {
type: "object",
properties: {
subCommand: {
type: "string",
description: "Rollout subcommand to execute",
enum: ["history", "pause", "restart", "resume", "status", "undo"],
default: "status"
},
resourceType: {
type: "string",
description: "Type of resource to manage rollout for",
enum: ["deployment", "daemonset", "statefulset"],
default: "deployment"
},
name: {
type: "string",
description: "Name of the resource"
},
namespace: {
type: "string",
description: "Namespace of the resource",
default: "default"
},
revision: {
type: "number",
description: "Revision to rollback to (for undo subcommand)"
},
toRevision: {
type: "number",
description: "Revision to roll back to (for history subcommand)"
},
timeout: {
type: "string",
description: "The length of time to wait before giving up (e.g., '30s', '1m', '2m30s')"
},
watch: {
type: "boolean",
description: "Watch the rollout status in real-time until completion",
default: false
}
},
required: ["subCommand", "resourceType", "name", "namespace"]
}
};
export async function kubectlRollout(k8sManager, input) {
try {
const namespace = input.namespace || "default";
const watch = input.watch || false;
// Build the kubectl rollout command
let command = `kubectl rollout ${input.subCommand} ${input.resourceType}/${input.name} -n ${namespace}`;
// Add revision for undo
if (input.subCommand === "undo" && input.revision !== undefined) {
command += ` --to-revision=${input.revision}`;
}
// Add revision for history
if (input.subCommand === "history" && input.toRevision !== undefined) {
command += ` --revision=${input.toRevision}`;
}
// Add timeout if specified
if (input.timeout) {
command += ` --timeout=${input.timeout}`;
}
// Execute the command
try {
// For status command with watch flag, we need to handle it differently
// since it's meant to be interactive and follow the progress
if (input.subCommand === "status" && watch) {
command += " --watch";
// For watch we are limited in what we can do - we'll execute it with a reasonable timeout
// and capture the output until that point
const result = execSync(command, {
encoding: "utf8",
timeout: 15000, // Reduced from 30 seconds to 15 seconds
env: { ...process.env, KUBECONFIG: process.env.KUBECONFIG }
});
return {
content: [
{
type: "text",
text: result + "\n\nNote: Watch operation was limited to 15 seconds. The rollout may still be in progress.",
},
],
};
}
else {
const result = execSync(command, { encoding: "utf8", env: { ...process.env, KUBECONFIG: process.env.KUBECONFIG } });
return {
content: [
{
type: "text",
text: result,
},
],
};
}
}
catch (error) {
throw new McpError(ErrorCode.InternalError, `Failed to execute rollout command: ${error.message}`);
}
}
catch (error) {
if (error instanceof McpError) {
throw error;
}
throw new McpError(ErrorCode.InternalError, `Failed to execute kubectl rollout command: ${error.message}`);
}
}