Both were caught by running the check against a state whose answer was already
known from the screen, which is the only reason they were caught at all. A
check that reports PENDING for a thing that has plainly happened is worse than
no check: it invites the reader to distrust the instrument or, worse, to
believe it.
1. It looked for a directory named after the plugin. Cowork installs into
rpm/plugin_<opaque id>/, so the name appears in no path -- only in
rpm/manifest.json, which is now what gets read. The old code also used an
unquoted $(find ...) in a for-loop over a path containing "Application
Support", so the space split every path in half. That is the exact
word-splitting failure this machine's shell rules warn about, and it made
the check report "not installed" while the server was running.
2. It expected ~/Library/Logs/Claude/mcp-server-<name>.log. That naming is for
Claude Desktop's own connectors; a plugin's MCP server is logged by
LocalMcpServerManager into main.log. An absent file at a guessed path is a
statement about the guess, not about the world.
What the corrected check now reads, and what it establishes:
rpm/manifest.json -> jobbsok-probe, plugin_01NxHfqM495jtJzjVjRvgWDm,
marketplace "My Uploads", installed 2026-09-04T16:48:20Z
installed copy -> 4 files, manifest version 0.0.1 (no stale cache)
main.log 18:48:28 -> Connecting to plugin:jobbsok-probe:probe-tools
negotiated protocol version: 2025-11-25
Connected ... (1 tools)
process -> pid 12997, /usr/local/bin/python3, a child of Claude.app
So a plugin-declared stdio MCP server does spawn and connect on this Intel Mac,
on the host interpreter rather than in the sandbox. The negotiated version also
vindicates one design choice: probe_tools.py echoes the client's protocolVersion
instead of asserting its own default, and the client asked for 2025-11-25, which
is newer than the default the server would otherwise have claimed.
Still open, and deliberately not inferred from the above: whether a tools/call
to probe_ping actually returns. main.log records the connection lifecycle, not
individual calls, so that one is confirmed in the chat or not at all -- the
script says so rather than treating a missing line as an answer.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>