mcp-server-kubernetes 0.3.0 → 0.3.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 +81 -21
- package/dist/index.js +49 -44
- package/dist/models/response-schemas.d.ts +22 -0
- package/dist/models/response-schemas.js +3 -0
- package/dist/tools/get_events.d.ts +28 -0
- package/dist/tools/get_events.js +66 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# MCP Server Kubernetes
|
|
2
|
+
|
|
3
|
+
[](https://github.com/yourusername/mcp-server-kubernetes/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/yourusername/mcp-server-kubernetes)
|
|
5
|
+
[](https://bun.sh)
|
|
6
|
+
[](https://kubernetes.io/)
|
|
7
|
+
[](https://www.docker.com/)
|
|
8
|
+
[](https://github.com/Flux159/mcp-server-kubernetes/stargazers)
|
|
9
|
+
[](https://github.com/Flux159/mcp-server-kubernetes/issues)
|
|
10
|
+
[](https://github.com/Flux159/mcp-server-kubernetes/pulls)
|
|
11
|
+
[](https://github.com/Flux159/mcp-server-kubernetes/commits/main)
|
|
12
|
+
[](https://smithery.ai/protocol/mcp-server-kubernetes)
|
|
2
13
|
|
|
3
14
|
MCP Server that can connect to a Kubernetes cluster and manage it.
|
|
4
15
|
|
|
@@ -30,6 +41,28 @@ You can verify your connection by asking Claude to list your pods or create a te
|
|
|
30
41
|
|
|
31
42
|
If you have errors open up a standard terminal and run `kubectl get pods` to see if you can connect to your cluster without credentials issues.
|
|
32
43
|
|
|
44
|
+
## Usage with mcp-chat
|
|
45
|
+
|
|
46
|
+
[mcp-chat](https://github.com/Flux159/mcp-chat) is a CLI chat client for MCP servers. You can use it to interact with the Kubernetes server.
|
|
47
|
+
|
|
48
|
+
```shell
|
|
49
|
+
npx mcp-chat --server "npx mcp-server-kubernetes"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Alternatively, pass it your existing Claude Desktop configuration file from above (Linux should pass the correct path to config):
|
|
53
|
+
|
|
54
|
+
Mac:
|
|
55
|
+
|
|
56
|
+
```shell
|
|
57
|
+
npx mcp-chat --config "~/Library/Application Support/Claude/claude_desktop_config.json"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Windows:
|
|
61
|
+
|
|
62
|
+
```shell
|
|
63
|
+
npx mcp-chat --config "%APPDATA%\Claude\claude_desktop_config.json"
|
|
64
|
+
```
|
|
65
|
+
|
|
33
66
|
## Features
|
|
34
67
|
|
|
35
68
|
- [x] Connect to a Kubernetes cluster
|
|
@@ -50,6 +83,7 @@ If you have errors open up a standard terminal and run `kubectl get pods` to see
|
|
|
50
83
|
- Support for version specification
|
|
51
84
|
- Support for custom repositories
|
|
52
85
|
- [x] kubectl explain and kubectl api-resources support
|
|
86
|
+
- [x] Get Kubernetes events from the cluster
|
|
53
87
|
- [ ] Port forward to a pod
|
|
54
88
|
- [ ] Choose namespace for next commands (memory)
|
|
55
89
|
|
|
@@ -88,34 +122,60 @@ npx @modelcontextprotocol/inspector node build/index.js
|
|
|
88
122
|
# Follow further instructions on terminal for Inspector link
|
|
89
123
|
```
|
|
90
124
|
|
|
125
|
+
5. Local testing with [mcp-chat](https://github.com/Flux159/mcp-chat)
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npm run chat
|
|
129
|
+
```
|
|
130
|
+
|
|
91
131
|
### Project Structure
|
|
92
132
|
|
|
93
133
|
```
|
|
94
134
|
├── src/
|
|
95
135
|
│ ├── index.ts # Main server implementation
|
|
96
136
|
│ ├── types.ts # Type re-exports
|
|
97
|
-
│ ├── config/
|
|
137
|
+
│ ├── config/ # Configuration files
|
|
98
138
|
│ │ ├── container-templates.ts # Container configurations
|
|
99
|
-
│ │ ├── server-config.ts
|
|
139
|
+
│ │ ├── server-config.ts # Server settings
|
|
100
140
|
│ │ ├── deployment-config.ts # Deployment schemas
|
|
101
|
-
│ │
|
|
102
|
-
│
|
|
103
|
-
│
|
|
104
|
-
│ │ ├──
|
|
105
|
-
│ │
|
|
106
|
-
│ ├──
|
|
107
|
-
│ │
|
|
108
|
-
│
|
|
109
|
-
│
|
|
110
|
-
│ └──
|
|
111
|
-
│
|
|
112
|
-
│
|
|
113
|
-
│
|
|
114
|
-
│
|
|
115
|
-
├──
|
|
116
|
-
│
|
|
117
|
-
│
|
|
118
|
-
|
|
141
|
+
│ │ ├── namespace-config.ts # Namespace schemas
|
|
142
|
+
│ │ └── cleanup-config.ts # Resource cleanup configuration
|
|
143
|
+
│ ├── models/ # Data models and schemas
|
|
144
|
+
│ │ ├── response-schemas.ts # API response schemas
|
|
145
|
+
│ │ ├── resource-models.ts # Resource models
|
|
146
|
+
│ │ ├── tool-models.ts # Tool schemas
|
|
147
|
+
│ │ ├── helm-models.ts # Helm operation schemas
|
|
148
|
+
│ │ └── kubectl-models.ts # Kubectl operation schemas
|
|
149
|
+
│ ├── utils/ # Utility classes
|
|
150
|
+
│ │ └── kubernetes-manager.ts # K8s management
|
|
151
|
+
│ ├── resources/ # Resource handlers
|
|
152
|
+
│ │ └── handlers.ts # Resource implementation
|
|
153
|
+
│ └── tools/ # Tool implementations
|
|
154
|
+
│ ├── list_pods.ts # Pod listing operations
|
|
155
|
+
│ ├── list_services.ts # Service listing operations
|
|
156
|
+
│ ├── list_deployments.ts # Deployment listing operations
|
|
157
|
+
│ ├── list_nodes.ts # Node listing operations
|
|
158
|
+
│ ├── create_pod.ts # Pod creation operations
|
|
159
|
+
│ ├── delete_pod.ts # Pod deletion operations
|
|
160
|
+
│ ├── describe_pod.ts # Pod description operations
|
|
161
|
+
│ ├── get_logs.ts # Container logs operations
|
|
162
|
+
│ ├── get_events.ts # Kubernetes events operations
|
|
163
|
+
│ ├── helm-operations.ts # Helm chart operations
|
|
164
|
+
│ └── kubectl-operations.ts # Kubectl utility operations
|
|
165
|
+
├── tests/ # Test files
|
|
166
|
+
│ ├── unit.test.ts # Unit tests for basic operations
|
|
167
|
+
│ ├── helm.test.ts # Helm-specific tests
|
|
168
|
+
│ └── kubectl.test.ts # Kubectl-specific tests
|
|
169
|
+
├── .github/ # GitHub configuration
|
|
170
|
+
│ └── workflows/ # CI/CD workflows
|
|
171
|
+
│ ├── ci.yml # Continuous integration
|
|
172
|
+
│ └── cd.yml # Continuous deployment
|
|
173
|
+
├── Dockerfile # Docker container definition
|
|
174
|
+
├── LICENSE # MIT license
|
|
175
|
+
├── README.md # Project documentation
|
|
176
|
+
├── package.json # NPM package configuration
|
|
177
|
+
├── tsconfig.json # TypeScript configuration
|
|
178
|
+
└── vitest.config.ts # Test configuration
|
|
119
179
|
```
|
|
120
180
|
|
|
121
181
|
### Contributing
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { createPod, createPodSchema } from "./tools/create_pod.js";
|
|
|
11
11
|
import { deletePod, deletePodSchema } from "./tools/delete_pod.js";
|
|
12
12
|
import { describePod, describePodSchema } from "./tools/describe_pod.js";
|
|
13
13
|
import { getLogs, getLogsSchema } from "./tools/get_logs.js";
|
|
14
|
+
import { getEvents, getEventsSchema } from "./tools/get_events.js";
|
|
14
15
|
import { getResourceHandlers } from "./resources/handlers.js";
|
|
15
16
|
import { ListResourcesRequestSchema, ReadResourceRequestSchema, ListToolsRequestSchema, CallToolRequestSchema, ErrorCode, McpError, } from "@modelcontextprotocol/sdk/types.js";
|
|
16
17
|
import { KubernetesManager } from "./types.js";
|
|
@@ -27,22 +28,23 @@ const server = new Server({
|
|
|
27
28
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
28
29
|
return {
|
|
29
30
|
tools: [
|
|
30
|
-
|
|
31
|
-
listDeploymentsSchema,
|
|
32
|
-
listServicesSchema,
|
|
33
|
-
listNamespacesSchema,
|
|
34
|
-
createPodSchema,
|
|
31
|
+
cleanupSchema,
|
|
35
32
|
createDeploymentSchema,
|
|
33
|
+
createPodSchema,
|
|
36
34
|
deletePodSchema,
|
|
37
35
|
describePodSchema,
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
explainResourceSchema,
|
|
37
|
+
getEventsSchema,
|
|
40
38
|
getLogsSchema,
|
|
41
39
|
installHelmChartSchema,
|
|
42
|
-
upgradeHelmChartSchema,
|
|
43
|
-
uninstallHelmChartSchema,
|
|
44
|
-
explainResourceSchema,
|
|
45
40
|
listApiResourcesSchema,
|
|
41
|
+
listDeploymentsSchema,
|
|
42
|
+
listNamespacesSchema,
|
|
43
|
+
listNodesSchema,
|
|
44
|
+
listPodsSchema,
|
|
45
|
+
listServicesSchema,
|
|
46
|
+
uninstallHelmChartSchema,
|
|
47
|
+
upgradeHelmChartSchema,
|
|
46
48
|
],
|
|
47
49
|
};
|
|
48
50
|
});
|
|
@@ -50,27 +52,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
50
52
|
try {
|
|
51
53
|
const { name, arguments: input = {} } = request.params;
|
|
52
54
|
switch (name) {
|
|
53
|
-
case "
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
case "list_deployments": {
|
|
57
|
-
return await listDeployments(k8sManager, input);
|
|
58
|
-
}
|
|
59
|
-
case "list_services": {
|
|
60
|
-
return await listServices(k8sManager, input);
|
|
61
|
-
}
|
|
62
|
-
case "list_namespaces": {
|
|
63
|
-
const { body } = await k8sManager.getCoreApi().listNamespace();
|
|
64
|
-
const namespaces = body.items.map((ns) => ({
|
|
65
|
-
name: ns.metadata?.name || "",
|
|
66
|
-
status: ns.status?.phase || "",
|
|
67
|
-
createdAt: ns.metadata?.creationTimestamp,
|
|
68
|
-
}));
|
|
55
|
+
case "cleanup": {
|
|
56
|
+
await k8sManager.cleanup();
|
|
69
57
|
return {
|
|
70
58
|
content: [
|
|
71
59
|
{
|
|
72
60
|
type: "text",
|
|
73
|
-
text: JSON.stringify({
|
|
61
|
+
text: JSON.stringify({
|
|
62
|
+
success: true,
|
|
63
|
+
}, null, 2),
|
|
74
64
|
},
|
|
75
65
|
],
|
|
76
66
|
};
|
|
@@ -84,15 +74,36 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
84
74
|
case "describe_pod": {
|
|
85
75
|
return await describePod(k8sManager, input);
|
|
86
76
|
}
|
|
87
|
-
case "
|
|
88
|
-
await
|
|
77
|
+
case "explain_resource": {
|
|
78
|
+
return await explainResource(input);
|
|
79
|
+
}
|
|
80
|
+
case "get_events": {
|
|
81
|
+
return await getEvents(k8sManager, input);
|
|
82
|
+
}
|
|
83
|
+
case "get_logs": {
|
|
84
|
+
return await getLogs(k8sManager, input);
|
|
85
|
+
}
|
|
86
|
+
case "install_helm_chart": {
|
|
87
|
+
return await installHelmChart(input);
|
|
88
|
+
}
|
|
89
|
+
case "list_api_resources": {
|
|
90
|
+
return await listApiResources(input);
|
|
91
|
+
}
|
|
92
|
+
case "list_deployments": {
|
|
93
|
+
return await listDeployments(k8sManager, input);
|
|
94
|
+
}
|
|
95
|
+
case "list_namespaces": {
|
|
96
|
+
const { body } = await k8sManager.getCoreApi().listNamespace();
|
|
97
|
+
const namespaces = body.items.map((ns) => ({
|
|
98
|
+
name: ns.metadata?.name || "",
|
|
99
|
+
status: ns.status?.phase || "",
|
|
100
|
+
createdAt: ns.metadata?.creationTimestamp,
|
|
101
|
+
}));
|
|
89
102
|
return {
|
|
90
103
|
content: [
|
|
91
104
|
{
|
|
92
105
|
type: "text",
|
|
93
|
-
text: JSON.stringify({
|
|
94
|
-
success: true,
|
|
95
|
-
}, null, 2),
|
|
106
|
+
text: JSON.stringify({ namespaces }, null, 2),
|
|
96
107
|
},
|
|
97
108
|
],
|
|
98
109
|
};
|
|
@@ -100,23 +111,17 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
100
111
|
case "list_nodes": {
|
|
101
112
|
return await listNodes(k8sManager);
|
|
102
113
|
}
|
|
103
|
-
case "
|
|
104
|
-
return await
|
|
105
|
-
}
|
|
106
|
-
case "install_helm_chart": {
|
|
107
|
-
return await installHelmChart(input);
|
|
114
|
+
case "list_pods": {
|
|
115
|
+
return await listPods(k8sManager, input);
|
|
108
116
|
}
|
|
109
|
-
case "
|
|
110
|
-
return await
|
|
117
|
+
case "list_services": {
|
|
118
|
+
return await listServices(k8sManager, input);
|
|
111
119
|
}
|
|
112
120
|
case "uninstall_helm_chart": {
|
|
113
121
|
return await uninstallHelmChart(input);
|
|
114
122
|
}
|
|
115
|
-
case "
|
|
116
|
-
return await
|
|
117
|
-
}
|
|
118
|
-
case "list_api_resources": {
|
|
119
|
-
return await listApiResources(input);
|
|
123
|
+
case "upgrade_helm_chart": {
|
|
124
|
+
return await upgradeHelmChart(input);
|
|
120
125
|
}
|
|
121
126
|
default:
|
|
122
127
|
throw new McpError(ErrorCode.InvalidRequest, `Unknown tool: ${name}`);
|
|
@@ -219,3 +219,25 @@ export declare const GetLogsResponseSchema: z.ZodObject<{
|
|
|
219
219
|
text: string;
|
|
220
220
|
}[];
|
|
221
221
|
}>;
|
|
222
|
+
export declare const GetEventsResponseSchema: z.ZodObject<{
|
|
223
|
+
content: z.ZodArray<z.ZodObject<{
|
|
224
|
+
type: z.ZodLiteral<"text">;
|
|
225
|
+
text: z.ZodString;
|
|
226
|
+
}, "strip", z.ZodTypeAny, {
|
|
227
|
+
type: "text";
|
|
228
|
+
text: string;
|
|
229
|
+
}, {
|
|
230
|
+
type: "text";
|
|
231
|
+
text: string;
|
|
232
|
+
}>, "many">;
|
|
233
|
+
}, "strip", z.ZodTypeAny, {
|
|
234
|
+
content: {
|
|
235
|
+
type: "text";
|
|
236
|
+
text: string;
|
|
237
|
+
}[];
|
|
238
|
+
}, {
|
|
239
|
+
content: {
|
|
240
|
+
type: "text";
|
|
241
|
+
text: string;
|
|
242
|
+
}[];
|
|
243
|
+
}>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { KubernetesManager } from "../types.js";
|
|
2
|
+
export declare const getEventsSchema: {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: string;
|
|
7
|
+
properties: {
|
|
8
|
+
namespace: {
|
|
9
|
+
type: string;
|
|
10
|
+
description: string;
|
|
11
|
+
};
|
|
12
|
+
fieldSelector: {
|
|
13
|
+
type: string;
|
|
14
|
+
description: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
required: never[];
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare function getEvents(k8sManager: KubernetesManager, params: {
|
|
21
|
+
namespace?: string;
|
|
22
|
+
fieldSelector?: string;
|
|
23
|
+
}): Promise<{
|
|
24
|
+
content: {
|
|
25
|
+
type: string;
|
|
26
|
+
text: string;
|
|
27
|
+
}[];
|
|
28
|
+
}>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export const getEventsSchema = {
|
|
2
|
+
name: "get_events",
|
|
3
|
+
description: "Get Kubernetes events from the cluster",
|
|
4
|
+
inputSchema: {
|
|
5
|
+
type: "object",
|
|
6
|
+
properties: {
|
|
7
|
+
namespace: {
|
|
8
|
+
type: "string",
|
|
9
|
+
description: "Namespace to get events from. If not specified, gets events from all namespaces",
|
|
10
|
+
},
|
|
11
|
+
fieldSelector: {
|
|
12
|
+
type: "string",
|
|
13
|
+
description: "Field selector to filter events",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
required: [],
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
export async function getEvents(k8sManager, params) {
|
|
20
|
+
const { namespace, fieldSelector } = params;
|
|
21
|
+
const api = k8sManager.getCoreApi();
|
|
22
|
+
let events;
|
|
23
|
+
if (namespace) {
|
|
24
|
+
const { body } = await api.listNamespacedEvent(namespace, undefined, // pretty
|
|
25
|
+
undefined, // allowWatchBookmarks
|
|
26
|
+
undefined, // _continue
|
|
27
|
+
undefined, // fieldSelector
|
|
28
|
+
fieldSelector // fieldSelector
|
|
29
|
+
);
|
|
30
|
+
events = body;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const { body } = await api.listEventForAllNamespaces(undefined, // allowWatchBookmarks
|
|
34
|
+
undefined, // _continue
|
|
35
|
+
fieldSelector, // fieldSelector
|
|
36
|
+
undefined, // labelSelector
|
|
37
|
+
undefined, // limit
|
|
38
|
+
undefined, // pretty
|
|
39
|
+
undefined, // resourceVersion
|
|
40
|
+
undefined, // resourceVersionMatch
|
|
41
|
+
undefined // timeoutSeconds
|
|
42
|
+
);
|
|
43
|
+
events = body;
|
|
44
|
+
}
|
|
45
|
+
const formattedEvents = events.items.map((event) => ({
|
|
46
|
+
type: event.type || "",
|
|
47
|
+
reason: event.reason || "",
|
|
48
|
+
message: event.message || "",
|
|
49
|
+
involvedObject: {
|
|
50
|
+
kind: event.involvedObject.kind || "",
|
|
51
|
+
name: event.involvedObject.name || "",
|
|
52
|
+
namespace: event.involvedObject.namespace || "",
|
|
53
|
+
},
|
|
54
|
+
firstTimestamp: event.firstTimestamp || "",
|
|
55
|
+
lastTimestamp: event.lastTimestamp || "",
|
|
56
|
+
count: event.count || 0,
|
|
57
|
+
}));
|
|
58
|
+
return {
|
|
59
|
+
content: [
|
|
60
|
+
{
|
|
61
|
+
type: "text",
|
|
62
|
+
text: JSON.stringify({ events: formattedEvents }, null, 2),
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-server-kubernetes",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "MCP server for interacting with Kubernetes clusters via kubectl",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"start": "node dist/index.js",
|
|
22
22
|
"test": "vitest run",
|
|
23
23
|
"prepublishOnly": "npm run build",
|
|
24
|
-
"dockerbuild": "docker buildx build -t flux159/mcp-server-kubernetes --platform linux/amd64,linux/arm64 --push ."
|
|
24
|
+
"dockerbuild": "docker buildx build -t flux159/mcp-server-kubernetes --platform linux/amd64,linux/arm64 --push .",
|
|
25
|
+
"chat": "npx mcp-chat --server \"./dist/index.js\""
|
|
25
26
|
},
|
|
26
27
|
"keywords": [
|
|
27
28
|
"mcp",
|