Skip to content

Fix MCP env vars: send envValueMode direct across all SDKs#484

Merged
SteveSandersonMS merged 5 commits intomainfrom
stevesa/mcp-env-vars-fix
Feb 17, 2026
Merged

Fix MCP env vars: send envValueMode direct across all SDKs#484
SteveSandersonMS merged 5 commits intomainfrom
stevesa/mcp-env-vars-fix

Conversation

@SteveSandersonMS
Copy link
Contributor

@SteveSandersonMS SteveSandersonMS commented Feb 16, 2026

Fixes #163
Fixes #444

Problem

When SDK users configure MCP servers with literal environment variable values (e.g., env: { TEST_SECRET: "hunter2" }), the values are silently dropped. This is because the runtime's default indirect mode treats env values as names of environment variables to look up from process.env, not as literal values.

Solution

All four SDKs now send envValueMode: "direct" in session create and resume requests, telling the runtime to treat env values as literal strings.

Depends on runtime PR: https://github.com/github/copilot-agent-runtime/pull/3307

THIS PR WILL FAIL IN CI UNTIL WE GET THE RUNTIME THAT INCLUDES THE FIX

Copilot AI review requested due to automatic review settings February 16, 2026 14:16
@SteveSandersonMS SteveSandersonMS requested a review from a team as a code owner February 16, 2026 14:16
{
Type = "local",
Command = "node",
Args = [Path.Combine(testHarnessDir, "test-mcp-server.mjs")],
var dir = new DirectoryInfo(AppContext.BaseDirectory);
while (dir != null)
{
var candidate = Path.Combine(dir.FullName, "test", "harness", "test-mcp-server.mjs");
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request fixes an issue where literal environment variable values configured for MCP servers were being silently dropped. The fix ensures that all four SDKs (Node.js, Python, Go, and .NET) send envValueMode: "direct" unconditionally in session create and resume requests, which instructs the Copilot CLI runtime to treat env values as literal strings rather than as environment variable names to look up.

Changes:

  • Added envValueMode: "direct" to session create and resume requests across all four SDKs
  • Created test infrastructure including a minimal MCP server that echoes environment variables
  • Added E2E tests across all SDKs to verify literal env values are correctly passed to MCP server subprocesses

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/harness/test-mcp-server.mjs New minimal MCP server that exposes a get_env tool for reading environment variables in tests
test/harness/package.json Added @modelcontextprotocol/sdk dependency for the test MCP server
test/harness/package-lock.json Package lock updates for new MCP SDK dependency and transitive dependencies
test/snapshots/mcp_and_agents/should_pass_literal_env_values_to_mcp_server_subprocess.yaml Replay snapshot for the new E2E test
nodejs/src/client.ts Added envValueMode: "direct" to both create and resume session requests
nodejs/test/e2e/mcp_and_agents.test.ts Added E2E test for literal env values and updated test harness to support COPILOT_CLI_PATH
nodejs/test/e2e/harness/sdkTestContext.ts Added support for COPILOT_CLI_PATH environment variable
python/copilot/client.py Added envValueMode: "direct" to both create and resume session payloads
python/e2e/testharness/context.py Added support for COPILOT_CLI_PATH environment variable
python/e2e/test_mcp_and_agents.py Added E2E test for literal env values with test server path resolution
go/types.go Added EnvValueMode field to createSessionRequest and resumeSessionRequest structs
go/client.go Set EnvValueMode: "direct" on create and resume requests
go/internal/e2e/mcp_and_agents_test.go Added E2E test for literal env values
dotnet/src/Client.cs Added "direct" parameter to session create/resume calls and updated record signatures
dotnet/test/Harness/E2ETestContext.cs Set CliPath using COPILOT_CLI_PATH if available for E2E tests
dotnet/test/McpAndAgentsTests.cs Added E2E test for literal env values with helper method to find test harness directory
Files not reviewed (1)
  • test/harness/package-lock.json: Language not supported

@github-actions
Copy link

✅ Cross-SDK Consistency Review: APPROVED

I've reviewed PR #484 for consistency across all four SDK implementations (Node.js, Python, Go, and .NET). Excellent work on maintaining feature parity!

Consistency Verified ✓

All four SDKs implement the MCP environment variable fix identically:

  1. Core Change: All SDKs now send envValueMode: "direct" unconditionally in both create and resume session requests

    • Node.js: envValueMode: "direct" (lines 526, 609)
    • Python: payload["envValueMode"] = "direct" (lines ~507, 684)
    • Go: req.EnvValueMode = "direct" (lines 462, 580)
    • .NET: "direct" parameter (lines 385, 471)
  2. Positioning: The parameter is consistently placed after mcpServers and before customAgents in all SDKs

  3. E2E Tests: All four SDKs include the same test scenario:

    • Test name: should pass literal env values to MCP server subprocess (with language-appropriate casing)
    • Test data: TEST_SECRET: "hunter2" passed to the env-echo MCP server
    • Verification: All tests confirm the literal value reaches the subprocess
    • Shared snapshot: should_pass_literal_env_values_to_mcp_server_subprocess.yaml
  4. Type Definitions: Request types/structs updated consistently across all languages

No Consistency Issues Found

This PR exemplifies excellent multi-SDK development practices. The changes maintain feature parity while respecting each language's conventions (camelCase, snake_case, PascalCase).

AI generated by SDK Consistency Review Agent

@github-actions
Copy link

✅ SDK Consistency Review: Excellent

This PR demonstrates exemplary cross-SDK consistency. The envValueMode: "direct" feature has been implemented uniformly across all four SDK implementations.

Consistency Verification

All SDKs Updated

  • Node.js (nodejs/src/client.ts): envValueMode: "direct" added to both createSession and resumeSession
  • Python (python/copilot/client.py): payload["envValueMode"] = "direct" added to both create and resume
  • Go (go/client.go, go/types.go): req.EnvValueMode = "direct" added with proper type definitions
  • .NET (dotnet/src/Client.cs): "direct" parameter added with updated record types

Feature Parity

  • Both CreateSession and ResumeSession operations updated in all languages
  • Consistent hardcoded value "direct" across all implementations
  • Type definitions appropriately updated where needed (Go structs, .NET records)

Test Coverage

  • Equivalent E2E tests added to all four SDKs
  • New test harness MCP server (test-mcp-server.mjs) with get_env tool
  • All tests use identical scenario: TEST_SECRET="hunter2" environment variable
  • Shared test snapshot created

API Naming Consistency

  • Field name follows language conventions:
    • TypeScript: envValueMode (camelCase)
    • Python: envValueMode in JSON payload (matches wire protocol)
    • Go: EnvValueMode (PascalCase for exported field)
    • .NET: EnvValueMode parameter (PascalCase)

Summary

No consistency issues found. This PR fixes the MCP environment variable handling bug across all SDK implementations with complete feature parity and comprehensive test coverage. Great work! 🎉

AI generated by SDK Consistency Review Agent

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The CLI now injects dynamic <reminder> tags with SQL table state into user
messages. These tags vary based on runtime state and should not affect
snapshot matching.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link

✅ Cross-SDK Consistency Review

I've reviewed this PR for consistency across all four SDK implementations (Node.js, Python, Go, and .NET). No consistency issues found — this is an exemplary cross-language fix!

What Was Changed

This PR adds envValueMode: "direct" to session create and resume requests in all four SDKs to fix MCP environment variable handling (issues #163 and #444).

Consistency Analysis

✅ Feature Parity: EXCELLENT

  • All four SDKs implement the identical fix
  • Both CreateSession and ResumeSession operations updated in each language
  • Consistent E2E test coverage across all implementations

✅ API Naming: CONSISTENT

  • JSON field name: envValueMode (camelCase) — uniform across all languages
  • Language-specific naming follows proper conventions:
    • TypeScript: envValueMode
    • Python: payload["envValueMode"]
    • Go: EnvValueMode (struct field) ✅
    • .NET: EnvValueMode (record parameter) ✅

✅ Implementation: UNIFORM

  • All SDKs unconditionally send "direct" as the value
  • No user configuration exposed (appropriate for this bug fix)
  • Applied to both create and resume operations consistently

✅ Testing: COMPREHENSIVE

  • All four SDKs include the same E2E test scenario
  • Test verifies literal env values (TEST_SECRET: "hunter2") are passed to MCP server subprocess
  • Shared snapshot: test/snapshots/mcp_and_agents/should_pass_literal_env_values_to_mcp_server_subprocess.yaml

Summary

This PR demonstrates excellent cross-SDK development practices with perfect feature parity and consistent implementation across all language targets. 🎯

AI generated by SDK Consistency Review Agent

@SteveSandersonMS SteveSandersonMS merged commit 6003273 into main Feb 17, 2026
31 checks passed
@SteveSandersonMS SteveSandersonMS deleted the stevesa/mcp-env-vars-fix branch February 17, 2026 16:38
@richlanpowers5-afk
Copy link

richlanpowers5-afk commented Feb 17, 2026 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Environment variables in MCP Servers configuration seems to not be passed/used correctly Not reading environment variables for the mcp servers

2 participants