From 63ef3b128c874963a63310e5e5a11b1057369b55 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Fri, 1 May 2026 14:01:57 -0700 Subject: [PATCH] docs(mcp): correct server.ts reference + flag verification gap on experimental.claude/channel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to commit 0a87dec5 (PR #2461, merged before live verification). Two corrections to the docstring on `_build_initialize_result()`: 1. The original "mirrors molecule-mcp-claude-channel server.ts:374" claim is wrong on two axes. Line 374 is unrelated poll-init code (a comment inside `registerAsPoll`). The actual capability site is server.ts:475, where the bun bridge declares only `{ capabilities: { tools: {} } }` — *no* `experimental.claude/channel`. The bun bridge is reported to deliver `notifications/claude/channel` successfully in Claude Code despite this, which is direct counter- evidence that adding the capability was the bug fix. 2. The `@modelcontextprotocol/sdk` server's `assertNotificationCapability` does not include `notifications/claude/channel` in any of its switch cases, meaning custom (non-spec) notification methods are sent regardless of declared capabilities. Server-side, the declaration is almost certainly a no-op. This commit doesn't remove the capability — additive, not destructive, and the new tests pin its presence — but downgrades the docstring's certainty so the next person debugging "channel notification didn't fire" doesn't trust a stale claim and pursues the more likely root causes: - writer.drain() swallowing exceptions on a closed pipe - inbox-thread → asyncio.run_coroutine_threadsafe race during init - MCP transport not yet attached when the first inbox event fires Live verification per #2444 §2 (fresh Claude Code session on this wheel with a peer A2A message, observe whether the interrupt fires) remains the open hard-gate. Co-Authored-By: Claude Opus 4.7 (1M context) --- workspace/a2a_mcp_server.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/workspace/a2a_mcp_server.py b/workspace/a2a_mcp_server.py index eb4402aa..70d4b22e 100644 --- a/workspace/a2a_mcp_server.py +++ b/workspace/a2a_mcp_server.py @@ -152,16 +152,28 @@ _CHANNEL_NOTIFICATION_METHOD = "notifications/claude/channel" def _build_initialize_result() -> dict: """MCP initialize handshake result. - The ``experimental.claude/channel`` capability declaration is what - tells Claude Code's MCP client to route our - ``notifications/claude/channel`` emissions as conversation - interrupts (push UX). Without it the notification arrives over the - wire but is silently dropped instead of becoming a ```` - tag in the next agent turn — matching the - "Notification arrives but Claude Code doesn't surface it" failure - mode anticipated in molecule-core#2444. Mirrors the contract - declared by the molecule-mcp-claude-channel bun bridge - (server.ts:374). + Declares ``experimental.claude/channel`` as a *hypothesized* + contract for routing ``notifications/claude/channel`` emissions + into Claude Code as conversation interrupts (push UX). The + failure mode from molecule-core#2444 §2 — "notification arrives + over the wire but is silently dropped instead of becoming a + ```` tag" — motivated this declaration. + + UNVERIFIED: end-to-end push delivery has not been confirmed since + this capability was added. Counter-evidence: the + molecule-mcp-claude-channel bun bridge declares only + ``{ capabilities: { tools: {} } }`` (server.ts:475 — NOT line 374 + as the original commit message claimed; line 374 is unrelated + poll-init code) and is reported to deliver + ``notifications/claude/channel`` successfully in Claude Code. + The MCP SDK's ``assertNotificationCapability`` also does not gate + custom (non-spec) notification methods on a declared capability, + so server-side this declaration is likely a no-op. If push UX is + still missing after this ships, the real fault probably lives + in writer.drain swallowing on closed pipes, the inbox-thread → + asyncio loop bridge, or initialize-ordering between the inbox + callback and the MCP transport — not in this handshake. Treat + this as belt-and-braces until verified. """ return { "protocolVersion": "2024-11-05",