[BUG] [Cowork] Plugin-bundled stdio MCP servers silently dropped in cloud sessions (skill loads, MCP does not)
Summary
A plugin that passes claude plugin validate and works correctly in Claude Code is silently half-loaded in a Cowork cloud session: the plugin's skills/ are loaded and offered to the model, but the plugin's bundled stdio MCP server is never started and no warning is emitted to the user, to the model, or to the plugin author.
The model is therefore handed a skill whose entire purpose is to drive MCP tools that do not exist, with no indication that anything is missing.
Reproduction
- Build a plugin with both a skill and a bundled stdio MCP server (
plugin.json→"mcpServers": "./.mcp.json"). claude plugin validate <path>→ passes clean.- Install in Claude Code → works; MCP tools present and callable.
- Open a Cowork cloud session with the same plugin synced.
Expected
Either the MCP server starts, or the session surfaces a clear warning that the plugin's MCP servers cannot be loaded in this execution mode.
Actual
- Plugin is synced to disk in the cloud container:
/root/.claude/plugins/synced/<plugin>/ — including .claude-plugin/plugin.json and .mcp.json.
- The plugin's skill loads and appears in the model's available-skills list.
- The plugin's MCP server is not started. No
mcp__<server>__*tools exist. - No warning anywhere. Not in the UI, not in the session context, not in any tool result.
Evidence — same artifact, three surfaces
| Surface | Skill loads | MCP server loads | Warning on failure |
|---|---|---|---|
| claude plugin validate | n/a — passes clean | n/a — passes clean | n/a |
| Claude Code (local) | yes | yes | n/a |
| Cowork cloud session | yes | no | none |
Bundled .mcp.json, synced verbatim into the cloud container and then ignored:
{
"mcpServers": {
"example": {
"type": "stdio",
"command": "/Users/<user>/.../Example.app/Contents/MacOS/example",
"args": ["mcp"],
"env": {}
}
}
}
Why this is a defect regardless of the underlying architecture
claude plugin validate is the contract. It certifies the manifest — MCP server declaration included — as well-formed. A surface that accepts a validated manifest and then silently honours only half of it breaks that contract.
This holds whether or not stdio MCP servers are supposed to run in cloud sessions. If they are not supported there, that is a legitimate design decision — but it must be stated, at validate time, at install time, or at session start.
Severity is amplified by the install path
The GUI path for installing a custom plugin in Cowork is hard to discover. The population that finds it is therefore self-selected for persistence — and those users are precisely the ones who then hit an unexplained silent failure. The discoverability friction and the silent failure compound each other.
Secondary: portable MCP servers are dropped too
The cloud container executes arbitrary code by design (unrestricted shell, package managers, network). A plugin MCP server that is a plain Node/Python wrapper around a REST API has no dependency on the user's machine and could run in the container unchanged. Dropping all plugin MCP servers over-applies a constraint that only applies to servers requiring local resources.
Suggested split:
- Portable servers → run them in the cloud container (optionally behind a user/admin toggle).
- Servers requiring the local machine → proxy over the existing Claude Desktop bridge, or state clearly that a local session is required.
Appendix: contradictory documentation
Two first-party sources disagree, which is likely why this failure is not caught:
- The Cowork architecture overview states that local MCP servers do not run in sessions in the cloud.
- The in-session tool documentation for the remote-devices bridge states that the user's locally-installed MCP servers are proxied through that bridge and appear as
mcp__remote-devices__{server}__*tools.
Both cannot be current. Clarifying which is correct would also determine the right fix above.
Environment
- Cowork cloud session, Claude desktop app client (macOS)
- Plugin synced to
/root/.claude/plugins/synced/<plugin>/ - MCP server transport:
stdio - Same plugin verified working in Claude Code