You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit dde285c
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: CHANGELOG.md
+27Lines changed: 27 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
8
8
Releases before `1.2.0` predate this file and are not documented here.
9
9
10
+
## Unreleased
11
+
12
+
## [1.3.0] — 2026-10-19
13
+
14
+
### Added
15
+
16
+
- Caller-provided expected workspace changes and bounded executable checks, with additive per-run `workspace_delta` reports and verification states.
17
+
- Workspace-wide overlapping-directory leases, report-aware waits, and an independent lifecycle observer for accepted runs.
18
+
- Prompt dispatch now distinguishes definite HTTP 4xx rejection from ambiguous ACK failures. Ambiguous runs remain tracked with their writer lease held and return `dispatch_uncertain`; definite rejection rolls back only the provisional run.
19
+
- Caller message IDs use OpenCode's required `msg_` namespace; the real smoke includes a non-billable bare-UUID runtime probe.
20
+
- Bounded filesystem inventory, check output, and direct `shell: false` execution; report diagnostics disclose incomplete evidence and shared-workspace attribution uncertainty.
21
+
- Historical `run_id` status/result retrieval and cached final text/progress/report; tool getters do not execute checks again.
22
+
- Opt-in real OpenCode stdio smoke command (`pnpm smoke`) using only the exact `openai/gpt-6-luna` model, including directory-scoped permission handling and independent managed worktrees.
23
+
- Each accepted prompt has an additive `run_id` and run-history record. Explicit user-message IDs scope status, progress, and results to the active prompt; earlier assistant turns cannot appear as a pending continuation's output.
24
+
- Continuation dispatches are reserved per task, cancellation state is recorded only after an accepted abort, and accepted continuations clear prior cancellation state.
25
+
- Status and wait share terminal-state rules; `empty` and `cancelled` now finish long polls.
26
+
- SDK HTTP requests use a 30-second abort deadline; long-polling bounds each status read by the remaining total wait deadline.
27
+
- Server/task records optionally retain the canonical server working directory.
28
+
- Status, wait, and result payloads report direct assistant INFO usage with run/session snapshots, provider/model breakdowns, completeness metadata, and immutable per-run historical snapshots; missing metrics remain unknown and cost currency is unspecified.
29
+
- Optional task directories and managed detached Git worktrees bind SDK requests and per-session permission responders to the selected project. Worktree IDs/metadata appear in task history, and `opencode_cleanup_workspace` performs explicit serialized cleanup while preserving cached reports and usage.
30
+
31
+
### Fixed
32
+
33
+
- SDK response-level errors are surfaced for prompt dispatch, abort, status/message reads, and permission responses, including HTTP failures returned without throwing.
34
+
- Permission responder diagnostics go to stderr rather than MCP stdio.
35
+
-`opencode_wait_for_task` progress enrichment now shares the absolute wait deadline; a slow enrichment is aborted and returns the last observed task status/progress rather than extending the call.
36
+
10
37
## [1.2.0] — 2026-08-28
11
38
12
39
Delegated tasks could hang forever, or report `completed` after doing nothing.
|`opencode_start_server`| Start (or attach to) an OpenCode server instance |
30
+
|`opencode_start_server`| Start a new OpenCode server instance in the MCP process working directory|
31
31
|`opencode_stop_server`| Stop a running OpenCode server instance |
32
-
|`opencode_list_agents`| List agents/models available on a server instance |
32
+
|`opencode_list_agents`| List agents/models available on a server instance (optional `directory` selects a project)|
33
33
|`opencode_start_task`| Delegate a task to an agent by starting a new session and prompt (optional `agent` / `model` override) |
34
34
|`opencode_continue_task`| Send a follow-up prompt to an existing task's session for iterative back-and-forth with the subagent |
35
35
|`opencode_cancel_task`| Abort a running delegated task by cancelling its session |
36
-
|`opencode_get_task_status`| Poll the status of a delegated task (`pending` / `running` / `completed` / `failed`); optional `include_progress` adds a partial output snippet and the currently running tool while it's still running |
36
+
|`opencode_cleanup_workspace`| Explicitly remove an owned Git worktree after task reports finalize; dirty worktrees require opt-in discard |
37
+
|`opencode_get_task_status`| Poll the status of a delegated task (`pending` / `running` / `completed` / `failed` / `empty` / `cancelled`); optional `include_progress` adds a partial output snippet and the currently running tool while it's still running |
37
38
|`opencode_get_task_result`| Fetch the final result of a completed task |
38
-
|`opencode_wait_for_task`| Long-poll one or more delegated tasks until they finish (`mode: "all"` or `"any"`) or the timeout elapses; optional `include_progress` enriches any still-unfinished tasks in the final result with a partial output snippet and the currently running tool|
39
+
|`opencode_wait_for_task`| Long-poll one or more delegated tasks until they finish (`mode: "all"` or `"any"`) or the timeout elapses; optional `include_progress`best-effort enriches unfinished tasks within the same deadline, falling back to the last observed status/progress when time runs out|
Task delegation is **asynchronous**: starting a task returns immediately with a `task_id` instead of blocking until the subagent finishes. This lets Claude Code fire multiple `opencode_start_task` calls in parallel — each one opens an isolated OpenCode `Session` — without hitting MCP client timeouts on long-running work. Status and results are fetched separately via polling.
48
+
Task delegation is **asynchronous**: starting a task returns immediately with a `task_id` instead of blocking until the subagent finishes. This lets hosts fire multiple `opencode_start_task` calls in parallel — each opens an isolated OpenCode `Session` — without hitting MCP client timeouts on long-running work. Tasks use the selected directory directly by default; managed Git worktrees are an explicit opt-in. Status and results are fetched separately via polling. If the prompt ACK transport is lost after OpenCode may have accepted the request, the tool returns `dispatch_uncertain` with task/run IDs and retains its lease; poll that task or cancel it rather than retrying the prompt as a new task. Definite HTTP 4xx rejection rolls back provisional run state and lease.
49
+
50
+
Each accepted start or continuation prompt also receives a `run_id`. Status, progress, and results are scoped to that prompt's explicit message ID, while progress evidence remains cumulative across turns in the same run. `empty` and `cancelled` are terminal outcomes. A cancelled task can be continued; the accepted continuation becomes the current run and clears the previous cancellation state. Concurrent continuation dispatches for the same task are rejected with `dispatch_in_progress`.
51
+
52
+
OpenCode 1.18.34 requires caller message IDs to start with `msg`; the MCP uses `msg_${randomUUID()}` for both start and continuation prompts. The opt-in harness also probes a bare UUID through the installed SDK/runtime using an invalid provider/model so the identifier contract can be checked without a paid request.
53
+
54
+
### Execution reports and caller checks
55
+
56
+
`opencode_start_task` and `opencode_continue_task` accept optional `expected_changes` (`[{ path, change }]`, where `change` is `created`, `modified`, or `deleted`) and `checks` (`[{ executable, argv, cwd?, timeout_ms? }]`). Paths and check working directories are relative to the server workspace; checks run directly with `shell: false`. Reports are additive on status/result as `run_id`, `changes`, `verification`, `diagnostics`, and `evidence`. `opencode_get_task_result` and `opencode_get_task_status` accept an optional `run_id` to retrieve a historical run; omitted means the current run.
57
+
58
+
### Shared directories and managed worktrees
59
+
60
+
`opencode_start_task` accepts `directory` (relative to the server directory, defaulting to it), `workspace_mode` (`shared` by default or `worktree`), and `base_ref` (worktree mode only, default `HEAD`). The selected directory must already exist. Shared mode runs directly in that canonical directory. Worktree mode creates a unique detached Git worktree at the selected committed ref; source modifications and untracked files are neither copied nor altered. When the selected base does not contain the requested nested source directory, the request fails instead of silently changing the execution directory.
61
+
62
+
Start, status, result, wait, and historical-run payloads expose a `workspace` object with source and execution directories, mode, managed state, and (for worktrees) `workspace_id`, base commit, source dirty state, and lifecycle state. SDK requests are bound to the selected directory through OpenCode's directory routing. Permission responders are keyed by server and canonical directory and answer only sessions registered to that scope.
63
+
64
+
Accepted worktrees are retained after task completion. Call `opencode_cleanup_workspace` with the returned `workspace_id` after reports are finalized. Cleanup serializes against task continuation/dispatch, rejects unfinished reports and dirty worktrees, and removes only worktrees provisioned by this MCP process. Set `discard_changes: true` only when changes inside that owned worktree should be discarded. Cleanup never removes source files; cached results, usage, and historical runs remain readable after the worktree is removed.
65
+
66
+
### Usage reporting
67
+
68
+
Status, wait, and result payloads include an additive `usage` snapshot. Its `run` summary selects direct assistant messages whose `parentID` matches that run's user-message ID; `session` summarizes all direct assistant messages observed in the session snapshot. Neither includes descendants or separate subagent sessions. Per-provider/model breakdowns preserve raw input, output, reasoning, cache-read, cache-write, and OpenCode-reported cost independently; token categories are not combined into a potentially overlapping total. Step-finish part metrics are excluded.
69
+
70
+
Each metric has a nullable `value`, `complete` flag, and `missing_messages` count. Missing, invalid, or negative values remain unknown; explicit zero is known. Empty snapshots do not claim zero consumption. Cost is labeled as OpenCode-reported, with currency unspecified; it is not an invoice total. `captured_at` and `snapshot_kind` identify the observation. A finalized run caches its own run and session snapshot, so retrieving an older `run_id` after a continuation returns the historical session snapshot from that run's finalization—not a current cumulative total. Failed message reads return `report: null` with a diagnostic.
71
+
72
+
The MCP server captures a bounded workspace inventory before accepted dispatch and after execution. The inventory recursively hashes workspace files except `.git` and `node_modules`; caller-declared expected paths are also checked explicitly, including paths inside otherwise skipped directories. Created/untracked, modified (including pre-existing dirty files changed since baseline), deleted, binary, and symlink entries are reported. Changes are labeled `workspace_delta`: concurrent or unmanaged writers can still make attribution uncertain. A verified run holds an exclusive lease across the canonical workspace and overlapping directories; it blocks verified and ordinary MCP task writers and conflicts fail fast with `workspace_busy`. Ordinary unverified runs may share a workspace. `session.diff` is not used as task provenance. Capture errors, missing expected changes, and scope limits are disclosed. `opencode_wait_for_task` supports `until: "execution"` (default) or `until: "report"`; report waits end on finalized failed, unavailable, or cancelled reports while respecting the whole-call timeout.
73
+
74
+
Each accepted run retains its own baseline, criteria, lease, result, report, and finalized usage snapshot. Checks are executed once by the background lifecycle observer after terminal execution. Their result includes exit code/signal, duration, bounded output and exact truncation flags; timeout/cancellation terminates the child process group. Verification may be `not_requested`, `pending`, `running`, `passed`, `failed`, `unavailable`, or `cancelled`; execution success alone does not mean verification passed. Final task text/progress, reports, and usage snapshots are cached, so result queries do not rerun checks and historical results remain available after a continuation or backend removal. Workspace inventories are capped at 20,000 entries and 32 MiB of file content; check output is capped at 16 KiB per stream. These limits and shared-workspace attribution mean the report is evidence, not proof of exclusive authorship.
75
+
76
+
Run the opt-in real OpenCode stdio smoke harness with `pnpm smoke`. It uses only `openai/gpt-6-luna` for its paid prompts, creates and removes temporary fixtures, and checks real reports/usage, historical retrieval, no-change and cancellation continuations, two detached worktrees editing the same relative file independently, an external read permission in a scoped worktree session, continuation in that worktree, dirty-cleanup refusal, explicit discard, and cached history after removal. The no-model identifier probe is also runnable with `node --experimental-strip-types scripts/smoke.ts --message-id-only`. The paid smoke is intentionally not part of default CI because it requires configured credentials.
Copy file name to clipboardExpand all lines: package.json
+2-1Lines changed: 2 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
{
2
2
"name": "mcp-server-opencode",
3
-
"version": "1.2.0",
3
+
"version": "1.3.0",
4
4
"description": "MCP server that lets any MCP host (Claude Code, Codex CLI, Cursor, etc.) drive OpenCode and delegate tasks asynchronously to its agents",
0 commit comments