[BUG] Live Artifacts (CoworkArtifacts.callMcpTool) reject local stdio MCP servers on cold start — claude.ai relay rejects server name as non-UUID
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?
Live Artifacts in Claude Desktop fail to call local stdio MCP servers configured in claude_desktop_config.json after a cold start of Claude Desktop. Every tool call returns a 400 from claude.ai's remote
MCP relay because the request URL embeds the server name (e.g. macbook-mcp) where the API expects a server UUID. The local MCP server is never reached — its stderr log shows only initialize andtools/list, never tools/call.
After a direct tool invocation through Claude Chat, the artifact path starts working for the rest of the session — strongly suggesting a lazy-registration bug.
This appears to be a code path missed by #20377's fix: local stdio MCPs work in Cowork chat post-#20377, but the [CoworkArtifacts] path still routes through claude.ai's remote endpoint instead of the local stdio bridge.
What Should Happen?
Live Artifacts should invoke local stdio MCPs immediately on cold start — the same way Claude Chat and the Cowork chat tab do post-#20377. Either:
- Local stdio servers should be registered with the relay at startup, or
- CoworkArtifacts.callMcpTool should fall back to the local stdio bridge for servers that have no claude.ai-side UUID.
Error Messages/Logs
~/Library/Logs/Claude/main.log:
[info] [CoworkArtifacts] callMcpTool() cache bypass (artifactId=daily-attention tool=mcp__macbook-mcp__list_events ...)
[info] Making remote MCP tool call: list_events
[error] Remote tool call failed {
serverUuid: 'macbook-mcp',
toolName: 'list_events',
status: 400,
errorText: '{"type":"error","error":{"type":"invalid_request_error","message":"path.server_uuid: Input should be a valid UUID, invalid character: expected an optional prefix of `urn:uuid:` followed by
[0-9a-fA-F-], found `m` at 1"},"request_id":"req_011CafkutM43FaxLew16tWZS"}',
url: 'https://claude.ai/api/organizations/<ORG_UUID>/mcp/servers/macbook-mcp/tools/call'
}
The serverUuid field is being populated with the literal claude_desktop_config.json key (`macbook-mcp`) — not a real UUID — and that name is being substituted into the path of an endpoint that performs
strict UUID validation.
Local MCP server's own stderr (~/Library/Logs/Claude/mcp-server-macbook-mcp.log): only initialize + tools/list arrive, never tools/call. The 400 happens at claude.ai's relay, before the local server is
contacted.
Steps to Reproduce
- Configure any local stdio MCP server in
claude_desktop_config.json, for example:
```json
"macbook-mcp": {
"command": "/path/to/macbook-mcp",
"env": { "MACBOOK_MCP_CONFIG": "/path/to/config.yaml" }
}
- Cold start Claude Desktop (full quit + relaunch).
- Open a Live Artifact that calls one of the MCP's tools, fails with Tool call failed: 400.
- In a Claude Chat conversation, invoke any tool from that MCP directly (e.g. ask "list my calendar events for today").
- Reload the Live Artifact, it now works.
The bug only manifests on cold start before the MCP has been used directly via Chat. Once Claude Desktop has dispatched at least one tool call to the local stdio MCP, the Live Artifact path starts succeeding for the rest of the session which is why I suspect lazy registration of local stdio servers with claude.ai's remote MCP relay.
Claude Model
None
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
Claude Desktop version: 1.5354.0
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Other
Additional Information
Why this is distinct from #20377
- #20377 fixed local stdio MCPs in the Cowork chat tab, confirmed working in 1.1.1890+ and still working in 1.5354.0.
- This bug is in Live Artifacts (the
[CoworkArtifacts]module) which seems to use an entirely different code path:callMcpTool()→https://claude.ai/api/.../mcp/servers/{server_uuid}/tools/call(a remote
relay) instead of the local stdio bridge.
Showing cached comments. Read the full discussion on GitHub ↗
11 Comments
Same behavior on Windows 11 with a local Python stdio MCP server (Firebird database connector).
Symptoms: On cold start, any
callMcpTool()call from a Live Artifact returns Tool call failed: 400 immediately — no retries help, as the local server is never reached.Workaround confirmed: Opening a Cowork chat (not a regular Claude chat) and sending any message that triggers the MCP tool is enough to unblock it. After that, the Live Artifact works correctly for the rest of the session. A regular Claude.ai chat does not work for me as a workaround, it must be a Cowork chat specifically.
Environment:
Reproduced on Windows — also fails for Cowork's own built-in MCP server
Confirming this bug on Windows under a different MCP delivery mechanism, with one finding that broadens the scope beyond local-stdio plugins.
Environment
What I tested:
All calls passed the per-artifact mcp_tools allowlist check; the 400 is returned by the relay downstream.
The second row is the new finding: the bug is not specific to local-stdio plugin servers. Cowork's own built-in cowork MCP server — which works fine when invoked from the chat path in the same session — also returns 400 when called via window.cowork.callMcpTool from inside a Live Artifact. This suggests the issue may be in the bridge → relay routing itself rather than in UUID resolution for stdio-backed servers as the title frames it.
Workaround attempted, did not work
I followed the workaround from previous comment: invoke the tool via Chat first, then retry from the artifact. Did not change the outcome — same 400.
Found a more specific trigger: MCP server names containing
_fail from Live ArtifactcallMcpToolbut work fine from chat.Note that the manifest's
display_namewhitespace is normalized to_when synthesizing the MCP tool prefix, so any mcpb shipping adisplay_namewith spaces silently hits this too.Workaround for extension authors: omit
display_name(Cowork falls back toname, which is[a-z0-9-]+by npm convention).Hi,
in current Windows version (Claude 1.8089.1 (b98a06) 2026-05-19T18:28:48.000Z) the issue is fixed.
Same 400-from-the-relay symptom here, but with the built-in workspace MCP (not a user-configured stdio one).
Use case: a Live Artifact ("Lint Review Queue") that opens a local markdown file in my Cowork-mounted folder, shows one unresolved item at a time with action buttons, and writes the decision back. Pure local-file CRUD via callMcpTool('mcp__workspace__bash', ...). Every call returns Tool call failed: 400, so the artifact has shown "Queue clear" for weeks even though the file has 141 unresolved items.
A diagnostic build that probes bare pwd, ls /, ls /sessions, python glob, find, etc returns 400 for every call. So the rejection is at the relay before bash runs, matching your finding. The warmup workaround doesn't apply: I invoked mcp__workspace__bash directly from Claude Chat many times in the same session right before reloading the artifact, and the artifact's calls still 400'd. Looks like the relay rejects non-UUID server names at URL validation regardless of warmup state, since workspace isn't a UUID.
Net effect: Live Artifacts can talk to UUID-named user connectors (Drive, Calendar, Atlassian, Gmail) but can't touch any local file. Pretty limiting for anyone whose source of truth is a local repo or Obsidian vault. Would love either non-UUID names accepted, or built-ins like workspace getting a UUID at registration.
This issue is happening to me on macOS Claude desktop version 1.9659.2.
I fixed it temporarily by using the claude.ai site to first generate a UUID then restarting desktop and trying it there again.
the shape underneath this is 'shadow dispatch path.' Live Artifacts didn't reuse Chat's MCP router, it stood up a parallel callMcpTool that always assumes remote relay + UUID. so the local-stdio branch fixed in #20377 only lives on the Chat side. lazy registration 'works' for Chat as a side effect of dispatch, which is why one Chat tool call pre-warms Artifacts for the rest of the session. fallback inside callMcpTool patches the symptom, the real fix is one shared dispatch decision both surfaces route through, otherwise the next surface (sidebar, agent, whatever) reintroduces the same drift.
This limits the use of good local stdio MCP's. A fix on this would be good and stop limiting the usage of Claude Cowork
Confirming this bug on Windows with .mcpb Desktop Extensions — and the chat workaround does not work there
Environment: Claude Desktop on Windows 11, local MCP servers installed as Desktop Extensions (.mcpb, stdio), used from Cowork Live Artifacts via window.cowork.callMcpTool().
Observations:
Same failure mode as reported: every callMcpTool() from a Live Artifact returns Tool call failed: 400 in a constant ~200–300 ms, regardless of tool or arguments (even ping with an empty args object). The local server is never reached. This affects all local .mcpb connectors equally (tested three different ones), so it is not connector-specific.
This is a regression: artifacts created on/before ~June 18, 2026 successfully called local MCP tools live. An artifact created June 25 already failed with 400 at creation time. So the relay routing change appears to have shipped in a Desktop update between ~June 18–25.
The lazy-registration workaround does not work with .mcpb extensions on Windows: invoking a tool from the same connector directly in a regular Claude Chat conversation (confirmed successful response in chat), then re-running the artifact's tool calls in the same app session, still yields 400 on every call. Calls made via the Cowork chat/agent also do not register the server. So on Windows + .mcpb there is currently no known workaround — artifacts are limited to embedded snapshot data refreshed by scheduled tasks.
Happy to provide logs or run diagnostics if useful. This blocks the "live artifact over local connector data" use case entirely on Windows.
Wanted to add a data point here, because I think it broadens the scope of this bug in a useful way.
I hit this exact failure with scheduled-tasks, which is one of Cowork's own built-in local connectors — not something a user configured or installed as an extension. That matters because everyone reporting so far pointed at user-added stdio servers or .mcpb extensions; this shows it's happening to Anthropic's own first-party tools too, which suggests the fix needs to cover more ground than "handle third-party local servers better."
I also ruled out a couple of things people suspected. It's not a permissions or grant timing issue — I tested it both by adding the connector to an existing artifact and by creating a brand-new artifact with the connector granted from the start, and got the same instant 400 either way. And the "call it once from chat to warm it up" workaround some people found didn't help at all in my case, even tried repeatedly, before and after.
Every failed call came back in under 200ms, so this reads as an immediate rejection rather than a timeout.
Happy to share logs if useful. Running Claude Desktop on macOS — Claude 1.24012.9 (03c61d) 2026-07-24T04:59:17.000Z
Same bug on macOS, with a locally-deployed .mcpb MCP gateway (fronts several sub-servers, does its own OAuth to downstream). Adds two data points:
Non-ASCII display name → collapses to a bare underscore: .../mcp/servers/_/tools/call → 400
After remove + re-add with an ASCII name → the slugified name: .../mcp/servers/MCP_Hub/tools/call → still 400
So path.server_uuid is being populated with the connector name/slug (or _ when there's no ASCII to slugify) instead of a real UUID. Every call is cache bypass / readOnly=false, constant ~300 ms, isError=true with an empty body — the local server is never reached.
Chat works fine against the same connector all session; only the [CoworkArtifacts] remote-relay path fails. For a self-deployed local connector the platform has no server UUID to begin with, so routing artifact calls through claude.ai/.../mcp/servers/{uuid}/tools/call can't work — they should fall back to the same local bridge chat uses (option 2 in the OP).
Env: macOS, Claude Desktop (Cowork Live Artifacts), local .mcpb connector. Happy to share logs.