mcp-server-kubernetes 1.6.2 → 2.1.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.
Files changed (98) hide show
  1. package/README.md +46 -22
  2. package/dist/config/container-templates.d.ts +2 -2
  3. package/dist/index.d.ts +314 -736
  4. package/dist/index.js +93 -200
  5. package/dist/models/resource-models.d.ts +6 -6
  6. package/dist/tools/kubectl-apply.d.ts +46 -0
  7. package/dist/tools/kubectl-apply.js +110 -0
  8. package/dist/tools/kubectl-context.d.ts +49 -0
  9. package/dist/tools/kubectl-context.js +233 -0
  10. package/dist/tools/kubectl-create.d.ts +150 -0
  11. package/dist/tools/kubectl-create.js +321 -0
  12. package/dist/tools/kubectl-delete.d.ts +77 -0
  13. package/dist/tools/kubectl-delete.js +177 -0
  14. package/dist/tools/kubectl-describe.d.ts +47 -0
  15. package/dist/tools/kubectl-describe.js +96 -0
  16. package/dist/tools/kubectl-generic.d.ts +71 -0
  17. package/dist/tools/kubectl-generic.js +121 -0
  18. package/dist/tools/kubectl-get.d.ts +72 -0
  19. package/dist/tools/kubectl-get.js +251 -0
  20. package/dist/tools/kubectl-list.d.ts +61 -0
  21. package/dist/tools/kubectl-list.js +189 -0
  22. package/dist/tools/{get_logs.d.ts → kubectl-logs.d.ts} +35 -19
  23. package/dist/tools/kubectl-logs.js +312 -0
  24. package/dist/tools/kubectl-patch.d.ts +57 -0
  25. package/dist/tools/kubectl-patch.js +128 -0
  26. package/dist/tools/kubectl-rollout.d.ts +67 -0
  27. package/dist/tools/kubectl-rollout.js +115 -0
  28. package/dist/tools/{scale_deployment.d.ts → kubectl-scale.d.ts} +13 -3
  29. package/dist/tools/kubectl-scale.js +73 -0
  30. package/dist/utils/kubernetes-manager.d.ts +4 -0
  31. package/dist/utils/kubernetes-manager.js +21 -3
  32. package/package.json +1 -1
  33. package/dist/tools/create_configmap.d.ts +0 -33
  34. package/dist/tools/create_configmap.js +0 -66
  35. package/dist/tools/create_cronjob.d.ts +0 -47
  36. package/dist/tools/create_cronjob.js +0 -93
  37. package/dist/tools/create_deployment.d.ts +0 -135
  38. package/dist/tools/create_deployment.js +0 -162
  39. package/dist/tools/create_namespace.d.ts +0 -22
  40. package/dist/tools/create_namespace.js +0 -48
  41. package/dist/tools/create_pod.d.ts +0 -130
  42. package/dist/tools/create_pod.js +0 -153
  43. package/dist/tools/create_service.d.ts +0 -74
  44. package/dist/tools/create_service.js +0 -102
  45. package/dist/tools/delete_configmap.d.ts +0 -26
  46. package/dist/tools/delete_configmap.js +0 -49
  47. package/dist/tools/delete_cronjob.d.ts +0 -26
  48. package/dist/tools/delete_cronjob.js +0 -48
  49. package/dist/tools/delete_deployment.d.ts +0 -31
  50. package/dist/tools/delete_deployment.js +0 -47
  51. package/dist/tools/delete_namespace.d.ts +0 -27
  52. package/dist/tools/delete_namespace.js +0 -44
  53. package/dist/tools/delete_pod.d.ts +0 -31
  54. package/dist/tools/delete_pod.js +0 -45
  55. package/dist/tools/delete_service.d.ts +0 -32
  56. package/dist/tools/delete_service.js +0 -46
  57. package/dist/tools/describe_cronjob.d.ts +0 -27
  58. package/dist/tools/describe_cronjob.js +0 -83
  59. package/dist/tools/describe_deployment.d.ts +0 -26
  60. package/dist/tools/describe_deployment.js +0 -40
  61. package/dist/tools/describe_node.d.ts +0 -22
  62. package/dist/tools/describe_node.js +0 -84
  63. package/dist/tools/describe_pod.d.ts +0 -33
  64. package/dist/tools/describe_pod.js +0 -81
  65. package/dist/tools/describe_service.d.ts +0 -34
  66. package/dist/tools/describe_service.js +0 -85
  67. package/dist/tools/get_configmap.d.ts +0 -27
  68. package/dist/tools/get_configmap.js +0 -48
  69. package/dist/tools/get_current_context.d.ts +0 -23
  70. package/dist/tools/get_current_context.js +0 -55
  71. package/dist/tools/get_events.d.ts +0 -28
  72. package/dist/tools/get_events.js +0 -66
  73. package/dist/tools/get_job_logs.d.ts +0 -40
  74. package/dist/tools/get_job_logs.js +0 -104
  75. package/dist/tools/get_logs.js +0 -150
  76. package/dist/tools/list_contexts.d.ts +0 -23
  77. package/dist/tools/list_contexts.js +0 -39
  78. package/dist/tools/list_cronjobs.d.ts +0 -23
  79. package/dist/tools/list_cronjobs.js +0 -35
  80. package/dist/tools/list_deployments.d.ts +0 -23
  81. package/dist/tools/list_deployments.js +0 -30
  82. package/dist/tools/list_jobs.d.ts +0 -29
  83. package/dist/tools/list_jobs.js +0 -77
  84. package/dist/tools/list_nodes.d.ts +0 -15
  85. package/dist/tools/list_nodes.js +0 -21
  86. package/dist/tools/list_pods.d.ts +0 -23
  87. package/dist/tools/list_pods.js +0 -29
  88. package/dist/tools/list_services.d.ts +0 -23
  89. package/dist/tools/list_services.js +0 -31
  90. package/dist/tools/scale_deployment.js +0 -50
  91. package/dist/tools/set_current_context.d.ts +0 -23
  92. package/dist/tools/set_current_context.js +0 -35
  93. package/dist/tools/update_configmap.d.ts +0 -33
  94. package/dist/tools/update_configmap.js +0 -71
  95. package/dist/tools/update_deployment.d.ts +0 -113
  96. package/dist/tools/update_deployment.js +0 -155
  97. package/dist/tools/update_service.d.ts +0 -72
  98. package/dist/tools/update_service.js +0 -125
@@ -0,0 +1,321 @@
1
+ import { execSync } from "child_process";
2
+ import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
3
+ import * as fs from "fs";
4
+ import * as path from "path";
5
+ import * as os from "os";
6
+ export const kubectlCreateSchema = {
7
+ name: "kubectl_create",
8
+ description: "Create Kubernetes resources using various methods (from file or using subcommands)",
9
+ inputSchema: {
10
+ type: "object",
11
+ properties: {
12
+ // General options
13
+ dryRun: {
14
+ type: "boolean",
15
+ description: "If true, only validate the resource, don't actually create it",
16
+ default: false
17
+ },
18
+ output: {
19
+ type: "string",
20
+ enum: ["json", "yaml", "name", "go-template", "go-template-file", "template", "templatefile", "jsonpath", "jsonpath-as-json", "jsonpath-file"],
21
+ description: "Output format. One of: json|yaml|name|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-as-json|jsonpath-file",
22
+ default: "yaml"
23
+ },
24
+ validate: {
25
+ type: "boolean",
26
+ description: "If true, validate resource schema against server schema",
27
+ default: true
28
+ },
29
+ // Create from file method
30
+ manifest: {
31
+ type: "string",
32
+ description: "YAML manifest to create resources from"
33
+ },
34
+ filename: {
35
+ type: "string",
36
+ description: "Path to a YAML file to create resources from"
37
+ },
38
+ // Resource type to create (determines which subcommand to use)
39
+ resourceType: {
40
+ type: "string",
41
+ description: "Type of resource to create (namespace, configmap, deployment, service, etc.)"
42
+ },
43
+ // Common parameters for most resource types
44
+ name: {
45
+ type: "string",
46
+ description: "Name of the resource to create"
47
+ },
48
+ namespace: {
49
+ type: "string",
50
+ description: "Namespace to create the resource in",
51
+ default: "default"
52
+ },
53
+ // ConfigMap specific parameters
54
+ fromLiteral: {
55
+ type: "array",
56
+ items: { type: "string" },
57
+ description: "Key-value pair for creating configmap (e.g. [\"key1=value1\", \"key2=value2\"])"
58
+ },
59
+ fromFile: {
60
+ type: "array",
61
+ items: { type: "string" },
62
+ description: "Path to file for creating configmap (e.g. [\"key1=/path/to/file1\", \"key2=/path/to/file2\"])"
63
+ },
64
+ // Namespace specific parameters
65
+ // No special parameters for namespace, just name is needed
66
+ // Secret specific parameters
67
+ secretType: {
68
+ type: "string",
69
+ enum: ["generic", "docker-registry", "tls"],
70
+ description: "Type of secret to create (generic, docker-registry, tls)"
71
+ },
72
+ // Service specific parameters
73
+ serviceType: {
74
+ type: "string",
75
+ enum: ["clusterip", "nodeport", "loadbalancer", "externalname"],
76
+ description: "Type of service to create (clusterip, nodeport, loadbalancer, externalname)"
77
+ },
78
+ tcpPort: {
79
+ type: "array",
80
+ items: { type: "string" },
81
+ description: "Port pairs for tcp service (e.g. [\"80:8080\", \"443:8443\"])"
82
+ },
83
+ // Deployment specific parameters
84
+ image: {
85
+ type: "string",
86
+ description: "Image to use for the containers in the deployment"
87
+ },
88
+ replicas: {
89
+ type: "number",
90
+ description: "Number of replicas to create for the deployment",
91
+ default: 1
92
+ },
93
+ port: {
94
+ type: "number",
95
+ description: "Port that the container exposes"
96
+ },
97
+ // CronJob specific parameters
98
+ schedule: {
99
+ type: "string",
100
+ description: "Cron schedule expression for the CronJob (e.g. \"*/5 * * * *\")"
101
+ },
102
+ suspend: {
103
+ type: "boolean",
104
+ description: "Whether to suspend the CronJob",
105
+ default: false
106
+ },
107
+ // Job specific parameters
108
+ command: {
109
+ type: "array",
110
+ items: { type: "string" },
111
+ description: "Command to run in the container"
112
+ },
113
+ // Additional common parameters
114
+ labels: {
115
+ type: "array",
116
+ items: { type: "string" },
117
+ description: "Labels to apply to the resource (e.g. [\"key1=value1\", \"key2=value2\"])"
118
+ },
119
+ annotations: {
120
+ type: "array",
121
+ items: { type: "string" },
122
+ description: "Annotations to apply to the resource (e.g. [\"key1=value1\", \"key2=value2\"])"
123
+ }
124
+ },
125
+ required: [],
126
+ },
127
+ };
128
+ export async function kubectlCreate(k8sManager, input) {
129
+ try {
130
+ // Check if we have enough information to proceed
131
+ if (!input.manifest && !input.filename && !input.resourceType) {
132
+ throw new McpError(ErrorCode.InvalidRequest, "Either manifest, filename, or resourceType must be provided");
133
+ }
134
+ // If resourceType is provided, check if name is provided for most resource types
135
+ if (input.resourceType && !input.name && input.resourceType !== "namespace") {
136
+ throw new McpError(ErrorCode.InvalidRequest, `Name is required when creating a ${input.resourceType}`);
137
+ }
138
+ // Set up common parameters
139
+ const namespace = input.namespace || "default";
140
+ const dryRun = input.dryRun || false;
141
+ const validate = input.validate ?? true;
142
+ const output = input.output || "yaml";
143
+ let command = "kubectl create";
144
+ let tempFile = null;
145
+ // Process manifest content if provided (file-based creation)
146
+ if (input.manifest || input.filename) {
147
+ if (input.manifest) {
148
+ // Create temporary file for the manifest
149
+ const tmpDir = os.tmpdir();
150
+ tempFile = path.join(tmpDir, `create-manifest-${Date.now()}.yaml`);
151
+ fs.writeFileSync(tempFile, input.manifest);
152
+ command += ` -f ${tempFile}`;
153
+ }
154
+ else if (input.filename) {
155
+ command += ` -f ${input.filename}`;
156
+ }
157
+ }
158
+ else {
159
+ // Process subcommand-based creation
160
+ switch (input.resourceType?.toLowerCase()) {
161
+ case "namespace":
162
+ command += ` namespace ${input.name}`;
163
+ break;
164
+ case "configmap":
165
+ command += ` configmap ${input.name}`;
166
+ // Add --from-literal arguments
167
+ if (input.fromLiteral && input.fromLiteral.length > 0) {
168
+ input.fromLiteral.forEach(literal => {
169
+ command += ` --from-literal=${literal}`;
170
+ });
171
+ }
172
+ // Add --from-file arguments
173
+ if (input.fromFile && input.fromFile.length > 0) {
174
+ input.fromFile.forEach(file => {
175
+ command += ` --from-file=${file}`;
176
+ });
177
+ }
178
+ break;
179
+ case "secret":
180
+ if (!input.secretType) {
181
+ throw new McpError(ErrorCode.InvalidRequest, "secretType is required when creating a secret");
182
+ }
183
+ command += ` secret ${input.secretType} ${input.name}`;
184
+ // Add --from-literal arguments
185
+ if (input.fromLiteral && input.fromLiteral.length > 0) {
186
+ input.fromLiteral.forEach(literal => {
187
+ command += ` --from-literal=${literal}`;
188
+ });
189
+ }
190
+ // Add --from-file arguments
191
+ if (input.fromFile && input.fromFile.length > 0) {
192
+ input.fromFile.forEach(file => {
193
+ command += ` --from-file=${file}`;
194
+ });
195
+ }
196
+ break;
197
+ case "service":
198
+ if (!input.serviceType) {
199
+ // Default to clusterip if not specified
200
+ input.serviceType = "clusterip";
201
+ }
202
+ command += ` service ${input.serviceType} ${input.name}`;
203
+ // Add --tcp arguments for ports
204
+ if (input.tcpPort && input.tcpPort.length > 0) {
205
+ input.tcpPort.forEach(port => {
206
+ command += ` --tcp=${port}`;
207
+ });
208
+ }
209
+ break;
210
+ case "cronjob":
211
+ if (!input.image) {
212
+ throw new McpError(ErrorCode.InvalidRequest, "image is required when creating a cronjob");
213
+ }
214
+ if (!input.schedule) {
215
+ throw new McpError(ErrorCode.InvalidRequest, "schedule is required when creating a cronjob");
216
+ }
217
+ command += ` cronjob ${input.name} --image=${input.image} --schedule="${input.schedule}"`;
218
+ // Add command if specified
219
+ if (input.command && input.command.length > 0) {
220
+ command += ` -- ${input.command.join(" ")}`;
221
+ }
222
+ // Add suspend flag if specified
223
+ if (input.suspend === true) {
224
+ command += ` --suspend`;
225
+ }
226
+ break;
227
+ case "deployment":
228
+ if (!input.image) {
229
+ throw new McpError(ErrorCode.InvalidRequest, "image is required when creating a deployment");
230
+ }
231
+ command += ` deployment ${input.name} --image=${input.image}`;
232
+ // Add replicas if specified
233
+ if (input.replicas) {
234
+ command += ` --replicas=${input.replicas}`;
235
+ }
236
+ // Add port if specified
237
+ if (input.port) {
238
+ command += ` --port=${input.port}`;
239
+ }
240
+ break;
241
+ case "job":
242
+ if (!input.image) {
243
+ throw new McpError(ErrorCode.InvalidRequest, "image is required when creating a job");
244
+ }
245
+ command += ` job ${input.name} --image=${input.image}`;
246
+ // Add command if specified
247
+ if (input.command && input.command.length > 0) {
248
+ command += ` -- ${input.command.join(" ")}`;
249
+ }
250
+ break;
251
+ default:
252
+ throw new McpError(ErrorCode.InvalidRequest, `Unsupported resource type: ${input.resourceType}`);
253
+ }
254
+ }
255
+ // Add namespace if not creating a namespace itself
256
+ if (input.resourceType !== "namespace") {
257
+ command += ` -n ${namespace}`;
258
+ }
259
+ // Add labels if specified
260
+ if (input.labels && input.labels.length > 0) {
261
+ input.labels.forEach(label => {
262
+ command += ` -l ${label}`;
263
+ });
264
+ }
265
+ // Add annotations if specified
266
+ if (input.annotations && input.annotations.length > 0) {
267
+ input.annotations.forEach(annotation => {
268
+ command += ` --annotation=${annotation}`;
269
+ });
270
+ }
271
+ // Add dry-run flag if requested
272
+ if (dryRun) {
273
+ command += " --dry-run=client";
274
+ }
275
+ // Add validate flag if needed
276
+ if (!validate) {
277
+ command += " --validate=false";
278
+ }
279
+ // Add output format
280
+ command += ` -o ${output}`;
281
+ // Execute the command
282
+ try {
283
+ const result = execSync(command, { encoding: "utf8" });
284
+ // Clean up temp file if created
285
+ if (tempFile) {
286
+ try {
287
+ fs.unlinkSync(tempFile);
288
+ }
289
+ catch (err) {
290
+ console.warn(`Failed to delete temporary file ${tempFile}: ${err}`);
291
+ }
292
+ }
293
+ return {
294
+ content: [
295
+ {
296
+ type: "text",
297
+ text: result,
298
+ },
299
+ ],
300
+ };
301
+ }
302
+ catch (error) {
303
+ // Clean up temp file if created, even if command failed
304
+ if (tempFile) {
305
+ try {
306
+ fs.unlinkSync(tempFile);
307
+ }
308
+ catch (err) {
309
+ console.warn(`Failed to delete temporary file ${tempFile}: ${err}`);
310
+ }
311
+ }
312
+ throw new McpError(ErrorCode.InternalError, `Failed to create resource: ${error.message}`);
313
+ }
314
+ }
315
+ catch (error) {
316
+ if (error instanceof McpError) {
317
+ throw error;
318
+ }
319
+ throw new McpError(ErrorCode.InternalError, `Failed to execute kubectl create command: ${error.message}`);
320
+ }
321
+ }
@@ -0,0 +1,77 @@
1
+ import { KubernetesManager } from "../types.js";
2
+ export declare const kubectlDeleteSchema: {
3
+ readonly name: "kubectl_delete";
4
+ readonly description: "Delete Kubernetes resources by resource type, name, labels, or from a manifest file";
5
+ readonly inputSchema: {
6
+ readonly type: "object";
7
+ readonly properties: {
8
+ readonly resourceType: {
9
+ readonly type: "string";
10
+ readonly description: "Type of resource to delete (e.g., pods, deployments, services, etc.)";
11
+ };
12
+ readonly name: {
13
+ readonly type: "string";
14
+ readonly description: "Name of the resource to delete";
15
+ };
16
+ readonly namespace: {
17
+ readonly type: "string";
18
+ readonly description: "Namespace of the resource (optional - defaults to 'default' for namespaced resources)";
19
+ readonly default: "default";
20
+ };
21
+ readonly labelSelector: {
22
+ readonly type: "string";
23
+ readonly description: "Delete resources matching this label selector (e.g. 'app=nginx')";
24
+ readonly optional: true;
25
+ };
26
+ readonly manifest: {
27
+ readonly type: "string";
28
+ readonly description: "YAML manifest defining resources to delete (optional)";
29
+ readonly optional: true;
30
+ };
31
+ readonly filename: {
32
+ readonly type: "string";
33
+ readonly description: "Path to a YAML file to delete resources from (optional)";
34
+ readonly optional: true;
35
+ };
36
+ readonly allNamespaces: {
37
+ readonly type: "boolean";
38
+ readonly description: "If true, delete resources across all namespaces";
39
+ readonly default: false;
40
+ };
41
+ readonly force: {
42
+ readonly type: "boolean";
43
+ readonly description: "If true, immediately remove resources from API and bypass graceful deletion";
44
+ readonly default: false;
45
+ };
46
+ readonly gracePeriodSeconds: {
47
+ readonly type: "number";
48
+ readonly description: "Period of time in seconds given to the resource to terminate gracefully";
49
+ readonly optional: true;
50
+ };
51
+ };
52
+ readonly required: readonly [];
53
+ };
54
+ };
55
+ export declare function kubectlDelete(k8sManager: KubernetesManager, input: {
56
+ resourceType?: string;
57
+ name?: string;
58
+ namespace?: string;
59
+ labelSelector?: string;
60
+ manifest?: string;
61
+ filename?: string;
62
+ allNamespaces?: boolean;
63
+ force?: boolean;
64
+ gracePeriodSeconds?: number;
65
+ }): Promise<{
66
+ content: {
67
+ type: string;
68
+ text: string;
69
+ }[];
70
+ isError?: undefined;
71
+ } | {
72
+ content: {
73
+ type: string;
74
+ text: string;
75
+ }[];
76
+ isError: boolean;
77
+ }>;
@@ -0,0 +1,177 @@
1
+ import { execSync } from "child_process";
2
+ import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
3
+ import * as fs from "fs";
4
+ import * as path from "path";
5
+ import * as os from "os";
6
+ export const kubectlDeleteSchema = {
7
+ name: "kubectl_delete",
8
+ description: "Delete Kubernetes resources by resource type, name, labels, or from a manifest file",
9
+ inputSchema: {
10
+ type: "object",
11
+ properties: {
12
+ resourceType: {
13
+ type: "string",
14
+ description: "Type of resource to delete (e.g., pods, deployments, services, etc.)"
15
+ },
16
+ name: {
17
+ type: "string",
18
+ description: "Name of the resource to delete"
19
+ },
20
+ namespace: {
21
+ type: "string",
22
+ description: "Namespace of the resource (optional - defaults to 'default' for namespaced resources)",
23
+ default: "default"
24
+ },
25
+ labelSelector: {
26
+ type: "string",
27
+ description: "Delete resources matching this label selector (e.g. 'app=nginx')",
28
+ optional: true
29
+ },
30
+ manifest: {
31
+ type: "string",
32
+ description: "YAML manifest defining resources to delete (optional)",
33
+ optional: true
34
+ },
35
+ filename: {
36
+ type: "string",
37
+ description: "Path to a YAML file to delete resources from (optional)",
38
+ optional: true
39
+ },
40
+ allNamespaces: {
41
+ type: "boolean",
42
+ description: "If true, delete resources across all namespaces",
43
+ default: false
44
+ },
45
+ force: {
46
+ type: "boolean",
47
+ description: "If true, immediately remove resources from API and bypass graceful deletion",
48
+ default: false
49
+ },
50
+ gracePeriodSeconds: {
51
+ type: "number",
52
+ description: "Period of time in seconds given to the resource to terminate gracefully",
53
+ optional: true
54
+ }
55
+ },
56
+ required: [],
57
+ },
58
+ };
59
+ export async function kubectlDelete(k8sManager, input) {
60
+ try {
61
+ // Validate input - need at least one way to identify resources
62
+ if (!input.resourceType && !input.manifest && !input.filename) {
63
+ throw new McpError(ErrorCode.InvalidRequest, "Either resourceType, manifest, or filename must be provided");
64
+ }
65
+ // If resourceType is provided, need either name or labelSelector
66
+ if (input.resourceType && !input.name && !input.labelSelector) {
67
+ throw new McpError(ErrorCode.InvalidRequest, "When using resourceType, either name or labelSelector must be provided");
68
+ }
69
+ const namespace = input.namespace || "default";
70
+ const allNamespaces = input.allNamespaces || false;
71
+ const force = input.force || false;
72
+ let command = "kubectl delete";
73
+ let tempFile = null;
74
+ // Handle deleting from manifest or file
75
+ if (input.manifest) {
76
+ // Create temporary file for the manifest
77
+ const tmpDir = os.tmpdir();
78
+ tempFile = path.join(tmpDir, `delete-manifest-${Date.now()}.yaml`);
79
+ fs.writeFileSync(tempFile, input.manifest);
80
+ command += ` -f ${tempFile}`;
81
+ }
82
+ else if (input.filename) {
83
+ command += ` -f ${input.filename}`;
84
+ }
85
+ else {
86
+ // Handle deleting by resource type and name/selector
87
+ command += ` ${input.resourceType}`;
88
+ if (input.name) {
89
+ command += ` ${input.name}`;
90
+ }
91
+ if (input.labelSelector) {
92
+ command += ` -l ${input.labelSelector}`;
93
+ }
94
+ }
95
+ // Add namespace flags
96
+ if (allNamespaces) {
97
+ command += " --all-namespaces";
98
+ }
99
+ else if (namespace && input.resourceType && !isNonNamespacedResource(input.resourceType)) {
100
+ command += ` -n ${namespace}`;
101
+ }
102
+ // Add force flag if requested
103
+ if (force) {
104
+ command += " --force";
105
+ }
106
+ // Add grace period if specified
107
+ if (input.gracePeriodSeconds !== undefined) {
108
+ command += ` --grace-period=${input.gracePeriodSeconds}`;
109
+ }
110
+ // Execute the command
111
+ try {
112
+ const result = execSync(command, { encoding: "utf8" });
113
+ // Clean up temp file if created
114
+ if (tempFile) {
115
+ try {
116
+ fs.unlinkSync(tempFile);
117
+ }
118
+ catch (err) {
119
+ console.warn(`Failed to delete temporary file ${tempFile}: ${err}`);
120
+ }
121
+ }
122
+ return {
123
+ content: [
124
+ {
125
+ type: "text",
126
+ text: result,
127
+ },
128
+ ],
129
+ };
130
+ }
131
+ catch (error) {
132
+ // Clean up temp file if created, even if command failed
133
+ if (tempFile) {
134
+ try {
135
+ fs.unlinkSync(tempFile);
136
+ }
137
+ catch (err) {
138
+ console.warn(`Failed to delete temporary file ${tempFile}: ${err}`);
139
+ }
140
+ }
141
+ if (error.status === 404 || error.message.includes("not found")) {
142
+ return {
143
+ content: [
144
+ {
145
+ type: "text",
146
+ text: JSON.stringify({
147
+ error: `Resource not found`,
148
+ status: "not_found",
149
+ }, null, 2),
150
+ },
151
+ ],
152
+ isError: true,
153
+ };
154
+ }
155
+ throw new McpError(ErrorCode.InternalError, `Failed to delete resource: ${error.message}`);
156
+ }
157
+ }
158
+ catch (error) {
159
+ if (error instanceof McpError) {
160
+ throw error;
161
+ }
162
+ throw new McpError(ErrorCode.InternalError, `Failed to execute kubectl delete command: ${error.message}`);
163
+ }
164
+ }
165
+ // Helper function to determine if a resource is non-namespaced
166
+ function isNonNamespacedResource(resourceType) {
167
+ const nonNamespacedResources = [
168
+ "nodes", "node", "no",
169
+ "namespaces", "namespace", "ns",
170
+ "persistentvolumes", "pv",
171
+ "storageclasses", "sc",
172
+ "clusterroles",
173
+ "clusterrolebindings",
174
+ "customresourcedefinitions", "crd", "crds"
175
+ ];
176
+ return nonNamespacedResources.includes(resourceType.toLowerCase());
177
+ }
@@ -0,0 +1,47 @@
1
+ import { KubernetesManager } from "../types.js";
2
+ export declare const kubectlDescribeSchema: {
3
+ readonly name: "kubectl_describe";
4
+ readonly description: "Describe Kubernetes resources by resource type, name, and optionally namespace";
5
+ readonly inputSchema: {
6
+ readonly type: "object";
7
+ readonly properties: {
8
+ readonly resourceType: {
9
+ readonly type: "string";
10
+ readonly description: "Type of resource to describe (e.g., pods, deployments, services, etc.)";
11
+ };
12
+ readonly name: {
13
+ readonly type: "string";
14
+ readonly description: "Name of the resource to describe";
15
+ };
16
+ readonly namespace: {
17
+ readonly type: "string";
18
+ readonly description: "Namespace of the resource (optional - defaults to 'default' for namespaced resources)";
19
+ readonly default: "default";
20
+ };
21
+ readonly allNamespaces: {
22
+ readonly type: "boolean";
23
+ readonly description: "If true, describe resources across all namespaces";
24
+ readonly default: false;
25
+ };
26
+ };
27
+ readonly required: readonly ["resourceType", "name"];
28
+ };
29
+ };
30
+ export declare function kubectlDescribe(k8sManager: KubernetesManager, input: {
31
+ resourceType: string;
32
+ name: string;
33
+ namespace?: string;
34
+ allNamespaces?: boolean;
35
+ }): Promise<{
36
+ content: {
37
+ type: string;
38
+ text: string;
39
+ }[];
40
+ isError?: undefined;
41
+ } | {
42
+ content: {
43
+ type: string;
44
+ text: string;
45
+ }[];
46
+ isError: boolean;
47
+ }>;