Skip to content

MCP naming conflict: /mcp UI lists user-level entry but runtime uses repo-level settings #3379

@DrEsteban

Description

@DrEsteban

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

  1. 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"]
    }
  2. 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).
  3. Launch copilot from inside that repo.
  4. Run /mcp. Observe that the playwright entry appears in the user-level section showing the user-level args.
  5. Trigger any playwright tool call. Observe that the launched process uses the project-level args (looking for chrome instead of msedge).

Expected behavior

Either:

  1. 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
  2. A naming conflict should be surfaced as a warning/error at startup with guidance, OR
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:mcpMCP server configuration, discovery, connectivity, OAuth, policy, and registry

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions