opencode-agora MCP server
Commit Nov 13, 2026Enables multi-agent orchestration for opencode v2 by running tests in isolated git worktrees and performing verified merges.
Also known as guangbin79/opencode-agora
- Stars
- 2
- Tools
- —
- Downloads, 30 days
- —
- Latest version
- —
- Last commit
- Nov 13, 2026
- License
- MIT
What is opencode-agora MCP?
opencode-agora enables multi-agent orchestration for opencode v2 by running tests in isolated git worktrees and performing verified merges.
Summary generated from the project's README
About opencode-agora MCP server
Orchestrating complex coding tasks across multiple repositories is what opencode-agora enables for developers using opencode v2. This MCP server transforms a standard LLM session into an orchestration agent where the model handles high-level planning and scheduling while a local Python service manages execution and verification. It is designed for developers who need to automate multi-step workflows, such as applying a single fix across several sibling repositories using dependency chains.
The system operates by spawning workers in isolated git worktrees to ensure that your main codebase remains untouched during development. It uses a unique dual-gate system to maintain code quality: a verify gate that runs test commands like pytest under a separate service to prevent agents from self-reporting success, and a review gate that integrates with external tools or human checklists via an anchor file. Users interact with the server through natural language, managing tasks, viewing live progress on a TUI dashboard, or canceling operations through the conversation interface.
What you can do with it
- 1Cross-repository dependency chainsA developer can instruct the agent to update a dependency in one repository and then automatically apply the corresponding fixes to multiple other repositories.
- 2Isolated automated testingYou can delegate a bug fix to an agent and require it to pass specific test suites before any code is merged.
- 3Real-time task monitoringDevelopers can check the current status of multiple running agents and their dependency chains using a specialized dashboard.
- 4Verified code integrationThe system ensures that only code passing both automated tests and external review processes is merged into the target branch.
Written from the project's README. Every use case is checked against a quote from it.
README
View on GitHubopencode-agora
Multi-agent delegation for opencode v2. Installing it upgrades your main session into an orchestration agent — the LLM plans, the machine verifies. Each task runs in its own git worktree; only verified work gets merged.
You: "Fix the login bug in repoB. Run pytest -q, merge when green."
agora: └─ spawns a worker in an isolated git worktree
worker fixes → service runs pytest itself → review green → ff-only merge
You: "How's it going?" → board: ✅ merged
The difference in one line: the LLM holds the steering wheel; the machine holds the brakes. Orchestration — what to run, in what order, when to replan — stays in your conversation, so mid-flight intent ("now apply the same fix to repoB and repoC") becomes a new schedule on the spot. And agents don't grade their own homework here: the verify command runs under the service, not the worker — green means the tests actually passed on the exact commit being merged.
Super Agent pillars: this repo is the dispatch pillar (Router). The other two: silicon-memory (memory/state separation) and coding-gates (quality supervision gates). Together they form the super agent implementation.
Quick Start
Prerequisites: opencode v2 (curl -fsSL https://opencode.ai/v2/install | bash), bun (curl -fsSL https://bun.sh/install | bash), git, python3 ≥ 3.10 (stdlib only — zero pip dependencies).
git clone https://github.com/guangbin79/opencode-agora.git
cd opencode-agora && ./install.sh
From PyPI instead — equivalent install, no clone needed (the git route above stays as the source-code form):
pipx install opencode-agora
agora-install
That's it. The installer is idempotent (safe to re-run); it registers the MCP server, copies the plugin + skills, and leaves a root credential at $AGORA_HOME/.agora/root.token (0600).
Now just talk to your opencode session as usual:
| You say | What happens |
|---|---|
"Have an agent fix X in repoY, verify with pytest -q" |
Task created, worker dispatched into its own worktree |
| "How's it going?" | Live board: five buckets, dependency chains, escalation feed |
| "Stop that task" | Cascade-cancel with confirmation |
| "Bump the dependency in repoA, then apply the same fix in repoB and repoC" | after: dependency chain — B and C wait for A, unrelated repos run in parallel |
Standalone dashboard: agora-board (vi-motion TUI). Update path: git pull && ./install.sh.
Where It Sits
| LLM-led orchestration | Machine-run quality gate | |
|---|---|---|
| Task-graph orchestrators (plan once, execute a static graph) | ✗ | ✓ |
| Agent-swarm frameworks | ✓ | ✗ (agents self-report) |
| opencode-agora | ✓ | ✓ |
Orchestration needs the model's flexibility — real intent surfaces mid-conversation, not in an upfront plan. Merge quality must not trust the agent — it has to run where the agent can't fake it. Most projects take one side; agora is built on the bet that you need both.
Making your session an orchestrator isn't unique — subagent trees do that too. The unique part, on an open-source and model-neutral stack, is the control plane that keeps the orchestrator honest: verify gate, role-separated credentials, and append-only audit running as an independent service the agent cannot rewrite. Native tools may absorb this tomorrow; today the gap is real.
Two capabilities this control plane buys in practice:
- Single repo: enforced worktree writes. Every agent edit is forced into the task's own worktree by the plugin gate + session tokens — your main checkout is never touched. Convention becomes mechanism.
- Multiple repos: one root agent, sibling repos. A single session at the parent directory orchestrates cross-repo chains with
after:— the downstream task sees the upstream repo's merged result through the../sibling layout, while unrelated repos run in parallel.
Honest trade-offs (the same reasons you might not want this):
- A wrong
verify_cmdat creation can stall a task — it fails safe: workers can't edit verify, so the worst case is a stuck task, never a bad merge - Your main session's context is the orchestration bottleneck — that's why
agora-boardexists: five-bucket state at a glance without spending conversation window - Every scheduling decision is a model call — if your work pre-decomposes into a clean static graph, a zero-token orchestrator is cheaper and more reproducible
How It Works
Human ──▶ Main session (skills: agora-dispatch / agora-ops)
│ MCP (14 tools)
▼
agorad — Python stdlib service on localhost
state authority · verify gate · auto-merge · message routing
crash recovery · audit ledger
│
Per-task git worktrees (enforced isolation)
Task lifecycle: create → dispatch → worker codes → verify (service-run) → auto-merge (ff-only) → closed
After install, your session gains two skills (agora-dispatch / agora-ops) and 13 MCP tools. There is no background planner: the model you talk to is the orchestrator — task creation, after: chains, cancels, escalation replies are all model decisions from conversation context. agorad stays the state authority: verify executor, merge gate, message router, audit ledger.
Two Quality Gates
Verify gate — the non-negotiable one. The verify command is registered at task creation (task_create(verify_cmd="pytest -q"), or verify_pending: true to defer). The service runs it in the task worktree, then trial-merges into a detached integration worktree and runs it again. Only two green runs advance the target branch; integration failures and test side effects never touch your main checkout. Fresh checkouts come pre-seeded: submodules recorded in the target commit are populated from the local main checkout — no network, no credentials; pins the reference lacks are skipped and reported, never fetched. git-lfs-tracked files are materialized from the shared local LFS object store the same way (a pointer-only file is the symptom of a missing local object, which is reported, never fetched). After a successful merge the service pushes the target branch to origin — best-effort and idempotent: a non-fast-forward rejection or push failure only warns the dispatcher with the git output tail (never forces, never touches the merge), and repos without origin are silent. One hard requirement: your main checkout must be clean (no uncommitted or untracked changes) before the final push, otherwise the task reopens with a cleanup hint. The gate first idempotently writes the $AGORA_HOME/.agora/ignore.roster roster (one gitignore pattern per line) into the repo's .git/info/exclude; rostered paths don't count as untracked dirt. Root-level untracked hidden directories are auto-exempted: when every blocker is an untracked dot-directory at the repo root (?? .dir/), the gate appends those directories to the roster, re-applies it, retries the clean check in the same run, and lists them in the merged notification; mixed dirt (tracked changes, non-hidden paths, nested new files) still reopens unchanged. Data-layer churn gets its own exemption (clean-ignore): declare paths in the repo-root .agora/clean-ignore (one gitignore-style entry per line) and/or the deployment env AGORA_CLEAN_IGNORE (comma-separated); entries match by root-anchored directory prefix, and changes on declared paths — tracked or untracked — no longer block the gate. Division of labor: the roster hides untracked paths from git status via info/exclude; clean-ignore subtracts declared paths themselves (tracked changes included) from the clean check — keep task deliverables out of declared paths, or the gate will not see you touch them. Each run has two caps: a soft top (300 seconds by default) that only pings the dispatcher once — still running, no action needed — and a hard top (4× soft by default) that kills the process group. A hard-top kill (rc=124) routes to the dispatcher with the output tail: no worker retry loop, no fail streak, the task stays in done. Red = the worker gets the output and retries. Three consecutive failures = blocked + escalation ping. The worker cannot skip it, fake it, or report results itself. Command hygiene is checked statically at registration (F99): the command text is lexed without execution — an absolute cd/pushd, or an absolute path (including $HOME/~ expansion) landing inside the repo outside dependency dirs (venv/, node_modules/, …) in a bare token or VAR= assignment, is rejected with a fix hint; --flag=<absolute-path> option-value forms are not detected, so keep option values relative too. Paths under ~/.config and friends only warn. Relative paths, absolute toolchains outside the repo, cross-repo references and dependency dirs pass. Commands already registered before the gate run unchanged — doctor audits them read-only (verify_hygiene_findings) instead of rewriting history, and the quick lane filters escape commands out of the history vote.
Review gate — an open standard, bring your own reviewer. The contract is one anchor file:
- The last-reviewed anchor is checked at
done— missing, stale, or not green rejectsdoneback to the worker — and re-checked immediately before merge (closes the "reviewed, then sneaked a commit" window; a failed re-check auto-reopens the task, it never parks). A done with zero new commits over the target is rejected the same way — unless it is a valid delivery already landed there (env HEAD advanced past the task's start base, or the previously accepted commit is reachable on the target); a true zero-work done (HEAD still at the start base) is rejected — the worker reports no-op via post(kind=question) and the dispatcher cancels to archive. - Anchor green + verify green = automatic ff-only merge — a behind task branch is rebased onto the target in-gate first (clean sync self-heals; only sync conflicts reopen).
- Phantom-merge guards —
mergedis booked only when the target branch actually contains the delivered commit: an empty rebase (no new commits on the env boot branch) or an idempotent-ff false success reopens the task instead of silently losing the delivery. - No
.review-loop/directory?doneis rejected with instructions to add one — auto-merge requires both gates. Autonomy is earned, not assumed.
Any reviewer fits — OpenCodeReview, CodeRabbit, a human checklist — agora only reads the anchor. A minimal reviewer is ~10 lines:
#!/usr/bin/env bash
# review-loop.sh <worktree> <target_branch> — run after each commit; exit non-zero if not green
set -euo pipefail
cd "$1"
base=$(git merge-base HEAD "${2:?}"); sha=$(git rev-parse HEAD)
findings=$(your_reviewer "$(git diff "$base"..HEAD)") # OCR / CodeRabbit / human list
printf '%s\n' "$findings" | grep -qiE 'blocker|high' && { printf '%s\n' "$findings"; exit 1; }
mkdir -p .review-loop && printf '%s\n' "$sha" > .review-loop/.last-reviewed
Full spec — contract details, worker protocol, threat model, idle auto-trigger design notes: docs/review-loop.md (Chinese).
Delivery Semantics
Where your commits land depends on the delivery mode and where authority lives. Every task row carries a machine-readable delivery projection (mode/status/commit/base/attempt/local_status/error).
- Managed tasks (the default) with
origin— remote authority, origin-first. The env is based on the remote tip; the gate integrates on the freshest remote tip, replays with an in-gate rebase when the remote has moved, re-verifies, then publishes under a repo-level delivery lock: an exact<sha>:refs/heads/<branch>fast-forward push, never a force. A clean non-ff (someone else advanced the remote) or a lock timeout consumes one of at most three total attempts; exhaustion is a delivery failure (retry_exhausted). Content conflicts on rebase and push failures are terminal delivery failures too: the task goesblockedwithdelivery.status=failedand a machine-readable error, the authoritative target stays untouched, the worker is not bounced, and fail-streak is not counted — delivery failure is not a quality verdict. Your local checkout is never touched: after the remote lands, the service best-effort syncs the local branch (local_status=synced) or recordslocal_status=pending— a checked-out, held, or dirty local branch stays exactly as it is, and local pending never rolls back the remote delivery. - Managed tasks without
origin— local authority, CAS ff-only. The pinned local branch tip is the authority: the gate advances it only via a compare-and-swap fast-forward under the delivery lock. A dirty or occupied target is a terminal delivery failure (local_target_dirty/local_target_busy) — never a fake pending, never a cleanup. Startup recovery converges crash leftovers; a failed delivery never auto-retries (redispatch resets the projection). external_branchtasks — external dispatcher authority. For externally managed dev branches, agora never pushesoriginand never merges the default branch: the gate verifies privately on the pinned branch, then parks the task atdone+awaiting_external(commit/base/attempt recorded, env and credentials kept). The external dispatcher acknowledges viatask_deliver:deliveredcloses the task,non_ffwith the fresh external tip rebases and re-verifies into a new handoff commit (same three-attempt budget; the fourth acknowledgement isretry_exhausted),failedblocks with a machine-readable error. An acknowledgement carrying a stale handoff commit is rejected with zero state mutation.- Multi-instance safety. Several agora instances may work the same repository: each owns its task worktrees (instance-stamped names; cleanup deregisters by exact path and never removes another instance's registered worktree), and the repo-level delivery lock serializes final advances, so concurrent deliveries produce a linear first-parent history. End-to-end proof:
python3 tests/e2e/multi_instance_delivery.py(two real service instances, nine scenarios). Mixing old (pre-F96) and new agora instances on the same repository is not allowed — every same-repo writer must be upgraded to the lock/instance protocol.
Deployment note: the plugin and service payloads are copies — after upgrading the agora repo you must rerun ./install.sh and restart the service, or the running daemon keeps the old delivery code.
Highlights
- Verified autonomy — auto-merge only after service-run tests pass and the review anchor is green, with the anchor re-verified at merge time
- Enforced isolation — plugin-level gate blocks git-repo writes without task credentials; workers can't touch your main checkout.
- Cross-repo and nested orchestration —
after:dependency chains; workers can create and manage their own subtasks, and a parent can finish only after child results return; hard limits on nesting (3) and concurrency (6); leaf workers cannot dispatch subtasks (F41) - Role-separated credentials — root / dispatcher / worker session tokens; workers can cancel or register verify only for their own subtasks, never manage parents or other tasks, or read the board
- Root token is daemon-bound — issuance targets the daemon identity (
sid="root"), never a client session sid, and root calls carryingX-Agora-Sidnever rebind the token: the live session only updatesmain_sidwhile task attribution records the real caller sid (chain edges judge by the recorded value). Legacy ledger entries that still bind a root token to a session sid are migrated once at startup back tosid="root"(old sid kept in lineage, idempotent, in-flight worker tokens untouched); startup audit remains as a residue watchdog — never revokes, since the root token is often the sole governance credential - Crash recovery —
kill -9the service at any moment; append-only state + worker re-injection with the same credentials on restart - Real-time accountability — escalation pings to the main session, append-only JSONL audit for every state change, health patrol for dead dispatchers
- PR-workflow friendly —
task_create(target_branch="feature/x")merges into a feature branch instead of main - Server-side req numbering —
task_create(req_id="F34")registers and de-duplicates feature numbers (seeded fromdocs/reqs/, duplicate issuance rejected). Server allocation is the authoritative number source; workers take the number from the task page. Bypassing is not prevented — a convention, not a gate - Quick micro-tasks — a light lane for small single-repo changes:
task_create(quick=true)needs no verify_cmd; the verify command is resolved dynamically from ledger history (the unique most-frequent command among the repo's merged non-quick tasks, count ≥ 2; insufficient evidence rejects with the candidates — just dispatch the task normally, there is no manual table path); over-envelope diffs are measured mechanically at the gate and fail like a verify red; the worker BOOT drops three informational lines - Lightweight — Python stdlib service, zero pip dependencies, localhost only, no telemetry
Comparison
| Manual multi-session | Swarm frameworks | opencode-agora | |
|---|---|---|---|
| Per-task isolation | you manage worktrees | varies | enforced (plugin gate + worktree per task) |
| "Tests pass" means | agent says so | agent says so | service ran the command itself |
| Cross-repo dependencies | manual sequencing | yes | after: chains, parallel when unrelated |
| Merge | manual | varies | automatic, only when both gates are green |
| Audit trail | none | partial | append-only JSONL, every state change |
| Install footprint | — | heavy runtimes | python3 stdlib + git + bun |
Configuration
| Option | Default | Description |
|---|---|---|
AGORA_HOME |
~/plaza |
Ledger home (state, messages, audit, wiki) |
$AGORA_HOME/.agora/inactive-repos |
empty | Repos where agora is fully dormant (one path per line) |
AGORA_BOARD_INTERVAL |
5 |
Dashboard poll interval (seconds) |
AGORA_HEALTH_INTERVAL |
300 |
Dispatcher health patrol (seconds) |
AGORA_VERIFY_TIMEOUT |
300 |
Soft top per task/integration verify run (seconds): notify the dispatcher on expiry, no kill |
AGORA_VERIFY_CEILING |
4× soft top |
Hard top (seconds): expiry kills the verify process group; overrun routes to the dispatcher (no worker retry, task stays done) |
AGORA_QUICK_MAX_FILES |
3 |
Quick-task envelope: cumulative changed-files cap, measured mechanically before verify; over the cap the task fails like a verify red |
AGORA_QUICK_MAX_LINES |
30 |
Quick-task envelope: cumulative added+deleted lines cap, same red path |
$AGORA_HOME/.agora/agorad.env |
— | Knob defaults file (KEY=VALUE, # comments); explicit process env takes precedence, survives daemon restarts |
enforce |
on | Global gate switch (root only, audited) |
$AGORA_HOME/.agora/email.json |
off | Stuck-task email alerts ({"to","command"}) |
Note: install.sh seeds AGORA_VERIFY_TIMEOUT=3600 into $AGORA_HOME/.agora/agorad.env — the code/README default is 300 (soft top notifies, never kills); the installer widens it because long-build repos measurably outgrow 300s.
Safety Model
Honest by design — what's machine-checked vs what's trusted:
Enforced (cannot be bypassed):
- Git-repo writes only within task worktrees (plugin gate + session tokens)
- Verify must actually run and pass, executed by the service
- Role matrix: workers can't cancel, modify verify, or toggle enforce
- Every state change lands in the append-only audit ledger
Accepted risks (single-machine trust model):
- A worker using raw
bashcan bypass the write gate (audit is the backstop) - Token theft within the same user account
- The review anchor is a process protocol, not an anti-cheat: the worker writes it, the service reads it. The verify gate is the real quality bar; review adds discipline, not security
FAQ
How do I update? git pull && ./install.sh — the plugin and service payloads are copies, so re-running the installer is required after pulling.
How do I uninstall?
rm -rf ~/.config/opencode/plugins/agora ~/.config/opencode/skills/agora-dispatch \
~/.config/opencode/skills/agora-ops ~/.local/bin/agora ~/.local/bin/agora-board \
~/plaza ~/.agora-home
# then remove the "agora" entry from the mcp section of ~/.config/opencode/opencode.json
(~/plaza is the default AGORA_HOME — if you configured a custom one, remove that directory instead.)
Does it work without a review-loop? Verify still gates everything, but done needs an anchor: without one, done is bounced back to the worker with instructions. Implement the open standard to unlock auto-merge.
Where does my code go? Nowhere. agorad binds to localhost, workers are local opencode sessions, there is no telemetry, no cloud, no agora API keys. Whatever models your opencode uses, agora orchestrates them.
Platforms? Linux (verified). macOS: the code paths are in place (the installer falls back to nohup where setsid is absent) but not yet verified on a real Mac. Windows: run inside WSL.
License
MIT
opencode-agora MCP questions
How does opencode-agora ensure code quality?
It uses a verify gate where the service runs the specified test command in an isolated git worktree, ensuring the agent cannot fake test results.
Can I use this to manage multiple repositories at once?
Yes, a single session can orchestrate cross-repo dependency chains using the 'after:' command, allowing tasks in one repo to wait for another.
What happens if a task fails its verification?
The system fails safe; if a command fails or hits a hard timeout, the task is not merged and the worker is notified of the failure.
Does it require external dependencies?
The Python implementation uses only the standard library and has zero pip dependencies.