mcp-server-kubernetes 0.4.0 → 1.0.0

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 CHANGED
@@ -15,7 +15,7 @@ MCP Server that can connect to a Kubernetes cluster and manage it.
15
15
 
16
16
  https://github.com/user-attachments/assets/f25f8f4e-4d04-479b-9ae0-5dac452dd2ed
17
17
 
18
- <a href="https://glama.ai/mcp/servers/w71ieamqrt"><img width="380" height="200" src="https://glama.ai/mcp/servers/w71ieamqrt/badge" /></a>
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
20
  ## Usage with Claude Desktop
21
21
 
@@ -74,7 +74,9 @@ npx mcp-chat --config "%APPDATA%\Claude\claude_desktop_config.json"
74
74
  - [x] Delete a pod
75
75
  - [x] Describe a pod
76
76
  - [x] List all namespaces
77
- - [x] Get logs from a pod for debugging (supports pods deployments jobs and label selectors)
77
+ - [x] Create a namespace
78
+ - [x] Create custom pod & deployment configs
79
+ - [x] Get logs from a pod for debugging (supports pods, deployments, jobs, and label selectors)
78
80
  - [x] Support Helm v3 for installing charts
79
81
  - Install charts with custom values
80
82
  - Uninstall releases
@@ -84,8 +86,7 @@ npx mcp-chat --config "%APPDATA%\Claude\claude_desktop_config.json"
84
86
  - Support for custom repositories
85
87
  - [x] kubectl explain and kubectl api-resources support
86
88
  - [x] Get Kubernetes events from the cluster
87
- - [ ] Port forward to a pod
88
- - [ ] Choose namespace for next commands (memory)
89
+ - [x] Port forward to a pod or service
89
90
 
90
91
  ## Local Development
91
92
 
@@ -1,5 +1,106 @@
1
1
  import { z } from "zod";
2
2
  import * as k8s from "@kubernetes/client-node";
3
- export declare const ContainerTemplate: z.ZodEnum<["ubuntu", "nginx", "busybox", "alpine"]>;
3
+ export declare const ContainerTemplate: z.ZodEnum<["ubuntu", "nginx", "busybox", "alpine", "custom"]>;
4
4
  export type ContainerTemplateName = z.infer<typeof ContainerTemplate>;
5
+ export declare const CustomContainerConfig: z.ZodObject<{
6
+ image: z.ZodString;
7
+ command: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
8
+ args: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
9
+ ports: z.ZodOptional<z.ZodArray<z.ZodObject<{
10
+ containerPort: z.ZodNumber;
11
+ name: z.ZodOptional<z.ZodString>;
12
+ protocol: z.ZodOptional<z.ZodString>;
13
+ }, "strip", z.ZodTypeAny, {
14
+ containerPort: number;
15
+ name?: string | undefined;
16
+ protocol?: string | undefined;
17
+ }, {
18
+ containerPort: number;
19
+ name?: string | undefined;
20
+ protocol?: string | undefined;
21
+ }>, "many">>;
22
+ resources: z.ZodOptional<z.ZodObject<{
23
+ limits: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
24
+ requests: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
25
+ }, "strip", z.ZodTypeAny, {
26
+ limits?: Record<string, string> | undefined;
27
+ requests?: Record<string, string> | undefined;
28
+ }, {
29
+ limits?: Record<string, string> | undefined;
30
+ requests?: Record<string, string> | undefined;
31
+ }>>;
32
+ env: z.ZodOptional<z.ZodArray<z.ZodObject<{
33
+ name: z.ZodString;
34
+ value: z.ZodOptional<z.ZodString>;
35
+ valueFrom: z.ZodOptional<z.ZodAny>;
36
+ }, "strip", z.ZodTypeAny, {
37
+ name: string;
38
+ value?: string | undefined;
39
+ valueFrom?: any;
40
+ }, {
41
+ name: string;
42
+ value?: string | undefined;
43
+ valueFrom?: any;
44
+ }>, "many">>;
45
+ volumeMounts: z.ZodOptional<z.ZodArray<z.ZodObject<{
46
+ name: z.ZodString;
47
+ mountPath: z.ZodString;
48
+ readOnly: z.ZodOptional<z.ZodBoolean>;
49
+ }, "strip", z.ZodTypeAny, {
50
+ name: string;
51
+ mountPath: string;
52
+ readOnly?: boolean | undefined;
53
+ }, {
54
+ name: string;
55
+ mountPath: string;
56
+ readOnly?: boolean | undefined;
57
+ }>, "many">>;
58
+ }, "strip", z.ZodTypeAny, {
59
+ image: string;
60
+ resources?: {
61
+ limits?: Record<string, string> | undefined;
62
+ requests?: Record<string, string> | undefined;
63
+ } | undefined;
64
+ command?: string[] | undefined;
65
+ args?: string[] | undefined;
66
+ ports?: {
67
+ containerPort: number;
68
+ name?: string | undefined;
69
+ protocol?: string | undefined;
70
+ }[] | undefined;
71
+ env?: {
72
+ name: string;
73
+ value?: string | undefined;
74
+ valueFrom?: any;
75
+ }[] | undefined;
76
+ volumeMounts?: {
77
+ name: string;
78
+ mountPath: string;
79
+ readOnly?: boolean | undefined;
80
+ }[] | undefined;
81
+ }, {
82
+ image: string;
83
+ resources?: {
84
+ limits?: Record<string, string> | undefined;
85
+ requests?: Record<string, string> | undefined;
86
+ } | undefined;
87
+ command?: string[] | undefined;
88
+ args?: string[] | undefined;
89
+ ports?: {
90
+ containerPort: number;
91
+ name?: string | undefined;
92
+ protocol?: string | undefined;
93
+ }[] | undefined;
94
+ env?: {
95
+ name: string;
96
+ value?: string | undefined;
97
+ valueFrom?: any;
98
+ }[] | undefined;
99
+ volumeMounts?: {
100
+ name: string;
101
+ mountPath: string;
102
+ readOnly?: boolean | undefined;
103
+ }[] | undefined;
104
+ }>;
105
+ export type CustomContainerConfigType = z.infer<typeof CustomContainerConfig>;
5
106
  export declare const containerTemplates: Record<string, k8s.V1Container>;
@@ -5,7 +5,41 @@ export const ContainerTemplate = z.enum([
5
5
  "nginx",
6
6
  "busybox",
7
7
  "alpine",
8
+ "custom",
8
9
  ]);
10
+ // Custom container configuration schema
11
+ export const CustomContainerConfig = z.object({
12
+ image: z.string(),
13
+ command: z.array(z.string()).optional(),
14
+ args: z.array(z.string()).optional(),
15
+ ports: z
16
+ .array(z.object({
17
+ containerPort: z.number(),
18
+ name: z.string().optional(),
19
+ protocol: z.string().optional(),
20
+ }))
21
+ .optional(),
22
+ resources: z
23
+ .object({
24
+ limits: z.record(z.string()).optional(),
25
+ requests: z.record(z.string()).optional(),
26
+ })
27
+ .optional(),
28
+ env: z
29
+ .array(z.object({
30
+ name: z.string(),
31
+ value: z.string().optional(),
32
+ valueFrom: z.any().optional(),
33
+ }))
34
+ .optional(),
35
+ volumeMounts: z
36
+ .array(z.object({
37
+ name: z.string(),
38
+ mountPath: z.string(),
39
+ readOnly: z.boolean().optional(),
40
+ }))
41
+ .optional(),
42
+ });
9
43
  // Container template configurations with resource limits and settings
10
44
  export const containerTemplates = {
11
45
  ubuntu: {
@@ -106,4 +140,26 @@ export const containerTemplates = {
106
140
  periodSeconds: 10,
107
141
  },
108
142
  },
143
+ custom: {
144
+ name: "main",
145
+ image: "busybox:latest", // Default image, will be overridden by custom config
146
+ command: ["sh"],
147
+ args: ["-c", "sleep infinity"],
148
+ resources: {
149
+ limits: {
150
+ cpu: "100m",
151
+ memory: "64Mi",
152
+ },
153
+ requests: {
154
+ cpu: "50m",
155
+ memory: "32Mi",
156
+ },
157
+ },
158
+ livenessProbe: {
159
+ exec: {
160
+ command: ["true"],
161
+ },
162
+ periodSeconds: 10,
163
+ },
164
+ },
109
165
  };
@@ -12,7 +12,7 @@ export declare const createDeploymentSchema: {
12
12
  };
13
13
  readonly template: {
14
14
  readonly type: "string";
15
- readonly enum: ["ubuntu", "nginx", "busybox", "alpine"];
15
+ readonly enum: ["ubuntu", "nginx", "busybox", "alpine", "custom"];
16
16
  };
17
17
  readonly replicas: {
18
18
  readonly type: "number";
@@ -25,6 +25,95 @@ export declare const createDeploymentSchema: {
25
25
  };
26
26
  readonly optional: true;
27
27
  };
28
+ readonly customConfig: {
29
+ readonly type: "object";
30
+ readonly optional: true;
31
+ readonly properties: {
32
+ readonly image: {
33
+ readonly type: "string";
34
+ };
35
+ readonly command: {
36
+ readonly type: "array";
37
+ readonly items: {
38
+ readonly type: "string";
39
+ };
40
+ };
41
+ readonly args: {
42
+ readonly type: "array";
43
+ readonly items: {
44
+ readonly type: "string";
45
+ };
46
+ };
47
+ readonly ports: {
48
+ readonly type: "array";
49
+ readonly items: {
50
+ readonly type: "object";
51
+ readonly properties: {
52
+ readonly containerPort: {
53
+ readonly type: "number";
54
+ };
55
+ readonly name: {
56
+ readonly type: "string";
57
+ };
58
+ readonly protocol: {
59
+ readonly type: "string";
60
+ };
61
+ };
62
+ };
63
+ };
64
+ readonly resources: {
65
+ readonly type: "object";
66
+ readonly properties: {
67
+ readonly limits: {
68
+ readonly type: "object";
69
+ readonly additionalProperties: {
70
+ readonly type: "string";
71
+ };
72
+ };
73
+ readonly requests: {
74
+ readonly type: "object";
75
+ readonly additionalProperties: {
76
+ readonly type: "string";
77
+ };
78
+ };
79
+ };
80
+ };
81
+ readonly env: {
82
+ readonly type: "array";
83
+ readonly items: {
84
+ readonly type: "object";
85
+ readonly properties: {
86
+ readonly name: {
87
+ readonly type: "string";
88
+ };
89
+ readonly value: {
90
+ readonly type: "string";
91
+ };
92
+ readonly valueFrom: {
93
+ readonly type: "object";
94
+ };
95
+ };
96
+ };
97
+ };
98
+ readonly volumeMounts: {
99
+ readonly type: "array";
100
+ readonly items: {
101
+ readonly type: "object";
102
+ readonly properties: {
103
+ readonly name: {
104
+ readonly type: "string";
105
+ };
106
+ readonly mountPath: {
107
+ readonly type: "string";
108
+ };
109
+ readonly readOnly: {
110
+ readonly type: "boolean";
111
+ };
112
+ };
113
+ };
114
+ };
115
+ };
116
+ };
28
117
  };
29
118
  readonly required: readonly ["name", "namespace", "template"];
30
119
  };
@@ -1,4 +1,4 @@
1
- import { ContainerTemplate } from "./container-templates.js";
1
+ import { ContainerTemplate, } from "./container-templates.js";
2
2
  export const createDeploymentSchema = {
3
3
  name: "create_deployment",
4
4
  description: "Create a new Kubernetes deployment",
@@ -17,6 +17,61 @@ export const createDeploymentSchema = {
17
17
  items: { type: "number" },
18
18
  optional: true,
19
19
  },
20
+ customConfig: {
21
+ type: "object",
22
+ optional: true,
23
+ properties: {
24
+ image: { type: "string" },
25
+ command: { type: "array", items: { type: "string" } },
26
+ args: { type: "array", items: { type: "string" } },
27
+ ports: {
28
+ type: "array",
29
+ items: {
30
+ type: "object",
31
+ properties: {
32
+ containerPort: { type: "number" },
33
+ name: { type: "string" },
34
+ protocol: { type: "string" },
35
+ },
36
+ },
37
+ },
38
+ resources: {
39
+ type: "object",
40
+ properties: {
41
+ limits: {
42
+ type: "object",
43
+ additionalProperties: { type: "string" },
44
+ },
45
+ requests: {
46
+ type: "object",
47
+ additionalProperties: { type: "string" },
48
+ },
49
+ },
50
+ },
51
+ env: {
52
+ type: "array",
53
+ items: {
54
+ type: "object",
55
+ properties: {
56
+ name: { type: "string" },
57
+ value: { type: "string" },
58
+ valueFrom: { type: "object" },
59
+ },
60
+ },
61
+ },
62
+ volumeMounts: {
63
+ type: "array",
64
+ items: {
65
+ type: "object",
66
+ properties: {
67
+ name: { type: "string" },
68
+ mountPath: { type: "string" },
69
+ readOnly: { type: "boolean" },
70
+ },
71
+ },
72
+ },
73
+ },
74
+ },
20
75
  },
21
76
  required: ["name", "namespace", "template"],
22
77
  },
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ import { listServices, listServicesSchema } from "./tools/list_services.js";
7
7
  import { listDeployments, listDeploymentsSchema, } from "./tools/list_deployments.js";
8
8
  import { installHelmChart, installHelmChartSchema, upgradeHelmChart, upgradeHelmChartSchema, uninstallHelmChart, uninstallHelmChartSchema, } from "./tools/helm-operations.js";
9
9
  import { explainResource, explainResourceSchema, listApiResources, listApiResourcesSchema, } from "./tools/kubectl-operations.js";
10
+ import { createNamespace, createNamespaceSchema, } from "./tools/create_namespace.js";
10
11
  import { createPod, createPodSchema } from "./tools/create_pod.js";
11
12
  import { deletePod, deletePodSchema } from "./tools/delete_pod.js";
12
13
  import { describePod, describePodSchema } from "./tools/describe_pod.js";
@@ -20,6 +21,10 @@ import { createDeploymentSchema } from "./config/deployment-config.js";
20
21
  import { listNamespacesSchema } from "./config/namespace-config.js";
21
22
  import { cleanupSchema } from "./config/cleanup-config.js";
22
23
  import { startSSEServer } from "./utils/sse.js";
24
+ import { startPortForward, PortForwardSchema, stopPortForward, StopPortForwardSchema, } from "./tools/port_forward.js";
25
+ import { deleteDeployment } from "./tools/delete_deployment.js";
26
+ import { createDeployment } from "./tools/create_deployment.js";
27
+ import { describeDeployment, describeDeploymentSchema, } from "./tools/describe_deployment.js";
23
28
  const k8sManager = new KubernetesManager();
24
29
  const server = new Server({
25
30
  name: serverConfig.name,
@@ -31,9 +36,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
31
36
  tools: [
32
37
  cleanupSchema,
33
38
  createDeploymentSchema,
39
+ createNamespaceSchema,
34
40
  createPodSchema,
35
41
  deletePodSchema,
36
42
  describePodSchema,
43
+ describeDeploymentSchema,
37
44
  explainResourceSchema,
38
45
  getEventsSchema,
39
46
  getLogsSchema,
@@ -46,6 +53,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
46
53
  listServicesSchema,
47
54
  uninstallHelmChartSchema,
48
55
  upgradeHelmChartSchema,
56
+ PortForwardSchema,
57
+ StopPortForwardSchema,
49
58
  ],
50
59
  };
51
60
  });
@@ -66,6 +75,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
66
75
  ],
67
76
  };
68
77
  }
78
+ case "create_namespace": {
79
+ return await createNamespace(k8sManager, input);
80
+ }
69
81
  case "create_pod": {
70
82
  return await createPod(k8sManager, input);
71
83
  }
@@ -124,6 +136,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
124
136
  case "upgrade_helm_chart": {
125
137
  return await upgradeHelmChart(input);
126
138
  }
139
+ case "port_forward": {
140
+ return await startPortForward(k8sManager, input);
141
+ }
142
+ case "stop_port_forward": {
143
+ return await stopPortForward(k8sManager, input);
144
+ }
145
+ case "delete_deployment": {
146
+ return await deleteDeployment(k8sManager, input);
147
+ }
148
+ case "create_deployment": {
149
+ return await createDeployment(k8sManager, input);
150
+ }
151
+ case "describe_deployment": {
152
+ return await describeDeployment(k8sManager, input);
153
+ }
127
154
  default:
128
155
  throw new McpError(ErrorCode.InvalidRequest, `Unknown tool: ${name}`);
129
156
  }
@@ -1,4 +1,26 @@
1
1
  import { z } from "zod";
2
+ export declare const CreateNamespaceResponseSchema: z.ZodObject<{
3
+ content: z.ZodArray<z.ZodObject<{
4
+ type: z.ZodLiteral<"text">;
5
+ text: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ type: "text";
8
+ text: string;
9
+ }, {
10
+ type: "text";
11
+ text: string;
12
+ }>, "many">;
13
+ }, "strip", z.ZodTypeAny, {
14
+ content: {
15
+ type: "text";
16
+ text: string;
17
+ }[];
18
+ }, {
19
+ content: {
20
+ type: "text";
21
+ text: string;
22
+ }[];
23
+ }>;
2
24
  export declare const CreatePodResponseSchema: z.ZodObject<{
3
25
  content: z.ZodArray<z.ZodObject<{
4
26
  type: z.ZodLiteral<"text">;
@@ -65,6 +87,28 @@ export declare const DeletePodResponseSchema: z.ZodObject<{
65
87
  text: string;
66
88
  }[];
67
89
  }>;
90
+ export declare const DeleteDeploymentResponseSchema: z.ZodObject<{
91
+ content: z.ZodArray<z.ZodObject<{
92
+ type: z.ZodLiteral<"text">;
93
+ text: z.ZodString;
94
+ }, "strip", z.ZodTypeAny, {
95
+ type: "text";
96
+ text: string;
97
+ }, {
98
+ type: "text";
99
+ text: string;
100
+ }>, "many">;
101
+ }, "strip", z.ZodTypeAny, {
102
+ content: {
103
+ type: "text";
104
+ text: string;
105
+ }[];
106
+ }, {
107
+ content: {
108
+ type: "text";
109
+ text: string;
110
+ }[];
111
+ }>;
68
112
  export declare const CleanupResponseSchema: z.ZodObject<{
69
113
  content: z.ZodArray<z.ZodObject<{
70
114
  type: z.ZodLiteral<"text">;
@@ -241,3 +285,25 @@ export declare const GetEventsResponseSchema: z.ZodObject<{
241
285
  text: string;
242
286
  }[];
243
287
  }>;
288
+ export declare const PortForwardResponseSchema: z.ZodObject<{
289
+ content: z.ZodArray<z.ZodObject<{
290
+ success: z.ZodBoolean;
291
+ message: z.ZodString;
292
+ }, "strip", z.ZodTypeAny, {
293
+ message: string;
294
+ success: boolean;
295
+ }, {
296
+ message: string;
297
+ success: boolean;
298
+ }>, "many">;
299
+ }, "strip", z.ZodTypeAny, {
300
+ content: {
301
+ message: string;
302
+ success: boolean;
303
+ }[];
304
+ }, {
305
+ content: {
306
+ message: string;
307
+ success: boolean;
308
+ }[];
309
+ }>;
@@ -4,6 +4,9 @@ const ToolResponseContent = z.object({
4
4
  type: z.literal("text"),
5
5
  text: z.string(),
6
6
  });
7
+ export const CreateNamespaceResponseSchema = z.object({
8
+ content: z.array(ToolResponseContent),
9
+ });
7
10
  export const CreatePodResponseSchema = z.object({
8
11
  content: z.array(ToolResponseContent),
9
12
  });
@@ -13,6 +16,9 @@ export const CreateDeploymentResponseSchema = z.object({
13
16
  export const DeletePodResponseSchema = z.object({
14
17
  content: z.array(ToolResponseContent),
15
18
  });
19
+ export const DeleteDeploymentResponseSchema = z.object({
20
+ content: z.array(ToolResponseContent),
21
+ });
16
22
  export const CleanupResponseSchema = z.object({
17
23
  content: z.array(ToolResponseContent),
18
24
  });
@@ -37,3 +43,9 @@ export const GetLogsResponseSchema = z.object({
37
43
  export const GetEventsResponseSchema = z.object({
38
44
  content: z.array(ToolResponseContent),
39
45
  });
46
+ export const PortForwardResponseSchema = z.object({
47
+ content: z.array(z.object({
48
+ success: z.boolean(),
49
+ message: z.string(),
50
+ })),
51
+ });