From 34d467fe8a87db66a60dc573b9ddb43fcec0178e Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Wed, 29 Apr 2026 11:33:31 -0700 Subject: [PATCH] docs: surface molecule-mcp-claude-channel plugin in external-workspace creation + CONTRIBUTING MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a third snippet alongside externalCurlTemplate / externalPythonTemplate in workspace-server/internal/handlers/external_connection.go: the new externalChannelTemplate guides operators through installing the Claude Code channel plugin (Molecule-AI/molecule-mcp-claude-channel — scaffolded today) and dropping the .env config for it. Wires the new snippet into the external-workspace POST /workspaces response under key `claude_code_channel_snippet`, alongside the existing `curl_register_template` and `python_snippet`. Canvas's "external workspace created" modal can render it as a third tab. CONTRIBUTING.md gains a short "External integrations" section pointing at the three peer repos (workspace-runtime, sdk-python, mcp-claude-channel) so contributors know where related runtime artifacts live and to consider downstream impact when changing the A2A wire shape. The plugin itself is scaffolded at commit d07363c on the new repo's main branch; v0.1 is polling-based via the /activity?since_secs= filter shipped in PR #2300. README + roadmap details there. Co-Authored-By: Claude Opus 4.7 (1M context) --- CONTRIBUTING.md | 11 +++++++ .../internal/handlers/external_connection.go | 31 +++++++++++++++++++ .../internal/handlers/workspace.go | 11 +++++++ 3 files changed, 53 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a7474110..601533f4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -175,6 +175,17 @@ and run CI manually. - Type hints on public functions - pytest for all tests +## External integrations + +Code in this repo lands in molecule-core. Some related runtime artifacts +live in their own repos: + +- [`Molecule-AI/molecule-ai-workspace-runtime`](https://github.com/Molecule-AI/molecule-ai-workspace-runtime) — Python adapter SDK (`molecule_runtime`) that runs inside containerized Molecule workspaces. Bridges Claude Code SDK / hermes / langgraph / etc. → A2A queue. +- [`Molecule-AI/molecule-sdk-python`](https://github.com/Molecule-AI/molecule-sdk-python) — `A2AServer` + `RemoteAgentClient` for external agents that register over the public `/registry/register` flow. +- [`Molecule-AI/molecule-mcp-claude-channel`](https://github.com/Molecule-AI/molecule-mcp-claude-channel) — Claude Code channel plugin. Bridges A2A traffic into a running Claude Code session via MCP `notifications/claude/channel`. Polling-based (no tunnel required); install with `claude --channels plugin:molecule@Molecule-AI/molecule-mcp-claude-channel`. + +When extending the **A2A surface** in molecule-core (`workspace-server/internal/handlers/a2a_proxy.go` etc.), consider whether the change has a downstream impact on the runtime SDK or the channel plugin — they're versioned independently but share the wire shape. + ## Architecture Overview See `CLAUDE.md` for detailed architecture documentation, including: diff --git a/workspace-server/internal/handlers/external_connection.go b/workspace-server/internal/handlers/external_connection.go index 7a73a37b..12a3abfb 100644 --- a/workspace-server/internal/handlers/external_connection.go +++ b/workspace-server/internal/handlers/external_connection.go @@ -67,6 +67,37 @@ curl -fsS -X POST "{{PLATFORM_URL}}/registry/register" \ }' ` +// externalChannelTemplate — Claude Code channel plugin install + .env. For +// operators whose external agent IS a Claude Code session (laptop or +// remote dev VM); routes the workspace's A2A traffic into the running +// Claude Code session as conversation turns via MCP. The plugin source +// lives at github.com/Molecule-AI/molecule-mcp-claude-channel — polling +// based, no tunnel required (uses /workspaces/:id/activity?since_secs=, +// platform-side support shipped in #2300). +const externalChannelTemplate = `# Claude Code channel — bridges this workspace's A2A traffic into your +# Claude Code session. No tunnel/public URL needed (polling-based). +# +# 1. Save this token + workspace_id, then create ~/.claude/channels/molecule/.env: +mkdir -p ~/.claude/channels/molecule +cat > ~/.claude/channels/molecule/.env <<'EOF' +MOLECULE_PLATFORM_URL={{PLATFORM_URL}} +MOLECULE_WORKSPACE_IDS={{WORKSPACE_ID}} +MOLECULE_WORKSPACE_TOKENS= +EOF +chmod 600 ~/.claude/channels/molecule/.env + +# 2. Launch Claude Code with the channel enabled: +claude --channels plugin:molecule@Molecule-AI/molecule-mcp-claude-channel + +# Inbound A2A messages now surface as conversation turns. Claude's +# replies route back via the reply_to_workspace MCP tool — no extra +# wiring on your side. +# +# Multi-workspace: comma-separate IDs and tokens (same order). See +# https://github.com/Molecule-AI/molecule-mcp-claude-channel for +# pairing flow, push-mode upgrade, and v0.2 roadmap. +` + // externalPythonTemplate uses molecule-sdk-python's RemoteAgentClient + // A2AServer (PR #13 in that repo). Until the SDK cuts a v0.y release // to PyPI the snippet pins git+main. diff --git a/workspace-server/internal/handlers/workspace.go b/workspace-server/internal/handlers/workspace.go index 723b85b6..00d86b7e 100644 --- a/workspace-server/internal/handlers/workspace.go +++ b/workspace-server/internal/handlers/workspace.go @@ -370,6 +370,17 @@ func (h *WorkspaceHandler) Create(c *gin.Context) { "{{PLATFORM_URL}}", platformURL), "{{WORKSPACE_ID}}", id, ), + // Claude Code channel plugin snippet. For operators + // whose external agent IS a Claude Code session — + // the snippet sets up ~/.claude/channels/molecule/.env + // and points at the canonical first-party plugin at + // github.com/Molecule-AI/molecule-mcp-claude-channel. + // Polling-based; no tunnel needed. + "claude_code_channel_snippet": strings.ReplaceAll( + strings.ReplaceAll(externalChannelTemplate, + "{{PLATFORM_URL}}", platformURL), + "{{WORKSPACE_ID}}", id, + ), } } c.JSON(http.StatusCreated, resp)