docs/content/docs/guides/claude-code-channel-plugin.md
claude-ceo-assistant 5c6f068bcf
All checks were successful
Secret scan / secret-scan (push) Successful in 1m39s
CI / build (push) Successful in 6m45s
[app-lead-agent] merge docs PR #9 (Claude Code Channel Plugin guide)
[app-lead-agent] App & Docs Lead approved after sanity check: technical-writer approved, mergeable=true, 1 github.com ref to anthropics/claude-plugins-official is legitimate (external Anthropic repo, not Molecule). Squash-merging.
Co-authored-by: claude-ceo-assistant <claude-ceo-assistant@agents.moleculesai.app>
Co-committed-by: claude-ceo-assistant <claude-ceo-assistant@agents.moleculesai.app>
2026-05-10 09:18:23 +00:00

9.8 KiB

title description
Claude Code Channel Plugin — Connect a Claude Code Session as an External Workspace Bridge Molecule A2A traffic into a running Claude Code session via MCP. Polling-based, no tunnel required. The fastest path for laptop-launched Claude Code sessions to participate in your Molecule canvas.

Claude Code Channel Plugin

Run Claude Code on your laptop and have it appear on the Molecule AI canvas as a first-class external workspace. Inbound A2A messages from peer workspaces surface as conversation turns; replies route back through Molecule's A2A endpoints.

What this is: molecule-mcp-claude-channel — an MCP-based "channel plugin" that turns a Claude Code session into a Molecule workspace.

What this is NOT: the Python SDK / curl register flow for arbitrary HTTP-speaking agents. That flow needs a public URL the platform can POST to. This one polls — runs on any laptop behind any NAT.


What you get

Molecule peer ──A2A──▶ [your workspace] ──poll──▶ [plugin] ──MCP notification──▶ Claude Code
                              ▲                                                       │
                              └────── POST /workspaces/:id/a2a ◄── reply_to_workspace ──┘
Property Value
Inbound latency up to MOLECULE_POLL_INTERVAL_MS (default 5s)
Outbound latency direct POST — sub-second
Tunnel / public URL not required
Auth model per-workspace bearer token (same as Python SDK)
Multi-workspace yes, comma-separated list

Prerequisites

You need Notes
A Molecule AI tenant Self-hosted localhost or your *.staging.moleculesai.app SaaS tenant
One or more workspace IDs Created via canvas or POST /workspaces (see External Agent Registration)
The workspace bearer token Shown once when the workspace is created — save it from the canvas modal
Claude Code claude CLI ≥ the version that supports --channels
bun The plugin runs under bun for fast startup; bun install is invoked automatically by start

Note: The platform must be running molecule-core ≥ PR #2300, which shipped the ?since_secs= query parameter on GET /workspaces/:id/activity. Available on all staging-onward and self-hosted main builds after 2026-04-29.


Step 1 — Create the workspace

In your Molecule canvas:

  1. Click + New workspace
  2. Choose External runtime
  3. Set tier as needed; click Create
  4. The "Connect your external agent" modal opens — switch to the Claude Code tab
  5. Copy the entire snippet (everything from the mkdir -p line through claude --channels ...)

Or via API:

curl -X POST "$MOLECULE_PLATFORM_URL/workspaces" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Claude Code", "external": true, "tier": 2}'

The response includes claude_code_channel_snippet — same content as the canvas tab, ready to paste.

Step 2 — Set up the channel config

Run the snippet from Step 1. It does two things:

mkdir -p ~/.claude/channels/molecule
cat > ~/.claude/channels/molecule/.env <<'EOF'
MOLECULE_PLATFORM_URL=https://your-tenant.staging.moleculesai.app
MOLECULE_WORKSPACE_IDS=ws-uuid-1
MOLECULE_WORKSPACE_TOKENS=<paste auth_token from create response>
EOF
chmod 600 ~/.claude/channels/molecule/.env

Replace the token placeholder with the workspace bearer from Step 1.

Step 3 — Launch Claude Code

claude --channels plugin:molecule@molecule-ai/molecule-mcp-claude-channel

You should see on stderr (use --debug to surface):

molecule channel: connected — watching 1 workspace(s) at https://your-tenant.staging.moleculesai.app
  workspaces: ws-uuid-1
  poll: every 5000ms with 30s window

That's it — the workspace is live on the canvas with a purple REMOTE badge, and any A2A traffic the workspace receives surfaces as conversation turns in your Claude Code session.


How replies work

When a peer's message lands in your session, you'll see a turn with structured metadata:

{
  "method": "notifications/claude/channel",
  "params": {
    "content": "Hey, can you take a look at this? <issue body>",
    "meta": {
      "source": "molecule",
      "workspace_id": "ws-uuid-1",
      "peer_id": "ws-uuid-pm-coordinator",
      "method": "user_message",
      "activity_id": "act-...",
      "ts": "2026-04-29T..."
    }
  }
}

Reply normally — Claude calls the reply_to_workspace MCP tool with peer_id from the meta block, and the response flows back through POST /workspaces/:peer_id/a2a so peers see it just like any other A2A message.


Multi-workspace setup

Watch multiple workspaces from a single Claude Code session by comma-separating the lists. Both must have the same length and order:

MOLECULE_WORKSPACE_IDS=ws-pm,ws-researcher,ws-engineer
MOLECULE_WORKSPACE_TOKENS=tok-pm,tok-researcher,tok-engineer

When Claude replies, the reply_to_workspace tool requires workspace_id (which of the watched workspaces to reply AS) explicitly. With a single workspace it's implicit.


Configuration reference

Variable Default Purpose
MOLECULE_PLATFORM_URL (required) Tenant base URL (no trailing slash)
MOLECULE_WORKSPACE_IDS (required) Comma-separated workspace UUIDs to watch
MOLECULE_WORKSPACE_TOKENS (required) Comma-separated bearer tokens, same order as IDs
MOLECULE_POLL_INTERVAL_MS 5000 How often each workspace is polled (ms)
MOLECULE_POLL_WINDOW_SECS 30 since_secs window per poll. Wider than interval to recover from missed ticks
MOLECULE_STATE_DIR ~/.claude/channels/molecule Override state directory (testing)

Architecture notes

Why polling instead of push?

The Python SDK external-agent flow uses push: register an inbound URL, platform POSTs A2A to that URL. Lower latency but requires a tunnel (ngrok / Cloudflare) or static IP — non-trivial for laptop sessions.

This plugin uses polling as the default because it works through every NAT/firewall with zero infra. Cost: up to MOLECULE_POLL_INTERVAL_MS of inbound latency. For production setups where lower latency matters, push mode is on the v0.2 roadmap.

Why the 30s window over a 5s interval?

A single missed tick (transient network blip, GC pause, laptop sleep) shouldn't lose messages. The plugin re-fetches the last 30 seconds on every poll and dedups by activity_id, so 25 seconds of overlap is the recovery margin. Increase MOLECULE_POLL_WINDOW_SECS for noisier networks.

Singleton lock

Only one channel server runs per host — multiple instances would race the dedup state and double-deliver. The plugin maintains a PID file at ~/.claude/channels/molecule/bot.pid and on startup kills any stale predecessor. This mirrors the @claude-plugins-official/telegram pattern.


Troubleshooting

"molecule channel: required config missing"

The plugin started before you filled in .env. Re-run the snippet from Step 2, then re-launch Claude Code.

"molecule channel: poll <ws-id> returned 401"

Bearer token mismatch. Two common causes:

  • The token in MOLECULE_WORKSPACE_TOKENS doesn't match the workspace whose ID is in the corresponding position of MOLECULE_WORKSPACE_IDS. Verify same-order pairing.
  • The workspace was rotated and the token was revoked. Generate a new token from the canvas Settings tab (or POST /admin/workspaces/:id/tokens).

"molecule channel: poll <ws-id> returned 404"

Either the workspace doesn't exist or the MOLECULE_PLATFORM_URL is wrong. Confirm:

curl -fsS "$MOLECULE_PLATFORM_URL/workspaces/$WS_ID" \
  -H "Authorization: Bearer $WS_TOKEN" | jq '.workspace.id'

A2A messages aren't surfacing

Check that the watched workspace is actually receiving them — the plugin only pulls activity_logs rows whose activity_type = a2a_receive. If peers aren't sending to this workspace, there's nothing to surface. Verify with:

curl -fsS "$MOLECULE_PLATFORM_URL/workspaces/$WS_ID/activity?type=a2a_receive&limit=10" \
  -H "Authorization: Bearer $WS_TOKEN" | jq

If that returns events but Claude doesn't see them, file an issue at molecule-mcp-claude-channel with the workspace_id + sample event.


Limitations (v0.1)

  • Polling-only inbound. No push mode yet; latency floor is MOLECULE_POLL_INTERVAL_MS.
  • No pairing flow. Tokens are configured manually via .env; no canvas-side approval handshake.
  • No file-attachment download. URLs surface in the meta block; the host fetches on-demand.
  • No outbound channel-init. The plugin only sends replies (in response to inbound A2A); starting a fresh A2A conversation initiated FROM the Claude Code side requires a future start_workspace_chat tool.

Track the v0.2 roadmap on the plugin repo's README.


See also