[BUG] MCP server deduplication ignores env vars and names - suppresses functionally different servers from plugins
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Since v2.1.70, plugin-provided MCP server deduplication matches only onvcommand + args, ignoring env vars entirely. This causes functionally different servers to be suppressed as "duplicates" when they share the same underlying package but target different systems, credentials, or access modes.
In a plugin marketplace with multiple plugins, only the first-loaded server survives — all others are silently suppressed. This is a blocker for any marketplace where multiple plugins legitimately use the same MCP package
(e.g. storybook, @zereight/mcp-gitlab etc.) with different configurations. It's common for us to use e.g. multiple storybook servers, multiple gitlab instance etc at the same time. Currently, its not possible.
What Should Happen?
MCP server deduplication should consider env vars as part of server identity. Two servers with identical command/args but different env configurations are NOT duplicates — they serve different purposes (different target URLs, different credentials, different access modes).
Error Messages/Logs
Steps to Reproduce
- Create a single plugin with an
.mcp.jsondefining two Storybook MCP servers using the same package but pointing at different Storybook instances:
``json``
{
"mcpServers": {
"ui5-storybook": {
"command": "npx",
"args": ["-y", "storybook-mcp@latest"],
"env": {
"STORYBOOK_URL": "https://ui5.github.io/webcomponents-react/v2/index.json"
}
},
"project-storybook": {
"command": "npx",
"args": ["-y", "storybook-mcp@latest"],
"env": {
"STORYBOOK_URL": "http://localhost:6006/index.json"
}
}
}
}
Simillary, you can create 2 plugins, each using storybook mcp with different storybook server sources.
- Start Claude Code
Expected: Both ui5-storybook and project-storybook load — they target completely different Storybook instances (external component library vs local project storybook). This is a common pattern for frontend plugins that need to reference both a design system and a project-specific storybook.
Actual: Only ui5-storybook loads. project-storybook is suppressed as a "duplicate" because the command+args are identical, even though the STORYBOOK_URL env var points to a completely different server.
Claude Model
Not sure / Multiple models
Is this a regression?
Yes, this worked in a previous version
Last Working Version
2.1.69
Claude Code Version
2.1.71
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Real-World Impact
In our internal plugin marketplace (6 plugins, 4 teams), this suppresses ~12 MCP server instances across 3 packages. We are using different jira servers, different gitlabs, different storybooks at the same time.
This is not an edge case. It is very common and expected to have multiple instances of the same MCP package within a single plugin - e.g. a frontend plugin connecting to 2-3 Storybook instances (component library, project
storybook, design system), or a project plugin connecting to multiple GitLab instances (production gitlab, tools gitlab, legacy gitlab), or multiple plugins from one marketplace that uses multiple instances of one mcp with different configuration. The current deduplication makes this pattern impossible, even though the servers are completely independent with different target URLs and credentials.
Suggested Fix
Include env in the deduplication key. A server should only be considered a duplicate if command + args + env all match. Alternatively, provide an opt-out mechanism (e.g. "deduplicate": false in the plugin/marketplace config).
4 Comments
Also, each mcp in a marketplace (its cross-plugin problem as well) has its own name that serves as a unique identifier that we use in skills, commands etc. to instruct models to do specific calls. Once the in one plugin is surpressed, it escalates and makes those skills / commands not working.
I would also expect that the name is used for deduplication. I can have multiple "gitlab" mcps - they are generic and I want to use only one of them, but then I may have "XX-gitlab" mcp, that is pre-configured for specific purpose, that should not be deduplicated with other gitlab mcps.
commenting to keep the issue alive. Bug is still present.
Confirming this is still present in v2.1.145 (latest as of 2026-05-20). Hit independently in a different ecosystem.
Repro — a plugin
my-dataikuhas the following.mcp.json:\
\\json\{
"mcpServers": {
"dataiku": {
"command": "uv",
"args": ["run", "--project", "\${CLAUDE_PLUGIN_ROOT}/mcp-servers/dataiku_factory", "dataiku-mcp-server"],
"env": { "DSS_HOST": "https://prod.example.com", "DSS_API_KEY": "<prod-key>" }
},
"dataiku-dev": {
"command": "uv",
"args": ["run", "--project", "\${CLAUDE_PLUGIN_ROOT}/mcp-servers/dataiku_factory", "dataiku-mcp-server"],
"env": { "DSS_HOST": "https://dev.example.com", "DSS_API_KEY": "<dev-key>" }
}
}
}
\
\Same binary, two Dataiku DSS hosts (prod vs dev). Both env-var sets are populated and the dev host accepts the dev key (verified with curl).
Result:
claude mcp list\→ only \plugin:my-dataiku:dataiku\registers.claude mcp get plugin:my-dataiku:dataiku-dev\→ \No MCP server found with name: ...\. The server isn't shown as Failed or Disabled — it's silently absent.A second plugin in the same marketplace declares two MSSQL MCP servers (\
analytics\+ \east-replica\) with same command/args differing only in env, and is dropped the same way. So this isn't limited to one server-package combo — it bites any plugin pattern where same-binary-different-env is the legitimate distinction (different hosts, credentials, schemas, etc.).Strongly seconding the original ask: please include \
env\(and ideally the server \name\) in the dedupe key. As-is, same-binary-different-env is unusable, which forces marketplace authors into ugly workarounds (wrapper launch scripts that perturb \args\) to bypass the dedupe.This still happens in 2.1.210