mcp-server-kubernetes 2.3.0 → 2.3.1

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.
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import * as k8s from "@kubernetes/client-node";
2
+ import type { V1Container } from "@kubernetes/client-node";
3
3
  export declare const ContainerTemplate: z.ZodEnum<["ubuntu", "nginx", "busybox", "alpine", "custom"]>;
4
4
  export type ContainerTemplateName = z.infer<typeof ContainerTemplate>;
5
5
  export declare const CustomContainerConfig: z.ZodObject<{
@@ -103,4 +103,4 @@ export declare const CustomContainerConfig: z.ZodObject<{
103
103
  }[] | undefined;
104
104
  }>;
105
105
  export type CustomContainerConfigType = z.infer<typeof CustomContainerConfig>;
106
- export declare const containerTemplates: Record<string, k8s.V1Container>;
106
+ export declare const containerTemplates: Record<string, V1Container>;
package/dist/index.js CHANGED
@@ -11,22 +11,22 @@ import { cleanupSchema } from "./config/cleanup-config.js";
11
11
  import { startSSEServer } from "./utils/sse.js";
12
12
  import { startPortForward, PortForwardSchema, stopPortForward, StopPortForwardSchema, } from "./tools/port_forward.js";
13
13
  import { kubectlScale, kubectlScaleSchema } from "./tools/kubectl-scale.js";
14
- import { kubectlContext, kubectlContextSchema } from "./tools/kubectl-context.js";
14
+ import { kubectlContext, kubectlContextSchema, } from "./tools/kubectl-context.js";
15
15
  import { kubectlGet, kubectlGetSchema } from "./tools/kubectl-get.js";
16
- import { kubectlDescribe, kubectlDescribeSchema } from "./tools/kubectl-describe.js";
16
+ import { kubectlDescribe, kubectlDescribeSchema, } from "./tools/kubectl-describe.js";
17
17
  import { kubectlList, kubectlListSchema } from "./tools/kubectl-list.js";
18
18
  import { kubectlApply, kubectlApplySchema } from "./tools/kubectl-apply.js";
19
19
  import { kubectlDelete, kubectlDeleteSchema } from "./tools/kubectl-delete.js";
20
20
  import { kubectlCreate, kubectlCreateSchema } from "./tools/kubectl-create.js";
21
21
  import { kubectlLogs, kubectlLogsSchema } from "./tools/kubectl-logs.js";
22
- import { kubectlGeneric, kubectlGenericSchema } from "./tools/kubectl-generic.js";
22
+ import { kubectlGeneric, kubectlGenericSchema, } from "./tools/kubectl-generic.js";
23
23
  import { kubectlPatch, kubectlPatchSchema } from "./tools/kubectl-patch.js";
24
- import { kubectlRollout, kubectlRolloutSchema } from "./tools/kubectl-rollout.js";
24
+ import { kubectlRollout, kubectlRolloutSchema, } from "./tools/kubectl-rollout.js";
25
25
  // Check if non-destructive tools only mode is enabled
26
26
  const nonDestructiveTools = process.env.ALLOW_ONLY_NON_DESTRUCTIVE_TOOLS === "true";
27
27
  // Define destructive tools (delete and uninstall operations)
28
28
  const destructiveTools = [
29
- kubectlDeleteSchema, // This replaces all individual delete operations
29
+ kubectlDeleteSchema, // This replaces all individual delete operations
30
30
  uninstallHelmChartSchema,
31
31
  cleanupSchema, // Cleanup is also destructive as it deletes resources
32
32
  kubectlGenericSchema, // Generic kubectl command can perform destructive operations
@@ -123,7 +123,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
123
123
  fieldSelector: input.fieldSelector,
124
124
  labelSelector: input.labelSelector,
125
125
  sortBy: input.sortBy,
126
- output: input.output
126
+ output: input.output,
127
127
  });
128
128
  }
129
129
  // Handle specific non-kubectl operations
@@ -44,13 +44,13 @@ export const getResourceHandlers = (k8sManager) => ({
44
44
  const isNodes = parts[0] === "nodes";
45
45
  if ((isNamespaces || isNodes) && parts.length === 1) {
46
46
  const fn = isNodes ? "listNode" : "listNamespace";
47
- const { body } = await k8sManager.getCoreApi()[fn]();
47
+ const { items } = await k8sManager.getCoreApi()[fn]();
48
48
  return {
49
49
  contents: [
50
50
  {
51
51
  uri: request.params.uri,
52
52
  mimeType: "application/json",
53
- text: JSON.stringify(body.items, null, 2),
53
+ text: JSON.stringify(items, null, 2),
54
54
  },
55
55
  ],
56
56
  };
@@ -58,43 +58,43 @@ export const getResourceHandlers = (k8sManager) => ({
58
58
  const [namespace, resourceType] = parts;
59
59
  switch (resourceType) {
60
60
  case "pods": {
61
- const { body } = await k8sManager
61
+ const { items } = await k8sManager
62
62
  .getCoreApi()
63
- .listNamespacedPod(namespace);
63
+ .listNamespacedPod({ namespace });
64
64
  return {
65
65
  contents: [
66
66
  {
67
67
  uri: request.params.uri,
68
68
  mimeType: "application/json",
69
- text: JSON.stringify(body.items, null, 2),
69
+ text: JSON.stringify(items, null, 2),
70
70
  },
71
71
  ],
72
72
  };
73
73
  }
74
74
  case "deployments": {
75
- const { body } = await k8sManager
75
+ const { items } = await k8sManager
76
76
  .getAppsApi()
77
- .listNamespacedDeployment(namespace);
77
+ .listNamespacedDeployment({ namespace });
78
78
  return {
79
79
  contents: [
80
80
  {
81
81
  uri: request.params.uri,
82
82
  mimeType: "application/json",
83
- text: JSON.stringify(body.items, null, 2),
83
+ text: JSON.stringify(items, null, 2),
84
84
  },
85
85
  ],
86
86
  };
87
87
  }
88
88
  case "services": {
89
- const { body } = await k8sManager
89
+ const { items } = await k8sManager
90
90
  .getCoreApi()
91
- .listNamespacedService(namespace);
91
+ .listNamespacedService({ namespace });
92
92
  return {
93
93
  contents: [
94
94
  {
95
95
  uri: request.params.uri,
96
96
  mimeType: "application/json",
97
- text: JSON.stringify(body.items, null, 2),
97
+ text: JSON.stringify(items, null, 2),
98
98
  },
99
99
  ],
100
100
  };
@@ -8,43 +8,43 @@ export const kubectlGetSchema = {
8
8
  properties: {
9
9
  resourceType: {
10
10
  type: "string",
11
- description: "Type of resource to get (e.g., pods, deployments, services, configmaps, events, etc.)"
11
+ description: "Type of resource to get (e.g., pods, deployments, services, configmaps, events, etc.)",
12
12
  },
13
13
  name: {
14
14
  type: "string",
15
- description: "Name of the resource (optional - if not provided, lists all resources of the specified type)"
15
+ description: "Name of the resource (optional - if not provided, lists all resources of the specified type)",
16
16
  },
17
17
  namespace: {
18
18
  type: "string",
19
19
  description: "Namespace of the resource (optional - defaults to 'default' for namespaced resources)",
20
- default: "default"
20
+ default: "default",
21
21
  },
22
22
  output: {
23
23
  type: "string",
24
24
  enum: ["json", "yaml", "wide", "name", "custom"],
25
25
  description: "Output format",
26
- default: "json"
26
+ default: "json",
27
27
  },
28
28
  allNamespaces: {
29
29
  type: "boolean",
30
30
  description: "If true, list resources across all namespaces",
31
- default: false
31
+ default: false,
32
32
  },
33
33
  labelSelector: {
34
34
  type: "string",
35
35
  description: "Filter resources by label selector (e.g. 'app=nginx')",
36
- optional: true
36
+ optional: true,
37
37
  },
38
38
  fieldSelector: {
39
39
  type: "string",
40
40
  description: "Filter resources by field selector (e.g. 'metadata.name=my-pod')",
41
- optional: true
41
+ optional: true,
42
42
  },
43
43
  sortBy: {
44
44
  type: "string",
45
45
  description: "Sort events by a field (default: lastTimestamp). Only applicable for events.",
46
- optional: true
47
- }
46
+ optional: true,
47
+ },
48
48
  },
49
49
  required: ["resourceType"],
50
50
  },
@@ -68,8 +68,11 @@ export async function kubectlGet(k8sManager, input) {
68
68
  command += ` ${name}`;
69
69
  }
70
70
  // For events, default to all namespaces unless explicitly specified
71
- const shouldShowAllNamespaces = resourceType === "events" ?
72
- (input.namespace ? false : true) : allNamespaces;
71
+ const shouldShowAllNamespaces = resourceType === "events"
72
+ ? input.namespace
73
+ ? false
74
+ : true
75
+ : allNamespaces;
73
76
  // Add namespace flag unless all namespaces is specified
74
77
  if (shouldShowAllNamespaces) {
75
78
  command += " --all-namespaces";
@@ -115,7 +118,10 @@ export async function kubectlGet(k8sManager, input) {
115
118
  }
116
119
  // Execute the command
117
120
  try {
118
- const result = execSync(command, { encoding: "utf8", env: { ...process.env, KUBECONFIG: process.env.KUBECONFIG } });
121
+ const result = execSync(command, {
122
+ encoding: "utf8",
123
+ env: { ...process.env, KUBECONFIG: process.env.KUBECONFIG },
124
+ });
119
125
  // Format the results for better readability
120
126
  const isListOperation = !name;
121
127
  if (isListOperation && output === "json") {
@@ -152,7 +158,7 @@ export async function kubectlGet(k8sManager, input) {
152
158
  namespace: item.metadata?.namespace || "",
153
159
  kind: item.kind || resourceType,
154
160
  status: getResourceStatus(item),
155
- createdAt: item.metadata?.creationTimestamp
161
+ createdAt: item.metadata?.creationTimestamp,
156
162
  }));
157
163
  return {
158
164
  content: [
@@ -239,13 +245,21 @@ function getResourceStatus(resource) {
239
245
  // Helper function to determine if a resource is non-namespaced
240
246
  function isNonNamespacedResource(resourceType) {
241
247
  const nonNamespacedResources = [
242
- "nodes", "node", "no",
243
- "namespaces", "namespace", "ns",
244
- "persistentvolumes", "pv",
245
- "storageclasses", "sc",
248
+ "nodes",
249
+ "node",
250
+ "no",
251
+ "namespaces",
252
+ "namespace",
253
+ "ns",
254
+ "persistentvolumes",
255
+ "pv",
256
+ "storageclasses",
257
+ "sc",
246
258
  "clusterroles",
247
259
  "clusterrolebindings",
248
- "customresourcedefinitions", "crd", "crds"
260
+ "customresourcedefinitions",
261
+ "crd",
262
+ "crds",
249
263
  ];
250
264
  return nonNamespacedResources.includes(resourceType.toLowerCase());
251
265
  }
@@ -217,16 +217,16 @@ export class KubernetesManager {
217
217
  async deleteResource(kind, name, namespace) {
218
218
  switch (kind.toLowerCase()) {
219
219
  case "pod":
220
- await this.k8sApi.deleteNamespacedPod(name, namespace);
220
+ await this.k8sApi.deleteNamespacedPod({ name, namespace });
221
221
  break;
222
222
  case "deployment":
223
- await this.k8sAppsApi.deleteNamespacedDeployment(name, namespace);
223
+ await this.k8sAppsApi.deleteNamespacedDeployment({ name, namespace });
224
224
  break;
225
225
  case "service":
226
- await this.k8sApi.deleteNamespacedService(name, namespace);
226
+ await this.k8sApi.deleteNamespacedService({ name, namespace });
227
227
  break;
228
228
  case "cronjob":
229
- await this.k8sBatchApi.deleteNamespacedCronJob(name, namespace);
229
+ await this.k8sBatchApi.deleteNamespacedCronJob({ name, namespace });
230
230
  break;
231
231
  }
232
232
  this.resources = this.resources.filter((r) => !(r.kind === kind && r.name === name && r.namespace === namespace));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-server-kubernetes",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "description": "MCP server for interacting with Kubernetes clusters via kubectl",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  "node": ">=18"
36
36
  },
37
37
  "dependencies": {
38
- "@kubernetes/client-node": "0.20.0",
38
+ "@kubernetes/client-node": "1.3.0",
39
39
  "@modelcontextprotocol/sdk": "1.7.0",
40
40
  "express": "4.21.2",
41
41
  "js-yaml": "4.1.0",
@@ -49,10 +49,5 @@
49
49
  "shx": "0.3.4",
50
50
  "typescript": "5.6.2",
51
51
  "vitest": "2.1.9"
52
- },
53
- "overrides": {
54
- "@kubernetes/client-node": {
55
- "jsonpath-plus": "^10.3.0"
56
- }
57
52
  }
58
53
  }