[BUG] Claude Desktop local sessions never surface marketplace-installed plugin tools (LocalPluginsReader only finds the bundled skills-plugin)
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?
Claude Code plugins installed via a custom/private marketplace and enabled in ~/.claude/settings.json (enabledPlugins) are never surfaced to Claude Desktop's local chat sessions ("Cowork" / local-agent-mode sessions) — even though the plugin's MCP server is correctly configured, connects successfully, and claude mcp list run from a terminal on the same machine reports it as ✔ Connected.
The same plugin's tools work fine when running claude directly in a terminal on the same machine, using the exact same ~/.claude configuration. They are simply never exposed inside a Desktop-hosted local session — no error or warning is shown to the user explaining why the tools are missing.
Root cause, confirmed via the app's own logs (%APPDATA%\Claude\logs\main.log): on every local session start, this repeats:
[LocalPluginsReader] Found 1 local plugins
[CCD] Using skills plugin at: ...\local-agent-mode-sessions\skills-plugin\<id>\<account-id>
[CCD] Passing 2 plugin(s) to SDK (skills: 1, remote: 0, local: 1)
The "1 local plugin" found is always the bundled skills-plugin — never the user-installed marketplace plugin. This is consistent across every session start observed (multiple sessions, across a full Desktop app restart). Remote connectors (claude.ai Connectors: Figma, GitHub, etc.) work correctly because they go through a completely separate code path (RemotePluginManager / replaceRemoteMcpServers), unrelated to this bug.
What Should Happen?
A Claude Desktop local session should expose the same plugins/tools that claude mcp list and the standalone CLI see, since both read the same ~/.claude configuration. Concretely: after installing and enabling a marketplace plugin (confirmed ✔ Connected via claude mcp list), a brand-new local chat/session in Claude Desktop should be able to call that plugin's MCP tools — the same way it can from a terminal claude session on the same machine.
Suggested fix direction: LocalPluginsReader (Desktop/"CCD" layer) should also enumerate plugins installed via the standard Claude Code plugin cache (~/.claude/plugins/cache/**/*/*/) that are enabled in ~/.claude/settings.json's enabledPlugins, not just the one bundled skills-plugin it currently reports.
Error Messages/Logs
From %APPDATA%\Claude\logs\main.log (repeats on every local session start):
[LocalPluginsReader] Found 1 local plugins
[CCD] Using skills plugin at: ...\local-agent-mode-sessions\skills-plugin\<id>\<account-id>
[CCD] Passing 2 plugin(s) to SDK (skills: 1, remote: 0, local: 1)
From a terminal on the same machine, at the same time:
claude mcp list
...
plugin:bamex-mssql:db: node C:/Users/<USER>/.claude/plugins/cache/bamex/bamex-mssql/0.4.0/server/index.cjs - Connected
Steps to Reproduce
- Install a custom Claude Code plugin via a private/custom marketplace (
claude plugin marketplace add <owner/repo>thenclaude plugin install <plugin>@<marketplace>), so it appears underenabledPluginsin~/.claude/settings.jsonand is cached at~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/, with an MCP server declared in the plugin's.mcp.json(stdio transport). - From a terminal on the same machine, confirm the server is healthy:
claude mcp listshowsplugin:<name>:<server> ... ✔ Connected. - Open Claude Desktop and start a brand-new local chat/session in the same project directory.
- Ask Claude to use any tool provided by that plugin's MCP server (e.g. a query/list tool).
- Observed: the tool is never available in the session (not found via the tool search / deferred tool list), even though step 2 confirms the server itself is healthy and connected.
- Check
%APPDATA%\Claude\logs\main.logaround session start — it shows:
```
[LocalPluginsReader] Found 1 local plugins
[CCD] Using skills plugin at: ...\local-agent-mode-sessions\skills-plugin\<id>\<account-id>
[CCD] Passing 2 plugin(s) to SDK (skills: 1, remote: 0, local: 1)
skills-plugin` — the marketplace plugin is never included in the count, in any session.
The "1 local plugin" is always the bundled
- Restarting Claude Desktop entirely and starting a fresh conversation afterward does not change the result —
LocalPluginsReaderreports the same "Found 1 local plugins" every time.
Also tested as part of narrowing this down: rebuilding the plugin's MCP server against a much older @modelcontextprotocol/sdk version (1.12.0 instead of 1.30.0) made no difference — same result in Desktop, ruling out an SDK/protocol-version incompatibility.
Related but distinct reports (different mechanism/log signature, so filing separately rather than piling on):
- #64763 — marketplace plugin skills never appear ("Skipping manifest write for out-of-bounds installPath"). That's about the skill manifest writer; this report is about MCP server tools never being passed to the SDK for local sessions (
LocalPluginsReader/CCD plugin passthrough). - #31838 — plugins/MCP servers become invisible after alternating between the CLI and the Antigravity IDE (VS Code extension). Our case never involves an IDE at all — it reproduces purely between the standalone
claudeCLI and Claude Desktop's local sessions on the same machine, with~/.claude.json'smcpServerslegitimately empty (not corrupted) the whole time.
Claude Model
None
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
2.1.219 (Claude Code engine embedded in the Claude Desktop local session — confirmed via the session transcript's version field, consistent across restarts). Standalone claude CLI on the same machine: 2.1.220 (latest at time of filing) — same behavior either way, this version gap is not the root cause.
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Other
Additional Information
Actual terminal used for the CLI-side checks: Git Bash (bundled with Git for Windows), not listed as an option above.
Plugin details, for reference:
- Marketplace: custom private marketplace, plugin
bamex-mssql@bamex, v0.4.0. - Installed at
~/.claude/plugins/cache/bamex/bamex-mssql/0.4.0/, contents complete and valid (.claude-plugin/plugin.json,.mcp.json,hooks/,server/index.cjs). .mcp.jsondeclares one stdio MCP server (keydb) spawned vianode ${CLAUDE_PLUGIN_ROOT}/server/index.cjs.~/.claude/settings.json→enabledPluginscorrectly lists"bamex-mssql@bamex": true.- Ruled out that this is specific to this one plugin's implementation: rebuilding its MCP server against
@modelcontextprotocol/sdk@1.12.0(vs. the original1.30.0) produced an identical result in Desktop, so the plugin's own server code/SDK version isn't the differentiator —LocalPluginsReader's "Found 1 local plugins" never changed regardless of which build was in the cache. claude mcp listfrom a terminal consistently reports:plugin:bamex-mssql:db: node C:/Users/<USER>/.claude/plugins/cache/bamex/bamex-mssql/0.4.0/server/index.cjs - ✔ Connected.
Also checked and ruled out as the mechanism at play here:
- claude.ai remote Connectors (Personalizar → Conectores) — no connector exists for this plugin.
claude_desktop_config.json— zeromcpServersentries, so Desktop's native local-MCP config isn't involved either.
Happy to provide the full main.log excerpt (redacted) or a minimal reproduction plugin if useful.
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
Confirming this reproduces on both platforms, with more isolation data — and a practical workaround worth noting for anyone else hitting this.
Reproduced today with a custom plugin (
marinemax-servicedesk-toolkit, a stdio MCP server via.mcp.json's${SDP_UV:-uv} run --script ...), installed both via a private GitHub-backed marketplace and via the desktop app's "Upload a plugin" zip-upload dialog. On macOS: the plugin shows correctly under Settings → Plugins, but the desktop chat/Assistant session can't reach its MCP server — no tools, connection reported as closed. Reproduced identically on Windows (Windows Sandbox) via the same two install methods.Ruled out three plausible local causes on Windows, each with a confirmed full app-process kill before relaunch:
directoryvs. zip-upload) — all fail identically in desktop chat.uv-resolution — setSDP_UVto the absolute path ofuv.exein~/.claude/settings.json'senvblock; no change.mcpServersentry inclaude_desktop_config.jsonalso produced no connector in desktop chat, suggesting this build may not read that file for MCP servers at all anymore, not just that the newer plugin-loading path (this issue, #86154) is buggy.Workaround that does work, confirmed on both Mac and Windows: the desktop app's own Code tab. Separate surface from the chat/Assistant interface — same app, no separate
claudeCLI install, no PATH edits, no manual config. The same plugin's MCP server connects and works normally there. This matchesLocalPluginsReaderonly being consulted for the chat/Assistant surface's local sessions, per this issue's own root-cause description — the Code tab apparently isn't affected the same way.Happy to share
plugin.json/.mcp.json/logs if useful.One addendum: a second person independently testing the same plugin on their own Windows machine (not a sandbox) confirms the same three-way split — Code tab works, chat does not, and Cowork does not either. That matches this issue's own description more precisely than my first comment did (I'd only tested chat directly) — it really is "every desktop-app session except the Code tab," not just the chat/Assistant interface specifically.
Independent confirmation on macOS, with a first-party plugin as the reproduction, plus a different log signature that may help localise it.
Environment: Claude Desktop 2.2553.1, macOS 14.6.1 (arm64). Plugin installed through Customize → Plugins (uploaded bundle), not a marketplace — so this is the Desktop install path rather than
~/.claude/plugins/cache, yet the end symptom matches.Reproduces with Anthropic's own
pdf-viewerpluginThis is the part I think is most useful here, because it removes the third-party plugin as a variable.
pdf-viewerships a local stdio MCP server. Installed and restarted, it behaves exactly like our own plugin: the server starts, announces, and its tool is absent from a chat session. The session reported that only the plugin's instructions had been loaded.A second log signature
Alongside the
LocalPluginsReaderline in this issue, there's a cleaner one at the session layer. In~/Library/Logs/Claude/main.log:…every server announcing with correct tool counts. Meanwhile the string
plugin:appears 0 times in the entire history of~/Library/Logs/Claude/claude.ai-web.log— the session-layer log. Servers registered the ordinary way inclaude_desktop_config.jsonappear in that same log by their bare names and are callable.So: the bridge announces plugin-namespaced servers, and the session layer never enumerates them. Announced, never delivered.
Three other surfaces on the same machine do not have this problem
Tested the same day, same plugin, same 15 stdio servers:
| surface | plugin skills | plugin MCP tools |
|---|---|---|
| Claude Code CLI 2.1.278 | work | work — called
mcp__plugin_lexa-bioscience_ensembl-mcp__gene_info, got the payload back || Claude Code in Desktop (embedded engine 2.1.275) | work | work — same
mcp__plugin_…namespace || Cowork | work | work — via
mcp__remote-devices__plugin_…|| Desktop chat | work | absent |
Note this differs from the original report, where Desktop local sessions were the failing surface — here local-agent-mode sessions (Code tab, Cowork) both work and only chat fails. Same component, possibly a different code path; flagging the difference rather than assuming they're identical.
Also observed
For
pdf-viewer, the plugin manager UI reports 9 tools whilelocalMcpBridgeannounces 3 — two components of Desktop disagreeing about the same first-party plugin.Separately,
LocalPluginsReaderlogged0 enabled local plugins (0 installed)at a moment when plugin servers were running and announcing, which lines up with the "Found 1 local plugins" behaviour described above.Impact
For a plugin whose value is its data layer, the failure is silent and total: the plugin installs, the skills load, the model behaves as if it is working, and every tool call it would have made simply never happens. Nothing in the UI indicates half the plugin is missing. Our workaround is to additionally register all 15 servers by hand in
claude_desktop_config.json, which has to be documented for every user.Happy to supply redacted
main.logexcerpts, or to run a specific test if it would help narrow this down.