From 9bce00d856ae6ad7a1af34e15fbc17329aa3e5a5 Mon Sep 17 00:00:00 2001 From: "molecule-ai[bot]" <276602405+molecule-ai[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 22:14:59 +0000 Subject: [PATCH] chore: sync opencode.md with main (conflict resolution post PR#842 merge) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR#842 merged the docs/opencode.json to main with the correct MCP URL path. PR#840 branch had an older version — sync to main's content to resolve conflict. --- docs/integrations/opencode.md | 136 ++++++++++++++++------------------ 1 file changed, 62 insertions(+), 74 deletions(-) diff --git a/docs/integrations/opencode.md b/docs/integrations/opencode.md index 370eecfa..741be90c 100644 --- a/docs/integrations/opencode.md +++ b/docs/integrations/opencode.md @@ -1,108 +1,96 @@ -# opencode MCP Integration +# Molecule AI + opencode Integration -Connect [opencode](https://opencode.ai) to the Molecule AI platform so your CLI sessions participate in the A2A mesh — delegate tasks to other workspaces, read shared memory, and send real-time messages to the canvas without leaving the terminal. +> **opencode** is an AI coding agent ([opencode.ai](https://opencode.ai)) that supports remote MCP servers via `opencode.json`. This guide shows how to wire it to your Molecule AI workspace. -## How it works +## Prerequisites -The platform exposes each workspace as a remote MCP server: +- A running Molecule platform (`MOLECULE_MCP_URL` — e.g. `https://api.molecule.ai`) +- A workspace-scoped bearer token (`MOLECULE_MCP_TOKEN`) issued via the platform API -``` -GET /workspaces/:id/mcp/stream — SSE transport (backwards compat) -POST /workspaces/:id/mcp — Streamable HTTP transport (primary) -``` +## 1. Declare Molecule as a remote MCP server -Both endpoints are protected by the workspace bearer token (same credential as the A2A API). The opencode client sends the token in `Authorization: Bearer ` on every request. - -## Quick start - -### 1. Get your credentials - -```bash -# Platform URL (default: http://localhost:8080 for local dev) -export MOLECULE_MCP_URL=http://localhost:8080 - -# Workspace ID — shown in the Canvas sidebar or via: -curl -s $MOLECULE_MCP_URL/workspaces | jq '.[0].id' - -# Bearer token — mint one via: -curl -s -X POST "$MOLECULE_MCP_URL/workspaces/$WORKSPACE_ID/tokens" \ - -H "Authorization: Bearer $ADMIN_TOKEN" | jq -r '.token' -``` - -### 2. Configure opencode - -Copy `org-templates/molecule-dev/opencode.json` to `~/.config/opencode/config.json` -(or merge it into your existing config) and set the environment variables: - -```bash -export MOLECULE_MCP_URL=http://localhost:8080 -export WORKSPACE_ID= -export MOLECULE_MCP_TOKEN= -``` - -Or set them inline in the config (not recommended for tokens): +Create (or extend) `opencode.json` in your project root: ```json { "mcpServers": { "molecule": { "type": "remote", - "url": "http://localhost:8080/workspaces/ws-abc123/mcp", - "headers": { - "Authorization": "Bearer msk_live_abc123..." - } + "url": "${MOLECULE_MCP_URL}/workspaces/${WORKSPACE_ID}/mcp", + "headers": { "Authorization": "Bearer ${MOLECULE_MCP_TOKEN}" }, + "description": "Molecule AI A2A orchestration — delegate_task, list_peers, check_task_status" } } } ``` -### 3. Start opencode +> ⚠️ **Never embed the token in the URL** (e.g. `?token=...`). Always use the `Authorization: Bearer` header. URL-embedded tokens appear in server logs, browser history, and Git history if the file is committed. + +A pre-configured template is available at `org-templates/molecule-dev/opencode.json`. + +## 2. Obtain a workspace-scoped token ```bash -opencode +curl -X POST https://$MOLECULE_MCP_URL/workspaces/$WORKSPACE_ID/tokens \ + -H "Authorization: Bearer $ADMIN_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"name": "opencode-agent", "scopes": ["mcp:read", "mcp:delegate"]}' ``` -The `molecule` MCP server is now available. Type `/tools` in opencode to confirm. +Store the returned token as `MOLECULE_MCP_TOKEN` in your `.env` (see `.env.example`). -## Available tools +## 3. Available tools + +When opencode connects to the Molecule MCP endpoint, the agent gains access to: | Tool | Description | |------|-------------| -| `list_peers` | List reachable workspaces (siblings, parent, children) | -| `get_workspace_info` | Get this workspace's ID, name, role, tier, status | -| `delegate_task` | Synchronous task delegation — waits up to 30 s for a response | -| `delegate_task_async` | Fire-and-forget delegation — returns a `task_id` immediately | -| `check_task_status` | Poll an async task's status and result | -| `commit_memory` | Save information to LOCAL or TEAM persistent memory | -| `recall_memory` | Search LOCAL or TEAM memory | -| `send_message_to_user` | Push a message to the canvas chat *(opt-in, see below)* | +| `list_peers` | Discover available workspaces in your org | +| `delegate_task` | Send a task to a peer workspace and wait for the result | +| `delegate_task_async` | Fire-and-forget task delegation; returns a `task_id` | +| `check_task_status` | Poll an async delegation by `task_id` | +| `commit_memory` | Persist information to LOCAL or TEAM memory scope | +| `recall_memory` | Search previously committed memories | -## Optional: enable send_message_to_user +### Restricted tools -`send_message_to_user` is excluded from the tool list by default to prevent -accidental WebSocket pushes from CLI sessions. To opt in, set: +- **`send_message_to_user`** — disabled for remote MCP callers by default; requires explicit opt-in via `MOLECULE_MCP_ALLOW_SEND_MESSAGE=true` +- **GLOBAL memory scope** — `commit_memory` with `scope: GLOBAL` is blocked for external agents; LOCAL and TEAM scopes are available -```bash -# In the platform's environment (e.g. .env or fly secrets set): -MOLECULE_MCP_ALLOW_SEND_MESSAGE=true +## 4. Example: delegate a research task + +```json +{ + "tool": "delegate_task", + "arguments": { + "target": "research-lead", + "task": "Summarise the last 7 days of commits in Molecule-AI/molecule-monorepo" + } +} ``` -## Rate limiting +opencode sends this tool call to the Molecule MCP endpoint. The platform routes it to your `research-lead` workspace and streams the response back. -The MCP bridge enforces **120 requests / minute / token**. Long-running opencode sessions that issue many tool calls in rapid succession will see `429 Too Many Requests` with a `Retry-After` header. The standard MCP client will back off automatically. +## 5. Security notes -## Security notes +### SAFE-T1401 — org topology exposure +`list_peers` returns the full set of workspace names and roles visible to your workspace. This is intentional: provisioned agents need to know their peers to delegate effectively. Be aware that any opencode agent with a valid `MOLECULE_MCP_TOKEN` can enumerate your org topology. -- **Scope isolation**: `commit_memory` and `recall_memory` only accept `LOCAL` and `TEAM` scopes. `GLOBAL` scope is blocked at the MCP layer (use the internal `a2a_mcp_server.py` for GLOBAL writes from within a workspace container). -- **Access control**: `delegate_task` / `delegate_task_async` verify `CanCommunicate(caller, target)` before forwarding any A2A message — the same check the A2A proxy enforces. -- **Token binding**: each bearer token is bound to a single workspace; cross-workspace impersonation is not possible. +### SAFE-T1201 — tool surface audit pending +The full `@molecule-ai/mcp-server` npm package exposes additional tools beyond those listed above. These are pending a SAFE-T1201 security audit (tracked in #747 follow-on) and **should not be exposed to external agents in production** until that audit completes. -## Troubleshooting +### Token scoping +Issue tokens with the minimum required scopes (`mcp:read`, `mcp:delegate`). Rotate tokens regularly. Revoke via `DELETE /workspaces/:id/tokens/:token_id`. -| Symptom | Likely cause | Fix | -|---------|-------------|-----| -| `401 Unauthorized` | Missing or expired bearer token | Mint a new token via `POST /workspaces/:id/tokens` | -| `403 Forbidden` on `delegate_task` | Target workspace is not a peer | Use `list_peers` to find valid targets | -| `429 Too Many Requests` | Rate limit exceeded | Wait `Retry-After` seconds; reduce call frequency | -| `delegate_task` hangs | Target workspace is offline / hibernated | Check workspace status in Canvas; wake it if hibernated | -| `send_message_to_user` returns permission error | Opt-in env var not set | Set `MOLECULE_MCP_ALLOW_SEND_MESSAGE=true` on the platform | +## 6. Environment variables + +Add to your `.env`: + +```bash +MOLECULE_MCP_URL=https://api.molecule.ai # or http://localhost:8080 for local dev +MOLECULE_MCP_TOKEN= # workspace-scoped bearer token from step 2 +WORKSPACE_ID= # UUID of the agent workspace opencode acts as + # find it in Canvas sidebar or GET /workspaces +``` + +See `.env.example` for the canonical reference.