mcp-server-kubernetes 2.0.0 → 2.1.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.
package/README.md CHANGED
@@ -175,6 +175,25 @@ For Claude Desktop configuration with non-destructive mode:
175
175
  }
176
176
  ```
177
177
 
178
+ ### Commands Available in Non-Destructive Mode
179
+
180
+ All read-only and resource creation/update operations remain available:
181
+
182
+ - Resource Information: `kubectl_get`, `kubectl_describe`, `kubectl_list`, `kubectl_logs`, `explain_resource`, `list_api_resources`
183
+ - Resource Creation/Modification: `kubectl_apply`, `kubectl_create`, `kubectl_scale`, `kubectl_patch`, `kubectl_rollout`
184
+ - Helm Operations: `install_helm_chart`, `upgrade_helm_chart`
185
+ - Connectivity: `port_forward`, `stop_port_forward`
186
+ - Context Management: `kubectl_context`
187
+
188
+ ### Commands Disabled in Non-Destructive Mode
189
+
190
+ The following destructive operations are disabled:
191
+
192
+ - `kubectl_delete`: Deleting any Kubernetes resources
193
+ - `uninstall_helm_chart`: Uninstalling Helm charts
194
+ - `cleanup`: Cleanup of managed resources
195
+ - `kubectl_generic`: General kubectl command access (may include destructive operations)
196
+
178
197
  For additional advanced features, see the [ADVANCED_README.md](ADVANCED_README.md).
179
198
 
180
199
  ## Architecture
@@ -190,19 +209,34 @@ The sequence diagram below illustrates how requests flow through the system:
190
209
  ```mermaid
191
210
  sequenceDiagram
192
211
  participant Client
193
- participant Transport as StdioTransport
212
+ participant Transport as Transport Layer
194
213
  participant Server as MCP Server
214
+ participant Filter as Tool Filter
195
215
  participant Handler as Request Handler
196
216
  participant K8sManager as KubernetesManager
197
217
  participant K8s as Kubernetes API
198
218
 
199
- Client->>Transport: Send Request via STDIO
219
+ Note over Transport: StdioTransport or<br>SSE Transport
220
+
221
+ Client->>Transport: Send Request
200
222
  Transport->>Server: Forward Request
201
223
 
202
224
  alt Tools Request
203
- Server->>Handler: Route to tools handler
204
- Handler->>K8sManager: Execute kubectl operation
205
- K8sManager->>K8s: Make API call
225
+ Server->>Filter: Filter available tools
226
+ Note over Filter: Remove destructive tools<br>if in non-destructive mode
227
+ Filter->>Handler: Route to tools handler
228
+
229
+ alt kubectl operations
230
+ Handler->>K8sManager: Execute kubectl operation
231
+ K8sManager->>K8s: Make API call
232
+ else Helm operations
233
+ Handler->>K8sManager: Execute Helm operation
234
+ K8sManager->>K8s: Make API call
235
+ else Port Forward operations
236
+ Handler->>K8sManager: Set up port forwarding
237
+ K8sManager->>K8s: Make API call
238
+ end
239
+
206
240
  K8s-->>K8sManager: Return result
207
241
  K8sManager-->>Handler: Process response
208
242
  Handler-->>Server: Return tool result
@@ -219,6 +253,8 @@ sequenceDiagram
219
253
  Transport-->>Client: Return Final Response
220
254
  ```
221
255
 
256
+ See this [DeepWiki link](https://deepwiki.com/Flux159/mcp-server-kubernetes) for a more indepth architecture overview created by Devin.
257
+
222
258
  ## Publishing new release
223
259
 
224
260
  Go to the [releases page](https://github.com/Flux159/mcp-server-kubernetes/releases), click on "Draft New Release", click "Choose a tag" and create a new tag by typing out a new version number using "v{major}.{minor}.{patch}" semver format. Then, write a release title "Release v{major}.{minor}.{patch}" and description / changelog if necessary and click "Publish Release".
@@ -227,4 +263,4 @@ This will create a new tag which will trigger a new release build via the cd.yml
227
263
 
228
264
  ## Not planned
229
265
 
230
- Authentication / adding clusters to kubectx.
266
+ Adding clusters to kubectx.
package/dist/index.js CHANGED
@@ -29,6 +29,7 @@ const destructiveTools = [
29
29
  kubectlDeleteSchema, // This replaces all individual delete operations
30
30
  uninstallHelmChartSchema,
31
31
  cleanupSchema, // Cleanup is also destructive as it deletes resources
32
+ kubectlGenericSchema, // Generic kubectl command can perform destructive operations
32
33
  ];
33
34
  // Get all available tools
34
35
  const allTools = [
@@ -181,7 +182,7 @@ if (process.env.ENABLE_UNSAFE_SSE_TRANSPORT) {
181
182
  }
182
183
  else {
183
184
  const transport = new StdioServerTransport();
184
- console.log(`Starting Kubernetes MCP server v${serverConfig.version}, handling commands...`);
185
+ console.error(`Starting Kubernetes MCP server v${serverConfig.version}, handling commands...`);
185
186
  server.connect(transport);
186
187
  }
187
188
  ["SIGINT", "SIGTERM"].forEach((signal) => {
@@ -97,7 +97,7 @@ export async function kubectlGeneric(k8sManager, input) {
97
97
  // Execute the command (join all args except the first "kubectl" which is used in execSync)
98
98
  const command = cmdArgs.slice(1).join(' ');
99
99
  try {
100
- console.log(`Executing: kubectl ${command}`);
100
+ console.error(`Executing: kubectl ${command}`);
101
101
  const result = execSync(`kubectl ${command}`, { encoding: "utf8" });
102
102
  return {
103
103
  content: [
@@ -9,6 +9,10 @@ export declare class KubernetesManager {
9
9
  private k8sAppsApi;
10
10
  private k8sBatchApi;
11
11
  constructor();
12
+ /**
13
+ * A very simple test to check if the application is running inside a Kubernetes cluster
14
+ */
15
+ private isRunningInCluster;
12
16
  /**
13
17
  * Set the current context to the desired context name.
14
18
  *
@@ -1,4 +1,5 @@
1
1
  import * as k8s from "@kubernetes/client-node";
2
+ import * as fs from "fs";
2
3
  export class KubernetesManager {
3
4
  resources = [];
4
5
  portForwards = [];
@@ -9,11 +10,28 @@ export class KubernetesManager {
9
10
  k8sBatchApi;
10
11
  constructor() {
11
12
  this.kc = new k8s.KubeConfig();
12
- this.kc.loadFromDefault();
13
+ if (this.isRunningInCluster()) {
14
+ this.kc.loadFromCluster();
15
+ }
16
+ else {
17
+ this.kc.loadFromDefault();
18
+ }
13
19
  this.k8sApi = this.kc.makeApiClient(k8s.CoreV1Api);
14
20
  this.k8sAppsApi = this.kc.makeApiClient(k8s.AppsV1Api);
15
21
  this.k8sBatchApi = this.kc.makeApiClient(k8s.BatchV1Api);
16
22
  }
23
+ /**
24
+ * A very simple test to check if the application is running inside a Kubernetes cluster
25
+ */
26
+ isRunningInCluster() {
27
+ const serviceAccountPath = "/var/run/secrets/kubernetes.io/serviceaccount/token";
28
+ try {
29
+ return fs.existsSync(serviceAccountPath);
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
17
35
  /**
18
36
  * Set the current context to the desired context name.
19
37
  *
@@ -22,10 +40,10 @@ export class KubernetesManager {
22
40
  setCurrentContext(contextName) {
23
41
  // Get all available contexts
24
42
  const contexts = this.kc.getContexts();
25
- const contextNames = contexts.map(context => context.name);
43
+ const contextNames = contexts.map((context) => context.name);
26
44
  // Check if the requested context exists
27
45
  if (!contextNames.includes(contextName)) {
28
- throw new Error(`Context '${contextName}' not found. Available contexts: ${contextNames.join(', ')}`);
46
+ throw new Error(`Context '${contextName}' not found. Available contexts: ${contextNames.join(", ")}`);
29
47
  }
30
48
  // Set the current context
31
49
  this.kc.setCurrentContext(contextName);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-server-kubernetes",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "description": "MCP server for interacting with Kubernetes clusters via kubectl",
5
5
  "license": "MIT",
6
6
  "type": "module",