Summary
When driving the Copilot CLI in server / SDK (programmatic) mode (copilot --server --stdio, via github-copilot-sdk), MCP servers provided on the session config (SessionConfig.with_mcp_servers(...) → the mcpServers field of the session.create request) are never started. The CLI's session.create handler does not forward mcpServers into the internal session it constructs, so initializeMcpHost() has nothing to start, no MCP tools are registered, and the model never sees them. The same MCP server works fine in interactive mode and standalone.
Environment
- Copilot CLI: reproduced on 1.0.51-2 and 1.0.64-0 (linux-x64)
- SDK:
github-copilot-sdk (Rust) 1.0.1
- OS: Linux
- MCP server under test: official Azure MCP —
npx -y @azure/mcp@latest server start --namespace kusto (stdio). Verified working standalone (responds to initialize + tools/list, exposes the kusto tool).
Steps to reproduce
- Start a client via the SDK and create a session with an explicit stdio MCP server:
let cfg = SessionConfig::default()
.with_model("claude-...")
.with_enable_config_discovery(false)
.with_mcp_servers(HashMap::from([(
"azure".to_string(),
McpServerConfig::Stdio(McpStdioServerConfig {
command: "npx".into(),
args: vec!["-y","@azure/mcp@latest","server","start","--namespace","kusto"]
.into_iter().map(Into::into).collect(),
..Default::default()
}),
)]));
let session = client.create_session(cfg).await?;
session.send(/* a prompt that needs the MCP tool */).await?;
- Send a prompt that requires the MCP tool.
Expected
The azure MCP server is started and its tools (e.g. azure-kusto) are registered and offered to the model.
Actual
- The server is never spawned (no
@azure/mcp / npx child process), no MCP tools are registered, and the model reports the tool is not available — e.g. its own reasoning log: "I'm looking for the kusto tool in my available functions, but I don't see it listed directly … it's not showing up in my tools." The model falls back to other tools.
Evidence / root cause
- The SDK does send the server. The
session.create request received by the CLI contains it:
{"enableConfigDiscovery":false,"enableSkills":true,
"mcpServers":{"azure":{"command":"npx","args":["-y","@azure/mcp@latest","server","start","--namespace","kusto"],"type":"stdio","timeout":120000,...}},
"model":"...","sessionId":"...","streaming":true,"tools":[]}
- The CLI's
session.create handler constructs the internal session by forwarding model, sessionId, systemMessage, largeOutput, availableTools, excludedTools, provider, enableStreaming — but not mcpServers (observed in the bundled app.js, both 1.0.51-2 and 1.0.64-0).
- As a result
initializeMcpHost() (which only acts when this.mcpServers / selectedCustomAgent.mcpServers is non-empty) never runs for these servers.
Workarounds tried (all fail in server mode)
- Upgrading the CLI 1.0.51-2 → 1.0.64-0: no change.
GITHUB_COPILOT_MCP_JSON + GITHUB_COPILOT_3P_MCP_ENABLED=true: not read in server mode (readMcpConfigFromEnv() is not invoked; no "User-provided MCPs" log line appears).
- Config/plugin discovery (
enable_config_discovery=true): does load plugin MCPs in server mode, but it pulls in all ambient servers — there is no supported way to inject a single explicit server in server mode.
The only thing that works is patching the bundled app.js to add mcpServers to the object passed to createSession(...), after which the server starts and azure-kusto is registered as expected — confirming the dropped field is the cause.
Related
These touch the programmatic surface but don't call out the specific session.create → mcpServers drop.
Summary
When driving the Copilot CLI in server / SDK (programmatic) mode (
copilot --server --stdio, viagithub-copilot-sdk), MCP servers provided on the session config (SessionConfig.with_mcp_servers(...)→ themcpServersfield of thesession.createrequest) are never started. The CLI'ssession.createhandler does not forwardmcpServersinto the internal session it constructs, soinitializeMcpHost()has nothing to start, no MCP tools are registered, and the model never sees them. The same MCP server works fine in interactive mode and standalone.Environment
github-copilot-sdk(Rust)1.0.1npx -y @azure/mcp@latest server start --namespace kusto(stdio). Verified working standalone (responds toinitialize+tools/list, exposes thekustotool).Steps to reproduce
Expected
The
azureMCP server is started and its tools (e.g.azure-kusto) are registered and offered to the model.Actual
@azure/mcp/npxchild process), no MCP tools are registered, and the model reports the tool is not available — e.g. its own reasoning log: "I'm looking for the kusto tool in my available functions, but I don't see it listed directly … it's not showing up in my tools." The model falls back to other tools.Evidence / root cause
session.createrequest received by the CLI contains it:{"enableConfigDiscovery":false,"enableSkills":true, "mcpServers":{"azure":{"command":"npx","args":["-y","@azure/mcp@latest","server","start","--namespace","kusto"],"type":"stdio","timeout":120000,...}}, "model":"...","sessionId":"...","streaming":true,"tools":[]}session.createhandler constructs the internal session by forwardingmodel,sessionId,systemMessage,largeOutput,availableTools,excludedTools,provider,enableStreaming— but notmcpServers(observed in the bundledapp.js, both 1.0.51-2 and 1.0.64-0).initializeMcpHost()(which only acts whenthis.mcpServers/selectedCustomAgent.mcpServersis non-empty) never runs for these servers.Workarounds tried (all fail in server mode)
GITHUB_COPILOT_MCP_JSON+GITHUB_COPILOT_3P_MCP_ENABLED=true: not read in server mode (readMcpConfigFromEnv()is not invoked; no "User-provided MCPs" log line appears).enable_config_discovery=true): does load plugin MCPs in server mode, but it pulls in all ambient servers — there is no supported way to inject a single explicit server in server mode.The only thing that works is patching the bundled
app.jsto addmcpServersto the object passed tocreateSession(...), after which the server starts andazure-kustois registered as expected — confirming the dropped field is the cause.Related
These touch the programmatic surface but don't call out the specific
session.create→mcpServersdrop.