{"version":"2.1.299","anchor":"new-claude-code-remote-mcp-config-env-var-passed-through-to","canonical_anchor":"new-claude-code-remote-mcp-config-env-var-passed-through-to","heading":"Headless and remote runs handle delivered MCP servers and --mcp-config differently","tier":"use","area":"Cloud Sessions","scope":"both","heads_up":true,"url":"https:\/\/changelogs.core-directive.com\/v\/2.1.299\/e\/new-claude-code-remote-mcp-config-env-var-passed-through-to","release_url":"https:\/\/changelogs.core-directive.com\/v\/2.1.299","markdown":"### Headless and remote runs handle delivered MCP servers and --mcp-config differently\n\nRemote runners get host-delivered MCP servers through CLAUDE_CODE_REMOTE_MCP_CONFIG, and --mcp-config sources are filtered by scope and ownership\n\n**Unclear.** What `CLAUDE_CODE_REMOTE_MCP_CONFIG` does when set is not stated.\n\n**What**\n\nMCP servers are outside programs that give Claude extra tools. Several changes affect how Claude Code loads them when it runs headless, meaning without the interactive screen, as with `-p` or the SDK, or when it runs as a remote runner.\n\n- `CLAUDE_CODE_REMOTE_MCP_CONFIG` is a new environment variable. It points to a file holding the MCP servers a host delivered to the runner. Claude Code reads that file as a `--mcp-config` source with the scope `dynamic` and a bridge session id, and only when a remote-session check passes.\n\n- The variable is added to the lists of variables that are passed on to child processes or protected, next to `CCR_SESSION_PROFILE` and `CLAUDE_RUNNER_ACTIVITY_FD`. When Claude Code starts the child process, it builds the variable for it.\n\n- A delivered server whose name matches one of the operator's own `--mcp-config` servers is refused as `reserved_name`.\n\n- If the variable did not reach the runner, a warning says that a later update of the delivered servers will shut down every `--mcp-config` server the update does not name. That includes the operator's own servers.\n\n- Several `--mcp-config` sources are now collected into a list and go through an ownership and refusal step before they are merged. Refused servers are logged as warnings. Before, the sources were simply merged together.\n\n- The headless MCP refresh now filters servers by scope and by `strict-mcp-config`, and logs how many configured servers it left out. Before, in some modes it applied every configured server except project and local ones. The same change adds a `mcpConfigOwnership` parameter, a `joinAlwaysLoadMcp` hook and a new `pluginDiffScope`.\n\n- When `joinAlwaysLoadMcp` is provided, headless startup waits for always-load MCP servers before it goes on, and then uses the refreshed MCP state.\n\n- When a Remote Control `remote_tool_call` request fails with status UNSPECIFIED, Claude is told not to retry and to carry on without the target.\n\n**Why**\n\nThis changes which MCP servers end up loaded when Claude Code runs from scripts, the SDK or self-hosted runners. With `strict-mcp-config` set, a refresh should no longer pull in extra servers. A wrapper that does not pass `CLAUDE_CODE_REMOTE_MCP_CONFIG` on can lose its own `--mcp-config` servers, and the warning says so.\n\n- Area: Cloud Sessions\n- Names: `CLAUDE_CODE_REMOTE_MCP_CONFIG`, `CCR_SESSION_PROFILE`, `CLAUDE_RUNNER_ACTIVITY_FD`\n- Tier: Use it now\n- Useful: 4\/5\n- Signal: 4\/5\n- Scope: both\n- Heads-up: yes"}