Describe the bug
When the same MCP server name appears in both the user-level config ($HOME/.copilot/mcp-config.json) and a project-level config (./.mcp.json or .github/mcp-config.json), the CLI silently uses different sources for the displayed metadata vs. the actually-launched process:
- The
/mcp UI shows the server under the user-level section (with the source path of the user config), strongly implying the user-level definition is in effect.
- But the process that actually gets launched uses the project-level args/command — the repo-level entry shadows the user-level one at runtime.
This is extremely confusing because you have no in-CLI indication that the displayed config isn't the one being used. In my case the user-level entry passed --browser msedge to @playwright/mcp, while the project's .mcp.json defined the same server with no --browser flag (defaulting to chrome). /mcp showed me the user-level entry with msedge, but the actually-running playwright process was looking for chrome and failing.
The naming conflict should at minimum be surfaced clearly (e.g., a warning in /mcp like "this server is also defined in ./.mcp.json and the project definition is being used"), and ideally a documented precedence policy with an easy way to opt into whichever scope the user prefers.
Affected version
1.0.49-6
Steps to reproduce the behavior
- Define an MCP server in
$HOME/.copilot/mcp-config.json with distinct args, e.g.:
"playwright": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@playwright/mcp@latest", "--browser", "msedge"]
}
- In a separate repo, define the same server name in
./.mcp.json with different args (e.g., no --browser flag, so it defaults to chrome).
- Launch
copilot from inside that repo.
- Run
/mcp. Observe that the playwright entry appears in the user-level section showing the user-level args.
- Trigger any playwright tool call. Observe that the launched process uses the project-level args (looking for chrome instead of msedge).
Expected behavior
Either:
- The
/mcp UI should display whichever config is actually in effect, with a clear annotation when there's a naming conflict ("shadowed by ./.mcp.json" or similar), OR
- A naming conflict should be surfaced as a warning/error at startup with guidance, OR
- Configs should be merged with a documented precedence (and
/mcp should display the merged result with provenance per field).
In all cases, the displayed metadata and the actually-launched process must match.
Additional context
- OS: Windows 11 (PowerShell 7).
- This isn't just a UI bug; it actively breaks debugging. I spent significant time troubleshooting why playwright was looking for chrome when the only config I could see said msedge. The fix turned out to be "realise the project's
.mcp.json is shadowing the user config you're looking at."
- Related: there's no easy way to ignore the project-level configs short of editing/deleting
.mcp.json in the repo (which can't be committed because it's a shared file). See the related feature request for a --disable-repo-mcps flag.
Describe the bug
When the same MCP server name appears in both the user-level config (
$HOME/.copilot/mcp-config.json) and a project-level config (./.mcp.jsonor.github/mcp-config.json), the CLI silently uses different sources for the displayed metadata vs. the actually-launched process:/mcpUI shows the server under the user-level section (with the source path of the user config), strongly implying the user-level definition is in effect.This is extremely confusing because you have no in-CLI indication that the displayed config isn't the one being used. In my case the user-level entry passed
--browser msedgeto@playwright/mcp, while the project's.mcp.jsondefined the same server with no--browserflag (defaulting to chrome)./mcpshowed me the user-level entry with msedge, but the actually-running playwright process was looking for chrome and failing.The naming conflict should at minimum be surfaced clearly (e.g., a warning in
/mcplike "this server is also defined in./.mcp.jsonand the project definition is being used"), and ideally a documented precedence policy with an easy way to opt into whichever scope the user prefers.Affected version
1.0.49-6
Steps to reproduce the behavior
$HOME/.copilot/mcp-config.jsonwith distinct args, e.g.:./.mcp.jsonwith different args (e.g., no--browserflag, so it defaults to chrome).copilotfrom inside that repo./mcp. Observe that the playwright entry appears in the user-level section showing the user-level args.Expected behavior
Either:
/mcpUI should display whichever config is actually in effect, with a clear annotation when there's a naming conflict ("shadowed by./.mcp.json" or similar), OR/mcpshould display the merged result with provenance per field).In all cases, the displayed metadata and the actually-launched process must match.
Additional context
.mcp.jsonis shadowing the user config you're looking at.".mcp.jsonin the repo (which can't be committed because it's a shared file). See the related feature request for a--disable-repo-mcpsflag.