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
|
|
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
|
-
|
|
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->>
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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);
|