Skip to main content
Glama
claude-opencode-mcp-v2
by choruzo

claude-opencode-mcp

claude-opencode-mcp-v2 is a port of putuandy/claude-opencode-mcp (MIT) to the OpenCode 2.x HTTP API (/api/*, tested on 2.0.22). It does not work with OpenCode 1.x. Differences: one shared server for all workspaces, SSE-based completion, diffs from the server, agents named researcher / reviewer / coder / tester (the old deepseek-* names are still accepted). See docs/v2-migration.md and research/FINDINGS.md. Status: alpha.

CI License: MIT Node

An MCP server that lets Claude Code delegate software-engineering tasks to OpenCode agents — with the model and provider you choose — while keeping every agent inside the same workspace/worktree.

Claude Code (orchestrator)
     │  MCP
     ▼
claude-opencode-mcp (this bridge)
     │  workspace + task + agent
     ▼
OpenCode (agent runtime: tools, sessions, permissions)
     │
     ▼
your model provider (anything configured in OpenCode)
     │
     ▼
your repository — the same working tree Claude Code is using

Claude Code stays in charge: it decomposes the work, picks agents, reviews the results and integrates changes. OpenCode does the repository exploration, editing and test execution. The bridge is deliberately thin.

Features

  • Seven focused MCP tools — delegate_task, create_session, send_message, get_session, get_diff, abort_session, list_agents.

  • Same worktree — the delegated OpenCode server runs with your project as its working directory; the agent reads and edits the real files.

  • Persistent sessions — follow-up messages keep the agent's context across separate MCP calls.

  • Four agent profiles — researcher, reviewer, coder, tester, each with permissions enforced by OpenCode (not by prompt wording).

  • Workspace boundaries — canonical paths, allowed roots, path-traversal rejection, and a per-run probe that proves the server is serving the right directory.

  • Safety defaults — .env/credential protection, git commit/git push denied, external directories denied, no ask rules that could hang a headless run.

  • Structured results — every tool returns JSON with stable error codes, and get_diff gives Claude Code the exact changes a coding session made.

  • Reliability — timeouts, cancellation, health checks, crash detection, graceful shutdown, request IDs and a rotating log file.

Related MCP server: mcp-opencode

Requirements

Component

Version

Node.js

20 or newer

Claude Code

recent 2.x

OpenCode

2.x (tested against 2.0.22; 1.x is not supported)

Model provider

Any provider configured in OpenCode. None is assumed: your OpenCode default model, or one you set per agent

Install

The package is published on npm (alpha channel):

npm install -g claude-opencode-mcp-v2@alpha

or run it on demand with npx -y claude-opencode-mcp-v2@alpha (recommended for .mcp.json). It installs two executables, claude-opencode-mcp-v2 (the MCP server) and claude-opencode-v2 (same binary).

The bridge finds OpenCode in PATH, in node_modules/.bin, in ~/.opencode/bin, or at an explicit OPENCODE_BIN / opencode.binary.

From source

git clone https://github.com/choruzo/claude-opencode-mcp-v2.git
cd claude-opencode-mcp-v2
npm install
npm run build
npm install -g .

Claude Code setup

The repository is also a Claude Code plugin marketplace. The opencode-bridge plugin bundles the MCP server and the opencode-delegation skill, which teaches Claude when to delegate, how to write self-contained briefs, the coder → reviewer + tester workflow, safe parallelism and how to handle each error code.

/plugin install opencode-bridge --marketplace choruzo/claude-opencode-mcp-v2

On older Claude Code versions, add the marketplace first:

/plugin marketplace add choruzo/claude-opencode-mcp-v2
/plugin install opencode-bridge@claude-opencode-mcp-v2

The plugin runs the server with npx -y claude-opencode-mcp-v2@alpha and a 40-minute tool timeout. Its tools appear as mcp__plugin_opencode-bridge_opencode__*. Don't also register the server through .mcp.json, or Claude will see two copies of every tool.

To try a local checkout: claude --plugin-dir /path/to/claude-opencode-mcp-v2.

Option B — project .mcp.json (MCP server only, no skill)

Create .mcp.json in your project root:

{
  "mcpServers": {
    "opencode": {
      "command": "npx",
      "args": ["-y", "claude-opencode-mcp-v2@alpha"],
      "type": "stdio",
      "timeout": 2400000
    }
  }
}

timeout is milliseconds and is a per-tool-call wall-clock limit. Delegated runs are long; without it Claude Code falls back to MCP_TOOL_TIMEOUT. Claude Code also moves main-conversation tool calls to a background task after two minutes, which is fine — the result arrives when the run finishes.

Option C — claude mcp add

claude mcp add opencode --scope project -- npx -y claude-opencode-mcp-v2@alpha

Or for one machine only:

claude mcp add opencode --scope user -- npx -y claude-opencode-mcp-v2@alpha

Verify:

claude mcp list        # opencode ... ✔ Connected

Inside Claude Code, /mcp shows the server and its seven tools.

The bridge reads CLAUDE_PROJECT_DIR, which Claude Code sets for stdio MCP servers, so delegation defaults to the project you launched Claude Code in.

OpenCode setup

The bridge starts and stops its own headless OpenCode server, so you do not need to run opencode serve yourself. You only need OpenCode 2.x installed and at least one provider authenticated.

  1. Install OpenCode 2.x and check the version

    opencode --version     # 2.x
  2. Authenticate a provider (once), or define it in your OpenCode config

    opencode auth login
  3. List the models you can use — the ids you will put in the bridge config are provider/model:

    opencode models
    # nan/deepseek-v4-flash
    # nan/glm5.3-flash
    # ...
  4. (Optional) validate the project

    cd my-project
    claude-opencode-v2 init

    init only creates .claude-opencode/ and validates the environment; it never modifies source code and is not required for delegation.

The OpenCode server started by the bridge also loads your global OpenCode config (~/.config/opencode), including its MCP servers and providers.

If you prefer to control OpenCode yourself, start opencode serve and point the bridge at it with opencode.url (plus opencode.password or OPENCODE_SERVER_PASSWORD, user opencode); see docs/configuration.md.

Choose a model per agent

Nothing is assumed: if you configure nothing, every agent uses your own default model in OpenCode. To pick models, create ~/.config/claude-opencode-mcp/config.json (all projects) or .claude-opencode/config.json in a project:

{
  "agents": {
    "researcher": { "model": "nan/deepseek-v4-flash" },
    "reviewer":   { "model": "nan/deepseek-v4-flash" },
    "tester":     { "model": "nan/deepseek-v4-flash" },
    "coder":      { "model": "nan/glm5.3-flash" }
  }
}

Use the exact provider/model ids from opencode models. Order of precedence: the model argument of a tool call, then agents.<name>.model, then defaults.model, then your OpenCode default. A bare id (no provider/) is looked up in OpenCode's catalog and must match exactly one provider. Full reference: docs/configuration.md and docs/agent-configuration.md.

Quick start

Restart Claude Code, then ask:

Use the opencode MCP server to have researcher map this repository: entry points, main modules, and where authentication lives.

Then something that edits:

Have coder add input validation to src/api/users.ts, run the tests, and report what changed. Then show me the diff with get_diff.

And a full workflow:

Ask the agents to inspect the authentication system, identify potential issues, implement a fix, and review the changes.

Claude Code typically orchestrates: researcher → coder → reviewer → tester, calling get_diff between steps.

Tools

All tools return JSON in content[0].text (mirrored in structuredContent). Errors return isError: true with { "error": { "code", "message", ... } }.

delegate_task

Run one task in a fresh session and wait for the agent's answer.

{
  "task": "Review the authentication implementation for bugs and security issues.",
  "agent": "reviewer",
  "cwd": "/Users/andy/projects/my-app",
  "paths": ["src/auth", "src/middleware", "tests/auth"],
  "model": "deepseek/deepseek-v4-pro",
  "timeout": 2400000,
  "allow_edits": false
}

Returns { status, session_id, agent, cwd, model, summary, findings, files_changed, changed_files, duration_ms, truncated, usage?, error? }.

  • files_changed is the number of changed files; changed_files lists them as { file, status, additions, deletions } (first 100). Use get_diff for the patch.

  • usage is { cost, input_tokens, output_tokens, reasoning_tokens, cache_read_tokens, cache_write_tokens } added up over the run's assistant messages, as OpenCode reports them (cost in USD; 0 for free models). It is omitted when OpenCode reports no usage.

  • Only one editing run (coder, or any agent with allow_edits: true) at a time per workspace: another editing run whose cwd is the same directory, a parent or a child fails with WORKSPACE_BUSY (retryable) instead of overwriting it. Read-only runs are not affected. The guard is per bridge process, so it does not see a second Claude Code session.

  • paths are exploration hints, not a boundary — the agent may inspect the whole workspace.

  • allow_edits / allow_bash grant or revoke edits and shell commands for the run (safe permission profiles; sensitive files and git history stay protected).

  • findings are parsed from a ## Findings section: - [severity: high] Title (path/to/file:42) — detail.

create_session

{ "cwd": "/abs/path", "agent": "researcher", "model": null, "title": "auth investigation", "allow_edits": true }

Returns { session_id, cwd, agent, model, title, status, can_edit, can_run_bash, created_at }. Permission overrides set here persist for the session.

send_message

Continue a session; the agent keeps its context and permission level.

{ "session_id": "ses_...", "message": "Now implement the fix.", "allow_edits": true, "timeout": 900000 }

allow_edits / allow_bash may change the level from this message onward. timeout (milliseconds, optional) overrides the bridge's execution timeout for this message. Returns the same result as delegate_task, with usage for this message only.

get_session

Returns the stored session state plus live OpenCode status (opencode.status is idle, busy or retry when a server is running), and usage added up over every run of the session.

get_diff

Returns the changes associated with a session:

  • OpenCode's own session diff when the server reports one (source: "opencode"), otherwise

  • a git diff against a baseline captured when the session was created (source: "git"), so pre-existing uncommitted work is not attributed to the agent. OpenCode does not always report edits made by the agent's tools, so this fallback is what usually answers inside a git repository. The same fallback feeds files_changed and changed_files. Outside a git repository only OpenCode's diff is available.

Returns { source, files, diff, truncated, note? }.

abort_session

Stops a running delegation. Safe to call when the session is idle.

list_agents

Lists the built-in agents plus project-local agents from .claude-opencode/agents/, with read_only, can_edit, can_run_bash flags.

Agents

Agent

Purpose

Edit default

Shell default

researcher

architecture, exploration, dependency analysis, recommendations

deny

deny

reviewer

code review, bugs, regressions, security, architecture

deny

deny

coder

implementation, refactoring, running tests and fixing failures

allow

allow (no git commit/git push)

tester

run tests, inspect failures, root causes, suggested fixes

deny

allow (no git commit/git push)

The orchestrator is not limited to those defaults: every tool that starts or continues a run accepts allow_edits and allow_bash (true grants, false revokes, omitted keeps the default). Grants map to safe permission profiles, so allow_edits: true still protects .env/credential files and allow_bash: true still denies git history changes. A researcher with write access is one call:

{
  "agent": "researcher",
  "task": "Investigate the caching layer, then implement and test the fix.",
  "allow_edits": true,
  "allow_bash": true
}

Agent prompts live in agents/ and are loaded into the OpenCode server configuration at startup. Project-local copies in .claude-opencode/agents/*.md override the prompt, description, model and temperature; permissions always come from the bridge policy (configurable through security.* and the per-call overrides).

See docs/agent-configuration.md for frontmatter details and custom agents.

Workspace model

Resolution order for every call:

  1. explicit cwd argument

  2. CLAUDE_PROJECT_DIR (set by Claude Code)

  3. the MCP server process working directory

  4. workspace.defaultCwd from configuration

The first two are required: if they are present but invalid, the call fails instead of silently using a different directory.

Always pass cwd explicitly. Without it (and without CLAUDE_PROJECT_DIR) the workspace is the directory the bridge was started in, which may be a parent of your project. Agents, including tester, then run from there and e.g. fail to find the project's tests. The resolved cwd is returned in the result so you can check it.

Validation happens before any session is created:

  • the path must exist, be a directory, and be readable;

  • it is canonicalized with realpath;

  • when workspace.allowedRoots is set, the canonical path must live inside one of those roots (traversal is rejected);

  • the git root is detected for diff isolation.

During the first request for a workspace the bridge reads back directory from the OpenCode server and compares it with the requested path, so a misrouted request can never reach the wrong repository.

A single OpenCode 2 server is started (or opencode.url is used) and shared by all workspaces; each session is bound to its directory through location.directory.

Security

Control

Default

Where

Workspace must exist, be readable, be a directory

always

bridge

workspace.allowedRoots containment

disabled (empty)

config

Path hints cannot escape the workspace

always

bridge

.env/.env.*, keys, credentials, .ssh/* protection

on, even when edits are granted

OpenCode permissions

git commit / git push for shell-enabled agents

denied, even when shell is granted

OpenCode permissions

Paths outside the workspace

denied

OpenCode external_directory

Subagent spawning (task)

denied

OpenCode permissions

Interactive questions (question)

denied (headless)

OpenCode permissions

ask permission rules

never emitted by the bridge

OpenCode permissions

The bridge also listens to OpenCode's event stream and auto-rejects any permission request that would otherwise wait for a human, so a delegated run can never hang on approval.

Caveats, stated plainly:

  • A shell-enabled agent (coder, tester) can technically write files through shell commands. The bridge denies the edit tools for the tester and forbids git history changes for both, but shell access is inherently powerful.

  • .env protection applies to the file tools. A shell-enabled agent could still cat a file through bash; the OpenCode project permission model has the same property.

  • When connecting to an external OpenCode server (opencode.url), the bridge cannot inject agent permissions. It verifies the agents exist and refuses to run otherwise.

Details and hardening options: docs/security.md.

Configuration

Global file: ~/.config/claude-opencode-mcp/config.json (honours XDG_CONFIG_HOME). Project file: <project>/.claude-opencode/config.json (overrides global). Extra file: CLAUDE_OPENCODE_CONFIG=/path/to/config.json (highest precedence).

{
  "opencode": {
    "url": null,
    "autoStart": true,
    "hostname": "127.0.0.1",
    "port": 0,
    "startupTimeout": 30000,
    "binary": null,
    "username": null,
    "password": null
  },
  "workspace": {
    "allowedRoots": [],
    "defaultCwd": null
  },
  "defaults": {
    "agent": "researcher",
    "provider": null,
    "model": null
  },
  "timeouts": {
    "execution": 2400000
  },
  "security": {
    "protectEnvFiles": true,
    "denyGitPush": true,
    "denyGitCommit": true,
    "externalDirectory": "deny",
    "extraProtectedPatterns": []
  },
  "limits": {
    "summaryChars": 16000,
    "sessionChars": 20000,
    "diffChars": 60000
  },
  "agents": {
    "researcher": { "model": "deepseek/deepseek-v4-pro" }
  }
}
  • defaults.model accepts provider/model or a bare model id (completed with defaults.provider if set, otherwise looked up in OpenCode's catalog; ambiguous ids are rejected). When null, your own default model from OpenCode is used.

  • Provider credentials stay in OpenCode (opencode auth login) or environment variables; they are never duplicated in this config.

  • For auto-started servers the bridge passes OPENCODE_SERVER_USERNAME / OPENCODE_SERVER_PASSWORD through and authenticates its own requests. For external URLs it only uses credentials you configure.

Full reference: docs/configuration.md.

Sessions

  • Sessions are OpenCode sessions; the bridge keeps a small registry at ~/.local/state/claude-opencode-mcp/sessions.json (override with CLAUDE_OPENCODE_STATE_DIR) so get_session, get_diff and send_message survive a bridge restart.

  • Records older than 14 days are pruned at startup.

  • If an OpenCode server restarts, persisted sessions are still addressable; get_session reports live status when a server is running.

  • Logs: ~/.local/state/claude-opencode-mcp/bridge.log (rotated at 5 MB). Set CLAUDE_OPENCODE_LOG=debug|info|warn|error|silent.

Troubleshooting

Symptom

Fix

OPENCODE_NOT_AVAILABLE

npm install -g opencode-ai or set OPENCODE_BIN / opencode.binary.

OPENCODE_START_TIMEOUT

run opencode serve manually to see the error; raise opencode.startupTimeout; check OPENCODE_SERVER_PASSWORD handling.

MODEL_NOT_AVAILABLE

authenticate a provider (opencode auth login) or set defaults.model, e.g. "deepseek/deepseek-v4-pro".

ProviderAuthError in a result

The provider credentials are missing or expired; re-run opencode auth login.

AGENT_NOT_FOUND with an external server

add the four agents to that server's config or stop using opencode.url.

AGENT_TIMEOUT

raise timeouts.execution or the timeout argument; consider a narrower task.

WORKSPACE_NOT_ALLOWED

add the project to workspace.allowedRoots or clear the list.

Tool call seems to hang in Claude Code

Claude Code backgrounds long calls after 2 minutes; progress notifications are sent, and the bridge always resolves or aborts — check bridge.log.

Claude Code kills the call at 60s

set "timeout": 2400000 in the .mcp.json entry (or MCP_TOOL_TIMEOUT).

More: docs/troubleshooting.md.

Development

npm install
npm run lint        # Biome
npm run typecheck
npm test            # unit + integration (no OpenCode needed)
npm run build

Real end-to-end tests need an OpenCode 2.x install with a provider authenticated:

npm run test:e2e                                  # checkpoints: workspace, agents, sessions, diff, abort, stdio
CLAUDE_OPENCODE_E2E_WORKFLOW=1 npm run test:e2e   # full researcher → coder → reviewer → tester workflow

Layout:

src/
  index.ts              CLI entry (MCP server + `init`)
  cli/                  `claude-opencode-v2 init`
  config/               configuration loading and merging
  workspace/            resolver, validator, task context
  security/             path policy + OpenCode permission profiles
  opencode/             binary resolution, manager, client, agents, sessions, runner
  mcp/                  MCP server and the seven tools
agents/                 built-in agent prompts
tests/                  unit, integration, e2e
docs/                   documentation

See docs/development.md and docs/architecture.md.

Documentation

Contributing

Bug reports, feature requests, and pull requests are welcome. Start with CONTRIBUTING.md; for vulnerabilities use SECURITY.md instead of a public issue.

License

MIT — see LICENSE.

Available Tools

7 tools
abort_sessionAbort a running delegated sessionA
Destructive

Stop a long-running or unwanted delegated task. Safe to call when the session is already idle.

Inputs: session_id (required).

create_sessionCreate a persistent OpenCode agent sessionA

Create a persistent delegation session in a workspace without running a task yet. Follow up with send_message to keep the agent's context between calls.

Inputs: cwd (required), agent, model, title, +2 more.

delegate_taskDelegate task to OpenCode agentA

Delegate a software-engineering task to an OpenCode agent (DeepSeek by default) that runs in the same workspace. The agent explores the repository itself and returns a concise summary plus structured findings. Every agent can be granted or denied edits and shell access per call with allow_edits / allow_bash; grants still enforce the bridge security policy (sensitive-file protection for edits, no git history changes for shell). Returns { status, session_id, summary, findings, files_changed }.

Inputs: task (required), cwd, agent, model, +4 more.

get_diffInspect changes made in a sessionB
Read-only

Return the file changes made by a delegated session, as reported by OpenCode (GET /api/session/{id}/diff).

Inputs: session_id (required).

get_sessionGet delegated session stateA
Read-only

Return the stored state of a delegated session plus its live OpenCode status when a server is running. Use get_diff to inspect file changes.

Inputs: session_id (required).

list_agentsList available delegated agentsA
Read-only

List the agents that delegate_task and create_session can use, including project-local agents from .claude-opencode/agents.

Inputs: cwd.

send_messageSend a follow-up message to a sessionA

Continue an existing delegated session with another message. The agent keeps its previous context and its permission level; allow_edits / allow_bash can change that level for this and later messages.

Inputs: message (required), session_id (required), allow_bash, allow_edits.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 7 tools

    Disambiguation4/5

    Most tools map cleanly to distinct resources and actions (get_session/get_diff/abort_session/list_agents). The only fuzzy boundary is delegate_task vs. create_session+send_message, since a one-shot task is essentially create+send combined, but the descriptions explicitly distinguish one-shot vs. persistent session workflows.

    Naming Consistency5/5

    Every tool follows a clean verb_noun pattern (delegate_task, create_session, send_message, get_session, get_diff, abort_session, list_agents). No style mixing or vague verbs.

    Tool Count5/5

    Seven tools is well-scoped for a delegation bridge: session lifecycle, message continuation, diff inspection, abort, and agent discovery. Each tool earns its place with no redundant surface.

    Completeness4/5

    The session lifecycle is well covered (create, send, get, diff, abort, delegate, list_agents). Minor gaps: no list_sessions to enumerate existing sessions and no explicit close/delete, though abort_session partially fills the teardown role.

    Maintenance

    ActivityMaintained
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers