Independent five-axis review of v0.2.1 surfaced three issues. All
three only manifest after the upgrade-or-die path actually fires,
which is rare in normal operation but exactly the failure mode the
probe was added for — so quiet correctness matters.
1. **CRITICAL: process.exit(2) orphans PID file → cross-process-kill
hazard.** v0.2.1 added a fatal exit on too_old probe response, but
left the PID file pointing at this (about-to-die) process. Next
launch reads PID_FILE, calls `process.kill(stale, 'SIGTERM')` —
the dead PID is now likely owned by an unrelated process, so the
plugin SIGTERMs whatever happens to be there. This is exactly the
bug the singleton lock dance was designed to prevent. Fix: install
a `process.on('exit')` listener that unlinks PID_FILE iff this
process still owns it (handles all exit paths: clean shutdown,
probe failure, unhandledException, etc.). Listener uses sync I/O
(only path 'exit' permits) and is no-op-safe if another process
has already taken ownership of the file.
2. **Probe ran AFTER mcp.connect(transport).** Claude Code had
already finished the MCP initialize handshake when the probe
detected too_old and exited; from Claude's perspective this looked
like "MCP server crashed mid-session" — the carefully-written
stderr explanation isn't surfaced. Probe must run BEFORE
mcp.connect so the failure mode is "server failed to start" with
stderr visible to the user.
3. **Probe ran AFTER registerAsPoll().** If the platform predates
delivery_mode=poll AND since_id (consistent — both shipped under
#2339), registerAsPoll() may have already mutated the workspace's
delivery_mode on the platform. Then the probe fails and we exit,
leaving the workspace in a broken half-configured state. Probe
must run BEFORE registerAsPoll for the same reason it must run
before mcp.connect — fail without side effects.
Reordered boot sequence:
loadCursors → probeCursorSupport (parallel via allSettled) →
mcp.connect → registerAsPoll → poll loop.
Also parallelized the probe with Promise.allSettled — sequentially
it was up to N × 15s on a hung platform, which adds up for
multi-workspace channels.
README updated to document that 401/403/404/5xx from the probe are
treated as inconclusive (orthogonal to cursor support — usually
auth or transient) and the plugin continues; this avoids users
debugging a phantom probe failure when the real issue is their
token.
Bumps to 0.2.2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
15 lines
396 B
JSON
15 lines
396 B
JSON
{
|
|
"name": "molecule-mcp-claude-channel",
|
|
"version": "0.2.2",
|
|
"description": "Molecule AI channel for Claude Code — bridges A2A traffic into a Claude Code session via MCP",
|
|
"license": "Apache-2.0",
|
|
"type": "module",
|
|
"bin": "./server.ts",
|
|
"scripts": {
|
|
"start": "bun install --no-summary && bun server.ts"
|
|
},
|
|
"dependencies": {
|
|
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
}
|
|
}
|