Plugin install pipeline strips top-level dotfiles (.mcp.json, .npmrc), breaking channel plugins
Summary
The Claude Code plugin install/cache pipeline appears to drop top-level dotfiles when copying a marketplace plugin into ~/.claude/plugins/cache/.... This breaks official channel plugins that declare their MCP server in .mcp.json.
Observed with discord@claude-plugins-official v0.0.4 on Linux/WSL. The marketplace source includes .mcp.json and .npmrc; the cached install initially did not. As a result, claude --channels plugin:discord@claude-plugins-official accepted the channel flag but only loaded the plugin's skills. It did not spawn the Discord MCP server, so there was no bun server.ts child and no channel registration.
Manually copying .mcp.json and .npmrc from the marketplace source into the cache unblocked server startup.
Environment
- Claude Code: 2.1.138 (linux-x64 bundled binary)
- OS: WSL2 Ubuntu, Linux 6.6.114.1
- Node: 22.22.0
- Bun: 1.3.13
- Auth: Claude Max OAuth (
organizationType: claude_max) - Plugin:
discord@claude-plugins-officialv0.0.4
Reproduce
- Install official Discord channel plugin:
``text``
/plugin install discord@claude-plugins-official
- Compare marketplace source vs cached install:
``bash``
diff \
<(ls -A ~/.claude/plugins/marketplaces/claude-plugins-official/external_plugins/discord/ | sort) \
<(ls -A ~/.claude/plugins/cache/claude-plugins-official/discord/0.0.4/ | grep -vE 'node_modules' | sort)
- Observed before workaround:
``text``
< .mcp.json
< .npmrc
Both were present in marketplace source and absent from the cached install.
- Launch:
``bash``
claude --channels plugin:discord@claude-plugins-official --debug all --debug-file /tmp/discord-channel.log
- Observe that only plugin skills load. No Discord MCP server spawn, no
bun server.tschild, noplugin:discord:discordconnection, and no channel notification registration.
Expected
The cache copy should preserve top-level plugin dotfiles such as .mcp.json and .npmrc.
For Discord, the cached plugin should include marketplace source file:
~/.claude/plugins/cache/claude-plugins-official/discord/0.0.4/.mcp.json
That file declares the plugin MCP server:
{
mcpServers: {
discord: {
command: bun,
args: [run, --cwd, ${CLAUDE_PLUGIN_ROOT}, --shell=bun, --silent, start]
}
}
}
With it present, claude --channels plugin:discord@claude-plugins-official should be able to spawn the server and elevate it as a channel.
Actual
The cached plugin initially lacked .mcp.json and .npmrc, so the plugin route had no MCP server declaration to spawn.
This made the failure look like a channel feature gate, account allowlist, or plugin schema issue. The CLI accepted --channels plugin:discord@claude-plugins-official, but nothing channel-related started.
Workaround
Copy the missing dotfiles manually:
cp ~/.claude/plugins/marketplaces/claude-plugins-official/external_plugins/discord/.mcp.json \
~/.claude/plugins/cache/claude-plugins-official/discord/0.0.4/.mcp.json
cp ~/.claude/plugins/marketplaces/claude-plugins-official/external_plugins/discord/.npmrc \
~/.claude/plugins/cache/claude-plugins-official/discord/0.0.4/.npmrc
After this workaround, Claude Code starts the plugin MCP server:
[DEBUG] MCP server plugin:discord:discord: Starting connection with timeout of 30000ms
[DEBUG] MCP server plugin:discord:discord: Successfully connected (transport: stdio) in 7474ms
[DEBUG] MCP server plugin:discord:discord: Connection established with capabilities: {hasTools:true,hasPrompts:false,hasResources:false,hasResourceSubscribe:false,serverVersion:{name:discord,version:1.0.0}}
Impact
Any official or third-party plugin that relies on a top-level .mcp.json for MCP server registration can be installed into cache in a broken state if the installer omits dotfiles.
For channel plugins, the symptom is especially confusing:
--channels plugin:NAME@MARKETPLACEparses successfully.- plugin skills may load.
- the channel MCP server never starts.
- no clear warning explains that
.mcp.jsonis missing from the cached plugin.
Suspected cause
The marketplace-to-cache copy/extract step likely uses a glob or filter that excludes dotfiles, such as:
cp src/* dst/- an archive/filter excluding
.* - a JS copy filter rejecting hidden files
Suggested fix: preserve dotfiles during plugin cache population, e.g. rsync -a, cp -a, or equivalent recursive copy semantics that include top-level dotfiles.
Related but distinct issues
There are existing channel delivery issues such as #36837, #36975, and #58018. This report is narrower: before any Discord gateway or notifications/claude/channel delivery can work, the installed plugin cache must preserve .mcp.json so the channel MCP server can start at all.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗