From b30c8ef8bf0ccad9eb7cb707ca7d7c22d85cb5d2 Mon Sep 17 00:00:00 2001 From: Will-hxw <1176843521@qq.com> Date: Tue, 21 Apr 2026 04:33:48 +0800 Subject: [PATCH 1/4] fix(everything): require key parameter for get-env tool Prevent leaking all process.env variables by requiring a specific key. This addresses a security concern where the tool was returning the entire environment without any parameter or filtering. Issue: modelcontextprotocol/servers#3986 Co-Authored-By: Claude Opus 4.7 --- src/everything/tools/get-env.ts | 34 ++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/everything/tools/get-env.ts b/src/everything/tools/get-env.ts index 0adbf5a14d..2cc387c733 100644 --- a/src/everything/tools/get-env.ts +++ b/src/everything/tools/get-env.ts @@ -6,26 +6,50 @@ const name = "get-env"; const config = { title: "Print Environment Tool", description: - "Returns all environment variables, helpful for debugging MCP server configuration", - inputSchema: {}, + "Returns the value of a specific environment variable, helpful for debugging MCP server configuration", + inputSchema: { + type: "object", + properties: { + key: { + type: "string", + description: + "The name of the environment variable to retrieve (e.g., 'PATH', 'HOME', 'USER')", + }, + }, + required: ["key"], + }, }; /** * Registers the 'get-env' tool. * - * The registered tool Retrieves and returns the environment variables - * of the current process as a JSON-formatted string encapsulated in a text response. + * The registered tool retrieves and returns the value of a specific + * environment variable from the current process. * * @param {McpServer} server - The McpServer instance where the tool will be registered. * @returns {void} */ export const registerGetEnvTool = (server: McpServer) => { server.registerTool(name, config, async (args): Promise => { + const { key } = args as { key: string }; + const value = process.env[key]; + + if (value === undefined) { + return { + content: [ + { + type: "text", + text: `Environment variable '${key}' is not set.`, + }, + ], + }; + } + return { content: [ { type: "text", - text: JSON.stringify(process.env, null, 2), + text: `${key}=${value}`, }, ], }; From 0533f88e947f0d899cd2f5db765c07d45dd67317 Mon Sep 17 00:00:00 2001 From: Will-hxw Date: Fri, 24 Apr 2026 20:40:51 +0800 Subject: [PATCH 2/4] fix(everything): use Zod schema for get-env inputSchema The get-env tool was failing TypeScript strict mode checks because the inputSchema was declared as a plain object with 'type: string' instead of a Zod schema. This causes the type checker to reject the argument. Fixes TypeScript errors: - TS2345: inputSchema type not assignable to parameter type - TS7006: Parameter 'args' implicitly has an 'any' type --- src/everything/tools/get-env.ts | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/everything/tools/get-env.ts b/src/everything/tools/get-env.ts index 2cc387c733..abe93919d4 100644 --- a/src/everything/tools/get-env.ts +++ b/src/everything/tools/get-env.ts @@ -1,5 +1,13 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { z } from "zod"; + +// Tool input schema +export const GetEnvSchema = z.object({ + key: z.string().describe( + "The name of the environment variable to retrieve (e.g., 'PATH', 'HOME', 'USER')", + ), +}); // Tool configuration const name = "get-env"; @@ -7,17 +15,7 @@ const config = { title: "Print Environment Tool", description: "Returns the value of a specific environment variable, helpful for debugging MCP server configuration", - inputSchema: { - type: "object", - properties: { - key: { - type: "string", - description: - "The name of the environment variable to retrieve (e.g., 'PATH', 'HOME', 'USER')", - }, - }, - required: ["key"], - }, + inputSchema: GetEnvSchema, }; /** @@ -31,7 +29,7 @@ const config = { */ export const registerGetEnvTool = (server: McpServer) => { server.registerTool(name, config, async (args): Promise => { - const { key } = args as { key: string }; + const { key } = GetEnvSchema.parse(args); const value = process.env[key]; if (value === undefined) { From 752e4f946688bb89eafdc38ae51c2dc0cf971814 Mon Sep 17 00:00:00 2001 From: Will-hxw Date: Fri, 24 Apr 2026 20:44:23 +0800 Subject: [PATCH 3/4] test(everything): update get-env tests to pass required key parameter The get-env tool now requires a 'key' parameter. Updated tests to pass { key: 'TEST_VAR_EVERYTHING' } and { key: 'PATH' } instead of empty object {}. --- src/everything/__tests__/tools.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/everything/__tests__/tools.test.ts b/src/everything/__tests__/tools.test.ts index dbe463b2a5..7316111049 100644 --- a/src/everything/__tests__/tools.test.ts +++ b/src/everything/__tests__/tools.test.ts @@ -157,7 +157,7 @@ describe('Tools', () => { const handler = handlers.get('get-env')!; process.env.TEST_VAR_EVERYTHING = 'test_value'; - const result = await handler({}); + const result = await handler({ key: 'TEST_VAR_EVERYTHING' }); expect(result.content).toHaveLength(1); expect(result.content[0].type).toBe('text'); @@ -173,7 +173,7 @@ describe('Tools', () => { registerGetEnvTool(mockServer); const handler = handlers.get('get-env')!; - const result = await handler({}); + const result = await handler({ key: 'PATH' }); expect(() => JSON.parse(result.content[0].text)).not.toThrow(); }); From e02b42bff3ccd4cd7d035691576839d0aa42d837 Mon Sep 17 00:00:00 2001 From: Will-hxw Date: Fri, 24 Apr 2026 20:47:27 +0800 Subject: [PATCH 4/4] test(everything): fix get-env tests to match actual output format The get-env tool returns 'KEY=value' format, not JSON. Updated assertions accordingly. --- src/everything/__tests__/tools.test.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/everything/__tests__/tools.test.ts b/src/everything/__tests__/tools.test.ts index 7316111049..88778a1d2a 100644 --- a/src/everything/__tests__/tools.test.ts +++ b/src/everything/__tests__/tools.test.ts @@ -162,20 +162,22 @@ describe('Tools', () => { expect(result.content).toHaveLength(1); expect(result.content[0].type).toBe('text'); - const envJson = JSON.parse(result.content[0].text); - expect(envJson.TEST_VAR_EVERYTHING).toBe('test_value'); + const text = result.content[0].text; + expect(text).toBe('TEST_VAR_EVERYTHING=test_value'); delete process.env.TEST_VAR_EVERYTHING; }); - it('should return valid JSON', async () => { + it('should return valid output', async () => { const { mockServer, handlers } = createMockServer(); registerGetEnvTool(mockServer); const handler = handlers.get('get-env')!; const result = await handler({ key: 'PATH' }); - expect(() => JSON.parse(result.content[0].text)).not.toThrow(); + expect(result.content).toHaveLength(1); + expect(result.content[0].type).toBe('text'); + expect(result.content[0].text).toMatch(/^PATH=/); }); });