mcp-server-kubernetes 2.4.0 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/dist/index.js +10 -1
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.js +108 -0
- package/dist/tools/kubectl-logs.js +30 -0
- package/dist/utils/sse.js +11 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,6 @@ https://github.com/user-attachments/assets/f25f8f4e-4d04-479b-9ae0-5dac452dd2ed
|
|
|
17
17
|
|
|
18
18
|
<a href="https://glama.ai/mcp/servers/w71ieamqrt"><img width="380" height="200" src="https://glama.ai/mcp/servers/w71ieamqrt/badge" /></a>
|
|
19
19
|
|
|
20
|
-
|
|
21
20
|
## Usage with Claude Desktop
|
|
22
21
|
|
|
23
22
|
```json
|
|
@@ -90,8 +89,19 @@ npx mcp-chat --config "%APPDATA%\Claude\claude_desktop_config.json"
|
|
|
90
89
|
- Run Helm operations
|
|
91
90
|
- Install, upgrade, and uninstall charts
|
|
92
91
|
- Support for custom values, repositories, and versions
|
|
92
|
+
- [x] Troubleshooting Prompt (`k8s-troubleshoot`)
|
|
93
|
+
- Guides through a systematic Kubernetes troubleshooting flow for pods based on a keyword and optional namespace.
|
|
93
94
|
- [x] Non-destructive mode for read and create/update-only access to clusters
|
|
94
95
|
|
|
96
|
+
## Prompts
|
|
97
|
+
|
|
98
|
+
The MCP Kubernetes server includes specialized prompts to assist with common operations.
|
|
99
|
+
|
|
100
|
+
### k8s-troubleshoot Prompt
|
|
101
|
+
|
|
102
|
+
This prompt provides a systematic troubleshooting flow for Kubernetes pods. It accepts a `keyword` to identify relevant pods and an optional `namespace` to narrow the search.
|
|
103
|
+
The prompt's output will guide you through an autonomous troubleshooting flow, providing instructions for identifying issues, collecting evidence, and suggesting remediation steps.
|
|
104
|
+
|
|
95
105
|
## Local Development
|
|
96
106
|
|
|
97
107
|
Make sure that you have [bun installed](https://bun.sh/docs/installation). Clone the repo & install dependencies:
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ import { kubectlLogs, kubectlLogsSchema } from "./tools/kubectl-logs.js";
|
|
|
22
22
|
import { kubectlGeneric, kubectlGenericSchema, } from "./tools/kubectl-generic.js";
|
|
23
23
|
import { kubectlPatch, kubectlPatchSchema } from "./tools/kubectl-patch.js";
|
|
24
24
|
import { kubectlRollout, kubectlRolloutSchema, } from "./tools/kubectl-rollout.js";
|
|
25
|
+
import { registerPromptHandlers } from "./prompts/index.js";
|
|
25
26
|
// Check if non-destructive tools only mode is enabled
|
|
26
27
|
const nonDestructiveTools = process.env.ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS === "true";
|
|
27
28
|
// Define destructive tools (delete and uninstall operations)
|
|
@@ -66,11 +67,19 @@ const k8sManager = new KubernetesManager();
|
|
|
66
67
|
const server = new Server({
|
|
67
68
|
name: serverConfig.name,
|
|
68
69
|
version: serverConfig.version,
|
|
69
|
-
},
|
|
70
|
+
}, {
|
|
71
|
+
...serverConfig,
|
|
72
|
+
capabilities: {
|
|
73
|
+
prompts: {},
|
|
74
|
+
...serverConfig.capabilities,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
70
77
|
// Resources handlers
|
|
71
78
|
const resourceHandlers = getResourceHandlers(k8sManager);
|
|
72
79
|
server.setRequestHandler(ListResourcesRequestSchema, resourceHandlers.listResources);
|
|
73
80
|
server.setRequestHandler(ReadResourceRequestSchema, resourceHandlers.readResource);
|
|
81
|
+
// Register prompt handlers
|
|
82
|
+
registerPromptHandlers(server, k8sManager);
|
|
74
83
|
// Tools handlers
|
|
75
84
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
76
85
|
// Filter out destructive tools if ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS is set to 'true'
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { ListPromptsRequestSchema, GetPromptRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
export function registerPromptHandlers(server, k8sManager) {
|
|
3
|
+
// Register prompts list handler
|
|
4
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
5
|
+
return {
|
|
6
|
+
prompts: [
|
|
7
|
+
{
|
|
8
|
+
name: "k8s-troubleshoot",
|
|
9
|
+
description: "Troubleshoot Kubernetes Resources.",
|
|
10
|
+
arguments: [
|
|
11
|
+
{
|
|
12
|
+
name: "keyword",
|
|
13
|
+
description: "A keyword to search pod/node names.",
|
|
14
|
+
required: true,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "namespace",
|
|
18
|
+
description: "Optional: Specify a namespace to narrow down the search.",
|
|
19
|
+
required: false,
|
|
20
|
+
default: "all"
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
// Register prompt handler
|
|
28
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
29
|
+
const { name, arguments: args } = request.params;
|
|
30
|
+
if (name === "k8s-troubleshoot") {
|
|
31
|
+
const keyword = args?.keyword;
|
|
32
|
+
const namespace = args?.namespace;
|
|
33
|
+
if (!keyword) {
|
|
34
|
+
throw new Error("Keyword parameter is required for k8s-troubleshoot prompt");
|
|
35
|
+
}
|
|
36
|
+
const actualNamespace = namespace || "all";
|
|
37
|
+
const message = `Troubleshooting for resources (pods, nodes, etc.) containing keyword "${keyword}" in their names within namespace "${actualNamespace}" (or across all namespaces if specified) for this investigation:
|
|
38
|
+
|
|
39
|
+
**Autonomous Kubernetes Troubleshooting Flow**
|
|
40
|
+
|
|
41
|
+
0. **Perform Quick Health Checks / Golden Signals Analysis**
|
|
42
|
+
- Assess latency, errors, and resource utilization. If a clear issue is identified (e.g., node not ready, network partition), streamline or deprioritize subsequent detailed steps.
|
|
43
|
+
|
|
44
|
+
1. **Identify Resource Type and Scope**
|
|
45
|
+
- Determine the specific resource type (e.g., Pod, Node, Deployment, Service, Customresourcedefination) by analyzing labels, controller relationships, and initial observations.
|
|
46
|
+
- If needed we can use kubectl_explain tool to get list of resource type
|
|
47
|
+
- Note when you need customresourcedefinitions please use kubectl_explain
|
|
48
|
+
|
|
49
|
+
2. **Assess Current State**
|
|
50
|
+
- Check resource status (e.g., ready state, desired vs. current replicas for deployments).
|
|
51
|
+
- Identify any non-running or unhealthy states (e.g., CrashLoopBackOff, NotReady, Pending, Evicted).
|
|
52
|
+
- Review placement and distribution patterns across nodes.
|
|
53
|
+
|
|
54
|
+
3. **Analyze Operational History**
|
|
55
|
+
- Review recent events and warnings related to the resource.
|
|
56
|
+
- Check rollout history and update strategies for controllers (e.g., Deployments).
|
|
57
|
+
- Examine recent configuration changes or applied manifests.
|
|
58
|
+
|
|
59
|
+
4. **Inspect Runtime Behavior**
|
|
60
|
+
- Collect logs from current and previous instances for errors or anomalies (e.g., container logs for pods, system logs for nodes).
|
|
61
|
+
- Test intra-cluster networking and DNS resolution.
|
|
62
|
+
- Verify storage mounts, secret accessibility, and configuration usage.
|
|
63
|
+
|
|
64
|
+
5. **Evaluate Dependencies**
|
|
65
|
+
- Validate references to ConfigMaps, Secrets, and other dependent resources.
|
|
66
|
+
- Check associated service account permissions and RBAC rules.
|
|
67
|
+
- Confirm initContainers and sidecar containers have completed successfully or are running as expected.
|
|
68
|
+
|
|
69
|
+
6. **Audit Resource Constraints**
|
|
70
|
+
- Analyze CPU, memory, and storage usage trends against defined requests and limits.
|
|
71
|
+
- Check node allocatable resources and capacity.
|
|
72
|
+
- Review pod disruption budgets and quotas affecting the resource.
|
|
73
|
+
|
|
74
|
+
7. **Validate Cluster Context & Environment**
|
|
75
|
+
- Inspect node readiness, taints, and tolerations.
|
|
76
|
+
- Verify the current Kubernetes context and namespace.
|
|
77
|
+
- Confirm API server availability and connectivity.
|
|
78
|
+
- Check Kubernetes version compatibility (if applicable).
|
|
79
|
+
|
|
80
|
+
8. **Compare Against Patterns**
|
|
81
|
+
- Benchmark against workload-specific best practices and known healthy configurations.
|
|
82
|
+
- Verify liveness, readiness, and startup probe configurations.
|
|
83
|
+
- Audit security context settings and network policies.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
**Instructions:**
|
|
88
|
+
- For each finding, clearly state the observation, its severity (e.g., \`CRITICAL\`, \`WARNING\`, \`INFO\`), and the evidence (e.g., \`kubectl output\`, error message in POD_NAME, timestamp). Also, print which object they found symptoms, e.g., error message in POD_NAME.
|
|
89
|
+
- If there are more than 4 relevant resources (e.g., pods, nodes), pick up to 3 resources which are exhibiting the most severe or illustrative symptoms.
|
|
90
|
+
- If there's a typo in user input and a closest matching object name exists, consider an auto-correction or suggest the correct name.
|
|
91
|
+
- Summarize the root cause clearly and concisely at the end of the investigation, along with clear, actionable steps for remediation, including specific \`kubectl\` commands or configuration changes required.
|
|
92
|
+
- If there is a node-level issue, thoroughly analyze it and explicitly post the findings.
|
|
93
|
+
- **Keep the output crisp, to the point, professional, direct, and systematic, avoiding verbose descriptions. Focus on actionable insights for engineers.**`;
|
|
94
|
+
return {
|
|
95
|
+
messages: [
|
|
96
|
+
{
|
|
97
|
+
role: "user",
|
|
98
|
+
content: {
|
|
99
|
+
type: "text",
|
|
100
|
+
text: message,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
throw new Error(`Unknown prompt: ${name}`);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
@@ -293,12 +293,42 @@ function handleCommandError(error, resourceDescription) {
|
|
|
293
293
|
isError: true,
|
|
294
294
|
};
|
|
295
295
|
}
|
|
296
|
+
// Check for multi-container pod error
|
|
297
|
+
if (error.message.includes("a container name must be specified")) {
|
|
298
|
+
// Extract pod name and available containers from error message
|
|
299
|
+
const podNameMatch = error.message.match(/for pod ([^,]+)/);
|
|
300
|
+
const containersMatch = error.message.match(/choose one of: \[([^\]]+)\]/);
|
|
301
|
+
const initContainersMatch = error.message.match(/or one of the init containers: \[([^\]]+)\]/);
|
|
302
|
+
const podName = podNameMatch ? podNameMatch[1] : 'unknown';
|
|
303
|
+
const containers = containersMatch ? containersMatch[1].split(' ').map((c) => c.trim()) : [];
|
|
304
|
+
const initContainers = initContainersMatch ? initContainersMatch[1].split(' ').map((c) => c.trim()) : [];
|
|
305
|
+
// Generate structured context for the MCP client to make decisions
|
|
306
|
+
const context = {
|
|
307
|
+
error: "Multi-container pod requires container specification",
|
|
308
|
+
status: "multi_container_error",
|
|
309
|
+
pod_name: podName,
|
|
310
|
+
available_containers: containers,
|
|
311
|
+
init_containers: initContainers,
|
|
312
|
+
suggestion: `Please specify a container name using the 'container' parameter. Available containers: ${containers.join(', ')}${initContainers.length > 0 ? `. Init containers: ${initContainers.join(', ')}` : ''}`
|
|
313
|
+
};
|
|
314
|
+
return {
|
|
315
|
+
content: [
|
|
316
|
+
{
|
|
317
|
+
type: "text",
|
|
318
|
+
text: JSON.stringify(context, null, 2),
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
isError: true,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
296
324
|
return {
|
|
297
325
|
content: [
|
|
298
326
|
{
|
|
299
327
|
type: "text",
|
|
300
328
|
text: JSON.stringify({
|
|
301
329
|
error: `Failed to get logs for ${resourceDescription}: ${error.message}`,
|
|
330
|
+
status: "general_error",
|
|
331
|
+
original_error: error.message
|
|
302
332
|
}, null, 2),
|
|
303
333
|
},
|
|
304
334
|
],
|
package/dist/utils/sse.js
CHANGED
|
@@ -21,7 +21,15 @@ export function startSSEServer(server) {
|
|
|
21
21
|
.send("Not found. Must pass valid sessionId as query param.");
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
let port = 3000;
|
|
25
|
+
try {
|
|
26
|
+
port = parseInt(process.env.PORT || "3000", 10);
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
console.error("Invalid PORT environment variable, using default port 3000.");
|
|
30
|
+
}
|
|
31
|
+
const host = process.env.HOST || "localhost";
|
|
32
|
+
app.listen(port, host, () => {
|
|
33
|
+
console.log(`mcp-kubernetes-server is listening on port ${port}\nUse the following url to connect to the server:\n\http://${host}:${port}/sse`);
|
|
34
|
+
});
|
|
27
35
|
}
|