Skip to main content
Glama
env-resolution.it.test.ts7.02 kB
import { resetEnv } from "../src/env.js"; import { TargetServer } from "../src/model/target-servers.js"; import { TESTKIT_SERVER_ENV_READER } from "../src/testkit/root.js"; import { getTestHarness } from "./utils.js"; const TEST_SECRET_VALUE = "super-secret-value-12345"; const TEST_ENV_VAR_NAME = "IT_TEST_SECRET_FOR_FROM_ENV"; const MISSING_ENV_VAR_NAME = "IT_TEST_MISSING_ENV_VAR_THAT_DOES_NOT_EXIST"; const INHERITED_ENV_VAR_NAME = "IT_TEST_INHERITED_VAR"; const INHERITED_ENV_VALUE = "inherited-value-xyz"; const OVERRIDE_VAR_NAME = "IT_TEST_OVERRIDE_VAR"; const OVERRIDE_PROCESS_VALUE = "from-process-env"; const OVERRIDE_EXPLICIT_VALUE = "from-explicit-config"; const envReaderWithFromEnv: TargetServer = { type: "stdio", name: "env-reader-fromenv", command: "node", args: [TESTKIT_SERVER_ENV_READER], env: { MY_SECRET: { fromEnv: TEST_ENV_VAR_NAME }, DIRECT_VALUE: "direct-string-value", }, }; const envReaderWithMissingVar: TargetServer = { type: "stdio", name: "env-reader-missing", command: "node", args: [TESTKIT_SERVER_ENV_READER], env: { MISSING_VAR: { fromEnv: MISSING_ENV_VAR_NAME }, PRESENT_VAR: "i-am-present", }, }; const envReaderMinimal: TargetServer = { type: "stdio", name: "env-reader-minimal", command: "node", args: [TESTKIT_SERVER_ENV_READER], env: { EXPLICIT_ONLY: "explicit-value", [OVERRIDE_VAR_NAME]: OVERRIDE_EXPLICIT_VALUE, }, }; describe("fromEnv Resolution (STDIO_INHERIT_PROCESS_ENV=false)", () => { const originalEnv = process.env[TEST_ENV_VAR_NAME]; const originalInheritedEnv = process.env[INHERITED_ENV_VAR_NAME]; beforeAll(() => { process.env[TEST_ENV_VAR_NAME] = TEST_SECRET_VALUE; process.env[INHERITED_ENV_VAR_NAME] = INHERITED_ENV_VALUE; delete process.env[MISSING_ENV_VAR_NAME]; process.env["STDIO_INHERIT_PROCESS_ENV"] = "false"; resetEnv(); }); afterAll(() => { if (originalEnv !== undefined) { process.env[TEST_ENV_VAR_NAME] = originalEnv; } else { delete process.env[TEST_ENV_VAR_NAME]; } if (originalInheritedEnv !== undefined) { process.env[INHERITED_ENV_VAR_NAME] = originalInheritedEnv; } else { delete process.env[INHERITED_ENV_VAR_NAME]; } }); describe("fromEnv resolution", () => { const testHarness = getTestHarness({ targetServers: [envReaderWithFromEnv, envReaderWithMissingVar], }); beforeAll(async () => { await testHarness.initialize("StreamableHTTP"); }); afterAll(async () => { await testHarness.shutdown(); }); it("resolves fromEnv reference to actual env value at spawn time", async () => { const result = await testHarness.client.callTool({ name: "env-reader-fromenv__getEnv", arguments: { name: "MY_SECRET" }, }); expect(result.content).toEqual([ { type: "text", text: TEST_SECRET_VALUE }, ]); }); it("passes through direct string env values unchanged", async () => { const result = await testHarness.client.callTool({ name: "env-reader-fromenv__getEnv", arguments: { name: "DIRECT_VALUE" }, }); expect(result.content).toEqual([ { type: "text", text: "direct-string-value" }, ]); }); it("skips env var when fromEnv reference is not found (server still starts)", async () => { const result = await testHarness.client.callTool({ name: "env-reader-missing__getEnv", arguments: { name: "MISSING_VAR" }, }); expect(result.content).toEqual([ { type: "text", text: "ENV_NOT_FOUND:MISSING_VAR" }, ]); }); it("still passes other env vars when one is missing", async () => { const result = await testHarness.client.callTool({ name: "env-reader-missing__getEnv", arguments: { name: "PRESENT_VAR" }, }); expect(result.content).toEqual([{ type: "text", text: "i-am-present" }]); }); }); describe("process.env isolation", () => { const testHarness = getTestHarness({ targetServers: [envReaderMinimal], }); beforeAll(async () => { await testHarness.initialize("StreamableHTTP"); }); afterAll(async () => { await testHarness.shutdown(); }); it("does NOT inherit parent process.env vars when STDIO_INHERIT_PROCESS_ENV=false", async () => { const result = await testHarness.client.callTool({ name: "env-reader-minimal__getEnv", arguments: { name: INHERITED_ENV_VAR_NAME }, }); expect(result.content).toEqual([ { type: "text", text: `ENV_NOT_FOUND:${INHERITED_ENV_VAR_NAME}` }, ]); }); it("still receives explicitly configured env vars", async () => { const result = await testHarness.client.callTool({ name: "env-reader-minimal__getEnv", arguments: { name: "EXPLICIT_ONLY" }, }); expect(result.content).toEqual([ { type: "text", text: "explicit-value" }, ]); }); }); }); describe("process.env inheritance (STDIO_INHERIT_PROCESS_ENV=true)", () => { const originalInheritedEnv = process.env[INHERITED_ENV_VAR_NAME]; const originalOverrideEnv = process.env[OVERRIDE_VAR_NAME]; beforeAll(() => { process.env[INHERITED_ENV_VAR_NAME] = INHERITED_ENV_VALUE; process.env[OVERRIDE_VAR_NAME] = OVERRIDE_PROCESS_VALUE; process.env["STDIO_INHERIT_PROCESS_ENV"] = "true"; resetEnv(); }); afterAll(() => { if (originalInheritedEnv !== undefined) { process.env[INHERITED_ENV_VAR_NAME] = originalInheritedEnv; } else { delete process.env[INHERITED_ENV_VAR_NAME]; } if (originalOverrideEnv !== undefined) { process.env[OVERRIDE_VAR_NAME] = originalOverrideEnv; } else { delete process.env[OVERRIDE_VAR_NAME]; } // Reset back to default process.env["STDIO_INHERIT_PROCESS_ENV"] = "false"; resetEnv(); }); const testHarness = getTestHarness({ targetServers: [envReaderMinimal], }); beforeAll(async () => { await testHarness.initialize("StreamableHTTP"); }); afterAll(async () => { await testHarness.shutdown(); }); it("inherits parent process.env vars when STDIO_INHERIT_PROCESS_ENV=true", async () => { const result = await testHarness.client.callTool({ name: "env-reader-minimal__getEnv", arguments: { name: INHERITED_ENV_VAR_NAME }, }); expect(result.content).toEqual([ { type: "text", text: INHERITED_ENV_VALUE }, ]); }); it("explicit env vars override inherited ones", async () => { // process.env has OVERRIDE_VAR_NAME = "from-process-env" // but explicit config has OVERRIDE_VAR_NAME = "from-explicit-config" // child should see the explicit value, not the inherited one const result = await testHarness.client.callTool({ name: "env-reader-minimal__getEnv", arguments: { name: OVERRIDE_VAR_NAME }, }); expect(result.content).toEqual([ { type: "text", text: OVERRIDE_EXPLICIT_VALUE }, ]); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TheLunarCompany/lunar'

If you have feedback or need assistance with the MCP directory API, please join our Discord server