claude-opencode-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/LICENSE +21 -0
- package/README.md +514 -0
- package/SECURITY.md +80 -0
- package/agents/deepseek-coder.md +32 -0
- package/agents/deepseek-researcher.md +36 -0
- package/agents/deepseek-reviewer.md +31 -0
- package/agents/deepseek-tester.md +31 -0
- package/dist/cli/init.d.ts +6 -0
- package/dist/cli/init.js +208 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/config/config.d.ts +109 -0
- package/dist/config/config.js +163 -0
- package/dist/config/config.js.map +1 -0
- package/dist/errors.d.ts +29 -0
- package/dist/errors.js +68 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/execute.d.ts +30 -0
- package/dist/mcp/execute.js +128 -0
- package/dist/mcp/execute.js.map +1 -0
- package/dist/mcp/server.d.ts +19 -0
- package/dist/mcp/server.js +38 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/session-utils.d.ts +5 -0
- package/dist/mcp/session-utils.js +55 -0
- package/dist/mcp/session-utils.js.map +1 -0
- package/dist/mcp/tool-utils.d.ts +11 -0
- package/dist/mcp/tool-utils.js +44 -0
- package/dist/mcp/tool-utils.js.map +1 -0
- package/dist/mcp/tools/abort-session.d.ts +3 -0
- package/dist/mcp/tools/abort-session.js +48 -0
- package/dist/mcp/tools/abort-session.js.map +1 -0
- package/dist/mcp/tools/create-session.d.ts +3 -0
- package/dist/mcp/tools/create-session.js +53 -0
- package/dist/mcp/tools/create-session.js.map +1 -0
- package/dist/mcp/tools/delegate-task.d.ts +4 -0
- package/dist/mcp/tools/delegate-task.js +98 -0
- package/dist/mcp/tools/delegate-task.js.map +1 -0
- package/dist/mcp/tools/get-diff.d.ts +3 -0
- package/dist/mcp/tools/get-diff.js +97 -0
- package/dist/mcp/tools/get-diff.js.map +1 -0
- package/dist/mcp/tools/get-session.d.ts +3 -0
- package/dist/mcp/tools/get-session.js +79 -0
- package/dist/mcp/tools/get-session.js.map +1 -0
- package/dist/mcp/tools/list-agents.d.ts +3 -0
- package/dist/mcp/tools/list-agents.js +72 -0
- package/dist/mcp/tools/list-agents.js.map +1 -0
- package/dist/mcp/tools/send-message.d.ts +3 -0
- package/dist/mcp/tools/send-message.js +59 -0
- package/dist/mcp/tools/send-message.js.map +1 -0
- package/dist/opencode/agents.d.ts +46 -0
- package/dist/opencode/agents.js +239 -0
- package/dist/opencode/agents.js.map +1 -0
- package/dist/opencode/binary.d.ts +19 -0
- package/dist/opencode/binary.js +129 -0
- package/dist/opencode/binary.js.map +1 -0
- package/dist/opencode/client.d.ts +32 -0
- package/dist/opencode/client.js +55 -0
- package/dist/opencode/client.js.map +1 -0
- package/dist/opencode/manager.d.ts +66 -0
- package/dist/opencode/manager.js +492 -0
- package/dist/opencode/manager.js.map +1 -0
- package/dist/opencode/permission-watcher.d.ts +26 -0
- package/dist/opencode/permission-watcher.js +144 -0
- package/dist/opencode/permission-watcher.js.map +1 -0
- package/dist/opencode/run.d.ts +39 -0
- package/dist/opencode/run.js +318 -0
- package/dist/opencode/run.js.map +1 -0
- package/dist/opencode/sessions.d.ts +26 -0
- package/dist/opencode/sessions.js +105 -0
- package/dist/opencode/sessions.js.map +1 -0
- package/dist/opencode/setup.d.ts +38 -0
- package/dist/opencode/setup.js +109 -0
- package/dist/opencode/setup.js.map +1 -0
- package/dist/security/paths.d.ts +20 -0
- package/dist/security/paths.js +93 -0
- package/dist/security/paths.js.map +1 -0
- package/dist/security/policy.d.ts +17 -0
- package/dist/security/policy.js +86 -0
- package/dist/security/policy.js.map +1 -0
- package/dist/types/index.d.ts +131 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/util/fs.d.ts +12 -0
- package/dist/util/fs.js +73 -0
- package/dist/util/fs.js.map +1 -0
- package/dist/util/git.d.ts +54 -0
- package/dist/util/git.js +202 -0
- package/dist/util/git.js.map +1 -0
- package/dist/util/logger.d.ts +21 -0
- package/dist/util/logger.js +129 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/text.d.ts +11 -0
- package/dist/util/text.js +126 -0
- package/dist/util/text.js.map +1 -0
- package/dist/workspace/context.d.ts +12 -0
- package/dist/workspace/context.js +67 -0
- package/dist/workspace/context.js.map +1 -0
- package/dist/workspace/resolver.d.ts +35 -0
- package/dist/workspace/resolver.js +112 -0
- package/dist/workspace/resolver.js.map +1 -0
- package/dist/workspace/validator.d.ts +13 -0
- package/dist/workspace/validator.js +102 -0
- package/dist/workspace/validator.js.map +1 -0
- package/docs/agent-configuration.md +100 -0
- package/docs/architecture.md +115 -0
- package/docs/claude-code-setup.md +116 -0
- package/docs/configuration.md +184 -0
- package/docs/contributing.md +71 -0
- package/docs/deepseek-setup.md +84 -0
- package/docs/development.md +146 -0
- package/docs/installation.md +88 -0
- package/docs/opencode-setup.md +97 -0
- package/docs/security-audit.md +80 -0
- package/docs/security.md +128 -0
- package/docs/troubleshooting.md +126 -0
- package/docs/workspace-model.md +126 -0
- package/package.json +79 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [1.0.0] - 2026-09-24
|
|
11
|
+
|
|
12
|
+
First stable release.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- MCP stdio server with seven tools: `delegate_task`, `create_session`,
|
|
17
|
+
`send_message`, `get_session`, `get_diff`, `abort_session`, `list_agents`.
|
|
18
|
+
- OpenCode runtime management: lazy start of one headless server per workspace,
|
|
19
|
+
health checks, LRU eviction (`opencode.maxServers`), crash detection,
|
|
20
|
+
graceful shutdown, and no orphaned processes.
|
|
21
|
+
- Agent system with four profiles enforced through OpenCode permissions:
|
|
22
|
+
`deepseek-researcher`, `deepseek-reviewer` (read-only),
|
|
23
|
+
`deepseek-coder` (edits + shell), `deepseek-tester` (shell, no edits).
|
|
24
|
+
- Workspace resolution (`cwd` → `CLAUDE_PROJECT_DIR` → process cwd →
|
|
25
|
+
configured default) with canonical-path validation, allowed roots, git-root
|
|
26
|
+
detection, and a per-workspace routing probe (`WORKSPACE_MISMATCH`).
|
|
27
|
+
- Persistent sessions: `create_session` / `send_message` keep agent context;
|
|
28
|
+
registry stored at `~/.local/state/claude-opencode-mcp/sessions.json`
|
|
29
|
+
(mode `0600`) and pruned after 14 days.
|
|
30
|
+
- `get_diff` for reviewing agent changes: OpenCode session diff when
|
|
31
|
+
available, otherwise a git diff against a baseline captured at session
|
|
32
|
+
creation (pre-existing dirty state is isolated).
|
|
33
|
+
- Reliability: per-run timeouts (`AGENT_TIMEOUT`), MCP cancellation
|
|
34
|
+
(`AGENT_ABORTED`), progress notifications, structured error codes, request
|
|
35
|
+
IDs, and a rotating `0600` log file.
|
|
36
|
+
- Security defaults: `.env`/key/credential read and edit protection, `git
|
|
37
|
+
commit`/`git push` denied for shell-enabled agents, `external_directory`
|
|
38
|
+
denied, no `ask` permission rules, and auto-rejection of stray permission
|
|
39
|
+
requests so headless runs cannot hang. Log fields matching
|
|
40
|
+
password/secret/token/api-key patterns are redacted.
|
|
41
|
+
- Configuration layering: global (`~/.config/claude-opencode-mcp/config.json`),
|
|
42
|
+
project (`.claude-opencode/config.json`), explicit
|
|
43
|
+
(`CLAUDE_OPENCODE_CONFIG`), with deep merge and Zod validation.
|
|
44
|
+
- `claude-opencode init` validator/scaffolder (config + agent files, optional
|
|
45
|
+
`.mcp.json`) and `claude-opencode-mcp` executable for `npx`.
|
|
46
|
+
- Documentation set covering installation, configuration, Claude Code, OpenCode,
|
|
47
|
+
DeepSeek, agents, workspace model, security, architecture, development,
|
|
48
|
+
contributing, and troubleshooting.
|
|
49
|
+
- Test suite: unit and integration tests with a fake OpenCode server, plus
|
|
50
|
+
opt-in real OpenCode/DeepSeek E2E checkpoints and a full multi-agent
|
|
51
|
+
workflow acceptance test.
|
|
52
|
+
- CI across Node 20/22/24 (Ubuntu) and Node 24 (macOS), plus an opt-in,
|
|
53
|
+
push-only real-provider E2E job.
|
|
54
|
+
|
|
55
|
+
[Unreleased]: https://github.com/putuandy/claude-opencode-mcp/compare/v1.0.0...HEAD
|
|
56
|
+
[1.0.0]: https://github.com/putuandy/claude-opencode-mcp/releases/tag/v1.0.0
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 claude-opencode-mcp contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
# claude-opencode-mcp
|
|
2
|
+
|
|
3
|
+
[](https://github.com/putuandy/claude-opencode-mcp/actions/workflows/ci.yml)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
|
|
7
|
+
An MCP server that lets **Claude Code delegate software-engineering tasks to
|
|
8
|
+
OpenCode agents** — DeepSeek by default — while keeping every agent inside the
|
|
9
|
+
same workspace/worktree.
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
Claude Code (orchestrator)
|
|
13
|
+
│ MCP
|
|
14
|
+
▼
|
|
15
|
+
claude-opencode-mcp (this bridge)
|
|
16
|
+
│ workspace + task + agent
|
|
17
|
+
▼
|
|
18
|
+
OpenCode (agent runtime: tools, sessions, permissions)
|
|
19
|
+
│
|
|
20
|
+
▼
|
|
21
|
+
DeepSeek (or any provider configured in OpenCode)
|
|
22
|
+
│
|
|
23
|
+
▼
|
|
24
|
+
your repository — the same working tree Claude Code is using
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Claude Code stays in charge: it decomposes the work, picks agents, reviews the
|
|
28
|
+
results and integrates changes. OpenCode does the repository exploration,
|
|
29
|
+
editing and test execution. The bridge is deliberately thin.
|
|
30
|
+
|
|
31
|
+
- [Features](#features)
|
|
32
|
+
- [Requirements](#requirements)
|
|
33
|
+
- [Install](#install)
|
|
34
|
+
- [Claude Code setup](#claude-code-setup)
|
|
35
|
+
- [OpenCode + DeepSeek setup](#opencode--deepseek-setup)
|
|
36
|
+
- [Quick start](#quick-start)
|
|
37
|
+
- [Tools](#tools)
|
|
38
|
+
- [Agents](#agents)
|
|
39
|
+
- [Workspace model](#workspace-model)
|
|
40
|
+
- [Security](#security)
|
|
41
|
+
- [Configuration](#configuration)
|
|
42
|
+
- [Sessions](#sessions)
|
|
43
|
+
- [Troubleshooting](#troubleshooting)
|
|
44
|
+
- [Development](#development)
|
|
45
|
+
- [Documentation](#documentation)
|
|
46
|
+
- [License](#license)
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- **Seven focused MCP tools** — `delegate_task`, `create_session`,
|
|
51
|
+
`send_message`, `get_session`, `get_diff`, `abort_session`, `list_agents`.
|
|
52
|
+
- **Same worktree** — the delegated OpenCode server runs with your project as
|
|
53
|
+
its working directory; the agent reads and edits the real files.
|
|
54
|
+
- **Persistent sessions** — follow-up messages keep the agent's context across
|
|
55
|
+
separate MCP calls.
|
|
56
|
+
- **Four agent profiles** — researcher, reviewer, coder, tester, each with
|
|
57
|
+
permissions enforced by OpenCode (not by prompt wording).
|
|
58
|
+
- **Workspace boundaries** — canonical paths, allowed roots, path-traversal
|
|
59
|
+
rejection, and a per-run probe that proves the server is serving the right
|
|
60
|
+
directory.
|
|
61
|
+
- **Safety defaults** — `.env`/credential protection, `git commit`/`git push`
|
|
62
|
+
denied, external directories denied, no `ask` rules that could hang a
|
|
63
|
+
headless run.
|
|
64
|
+
- **Structured results** — every tool returns JSON with stable error codes, and
|
|
65
|
+
`get_diff` gives Claude Code the exact changes a coding session made.
|
|
66
|
+
- **Reliability** — timeouts, cancellation, health checks, crash detection,
|
|
67
|
+
graceful shutdown, request IDs and a rotating log file.
|
|
68
|
+
|
|
69
|
+
## Requirements
|
|
70
|
+
|
|
71
|
+
| Component | Version |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| Node.js | 20 or newer |
|
|
74
|
+
| [Claude Code](https://docs.claude.com/en/docs/claude-code) | recent 2.x |
|
|
75
|
+
| [OpenCode](https://opencode.ai) | 1.18+ (tested against 1.18.32) |
|
|
76
|
+
| Model provider | DeepSeek by default; any provider OpenCode supports |
|
|
77
|
+
|
|
78
|
+
## Install
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm install -g claude-opencode-mcp
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
or run it on demand with `npx -y claude-opencode-mcp` (recommended for
|
|
85
|
+
`.mcp.json`).
|
|
86
|
+
|
|
87
|
+
The bridge can also use an OpenCode installation from `PATH`, from
|
|
88
|
+
`node_modules/.bin`, from `~/.opencode/bin`, or from an explicit
|
|
89
|
+
`OPENCODE_BIN`.
|
|
90
|
+
|
|
91
|
+
### From source
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
git clone https://github.com/putuandy/claude-opencode-mcp.git
|
|
95
|
+
cd claude-opencode-mcp
|
|
96
|
+
npm install
|
|
97
|
+
npm run build
|
|
98
|
+
npm install -g .
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Claude Code setup
|
|
102
|
+
|
|
103
|
+
### Option A — project `.mcp.json` (recommended)
|
|
104
|
+
|
|
105
|
+
Create `.mcp.json` in your project root:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"mcpServers": {
|
|
110
|
+
"opencode": {
|
|
111
|
+
"command": "npx",
|
|
112
|
+
"args": ["-y", "claude-opencode-mcp"],
|
|
113
|
+
"type": "stdio",
|
|
114
|
+
"timeout": 600000
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`timeout` is milliseconds and is a **per-tool-call** wall-clock limit. Delegated
|
|
121
|
+
runs are long; without it Claude Code falls back to `MCP_TOOL_TIMEOUT`.
|
|
122
|
+
Claude Code also moves main-conversation tool calls to a background task after
|
|
123
|
+
two minutes, which is fine — the result arrives when the run finishes.
|
|
124
|
+
|
|
125
|
+
### Option B — `claude mcp add`
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
claude mcp add opencode --scope project -- npx -y claude-opencode-mcp
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Or for one machine only:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
claude mcp add opencode --scope user -- npx -y claude-opencode-mcp
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Verify:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
claude mcp list # opencode ... ✔ Connected
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Inside Claude Code, `/mcp` shows the server and its seven tools.
|
|
144
|
+
|
|
145
|
+
> The bridge reads `CLAUDE_PROJECT_DIR`, which Claude Code sets for stdio MCP
|
|
146
|
+
> servers, so delegation defaults to the project you launched Claude Code in.
|
|
147
|
+
|
|
148
|
+
## OpenCode + DeepSeek setup
|
|
149
|
+
|
|
150
|
+
The bridge starts and stops its own headless OpenCode server, so you do not need
|
|
151
|
+
to run `opencode serve` yourself. You only need OpenCode installed and a
|
|
152
|
+
provider authenticated.
|
|
153
|
+
|
|
154
|
+
1. **Install OpenCode**
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npm install -g opencode-ai
|
|
158
|
+
# or: brew install sst/tap/opencode
|
|
159
|
+
opencode --version
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
2. **Authenticate DeepSeek** (once)
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
opencode auth login # choose DeepSeek, paste your API key
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Alternatively export `DEEPSEEK_API_KEY` before starting Claude Code; OpenCode
|
|
169
|
+
reads it for the `deepseek` provider.
|
|
170
|
+
|
|
171
|
+
3. **Check the models**
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
opencode models | grep deepseek
|
|
175
|
+
# deepseek/deepseek-flash
|
|
176
|
+
# deepseek/deepseek-v4-pro
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
4. **(Optional) validate the project**
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
cd my-project
|
|
183
|
+
claude-opencode init
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`init` only creates `.claude-opencode/` and validates the environment; it
|
|
187
|
+
never modifies source code and is not required for delegation.
|
|
188
|
+
|
|
189
|
+
If you prefer to control OpenCode yourself, start `opencode serve` and point
|
|
190
|
+
the bridge at it with `opencode.url`; see
|
|
191
|
+
[docs/configuration.md](docs/configuration.md#connecting-to-an-existing-opencode-server).
|
|
192
|
+
|
|
193
|
+
## Quick start
|
|
194
|
+
|
|
195
|
+
Restart Claude Code, then ask:
|
|
196
|
+
|
|
197
|
+
> Use the `opencode` MCP server to have `deepseek-researcher` map this
|
|
198
|
+
> repository: entry points, main modules, and where authentication lives.
|
|
199
|
+
|
|
200
|
+
Then something that edits:
|
|
201
|
+
|
|
202
|
+
> Have `deepseek-coder` add input validation to `src/api/users.ts`, run the
|
|
203
|
+
> tests, and report what changed. Then show me the diff with `get_diff`.
|
|
204
|
+
|
|
205
|
+
And a full workflow:
|
|
206
|
+
|
|
207
|
+
> Ask DeepSeek to inspect the authentication system, identify potential issues,
|
|
208
|
+
> implement a fix, and review the changes.
|
|
209
|
+
|
|
210
|
+
Claude Code typically orchestrates: `deepseek-researcher` → `deepseek-coder`
|
|
211
|
+
→ `deepseek-reviewer` → `deepseek-tester`, calling `get_diff` between steps.
|
|
212
|
+
|
|
213
|
+
## Tools
|
|
214
|
+
|
|
215
|
+
All tools return JSON in `content[0].text` (mirrored in `structuredContent`).
|
|
216
|
+
Errors return `isError: true` with `{ "error": { "code", "message", ... } }`.
|
|
217
|
+
|
|
218
|
+
### `delegate_task`
|
|
219
|
+
|
|
220
|
+
Run one task in a fresh session and wait for the agent's answer.
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"task": "Review the authentication implementation for bugs and security issues.",
|
|
225
|
+
"agent": "deepseek-reviewer",
|
|
226
|
+
"cwd": "/Users/andy/projects/my-app",
|
|
227
|
+
"paths": ["src/auth", "src/middleware", "tests/auth"],
|
|
228
|
+
"model": "deepseek/deepseek-v4-pro",
|
|
229
|
+
"timeout": 600000,
|
|
230
|
+
"allow_edits": false
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Returns `{ status, session_id, agent, cwd, model, summary, findings,
|
|
235
|
+
files_changed, duration_ms, truncated, error? }`.
|
|
236
|
+
|
|
237
|
+
- `paths` are exploration hints, not a boundary — the agent may inspect the
|
|
238
|
+
whole workspace.
|
|
239
|
+
- `allow_edits: false` disables the `edit`/`write`/`apply_patch` tools for that
|
|
240
|
+
call (the agent's own profile still applies; see [Security](#security)).
|
|
241
|
+
- `findings` are parsed from a `## Findings` section:
|
|
242
|
+
`- [severity: high] Title (path/to/file:42) — detail`.
|
|
243
|
+
|
|
244
|
+
### `create_session`
|
|
245
|
+
|
|
246
|
+
```json
|
|
247
|
+
{ "cwd": "/abs/path", "agent": "deepseek-researcher", "model": null, "title": "auth investigation" }
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Returns `{ session_id, cwd, agent, model, title, status, created_at }`.
|
|
251
|
+
|
|
252
|
+
### `send_message`
|
|
253
|
+
|
|
254
|
+
Continue a session; the agent keeps its context.
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{ "session_id": "ses_...", "message": "Now inspect the database layer for the same issue." }
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### `get_session`
|
|
261
|
+
|
|
262
|
+
Returns the stored session state plus live OpenCode status
|
|
263
|
+
(`opencode.status` is `idle`, `busy` or `retry` when a server is running).
|
|
264
|
+
|
|
265
|
+
### `get_diff`
|
|
266
|
+
|
|
267
|
+
Returns the changes associated with a session:
|
|
268
|
+
|
|
269
|
+
- OpenCode's own session diff when the server reports one, otherwise
|
|
270
|
+
- a **git diff against a baseline captured when the session was created**, so
|
|
271
|
+
pre-existing uncommitted work is not attributed to the agent.
|
|
272
|
+
|
|
273
|
+
Returns `{ source, files, diff, truncated, note? }`.
|
|
274
|
+
|
|
275
|
+
### `abort_session`
|
|
276
|
+
|
|
277
|
+
Stops a running delegation. Safe to call when the session is idle.
|
|
278
|
+
|
|
279
|
+
### `list_agents`
|
|
280
|
+
|
|
281
|
+
Lists the built-in agents plus project-local agents from
|
|
282
|
+
`.claude-opencode/agents/`, with `read_only`, `can_edit`, `can_run_bash` flags.
|
|
283
|
+
|
|
284
|
+
## Agents
|
|
285
|
+
|
|
286
|
+
| Agent | Purpose | Edit | Shell |
|
|
287
|
+
| --- | --- | --- | --- |
|
|
288
|
+
| `deepseek-researcher` | architecture, exploration, dependency analysis, recommendations | deny | deny |
|
|
289
|
+
| `deepseek-reviewer` | code review, bugs, regressions, security, architecture | deny | deny |
|
|
290
|
+
| `deepseek-coder` | implementation, refactoring, running tests and fixing failures | allow | allow (no `git commit`/`git push`) |
|
|
291
|
+
| `deepseek-tester` | run tests, inspect failures, root causes, suggested fixes | deny | allow (no `git commit`/`git push`) |
|
|
292
|
+
|
|
293
|
+
Agent prompts live in [`agents/`](agents/) and are loaded into the OpenCode
|
|
294
|
+
server configuration at startup. Project-local copies in
|
|
295
|
+
`.claude-opencode/agents/*.md` override the prompt, description, model and
|
|
296
|
+
temperature; permissions always come from the bridge policy (configurable
|
|
297
|
+
through `security.*`).
|
|
298
|
+
|
|
299
|
+
See [docs/agent-configuration.md](docs/agent-configuration.md) for frontmatter
|
|
300
|
+
details and custom agents.
|
|
301
|
+
|
|
302
|
+
## Workspace model
|
|
303
|
+
|
|
304
|
+
Resolution order for every call:
|
|
305
|
+
|
|
306
|
+
1. explicit `cwd` argument
|
|
307
|
+
2. `CLAUDE_PROJECT_DIR` (set by Claude Code)
|
|
308
|
+
3. the MCP server process working directory
|
|
309
|
+
4. `workspace.defaultCwd` from configuration
|
|
310
|
+
|
|
311
|
+
The first two are *required*: if they are present but invalid, the call fails
|
|
312
|
+
instead of silently using a different directory.
|
|
313
|
+
|
|
314
|
+
Validation happens before any session is created:
|
|
315
|
+
|
|
316
|
+
- the path must exist, be a directory, and be readable;
|
|
317
|
+
- it is canonicalized with `realpath`;
|
|
318
|
+
- when `workspace.allowedRoots` is set, the canonical path must live inside one
|
|
319
|
+
of those roots (traversal is rejected);
|
|
320
|
+
- the git root is detected for diff isolation.
|
|
321
|
+
|
|
322
|
+
During the first request for a workspace the bridge reads back `directory` from
|
|
323
|
+
the OpenCode server and compares it with the requested path, so a misrouted
|
|
324
|
+
request can never reach the wrong repository.
|
|
325
|
+
|
|
326
|
+
One OpenCode server is started per workspace directory and reused for all
|
|
327
|
+
sessions in that workspace; the server process itself runs with the workspace as
|
|
328
|
+
its working directory.
|
|
329
|
+
|
|
330
|
+
## Security
|
|
331
|
+
|
|
332
|
+
| Control | Default | Where |
|
|
333
|
+
| --- | --- | --- |
|
|
334
|
+
| Workspace must exist, be readable, be a directory | always | bridge |
|
|
335
|
+
| `workspace.allowedRoots` containment | disabled (empty) | config |
|
|
336
|
+
| Path hints cannot escape the workspace | always | bridge |
|
|
337
|
+
| `.env`/`.env.*`, keys, `credentials`, `.ssh/*` protection | on | OpenCode permissions |
|
|
338
|
+
| `git commit` / `git push` for shell-enabled agents | denied | OpenCode permissions |
|
|
339
|
+
| Paths outside the workspace | denied | OpenCode `external_directory` |
|
|
340
|
+
| Subagent spawning (`task`) | denied | OpenCode permissions |
|
|
341
|
+
| Interactive questions (`question`) | denied (headless) | OpenCode permissions |
|
|
342
|
+
| `ask` permission rules | never emitted by the bridge | OpenCode permissions |
|
|
343
|
+
|
|
344
|
+
The bridge also listens to OpenCode's event stream and **auto-rejects** any
|
|
345
|
+
permission request that would otherwise wait for a human, so a delegated run can
|
|
346
|
+
never hang on approval.
|
|
347
|
+
|
|
348
|
+
Caveats, stated plainly:
|
|
349
|
+
|
|
350
|
+
- A shell-enabled agent (`coder`, `tester`) can technically write files through
|
|
351
|
+
shell commands. The bridge denies the `edit` tools for the tester and forbids
|
|
352
|
+
git history changes for both, but shell access is inherently powerful.
|
|
353
|
+
- `.env` protection applies to the file tools. A shell-enabled agent could still
|
|
354
|
+
`cat` a file through `bash`; the OpenCode project permission model has the
|
|
355
|
+
same property.
|
|
356
|
+
- When connecting to an **external** OpenCode server (`opencode.url`), the
|
|
357
|
+
bridge cannot inject agent permissions. It verifies the agents exist and
|
|
358
|
+
refuses to run otherwise.
|
|
359
|
+
|
|
360
|
+
Details and hardening options: [docs/security.md](docs/security.md).
|
|
361
|
+
|
|
362
|
+
## Configuration
|
|
363
|
+
|
|
364
|
+
Global file: `~/.config/claude-opencode-mcp/config.json` (honours
|
|
365
|
+
`XDG_CONFIG_HOME`).
|
|
366
|
+
Project file: `<project>/.claude-opencode/config.json` (overrides global).
|
|
367
|
+
Extra file: `CLAUDE_OPENCODE_CONFIG=/path/to/config.json` (highest precedence).
|
|
368
|
+
|
|
369
|
+
```json
|
|
370
|
+
{
|
|
371
|
+
"opencode": {
|
|
372
|
+
"url": null,
|
|
373
|
+
"autoStart": true,
|
|
374
|
+
"hostname": "127.0.0.1",
|
|
375
|
+
"port": 0,
|
|
376
|
+
"startupTimeout": 30000,
|
|
377
|
+
"binary": null,
|
|
378
|
+
"username": null,
|
|
379
|
+
"password": null,
|
|
380
|
+
"maxServers": 4
|
|
381
|
+
},
|
|
382
|
+
"workspace": {
|
|
383
|
+
"allowedRoots": [],
|
|
384
|
+
"defaultCwd": null
|
|
385
|
+
},
|
|
386
|
+
"defaults": {
|
|
387
|
+
"agent": "deepseek-researcher",
|
|
388
|
+
"provider": "deepseek",
|
|
389
|
+
"model": null
|
|
390
|
+
},
|
|
391
|
+
"timeouts": {
|
|
392
|
+
"execution": 600000
|
|
393
|
+
},
|
|
394
|
+
"security": {
|
|
395
|
+
"protectEnvFiles": true,
|
|
396
|
+
"denyGitPush": true,
|
|
397
|
+
"denyGitCommit": true,
|
|
398
|
+
"externalDirectory": "deny",
|
|
399
|
+
"extraProtectedPatterns": []
|
|
400
|
+
},
|
|
401
|
+
"limits": {
|
|
402
|
+
"summaryChars": 6000,
|
|
403
|
+
"sessionChars": 20000,
|
|
404
|
+
"diffChars": 60000
|
|
405
|
+
},
|
|
406
|
+
"agents": {
|
|
407
|
+
"deepseek-researcher": { "model": "deepseek/deepseek-v4-pro" }
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
- `defaults.model` accepts `provider/model` or a bare model id (combined with
|
|
413
|
+
`defaults.provider`). When `null`, the provider's default model from OpenCode
|
|
414
|
+
is used.
|
|
415
|
+
- Provider credentials stay in OpenCode (`opencode auth login`) or environment
|
|
416
|
+
variables; they are never duplicated in this config.
|
|
417
|
+
- For auto-started servers the bridge passes `OPENCODE_SERVER_USERNAME` /
|
|
418
|
+
`OPENCODE_SERVER_PASSWORD` through and authenticates its own requests. For
|
|
419
|
+
external URLs it only uses credentials you configure.
|
|
420
|
+
|
|
421
|
+
Full reference: [docs/configuration.md](docs/configuration.md).
|
|
422
|
+
|
|
423
|
+
## Sessions
|
|
424
|
+
|
|
425
|
+
- Sessions are OpenCode sessions; the bridge keeps a small registry at
|
|
426
|
+
`~/.local/state/claude-opencode-mcp/sessions.json` (override with
|
|
427
|
+
`CLAUDE_OPENCODE_STATE_DIR`) so `get_session`, `get_diff` and `send_message`
|
|
428
|
+
survive a bridge restart.
|
|
429
|
+
- Records older than 14 days are pruned at startup.
|
|
430
|
+
- If an OpenCode server restarts, persisted sessions are still addressable;
|
|
431
|
+
`get_session` reports live status when a server is running.
|
|
432
|
+
- Logs: `~/.local/state/claude-opencode-mcp/bridge.log` (rotated at 5 MB).
|
|
433
|
+
Set `CLAUDE_OPENCODE_LOG=debug|info|warn|error|silent`.
|
|
434
|
+
|
|
435
|
+
## Troubleshooting
|
|
436
|
+
|
|
437
|
+
| Symptom | Fix |
|
|
438
|
+
| --- | --- |
|
|
439
|
+
| `OPENCODE_NOT_AVAILABLE` | `npm install -g opencode-ai` or set `OPENCODE_BIN` / `opencode.binary`. |
|
|
440
|
+
| `OPENCODE_START_TIMEOUT` | run `opencode serve` manually to see the error; raise `opencode.startupTimeout`; check `OPENCODE_SERVER_PASSWORD` handling. |
|
|
441
|
+
| `MODEL_NOT_AVAILABLE` | authenticate a provider (`opencode auth login`) or set `defaults.model`, e.g. `"deepseek/deepseek-v4-pro"`. |
|
|
442
|
+
| `ProviderAuthError` in a result | DeepSeek credentials are missing/expired; re-run `opencode auth login`. |
|
|
443
|
+
| `AGENT_NOT_FOUND` with an external server | add the four agents to that server's config or stop using `opencode.url`. |
|
|
444
|
+
| `AGENT_TIMEOUT` | raise `timeouts.execution` or the `timeout` argument; consider a narrower task. |
|
|
445
|
+
| `WORKSPACE_NOT_ALLOWED` | add the project to `workspace.allowedRoots` or clear the list. |
|
|
446
|
+
| 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`. |
|
|
447
|
+
| Claude Code kills the call at 60s | set `"timeout": 600000` in the `.mcp.json` entry (or `MCP_TOOL_TIMEOUT`). |
|
|
448
|
+
|
|
449
|
+
More: [docs/troubleshooting.md](docs/troubleshooting.md).
|
|
450
|
+
|
|
451
|
+
## Development
|
|
452
|
+
|
|
453
|
+
```bash
|
|
454
|
+
npm install
|
|
455
|
+
npm run lint # Biome
|
|
456
|
+
npm run typecheck
|
|
457
|
+
npm test # unit + integration (no OpenCode needed)
|
|
458
|
+
npm run build
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
Real end-to-end tests need an OpenCode install with DeepSeek authenticated:
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
npm run test:e2e # checkpoints: workspace, agents, sessions, diff, abort, stdio
|
|
465
|
+
CLAUDE_OPENCODE_E2E_WORKFLOW=1 npm run test:e2e # full researcher → coder → reviewer → tester workflow
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Layout:
|
|
469
|
+
|
|
470
|
+
```text
|
|
471
|
+
src/
|
|
472
|
+
index.ts CLI entry (MCP server + `init`)
|
|
473
|
+
cli/ `claude-opencode init`
|
|
474
|
+
config/ configuration loading and merging
|
|
475
|
+
workspace/ resolver, validator, task context
|
|
476
|
+
security/ path policy + OpenCode permission profiles
|
|
477
|
+
opencode/ binary resolution, manager, client, agents, sessions, runner
|
|
478
|
+
mcp/ MCP server and the seven tools
|
|
479
|
+
agents/ built-in agent prompts
|
|
480
|
+
tests/ unit, integration, e2e
|
|
481
|
+
docs/ documentation
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
See [docs/development.md](docs/development.md) and
|
|
485
|
+
[docs/architecture.md](docs/architecture.md).
|
|
486
|
+
|
|
487
|
+
## Documentation
|
|
488
|
+
|
|
489
|
+
- [Installation](docs/installation.md)
|
|
490
|
+
- [Configuration](docs/configuration.md)
|
|
491
|
+
- [Claude Code setup](docs/claude-code-setup.md)
|
|
492
|
+
- [OpenCode setup](docs/opencode-setup.md)
|
|
493
|
+
- [DeepSeek setup](docs/deepseek-setup.md)
|
|
494
|
+
- [Agent configuration](docs/agent-configuration.md)
|
|
495
|
+
- [Workspace model](docs/workspace-model.md)
|
|
496
|
+
- [Security](docs/security.md)
|
|
497
|
+
- [Security audit](docs/security-audit.md)
|
|
498
|
+
- [Troubleshooting](docs/troubleshooting.md)
|
|
499
|
+
- [Architecture](docs/architecture.md)
|
|
500
|
+
- [Development](docs/development.md)
|
|
501
|
+
- [Contributing](CONTRIBUTING.md)
|
|
502
|
+
- [Changelog](CHANGELOG.md)
|
|
503
|
+
- [Security policy](SECURITY.md)
|
|
504
|
+
- [Code of Conduct](CODE_OF_CONDUCT.md)
|
|
505
|
+
|
|
506
|
+
## Contributing
|
|
507
|
+
|
|
508
|
+
Bug reports, feature requests, and pull requests are welcome. Start with
|
|
509
|
+
[CONTRIBUTING.md](CONTRIBUTING.md); for vulnerabilities use
|
|
510
|
+
[SECURITY.md](SECURITY.md) instead of a public issue.
|
|
511
|
+
|
|
512
|
+
## License
|
|
513
|
+
|
|
514
|
+
MIT — see [LICENSE](LICENSE).
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
`claude-opencode-mcp` executes AI agents with file and shell access inside a
|
|
4
|
+
workspace. We take security reports seriously and appreciate responsible
|
|
5
|
+
disclosure.
|
|
6
|
+
|
|
7
|
+
## Supported versions
|
|
8
|
+
|
|
9
|
+
| Version | Supported |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| 1.x | Yes |
|
|
12
|
+
| < 1.0 | No |
|
|
13
|
+
|
|
14
|
+
## Reporting a vulnerability
|
|
15
|
+
|
|
16
|
+
Please **do not** open a public issue for a security problem.
|
|
17
|
+
|
|
18
|
+
Use GitHub's private vulnerability reporting:
|
|
19
|
+
<https://github.com/putuandy/claude-opencode-mcp/security/advisories/new>
|
|
20
|
+
|
|
21
|
+
Include:
|
|
22
|
+
|
|
23
|
+
- affected version (`claude-opencode-mcp --version`),
|
|
24
|
+
- OpenCode version (`opencode --version`),
|
|
25
|
+
- a minimal reproduction or proof of concept,
|
|
26
|
+
- the impact you believe it has,
|
|
27
|
+
- any suggested fix.
|
|
28
|
+
|
|
29
|
+
We aim to acknowledge reports within 72 hours and to ship a fix or mitigation
|
|
30
|
+
for confirmed issues as quickly as practical. We will credit reporters in the
|
|
31
|
+
advisory unless you prefer otherwise.
|
|
32
|
+
|
|
33
|
+
## Scope
|
|
34
|
+
|
|
35
|
+
In scope:
|
|
36
|
+
|
|
37
|
+
- bypassing workspace validation, `workspace.allowedRoots`, or path-hint checks,
|
|
38
|
+
- escaping the agent permission model (e.g. read-only agents writing files,
|
|
39
|
+
`git push`/`git commit` bypass, `.env` protection bypass),
|
|
40
|
+
- credential exposure through logs, errors, or network requests,
|
|
41
|
+
- command or argument injection in bridge-spawned processes,
|
|
42
|
+
- denial of service that hangs or crashes a Claude Code session,
|
|
43
|
+
- supply-chain issues in this package's own code or dependencies.
|
|
44
|
+
|
|
45
|
+
Out of scope (documented behavior, see [docs/security.md](docs/security.md)):
|
|
46
|
+
|
|
47
|
+
- an agent with shell access can write files through shell commands,
|
|
48
|
+
- `.env` protection applies to file tools, not to `bash`,
|
|
49
|
+
- prompt injection from repository content influencing a delegated agent,
|
|
50
|
+
- arbitrary code execution caused by a binary you explicitly configure via
|
|
51
|
+
`opencode.binary` / `OPENCODE_BIN`,
|
|
52
|
+
- vulnerabilities in OpenCode, Claude Code, or model providers themselves
|
|
53
|
+
(report those upstream).
|
|
54
|
+
|
|
55
|
+
## Threat model summary
|
|
56
|
+
|
|
57
|
+
The bridge assumes:
|
|
58
|
+
|
|
59
|
+
- the local user account and the workspace contents are trusted to the degree
|
|
60
|
+
the user chose to delegate,
|
|
61
|
+
- the OpenCode server is bound to `127.0.0.1` by default,
|
|
62
|
+
- provider credentials live in OpenCode or the environment, never in this
|
|
63
|
+
package's configuration or state.
|
|
64
|
+
|
|
65
|
+
Defenses: canonical-path workspace validation, allowed-root containment,
|
|
66
|
+
path-traversal rejection, an OpenCode permission matrix per agent profile
|
|
67
|
+
(no `ask` rules, auto-rejection of stray permission requests), sensitive-file
|
|
68
|
+
patterns, git history protections, bounded inputs/outputs, run timeouts and
|
|
69
|
+
cancellation, redacted logs, and `0600` state files.
|
|
70
|
+
|
|
71
|
+
## Hardening recommendations
|
|
72
|
+
|
|
73
|
+
- Keep `workspace.allowedRoots` narrow when delegating across projects.
|
|
74
|
+
- Leave `opencode.hostname` at `127.0.0.1`; binding to a routable address
|
|
75
|
+
exposes the OpenCode HTTP API to your network (and its token/password, if
|
|
76
|
+
set, becomes the only barrier).
|
|
77
|
+
- Review diffs with `get_diff` before accepting changes.
|
|
78
|
+
- Prefer read-only agents for untrusted repositories.
|
|
79
|
+
- Never commit `.claude-opencode/config.json` if you put credentials in it
|
|
80
|
+
(provider credentials belong in OpenCode or environment variables).
|