molecule-core/docs/integrations/runtime-native-mcp-status.md
documentation-specialist 26afbbfdf4
Some checks failed
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 5s
CI / Detect changes (pull_request) Successful in 5s
E2E API Smoke Test / detect-changes (pull_request) Successful in 6s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 6s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 6s
Runtime PR-Built Compatibility / detect-changes (pull_request) Successful in 5s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 5s
CI / Platform (Go) (pull_request) Successful in 3s
CI / Canvas (Next.js) (pull_request) Successful in 5s
CI / Python Lint & Test (pull_request) Successful in 3s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 4s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 8s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 4s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 4s
Runtime PR-Built Compatibility / PR-built wheel + import smoke (pull_request) Successful in 3s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Failing after 12s
CodeQL / Analyze (${{ matrix.language }}) (go) (pull_request) Failing after 51s
CodeQL / Analyze (${{ matrix.language }}) (javascript-typescript) (pull_request) Failing after 1m20s
CodeQL / Analyze (${{ matrix.language }}) (python) (pull_request) Failing after 1m20s
docs(internal): bulk-sed molecule-core .md docs → Gitea (#37 final molecule-core sweep)
Mass-sed across 17 files / 38 active refs in molecule-core .md docs
(README + CONTRIBUTING + docs/architecture/ + docs/blog/ + docs/guides/
+ docs/integrations/ + docs/quickstart.md + scripts/README.md).

Driver: /tmp/sweep_core.py — same pattern set as the
internal-marketing bulk-sed (PR #50). 4 url-substitution patterns +
SKIP_PATTERN preserves /pull/<n> /issues/<n> /commit/<sha>
/releases/... historical refs.

Files NOT touched in this PR:
- docs/workspace-runtime-package.md — owned by molecule-core#15
  (workspace-runtime source-edit per #41). Reverted my bulk-sed of
  that file to avoid merge conflict.
- 2 Go-import-path refs in docs/memory-plugins/testing-your-plugin.md
  (github.com/Molecule-AI/molecule-monorepo/platform/internal/...) —
  Q5 cross-repo Go-module migration territory.
- 1 GitHub Gist link in docs/guides/external-workspace-quickstart.md
  (gist.github.com/molecule-ai/...) — no Gitea equivalent;
  consistent with the same handling in docs#1.

Manual fixes (2):
- docs/blog/2026-04-20-chrome-devtools-mcp-seo/index.md:306 —
  GitHub Discussions (no Gitea equivalent) → issue tracker link
- docs/guides/external-workspace-quickstart.md:218 — tracking-issue
  ?q= query-string url (regex didn't catch) → reformulated text +
  Gitea search-by-query approach

Pattern matches my docs#1 (public docs site) PR + internal#50
(internal/marketing bulk-sed). Standard substitutions:
- https://github.com/Molecule-AI/<repo> → https://git.moleculesai.app/molecule-ai/<repo>
- /blob/<branch>/ + /tree/<branch>/ → /src/branch/<branch>/

Refs: molecule-ai/internal#37, molecule-ai/internal#38
2026-05-07 01:27:50 -07:00

10 KiB

Runtime native-MCP push parity — status

Goal: every workspace runtime delivers Molecule A2A inbox messages with the same UX as claude-code's MCP notifications/claude/channel push: session continuity + queued or interrupted handling of new messages mid-thread, no fresh subprocess per message.

Tracked across four runtime streams. Updated 2026-05-02.


claude-code

Status: Done. Native MCP notifications/claude/channel push shipped via workspace/a2a_mcp_server.py. Requires the host to launch with --dangerously-load-development-channels server:molecule.

No further work.


OpenClaw

Status: Scaffolded; awaiting validation + companion adapter rewrite.

Path: Channel-plugin SDK (openclaw/plugin-sdk), auto-discovered from ~/.openclaw/plugins/<name>/ or workspace .openclaw/. Plugin registers an HTTP webhook on openclaw gateway; Molecule workspace adapter POSTs A2A messages to it; gateway dispatches through the same dispatchReplyWithBufferedBlockDispatcher kernel call native channels (Telegram, Lark, Slack, Discord) use.

Artifacts landed:

  • molecule-ai-workspace-template-openclaw/packages/openclaw-channel-plugin/
    • package.json, openclaw.plugin.json (manifest), index.ts (channel + webhook handler), README.md, tsconfig.json
  • Pre-release v0.1.0-pre. Mirrors rabbit-lark-bot reference plugin shape.

Remaining (task #84, #87):

  1. Validate against a running OpenClaw gateway. Open questions in the plugin README: resolveAgentRoute peer-id shape, dispatchReplyWithBufferedBlockDispatcher async semantics, outbound.sendText no-op safety.
  2. Rewrite Python adapter (adapter.py) to stop shelling out openclaw agent --message ... and instead POST to the plugin's webhook + run /agent-reply callback HTTP server. Post-demo work (touches a working integration).

hermes

Status: Workspace template patch PR #32 MERGED 2026-05-02; image rebuild succeeded; plugin baked into the workspace runtime. Plugin package published. Real-subprocess full-chain E2E (scripts/e2e_full_chain.py) green — proves wire shape end-to-end against a real hermes gateway run subprocess + stub OpenAI-compat LLM. Caught + fixed a real KeyError in upstream hermes_cli/tools_config.py (PLATFORMS dict lookup crashed on plugin platforms) — fix on the patched fork branch (HongmingWang-Rabbit/hermes-agent feat/platform-adapter-plugins, commit 18e4849e). Upstream PR #18775 OPEN; CONFLICTING with main. Not on critical path for our platform — patched fork is what the workspace image installs.

Real A2A peer traffic on staging gated only on running the harness (molecule-core/scripts/test-all-runtimes-a2a-e2e.sh) — script ready, needs provider keys.

Path: Hermes's MODERN plugin system is hermes_cli/plugins.py (not the older plugins/memory/). It already does full discovery across user dir + project dir + pip entry_points (group: hermes_agent.plugins) for tools / hooks / CLI commands / slash commands / context engines / skills. Platform adapters are the only plugin type still hardcoded (gateway/run.py:_create_adapter).

The PR adds three pieces upstream:

  1. PluginContext.register_platform_adapter(name, adapter_class, requirements_check=None)
  2. GatewayConfig.plugin_platforms populated by from_dict for plugin-claimed names
  3. GatewayRunner._create_plugin_adapter(name, config) boot-path fallback

Plus a PluginPlatformIdentifier helper class so plugin adapters can satisfy BasePlatformAdapter.__init__(config, platform: Platform) without extending the closed Platform enum.

Total: ~100 LOC upstream change. External plugin then ships as hermes-platform-molecule-a2a via pip install + entry_points — no fork needed in production.

Artifacts landed:

  • Upstream PR: NousResearch/hermes-agent#18775 — 5 commits on feat/platform-adapter-plugins: registration surface, config + boot wiring, PluginPlatformIdentifier helper, resolve_platform_id for plugin-platform-safe deserialization, and self.adapters[adapter.platform] keying fix (caught by real-subprocess test before merge — see below).
  • Plugin package: Molecule-AI/hermes-platform-molecule-a2a v0.1.0 — public, MIT-licensed. 11 unit tests + 8 in-process E2E
    • 4 real-subprocess E2E checkpoints all green.
  • Workspace template patch: Molecule-AI/molecule-ai-workspace-template-hermes#32 — Dockerfile installs the patched fork + plugin into the hermes installer's venv; start.sh seeds platforms.molecule-a2a config stanza. Pre-demo deliberately install-only; adapter.py rewrite to USE the plugin path is a separate post-demo PR.
  • Real adapter package at ~/hermes-platform-molecule-a2a/:
    • pyproject.toml with hermes_agent.plugins entry point
    • hermes_platform_molecule_a2a/adapter.pyMoleculeA2APlatformAdapter(BasePlatformAdapter) with HTTP listener (aiohttp), inbound MessageEvent(internal=True) dispatch, outbound send() POST to per-chat callback URL, optional shared secret enforcement
    • tests/test_adapter.py11/11 unit tests pass covering plugin entry-point shape, lifecycle, inbound auth, outbound routing
    • scripts/e2e_validate.py — production-path validation (entry points → registry → GatewayConfig → boot → HTTP roundtrip), all 7 checkpoints pass
  • docs/integrations/hermes-platform-plugins-upstream-pr.md — PR draft including problem, prior art, proposal, code shape, backward compat, test plan, and open questions.
  • .hermes-validation/test_register_platform_adapter.py — local 9-check validation of the patched fork via the user-dir discovery path (complementary to the entry-points path tested by the package).

Why no short-term polling shim: earlier framing was wrong. Molecule runtime already polls the inbox via wait_for_message per turn; each polled message fires a fresh execute() on the adapter, which proxies to hermes's stateless /v1/chat/completions. Adding adapter- side polling would be duplicate work. The genuine short-term gap is session continuity (hermes daemon doesn't see a single conversation across turns because chat/completions is stateless), not push latency. That gap is solved by the upstream PR; no intermediate shim earns its complexity.

Remaining:

  1. Upstream PR review/merge (NousResearch/hermes-agent#18775). On maintainers — typical OSS review lag.
  2. Workspace template merge + image republish (PR #32). Once merged, publish-runtime.yml regenerates the hermes workspace image with the plugin baked in. Safe to merge as-is — install-only, no behavior change for current workspaces.
  3. Runtime adapter rewrite (task #87 equivalent for hermes). molecule-ai-workspace-template-hermes/adapter.py currently proxies A2A → /v1/chat/completions. Switching to POST /a2a/inbound is what unlocks single-session continuity. Post-demo timing (touches a working live integration).
  4. Real A2A peer traffic E2E (task #86): boot a real workspace from the republished image, send peer A2A message from another workspace, observe single-session reply. Gated on items 2 + 3.

Codex (OpenAI Codex CLI)

Status: Template SHIPPED. Repo live at Molecule-AI/molecule-ai-workspace-template-codex (14 files, 1411 LOC, 12/12 tests). molecule-core registration in PR #2512. E2E with real A2A traffic remains.

Path: Persistent codex app-server stdio JSON-RPC client (NDJSON-framed, v2 protocol). One app-server child per workspace session; one thread/start per session; each A2A message becomes a turn/start RPC; agent responses arrive as agent_message_delta notifications. Per-thread serialization for mid-turn arrivals (matches OpenClaw's per-chat sequentializer). Optional turn/interrupt for "latest message wins" workspaces.

Artifacts landed:

  • docs/integrations/codex-app-server-adapter-design.md — full design including RPC sequence, executor skeleton, eight open questions.
  • molecule-ai-workspace-template-codex/ — full template repo scaffolded:
    • app_server.py (286 LOC) — async JSON-RPC over NDJSON stdio
    • executor.py (~270 LOC) — thread bootstrap, turn dispatch, notification accumulation, mid-turn serialization
    • adapter.py — thin BaseAdapter shell + preflight
    • Dockerfile, start.sh, config.yaml, requirements.txt, README.md
    • tests/12/12 tests pass (7 vs NDJSON mock child, 5 vs fake AppServerProcess covering executor logic)

Validated against live codex-cli 0.72.0: NDJSON framing, initialize handshake, AND thread/start all work end-to-end. Schema-runtime drift caught: real binary returns thread.id, not thread.threadId as the JSON schema claims. Executor now accepts both shapes; without the smoke test this would have been a production bug.

Remaining (task #85, #86):

  1. Register codex in molecule-core's manifest.json + workspace-server/internal/handlers/runtime_registry.go. Defer to post-demo — touches working live registry.
  2. E2E verification with a real Molecule workspace + peer A2A traffic, per feedback_close_on_user_visible_not_merge.

Cross-cutting (task #86)

End-to-end verification per feedback_close_on_user_visible_not_merge. For each runtime, the closure criterion is not "code merged" but "observed: real workspace boots → A2A message from peer agent → delivered to running session → reply returned through A2A response queue → peer agent receives". No runtime stream closes until that chain is observed.


What's blocking what

Stream Blocked on
claude-code (done)
OpenClaw plugin live gateway validation, then post-demo adapter rewrite
OpenClaw adapter rewrite post-demo timing
hermes upstream PR user confirmation to submit + Discord pre-validation
hermes consumer plugin upstream PR merging
codex implementation resolve 8 open questions, then post-demo eng time
E2E verification each runtime stream completing

Three of four runtime streams are at decision points needing user input. Pre-demo (T-4d to 2026-05-06), the safe move is to land the remaining design + scaffolding work and defer all behavioral changes to post-demo.