opencode-samcp 0.0.1__tar.gz

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.
@@ -0,0 +1,12 @@
1
+ name: ci
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ matrix:
8
+ python: ["3.10", "3.12", "3.13"]
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+ - uses: astral-sh/setup-uv@v5
12
+ - run: uv run --python ${{ matrix.python }} --group dev pytest
@@ -0,0 +1,46 @@
1
+ name: publish
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ jobs:
8
+ verify:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: astral-sh/setup-uv@v5
13
+ - name: Tag, package.json and pyproject.toml versions must match
14
+ run: |
15
+ TAG="${GITHUB_REF_NAME#v}"
16
+ NPM_V=$(node -p "require('./package.json').version")
17
+ PY_V=$(python3 -c "import tomllib;print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
18
+ echo "tag=$TAG npm=$NPM_V pypi=$PY_V"
19
+ [ "$TAG" = "$NPM_V" ] && [ "$TAG" = "$PY_V" ] || { echo "version mismatch"; exit 1; }
20
+ - run: uv run --group dev pytest
21
+
22
+ pypi:
23
+ needs: verify
24
+ runs-on: ubuntu-latest
25
+ environment: pypi
26
+ permissions:
27
+ id-token: write # PyPI trusted publishing
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: astral-sh/setup-uv@v5
31
+ - run: uv build
32
+ - run: uv publish --trusted-publishing always
33
+
34
+ npm:
35
+ needs: verify
36
+ runs-on: ubuntu-latest
37
+ environment: npm
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+ - uses: actions/setup-node@v4
41
+ with:
42
+ node-version: 22
43
+ registry-url: https://registry.npmjs.org
44
+ - run: npm publish --access public
45
+ env:
46
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -0,0 +1,7 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ dist/
5
+ .pytest_cache/
6
+ node_modules/
7
+ *.tgz
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amir Daraby
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.
@@ -0,0 +1,124 @@
1
+ Metadata-Version: 2.5
2
+ Name: opencode-samcp
3
+ Version: 0.0.1
4
+ Summary: Sub-agent MCP: let Devin, Codex, Claude Code and other agents spawn opencode sessions to do work
5
+ Project-URL: Homepage, https://github.com/amirdaraby/opencode-samcp
6
+ Project-URL: Repository, https://github.com/amirdaraby/opencode-samcp
7
+ Project-URL: Issues, https://github.com/amirdaraby/opencode-samcp/issues
8
+ Author: Amir Daraby
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai-agents,codex,devin,mcp,opencode,subagent
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Software Development
15
+ Requires-Python: >=3.10
16
+ Requires-Dist: mcp<2,>=1.2
17
+ Description-Content-Type: text/markdown
18
+
19
+ # opencode-samcp
20
+
21
+ **S**ub-**A**gent **MCP** — an MCP server that lets an AI agent (Devin, Codex, Claude Code, Cursor, …) spawn [opencode](https://opencode.ai) sessions as sub-agents and hand them coding work.
22
+
23
+ The parent agent calls `opencode_run` with a prompt and a directory; opencode does the work headlessly (`opencode run --format json --auto`) and the result comes back as structured data: final message, tool-call summary, errors, token usage and cost. Sessions can be continued, forked, run in parallel in the background, inspected and deleted.
24
+
25
+ ## Requirements
26
+
27
+ - [opencode](https://opencode.ai) installed and authenticated (`opencode` on `PATH`, or set `OPENCODE_BIN`)
28
+ - [uv](https://docs.astral.sh/uv/) (or `pip install`)
29
+
30
+ ## Install / run
31
+
32
+ The server is Python; every option below needs [uv](https://docs.astral.sh/uv/) and opencode on the machine.
33
+
34
+ | Method | Command |
35
+ |---|---|
36
+ | **npx** (no install) | `npx -y opencode-samcp` |
37
+ | **npm** (global) | `npm i -g opencode-samcp` then `opencode-samcp` |
38
+ | **uvx** from PyPI | `uvx opencode-samcp` |
39
+ | **uvx** from GitHub | `uvx --from git+https://github.com/amirdaraby/opencode-samcp opencode-samcp` |
40
+ | **pip** | `pip install opencode-samcp` then `opencode-samcp` |
41
+
42
+ The npm package is a thin launcher: it bundles the Python server and runs it through `uvx`.
43
+ If `uv` or `opencode` is missing, it exits with a clear "not installed on machine" error.
44
+
45
+ ## Configure your client
46
+
47
+ ### Devin
48
+ Settings → MCP Marketplace → *Add Your Own* (STDIO):
49
+
50
+ | Field | Value |
51
+ |---|---|
52
+ | Command | `npx` |
53
+ | Args | `-y opencode-samcp` |
54
+
55
+ Devin runs in its own VM, so opencode must be installed and logged in **there** (add it to the machine setup / snapshot).
56
+
57
+ ### Codex (`~/.codex/config.toml`)
58
+ ```toml
59
+ [mcp_servers.opencode]
60
+ command = "npx"
61
+ args = ["-y", "opencode-samcp"]
62
+ ```
63
+
64
+ ### Claude Code
65
+ ```bash
66
+ claude mcp add opencode -- npx -y opencode-samcp
67
+ ```
68
+
69
+ ### Generic JSON
70
+ ```json
71
+ { "mcpServers": { "opencode": { "command": "npx", "args": ["-y", "opencode-samcp"] } } }
72
+ ```
73
+
74
+ ### HTTP transport
75
+ For clients that only speak remote MCP:
76
+ ```bash
77
+ opencode-samcp --transport streamable-http --host 127.0.0.1 --port 8765 # endpoint: /mcp
78
+ opencode-samcp --transport sse ... # endpoint: /sse
79
+ ```
80
+ There is **no authentication** and the sub-agent can edit files and run commands — keep it on localhost or behind an authenticated tunnel/proxy.
81
+
82
+ ## Tools
83
+
84
+ | Tool | Purpose |
85
+ |---|---|
86
+ | `opencode_run` | Start a session (or continue `session_id`, optionally `fork`) in `directory`. Waits up to `wait_seconds` (default 600); `0` runs in the background. Supports `model`, `agent`, `title`, `files`, `auto_approve`. |
87
+ | `opencode_job` | Poll/wait on a background job by `job_id`. |
88
+ | `opencode_jobs` | List jobs started by this server. |
89
+ | `opencode_cancel` | Stop a running job (session is kept). |
90
+ | `opencode_sessions` | List opencode sessions for a project directory. |
91
+ | `opencode_transcript` | Condensed transcript of a session. |
92
+ | `opencode_delete_session` | Delete a session and its children. |
93
+
94
+ **Parallel work:** start several jobs with `wait_seconds=0`, each in its own git worktree so they don't clash, then poll with `opencode_job`.
95
+
96
+ ## Environment variables
97
+
98
+ | Var | Meaning |
99
+ |---|---|
100
+ | `OPENCODE_BIN` | Path to the opencode binary (default `opencode`) |
101
+ | `OPENCODE_MODEL` | Default `provider/model` when the caller doesn't pass one |
102
+
103
+ ## Security
104
+
105
+ `auto_approve` defaults to `true` (required for headless runs): the sub-agent can modify files and run shell commands in the given directory. Only expose this server to agents you trust, and point it at disposable checkouts/worktrees where possible.
106
+
107
+ ## Notes
108
+
109
+ - Job state is in-memory; it is lost when the server process restarts (opencode sessions themselves persist and can be resumed by `session_id`).
110
+
111
+ ## Publishing (maintainers)
112
+
113
+ ```bash
114
+ npm publish # npm / npx
115
+ uv build && uv publish # PyPI / uvx / pip
116
+ ```
117
+
118
+ ## Development
119
+
120
+ ```bash
121
+ uv run --group dev pytest
122
+ ```
123
+
124
+ MIT licensed.
@@ -0,0 +1,106 @@
1
+ # opencode-samcp
2
+
3
+ **S**ub-**A**gent **MCP** — an MCP server that lets an AI agent (Devin, Codex, Claude Code, Cursor, …) spawn [opencode](https://opencode.ai) sessions as sub-agents and hand them coding work.
4
+
5
+ The parent agent calls `opencode_run` with a prompt and a directory; opencode does the work headlessly (`opencode run --format json --auto`) and the result comes back as structured data: final message, tool-call summary, errors, token usage and cost. Sessions can be continued, forked, run in parallel in the background, inspected and deleted.
6
+
7
+ ## Requirements
8
+
9
+ - [opencode](https://opencode.ai) installed and authenticated (`opencode` on `PATH`, or set `OPENCODE_BIN`)
10
+ - [uv](https://docs.astral.sh/uv/) (or `pip install`)
11
+
12
+ ## Install / run
13
+
14
+ The server is Python; every option below needs [uv](https://docs.astral.sh/uv/) and opencode on the machine.
15
+
16
+ | Method | Command |
17
+ |---|---|
18
+ | **npx** (no install) | `npx -y opencode-samcp` |
19
+ | **npm** (global) | `npm i -g opencode-samcp` then `opencode-samcp` |
20
+ | **uvx** from PyPI | `uvx opencode-samcp` |
21
+ | **uvx** from GitHub | `uvx --from git+https://github.com/amirdaraby/opencode-samcp opencode-samcp` |
22
+ | **pip** | `pip install opencode-samcp` then `opencode-samcp` |
23
+
24
+ The npm package is a thin launcher: it bundles the Python server and runs it through `uvx`.
25
+ If `uv` or `opencode` is missing, it exits with a clear "not installed on machine" error.
26
+
27
+ ## Configure your client
28
+
29
+ ### Devin
30
+ Settings → MCP Marketplace → *Add Your Own* (STDIO):
31
+
32
+ | Field | Value |
33
+ |---|---|
34
+ | Command | `npx` |
35
+ | Args | `-y opencode-samcp` |
36
+
37
+ Devin runs in its own VM, so opencode must be installed and logged in **there** (add it to the machine setup / snapshot).
38
+
39
+ ### Codex (`~/.codex/config.toml`)
40
+ ```toml
41
+ [mcp_servers.opencode]
42
+ command = "npx"
43
+ args = ["-y", "opencode-samcp"]
44
+ ```
45
+
46
+ ### Claude Code
47
+ ```bash
48
+ claude mcp add opencode -- npx -y opencode-samcp
49
+ ```
50
+
51
+ ### Generic JSON
52
+ ```json
53
+ { "mcpServers": { "opencode": { "command": "npx", "args": ["-y", "opencode-samcp"] } } }
54
+ ```
55
+
56
+ ### HTTP transport
57
+ For clients that only speak remote MCP:
58
+ ```bash
59
+ opencode-samcp --transport streamable-http --host 127.0.0.1 --port 8765 # endpoint: /mcp
60
+ opencode-samcp --transport sse ... # endpoint: /sse
61
+ ```
62
+ There is **no authentication** and the sub-agent can edit files and run commands — keep it on localhost or behind an authenticated tunnel/proxy.
63
+
64
+ ## Tools
65
+
66
+ | Tool | Purpose |
67
+ |---|---|
68
+ | `opencode_run` | Start a session (or continue `session_id`, optionally `fork`) in `directory`. Waits up to `wait_seconds` (default 600); `0` runs in the background. Supports `model`, `agent`, `title`, `files`, `auto_approve`. |
69
+ | `opencode_job` | Poll/wait on a background job by `job_id`. |
70
+ | `opencode_jobs` | List jobs started by this server. |
71
+ | `opencode_cancel` | Stop a running job (session is kept). |
72
+ | `opencode_sessions` | List opencode sessions for a project directory. |
73
+ | `opencode_transcript` | Condensed transcript of a session. |
74
+ | `opencode_delete_session` | Delete a session and its children. |
75
+
76
+ **Parallel work:** start several jobs with `wait_seconds=0`, each in its own git worktree so they don't clash, then poll with `opencode_job`.
77
+
78
+ ## Environment variables
79
+
80
+ | Var | Meaning |
81
+ |---|---|
82
+ | `OPENCODE_BIN` | Path to the opencode binary (default `opencode`) |
83
+ | `OPENCODE_MODEL` | Default `provider/model` when the caller doesn't pass one |
84
+
85
+ ## Security
86
+
87
+ `auto_approve` defaults to `true` (required for headless runs): the sub-agent can modify files and run shell commands in the given directory. Only expose this server to agents you trust, and point it at disposable checkouts/worktrees where possible.
88
+
89
+ ## Notes
90
+
91
+ - Job state is in-memory; it is lost when the server process restarts (opencode sessions themselves persist and can be resumed by `session_id`).
92
+
93
+ ## Publishing (maintainers)
94
+
95
+ ```bash
96
+ npm publish # npm / npx
97
+ uv build && uv publish # PyPI / uvx / pip
98
+ ```
99
+
100
+ ## Development
101
+
102
+ ```bash
103
+ uv run --group dev pytest
104
+ ```
105
+
106
+ MIT licensed.
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ // npm launcher for opencode-samcp. The server itself is Python; this shim runs the
3
+ // copy bundled in this package through uv (uvx), so no manual Python setup is needed.
4
+ const { spawn, spawnSync } = require("node:child_process");
5
+ const path = require("node:path");
6
+
7
+ const pkgRoot = path.resolve(__dirname, "..");
8
+ const args = process.argv.slice(2);
9
+
10
+ function has(cmd) {
11
+ return spawnSync(cmd, ["--version"], { stdio: "ignore" }).status === 0;
12
+ }
13
+
14
+ let cmd, cmdArgs;
15
+ if (has("uvx")) {
16
+ [cmd, cmdArgs] = ["uvx", ["--from", pkgRoot, "opencode-samcp", ...args]];
17
+ } else if (has("uv")) {
18
+ [cmd, cmdArgs] = ["uv", ["tool", "run", "--from", pkgRoot, "opencode-samcp", ...args]];
19
+ } else {
20
+ console.error(
21
+ "opencode-samcp failed: uv is not installed on machine (needed to run the Python server). " +
22
+ "Install it from https://docs.astral.sh/uv/getting-started/installation/"
23
+ );
24
+ process.exit(1);
25
+ }
26
+
27
+ const child = spawn(cmd, cmdArgs, { stdio: "inherit" });
28
+ for (const sig of ["SIGINT", "SIGTERM"]) process.on(sig, () => child.kill(sig));
29
+ child.on("error", (e) => { console.error(`opencode-samcp failed to start: ${e.message}`); process.exit(1); });
30
+ child.on("exit", (code, signal) => process.exit(signal ? 1 : code ?? 1));
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "opencode-samcp",
3
+ "version": "0.0.1",
4
+ "description": "Sub-agent MCP: let Devin, Codex, Claude Code and other agents spawn opencode sessions to do work",
5
+ "license": "MIT",
6
+ "author": "Amir Daraby",
7
+ "repository": { "type": "git", "url": "git+https://github.com/amirdaraby/opencode-samcp.git" },
8
+ "homepage": "https://github.com/amirdaraby/opencode-samcp#readme",
9
+ "bugs": { "url": "https://github.com/amirdaraby/opencode-samcp/issues" },
10
+ "bin": { "opencode-samcp": "bin/opencode-samcp.js" },
11
+ "files": ["bin", "src", "!**/__pycache__", "pyproject.toml", "README.md", "LICENSE"],
12
+ "keywords": ["mcp", "opencode", "subagent", "devin", "codex", "ai-agents"],
13
+ "engines": { "node": ">=18" }
14
+ }
@@ -0,0 +1,37 @@
1
+ [project]
2
+ name = "opencode-samcp"
3
+ version = "0.0.1"
4
+ description = "Sub-agent MCP: let Devin, Codex, Claude Code and other agents spawn opencode sessions to do work"
5
+ readme = "README.md"
6
+ license = { text = "MIT" }
7
+ requires-python = ">=3.10"
8
+ dependencies = ["mcp>=1.2,<2"]
9
+ authors = [{ name = "Amir Daraby" }]
10
+ classifiers = [
11
+ "License :: OSI Approved :: MIT License",
12
+ "Programming Language :: Python :: 3",
13
+ "Topic :: Software Development",
14
+ ]
15
+ keywords = ["mcp", "opencode", "subagent", "devin", "codex", "ai-agents"]
16
+
17
+ [project.urls]
18
+ Homepage = "https://github.com/amirdaraby/opencode-samcp"
19
+ Repository = "https://github.com/amirdaraby/opencode-samcp"
20
+ Issues = "https://github.com/amirdaraby/opencode-samcp/issues"
21
+
22
+ [project.scripts]
23
+ opencode-samcp = "opencode_samcp.server:main"
24
+
25
+ [dependency-groups]
26
+ dev = ["pytest>=8", "pytest-asyncio>=0.23"]
27
+
28
+ [build-system]
29
+ requires = ["hatchling"]
30
+ build-backend = "hatchling.build"
31
+
32
+ [tool.hatch.build.targets.wheel]
33
+ packages = ["src/opencode_samcp"]
34
+
35
+ [tool.pytest.ini_options]
36
+ asyncio_mode = "auto"
37
+ asyncio_default_fixture_loop_scope = "function"
@@ -0,0 +1 @@
1
+ """opencode-samcp: sub-agent MCP server for opencode."""
@@ -0,0 +1,3 @@
1
+ from opencode_samcp.server import main
2
+
3
+ main()