devin-mcp-bridge
by phenasdev
README.md
# devin-mcp-bridge
Lets Claude Code delegate work to Devin.
```
Claude Code ──MCP/stdio──▶ devin-mcp-bridge ──ACP/stdio──▶ devin acp
```
Devin ships an [ACP](https://agentclientprotocol.com) agent (`devin acp`), which is what
makes it usable from Zed. Claude Code speaks MCP, not ACP. This process sits in the middle:
it is an ACP *client* toward Devin (spawning the agent, answering its filesystem and
permission requests) and an MCP *server* toward Claude Code.
## Tools
| Tool | Purpose |
| --- | --- |
| `devin_task({ task, cwd? })` | Send a task to Devin, return its full response. Session persists per `cwd`, so follow-up calls keep context. |
| `devin_reset({ cwd? })` | Kill the agent and drop its context. Next `devin_task` starts fresh. |
## Install
```bash
git clone https://github.com/phenasdev/devin-mcp-bridge.git
cd devin-mcp-bridge
npm install
npm run smoke # boots the server, lists tools — no Devin needed
npm run smoke:call # full turn against a fake ACP agent
npm run smoke:sandbox # verifies symlinks cannot escape the session root
```
Register with Claude Code, using an absolute path to your clone:
```bash
# this project only
claude mcp add devin -- node "$PWD/src/devin-mcp.mjs"
# every project
claude mcp add -s user devin -- node "$PWD/src/devin-mcp.mjs"
```
Verify with `/mcp` inside Claude Code. Tool names appear as `mcp__devin__devin_task`.
## Security
Devin runs autonomously and, over ACP, asks *this* process for permission and for filesystem
access. Two controls exist, both on by default:
- **`DEVIN_MCP_PERMISSION=once`** (default) — grant only one-shot permissions; never
`allow_always`, which would remove the decision for the rest of the session.
`all` approves everything including persistent grants. `deny` refuses everything.
- **`DEVIN_MCP_SANDBOX_FS=1`** (default) — `fs/read_text_file` and `fs/write_text_file` are
confined to the session root; paths resolving outside it, including through symlinks, are
rejected. Set `0` to disable. This path check is not an OS sandbox and cannot prevent a
concurrent filesystem race.
When the bridge refuses a request, the turn result carries a `[bridge] ... refused` block naming
the operation and path. Without it a sandbox rejection reaches Claude Code as a bare
`[tool failed]`, indistinguishable from a genuine Devin error.
There is no human in the loop on permission decisions — Claude Code sees one tool call, while
Devin may perform many actions behind it. Before pointing this at a repo you care about,
prefer a disposable worktree or a container, and keep the sandbox on.
## Config
| Env var | Default | Meaning |
| --- | --- | --- |
| `DEVIN_MCP_AGENT_CMD` | `devin` | Agent binary. Set to `npx` to bridge a different ACP agent. |
| `DEVIN_MCP_AGENT_ARGS` | `acp` | Space-separated args. |
| `DEVIN_MCP_PERMISSION` | `once` | `once` \| `all` \| `deny` |
| `DEVIN_MCP_SANDBOX_FS` | `1` | `0` disables the path guard. |
| `DEVIN_MCP_TIMEOUT_MS` | `900000` | Per-turn cap; the turn is cancelled on expiry. |
Because the agent command is configurable, the same bridge works for any ACP agent —
e.g. `DEVIN_MCP_AGENT_CMD=npx DEVIN_MCP_AGENT_ARGS="-y @zed-industries/claude-code-acp"`.
## Debugging
Agent stderr is inherited, so `claude --debug` shows both the bridge's `[devin-mcp]` log lines
and Devin's own output. `claude mcp list` shows connection status.
## Layout
- `src/devin-mcp.mjs` — the bridge; ACP client + MCP server in one process.
- `scripts/fake-agent.mjs` — minimal ACP agent used by the smoke test, so the wiring can be
exercised without opening a real Devin session. It also probes the fs sandbox.
- `scripts/smoke.mjs` — MCP handshake, `tools/list`, and optionally one full turn.
TDQS
A4.2/5.0
Scored across 2 tools
Disambiguation5/5
The two tools have clearly distinct purposes: one sends a task to Devin, the other resets the session. No overlap or confusion possible.
Naming Consistency4/5
Both tools use the 'devin_' prefix and snake_case, but the pattern is slightly inconsistent: 'devin_task' is a noun while 'devin_reset' is a verb. However, the prefix makes them clearly related.
Tool Count4/5
With only 2 tools, the server is minimal. For its purpose as a bridge to an autonomous agent, this is reasonable but slightly thin. A status or cancel tool could be added.
Completeness3/5
The server covers the basic workflow of sending tasks and resetting, but lacks features like checking task status or interrupting a running task. Some gaps exist but core functionality is present.
Maintenance
ActivityMaintained
ResponsivenessSyncing