mcp-server-kubernetes 3.1.0 → 3.2.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/dist/index.d.ts CHANGED
@@ -145,7 +145,7 @@ declare const destructiveTools: ({
145
145
  default: string;
146
146
  };
147
147
  };
148
- readonly required: readonly ["resourceType", "name", "namespace"];
148
+ readonly required: readonly [];
149
149
  };
150
150
  })[];
151
151
  declare const allTools: ({
@@ -444,7 +444,7 @@ declare const allTools: ({
444
444
  default: string;
445
445
  };
446
446
  };
447
- readonly required: readonly ["resourceType", "name", "namespace"];
447
+ readonly required: readonly ["resourceType"];
448
448
  };
449
449
  } | {
450
450
  readonly name: "kubectl_describe";
@@ -575,7 +575,7 @@ declare const allTools: ({
575
575
  default: string;
576
576
  };
577
577
  };
578
- readonly required: readonly ["resourceType", "name", "namespace"];
578
+ readonly required: readonly [];
579
579
  };
580
580
  } | {
581
581
  readonly name: "kubectl_create";
@@ -53,7 +53,7 @@ export declare const kubectlDeleteSchema: {
53
53
  default: string;
54
54
  };
55
55
  };
56
- readonly required: readonly ["resourceType", "name", "namespace"];
56
+ readonly required: readonly [];
57
57
  };
58
58
  };
59
59
  export declare function kubectlDelete(k8sManager: KubernetesManager, input: {
@@ -51,7 +51,7 @@ export const kubectlDeleteSchema = {
51
51
  },
52
52
  context: contextParameter,
53
53
  },
54
- required: ["resourceType", "name", "namespace"],
54
+ required: [],
55
55
  },
56
56
  };
57
57
  export async function kubectlDelete(k8sManager, input) {
@@ -50,7 +50,7 @@ export declare const kubectlGetSchema: {
50
50
  default: string;
51
51
  };
52
52
  };
53
- readonly required: readonly ["resourceType", "name", "namespace"];
53
+ readonly required: readonly ["resourceType"];
54
54
  };
55
55
  };
56
56
  export declare function kubectlGet(k8sManager: KubernetesManager, input: {
@@ -46,7 +46,7 @@ export const kubectlGetSchema = {
46
46
  },
47
47
  context: contextParameter,
48
48
  },
49
- required: ["resourceType", "name", "namespace"],
49
+ required: ["resourceType"],
50
50
  },
51
51
  };
52
52
  export async function kubectlGet(k8sManager, input) {
@@ -0,0 +1,19 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ /**
3
+ * Authentication middleware for MCP HTTP transports.
4
+ *
5
+ * When the MCP_AUTH_TOKEN environment variable is set, this middleware
6
+ * requires all requests to include a matching X-MCP-AUTH header.
7
+ *
8
+ * This provides a simple authentication mechanism for securing MCP endpoints
9
+ * in cluster environments where full OAuth may be overkill.
10
+ *
11
+ * Example usage:
12
+ * Server: MCP_AUTH_TOKEN=my-secret-token
13
+ * Client: X-MCP-AUTH: my-secret-token
14
+ */
15
+ export declare function createAuthMiddleware(): (req: Request, res: Response, next: NextFunction) => void;
16
+ /**
17
+ * Returns whether authentication is enabled (MCP_AUTH_TOKEN is set)
18
+ */
19
+ export declare function isAuthEnabled(): boolean;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Authentication middleware for MCP HTTP transports.
3
+ *
4
+ * When the MCP_AUTH_TOKEN environment variable is set, this middleware
5
+ * requires all requests to include a matching X-MCP-AUTH header.
6
+ *
7
+ * This provides a simple authentication mechanism for securing MCP endpoints
8
+ * in cluster environments where full OAuth may be overkill.
9
+ *
10
+ * Example usage:
11
+ * Server: MCP_AUTH_TOKEN=my-secret-token
12
+ * Client: X-MCP-AUTH: my-secret-token
13
+ */
14
+ export function createAuthMiddleware() {
15
+ const authToken = process.env.MCP_AUTH_TOKEN;
16
+ return (req, res, next) => {
17
+ // If no auth token is configured, allow all requests
18
+ if (!authToken) {
19
+ next();
20
+ return;
21
+ }
22
+ const providedToken = req.headers["x-mcp-auth"];
23
+ if (!providedToken) {
24
+ res.status(401).json({
25
+ jsonrpc: "2.0",
26
+ error: {
27
+ code: -32001,
28
+ message: "Unauthorized: X-MCP-AUTH header is required",
29
+ },
30
+ id: null,
31
+ });
32
+ return;
33
+ }
34
+ if (providedToken !== authToken) {
35
+ res.status(403).json({
36
+ jsonrpc: "2.0",
37
+ error: {
38
+ code: -32002,
39
+ message: "Forbidden: Invalid authentication token",
40
+ },
41
+ id: null,
42
+ });
43
+ return;
44
+ }
45
+ next();
46
+ };
47
+ }
48
+ /**
49
+ * Returns whether authentication is enabled (MCP_AUTH_TOKEN is set)
50
+ */
51
+ export function isAuthEnabled() {
52
+ return !!process.env.MCP_AUTH_TOKEN;
53
+ }
package/dist/utils/sse.js CHANGED
@@ -1,16 +1,19 @@
1
1
  import express from "express";
2
2
  import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
3
+ import { createAuthMiddleware, isAuthEnabled } from "./auth.js";
3
4
  export function startSSEServer(server) {
4
5
  const app = express();
6
+ // Create auth middleware - when MCP_AUTH_TOKEN is set, requires X-MCP-AUTH header
7
+ const authMiddleware = createAuthMiddleware();
5
8
  // Currently just copying from docs & allowing for multiple transport connections: https://modelcontextprotocol.io/docs/concepts/transports#server-sent-events-sse
6
- // TODO: If exposed to web, then this will enable any client to connect to the server via http - so marked as UNSAFE until mcp has a proper auth solution.
9
+ // Note: When MCP_AUTH_TOKEN is set, requests require X-MCP-AUTH header for authentication
7
10
  let transports = [];
8
- app.get("/sse", async (req, res) => {
11
+ app.get("/sse", authMiddleware, async (req, res) => {
9
12
  const transport = new SSEServerTransport("/messages", res);
10
13
  transports.push(transport);
11
14
  await server.connect(transport);
12
15
  });
13
- app.post("/messages", (req, res) => {
16
+ app.post("/messages", authMiddleware, (req, res) => {
14
17
  const transport = transports.find((t) => t.sessionId === req.query.sessionId);
15
18
  if (transport) {
16
19
  transport.handlePostMessage(req, res);
@@ -51,6 +54,9 @@ export function startSSEServer(server) {
51
54
  }
52
55
  const host = process.env.HOST || "localhost";
53
56
  app.listen(port, host, () => {
54
- console.log(`mcp-kubernetes-server is listening on port ${port}\nUse the following url to connect to the server:\n\http://${host}:${port}/sse`);
57
+ console.log(`mcp-kubernetes-server is listening on port ${port}\nUse the following url to connect to the server:\nhttp://${host}:${port}/sse`);
58
+ if (isAuthEnabled()) {
59
+ console.log("Authentication enabled: X-MCP-AUTH header required for all MCP requests");
60
+ }
55
61
  });
56
62
  }
@@ -1,9 +1,12 @@
1
1
  import express from "express";
2
2
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3
+ import { createAuthMiddleware, isAuthEnabled } from "./auth.js";
3
4
  export function startStreamableHTTPServer(server) {
4
5
  const app = express();
5
6
  app.use(express.json());
6
- app.post("/mcp", async (req, res) => {
7
+ // Create auth middleware - when MCP_AUTH_TOKEN is set, requires X-MCP-AUTH header
8
+ const authMiddleware = createAuthMiddleware();
9
+ app.post("/mcp", authMiddleware, async (req, res) => {
7
10
  // In stateless mode, create a new instance of transport and server for each request
8
11
  // to ensure complete isolation. A single instance would cause request ID collisions
9
12
  // when multiple clients connect concurrently.
@@ -44,7 +47,7 @@ export function startStreamableHTTPServer(server) {
44
47
  }
45
48
  });
46
49
  // SSE notifications not supported in stateless mode
47
- app.get("/mcp", async (req, res) => {
50
+ app.get("/mcp", authMiddleware, async (req, res) => {
48
51
  console.log("Received GET MCP request");
49
52
  res.writeHead(405).end(JSON.stringify({
50
53
  jsonrpc: "2.0",
@@ -56,7 +59,7 @@ export function startStreamableHTTPServer(server) {
56
59
  }));
57
60
  });
58
61
  // Session termination not needed in stateless mode
59
- app.delete("/mcp", async (req, res) => {
62
+ app.delete("/mcp", authMiddleware, async (req, res) => {
60
63
  console.log("Received DELETE MCP request");
61
64
  res.writeHead(405).end(JSON.stringify({
62
65
  jsonrpc: "2.0",
@@ -98,6 +101,9 @@ export function startStreamableHTTPServer(server) {
98
101
  const host = process.env.HOST || "localhost";
99
102
  const httpServer = app.listen(port, host, () => {
100
103
  console.log(`mcp-kubernetes-server is listening on port ${port}\nUse the following url to connect to the server:\nhttp://${host}:${port}/mcp`);
104
+ if (isAuthEnabled()) {
105
+ console.log("Authentication enabled: X-MCP-AUTH header required for all MCP requests");
106
+ }
101
107
  });
102
108
  return httpServer;
103
109
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-server-kubernetes",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "MCP server for interacting with Kubernetes clusters via kubectl",
5
5
  "license": "MIT",
6
6
  "type": "module",