feat(mcp): notifications/claude/channel for push-feel inbox UX - #2433
Merged
Merged
Conversation
Adds a notification seam to the universal molecule-mcp wheel so push- notification-capable MCP hosts (Claude Code today; any compliant client tomorrow) get inbound A2A messages as conversation interrupts instead of having to poll wait_for_message / inbox_peek. Wire-up: - inbox.py: module-level _NOTIFICATION_CALLBACK + set_notification_callback() Fires from InboxState.record() AFTER lock release, with same dict shape inbox_peek returns. Best-effort — a raising callback never prevents the message from landing in the queue. - a2a_mcp_server.py: _build_channel_notification() pure helper + bridge wiring in main() that schedules notifications via asyncio.run_coroutine_threadsafe (poller is a daemon thread, MCP loop is asyncio). - Method name 'notifications/claude/channel' matches the contract documented in molecule-mcp-claude-channel/server.ts:509. - wheel_smoke.py: pin set_notification_callback as a published name, same regression class as the 0.1.16 main_sync incident. Pollers (wait_for_message / inbox_peek) keep working unchanged for runtimes without notification support. Tests: 6 new in test_inbox.py (callback fires once on record, dedupe short-circuits before fire, raising cb doesn't break inbox, set/clear semantics), 5 new in test_a2a_mcp_server.py (method name pin, content mapping, meta routing, no-id JSON-RPC notification spec, missing- field tolerance). All 59 combined tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HongmingWang-Rabbit
requested a review
from hongmingwang-moleculeai
as a code owner
May 1, 2026 03:10
HongmingWang-Rabbit
enabled auto-merge
May 1, 2026 03:10
This was referenced May 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a notification seam to the universal
molecule-mcpwheel so MCP hosts that support push-style notifications (Claude Code today; any compliant client tomorrow) get inbound A2A messages as conversation interrupts instead of having to pollwait_for_message/inbox_peek.The method name
notifications/claude/channelmatches the existing contract from themolecule-mcp-claude-channelbun bridge — same wire shape, now native to the universal wheel. Pollers continue to work unchanged for runtimes without notification support.inbox.py— module-level_NOTIFICATION_CALLBACK+set_notification_callback(). Fires fromInboxState.record()AFTER lock release with the same dict shapeinbox_peekreturns. Best-effort: a raising callback never prevents the message from landing in the queue.a2a_mcp_server.py—_build_channel_notification()pure helper (unit-testable wire shape) + bridge wiring inmain()that schedules notifications viaasyncio.run_coroutine_threadsafe(the inbox poller is a daemon thread; the MCP server loop is asyncio).wheel_smoke.py— pinset_notification_callbackas a published wheel surface, same regression class as the 0.1.16main_syncincident.Test plan
tests/test_inbox.py— 6 new tests: callback fires withto_dict()payload, dedupe short-circuits BEFORE fire (no duplicate notifications on backlog overlap), raising callback doesn't crash the inbox,set/Nonesemanticstests/test_a2a_mcp_server.py— 5 new tests: method name pin (matchesmolecule-mcp-claude-channelserver.ts:509), content↔text mapping, meta routing fields, noidfield (JSON-RPC notification spec compliance), missing-field toleranceFollow-ups
molecule-docsto surface the push-UX behavior inruntime-mcp.mdx(separate PR — keeps the docs cross-rebase-able if the wire shape needs tweaking)🤖 Generated with Claude Code