From cee615d00145bcd1742ffa315bcb9df22fed137d Mon Sep 17 00:00:00 2001 From: Lubrsy706 Date: Fri, 15 May 2026 03:18:27 +0800 Subject: [PATCH] fix(everything): limit get-env to one key --- src/everything/__tests__/tools.test.ts | 26 +++++++++++++++++---- src/everything/docs/features.md | 2 +- src/everything/docs/structure.md | 2 +- src/everything/tools/get-env.ts | 31 +++++++++++++++++++++----- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/everything/__tests__/tools.test.ts b/src/everything/__tests__/tools.test.ts index dbe463b2a5..6a56ea53b1 100644 --- a/src/everything/__tests__/tools.test.ts +++ b/src/everything/__tests__/tools.test.ts @@ -151,29 +151,47 @@ describe('Tools', () => { }); describe('get-env', () => { - it('should return all environment variables as JSON', async () => { + it('should return a single environment variable as JSON', async () => { const { mockServer, handlers } = createMockServer(); registerGetEnvTool(mockServer); 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'); const envJson = JSON.parse(result.content[0].text); - expect(envJson.TEST_VAR_EVERYTHING).toBe('test_value'); + expect(envJson).toEqual({ + key: 'TEST_VAR_EVERYTHING', + value: 'test_value', + found: true, + }); delete process.env.TEST_VAR_EVERYTHING; }); + it('should return null for missing environment variables', async () => { + const { mockServer, handlers } = createMockServer(); + registerGetEnvTool(mockServer); + + const handler = handlers.get('get-env')!; + const result = await handler({ key: 'TEST_VAR_EVERYTHING_MISSING' }); + + expect(JSON.parse(result.content[0].text)).toEqual({ + key: 'TEST_VAR_EVERYTHING_MISSING', + value: null, + found: false, + }); + }); + it('should return valid JSON', async () => { const { mockServer, handlers } = createMockServer(); 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(); }); diff --git a/src/everything/docs/features.md b/src/everything/docs/features.md index 145595b820..8146e5c30b 100644 --- a/src/everything/docs/features.md +++ b/src/everything/docs/features.md @@ -11,7 +11,7 @@ - `echo` (tools/echo.ts): Echoes the provided `message: string`. Uses Zod to validate inputs. - `get-annotated-message` (tools/get-annotated-message.ts): Returns a `text` message annotated with `priority` and `audience` based on `messageType` (`error`, `success`, or `debug`); can optionally include an annotated `image`. -- `get-env` (tools/get-env.ts): Returns all environment variables from the running process as pretty-printed JSON text. +- `get-env` (tools/get-env.ts): Returns one requested environment variable from the running process as pretty-printed JSON text. - `get-resource-links` (tools/get-resource-links.ts): Returns an intro `text` block followed by multiple `resource_link` items. For a requested `count` (1–10), alternates between dynamic Text and Blob resources using URIs from `resources/templates.ts`. - `get-resource-reference` (tools/get-resource-reference.ts): Accepts `resourceType` (`text` or `blob`) and `resourceId` (positive integer). Returns a concrete `resource` content block (with its `uri`, `mimeType`, and data) with surrounding explanatory `text`. - `get-roots-list` (tools/get-roots-list.ts): Returns the last list of roots sent by the client. diff --git a/src/everything/docs/structure.md b/src/everything/docs/structure.md index 6bcedcd425..b62761453b 100644 --- a/src/everything/docs/structure.md +++ b/src/everything/docs/structure.md @@ -131,7 +131,7 @@ src/everything - `get-annotated-message.ts` - Registers an `annotated-message` tool which demonstrates annotated content items by emitting a primary `text` message with `annotations` that vary by `messageType` (`"error" | "success" | "debug"`), and optionally includes an annotated `image` (tiny PNG) when `includeImage` is true. - `get-env.ts` - - Registers a `get-env` tool that returns the current process environment variables as formatted JSON text; useful for debugging configuration. + - Registers a `get-env` tool that returns one requested environment variable as formatted JSON text; useful for debugging configuration without dumping the full process environment. - `get-resource-links.ts` - Registers a `get-resource-links` tool that returns an intro `text` block followed by multiple `resource_link` items. - `get-resource-reference.ts` diff --git a/src/everything/tools/get-env.ts b/src/everything/tools/get-env.ts index 0adbf5a14d..43278f8b6a 100644 --- a/src/everything/tools/get-env.ts +++ b/src/everything/tools/get-env.ts @@ -1,31 +1,52 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; +import { z } from "zod"; // Tool configuration const name = "get-env"; +const GetEnvSchema = { + key: z + .string() + .min(1) + .describe("Name of the single environment variable to read."), +}; const config = { title: "Print Environment Tool", description: - "Returns all environment variables, helpful for debugging MCP server configuration", - inputSchema: {}, + "Returns a single environment variable by name, helpful for debugging MCP server configuration without dumping the full process environment.", + inputSchema: GetEnvSchema, + annotations: { + readOnlyHint: true, + }, }; /** * 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 a single environment variable + * from the current process as a JSON-formatted string encapsulated in a text response. * * @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.key; + const value = process.env[key]; + return { content: [ { type: "text", - text: JSON.stringify(process.env, null, 2), + text: JSON.stringify( + { + key, + value: value ?? null, + found: value !== undefined, + }, + null, + 2 + ), }, ], };