TaskBridge
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@TaskBridgeFix the failing tests in the auth module and show me the diff"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
TaskBridge
Claude plans. OpenCode builds. Dispatch real coding work from Claude to headless OpenCode agents via a durable SQLite queue.
Claude submits tasks over MCP. An auto-worker picks them up in ~60 s, runs opencode run in an isolated worktree, and returns a structured summary, git-aware diff, logs, and usage for Claude to read. Works from Claude Desktop (stdio), any MCP client over HTTP, and in reverse — OpenCode can drive Claude too.
Why this exists
Claude is a powerful planner that can't touch your filesystem. OpenCode runs code locally but lives outside Claude's context. The bridge closes the loop:
Claude stays the interface — breaks work down, delegates, and reads results.
OpenCode does the execution — edits, tests, shell, headlessly and reproducibly.
SQLite is the durable handoff — survives restarts, supports retries, priorities, dependencies, and two-way questions.
Related MCP server: CatHub Nyaanes
Features
16 MCP tools for Claude —
submit_task,submit_batch(up to 20),get_task/get_task_result,get_task_logs(live tail),wait_for,answer_task,list_tasks,queue_status/worker_heartbeat,add_task_note,cancel_task/clear_finished,list_models/set_default_model,ping. No polling loops, full observability.Headless auto-worker (
worker.py) — launchd polls every 60 s, claims oldest-first by priority, streams output totask_logs/<id>.log, returns structured{summary, files_touched, tests_run, open_questions}plus a git-aware diff.Two-way questions — worker can pause with a
questionblock → task goeswaiting+ macOS banner → Claude answers viaanswer_task→ run resumes with the answer in context.Worktree isolation — per-task branch +
git worktree, auto-committed on success, cleaned up unlessworktree_keep.Honest permissions —
readonlyreverts writes and reportsrevertedfiles;no-network/no-shellare prompt-level and explicitly labeled.Reverse bridge (
claude_control_mcp.py) — 6 tools for OpenCode to drive Claude:claude_ask(sync),claude_submit/claude_poll/claude_result/claude_cancel(background),claude_status. Uses Anthropic API ifANTHROPIC_API_KEYis set, elseclaude -p.Public-URL mode (
install.sh/start_public.sh) — one command to expose MCP via ngrok (the installer prompts for your Authtoken) or Cloudflare quick tunnel with automaticMCP_ALLOWED_HOSTSpairing.Live dispatch board (
bridge_dashboard.html) — served atGET /on the same host. Tally counts, per-task live logs, reverse jobs, engine tail, and a scrolling feed of fresh output. Polls/api/*; MCP stays at/mcp.Caller detection —
submit_task/submit_batchstamp the true caller from the MCP handshakeclientInfo, so Claude and ChatGPT dockets stay separate.origincan be overridden explicitly.Production reliability — per-attempt timeouts, 15-min stale-
runningreaper with pid-reuse guard, single-instance flock, heartbeat file, macOS banners (WORKER_NOTIFY=0to silence).
Quickstart
Prerequisites: Python 3.12, opencode CLI on PATH, and (for public access) a free ngrok account.
One command — install, tunnel, serve, print your connector box:
git clone https://github.com/Parithosh-Varma/TaskBridge.git
cd TaskBridge
./install.shinstall.sh prompts for your ngrok Authtoken (blank = already configured), installs dependencies into .venv, generates or reuses the bearer token in .bridge-token, opens the ngrok tunnel (fixed domain from .ngrok-domain when present), pairs MCP_ALLOWED_HOSTS, prints the public URL + token box, then serves MCP in the foreground. Ctrl+C stops the server; the tunnel stays up for the next run. Rotate the token with ./install.sh --rotate.
Manual setup (stdio / local dev):
git clone https://github.com/Parithosh-Varma/TaskBridge.git
cd TaskBridge
python3.12 -m venv .venv
./.venv/bin/pip install -r requirements.txtRun the MCP server (stdio — Claude Desktop spawns this):
./.venv/bin/python opencode_bridge_mcp.pyOr serve HTTP locally:
./.venv/bin/python opencode_bridge_mcp.py --transport streamable-http --port 8000
# → http://127.0.0.1:8000/mcpWire into Claude Desktop — merge claude_desktop_config.snippet.json into
~/Library/Application Support/Claude/claude_desktop_config.json under mcpServers
(replace <REPO_PATH> with your checkout path), then restart Claude Desktop.
Verify: ask Claude to list MCP tools — you should see submit_task, get_task, list_tasks under taskbridge.
Authentication (HTTP mode)
install.sh generates the bearer token and serves the public endpoint:
./install.sh # reuse or generate .bridge-token, tunnel + serve
./install.sh --rotate # regenerate the bearer token firstToken is loaded from .bridge-token file or BRIDGE_AUTH_TOKEN env var.
install.sh and start_public.sh (the background / Cloudflare-tunnel variant) both pick it up automatically.
Public URL access requires:
Authorization: Bearer <your-token>/healthis open (monitoring)/dashboard prompts for token (stored in sessionStorage)/api/*and/mcprequire Bearer tokenstdio transport (Claude Desktop) is local-only, no token needed
To rotate token: ./install.sh --rotate
Run one worker pass manually:
./.venv/bin/python worker.pyOr schedule it every 60s with launchd (macOS) — see worker.py header and adjust the plist ProgramArguments to your checkout path.
Usage
From Claude:
submit_task(title="Add retry tests", instructions="Steps..., paths..., acceptance criteria...", working_dir="/path/to/target-repo")→ returnsidwait_for(task_ids=["<id>"], timeout_sec=120)— blocks instead of pollingget_task_result(task_id="<id>")→result,structured,usage,diff
Batch + follow-ups:
submit_batch(tasks=[...])— up to 20 tasks with per-itemmodel,depends_on,priority,timeout_sec,max_retries/retry_model,tags,idempotency_key,permission,worktree_*get_task_logs(task_id="...", since_offset=0)— tail live outputanswer_task(task_id="...", answer="...")— answer awaitingtask's questionqueue_status()/worker_heartbeat()— queue counts + daemon liveness
From OpenCode (manual worker loop):
./.venv/bin/python tasks_cli.py pending
./.venv/bin/python tasks_cli.py show <id>
./.venv/bin/python tasks_cli.py claim <id>
# ... do the work (edits, shell, tests) ...
./.venv/bin/python tasks_cli.py complete <id> --result "..."
./.venv/bin/python tasks_cli.py fail <id> --error "..."Reverse (OpenCode → Claude) via claude_control_mcp.py (registered as an OpenCode MCP server): claude_ask for one-shot answers, claude_submit + claude_poll / claude_result for background jobs.
How it works
flowchart LR
Claude -- MCP stdio/HTTP --> Bridge[opencode_bridge_mcp.py]
Bridge -- read/write --> DB[(tasks.db - SQLite)]
CLI[tasks_cli.py] -- claim/complete --> DB
Worker[worker.py - launchd 60s] -- polls DB, runs opencode run --> Target[working_dir / worktree]
Worker -- streams logs --> Logs[task_logs/ID.log]
Worker -- result/structured/usage --> DB
Claude -- get_task_result / wait_for --> Bridge
OpenCode -- claude_ask/submit --> Reverse[claude_control_mcp.py]
Reverse --> ClaudeCLI[claude -p / Anthropic API]Key components:
File | Role |
| MCP server (Claude side), stdio + |
| Shared SQLite logic: submit/claim/complete, retries, deps, notes, heartbeat |
| CLI for manual runs: |
| Headless executor: |
| Reverse MCP server (OpenCode → Claude) |
| One command: deps + bearer token + ngrok tunnel + allowlist + serve |
| Background variant: tunnel + allowlisted MCP server (ngrok fixed domain or Cloudflare) |
| Claude Desktop wiring template ( |
Configuration
Variable | Used by | Purpose |
| bridge, CLI | SQLite path (default: |
| worker | Default model, e.g. |
| worker |
|
| worker |
|
| bridge (HTTP) | Comma-separated tunnel hosts (required behind ngrok/cloudflared, else 421) |
| bridge (HTTP) | Bearer token for MCP/API access (defaults to |
| OAuth consent | Secret for the /approve "this was me" page (defaults to the bridge token) |
| OAuth | Access-token lifetime (default 86400 = 24h) |
| OAuth | Refresh-token lifetime (default 2592000 = 30d) |
| bridge (HTTP) | Force the public origin in OAuth documents when behind unusual proxies |
| reverse bridge | Direct API backend; else |
| reverse bridge | Model override / shadow HOME for CLI backend |
start_public.sh: uses .ngrok-domain if present (fixed domain), else Cloudflare quick tunnel. It re-pairs MCP_ALLOWED_HOSTS automatically — rerun it whenever the URL changes. If .bridge-token exists, BRIDGE_AUTH_TOKEN is loaded automatically. install.sh is the interactive equivalent — it prompts for the ngrok Authtoken and serves MCP in the foreground.
Project structure
.
├── opencode_bridge_mcp.py # MCP server (Claude → queue)
├── task_store.py # SQLite queue logic
├── tasks_cli.py # Manual worker CLI
├── worker.py # Auto-worker (launchd, 60s)
├── claude_control_mcp.py # Reverse bridge (OpenCode → Claude)
├── install.sh # One-command installer: deps, token, tunnel, serve
├── start_public.sh # Public tunnel + server launcher (background)
├── claude_desktop_config.snippet.json
├── claude-clean.settings.json
├── requirements.txt # mcp>=1.0,<2
└── .gitignore # excludes .venv/, tasks.db, logs, task_logs/, claude_jobs/, worktrees/Runtime state (never committed): tasks.db, task_logs/, claude_jobs/, worktrees/, *.log, heartbeat.json.
Troubleshooting / FAQ
421 behind tunnel:
MCP_ALLOWED_HOSTSmust exactly match the tunnel host. Run./install.shor./start_public.sh— they set this automatically.Tunnel URL changed (Cloudflare): quick-tunnel hostnames rotate every restart. Rerun
./install.sh(or./start_public.sh), or reserve an ngrok fixed domain via.ngrok-domain.Worker looks stuck: check
./.venv/bin/python tasks_cli.py heartbeatandtask_logs/<id>.log. Stalerunningtasks are reaped after 15 min (per-tasktimeout_sec+ slack honored).Double-run after kill: every attempt spawns
opencode run --standalone --title br-<id>-a<n>(per-attempt argv marker, ps-visible). The reaper kills the orphaned CLI child plus its ppid tree (loop-until-empty, hard-capped so a matching bug can't mass-kill); a per-pass sweep catches tagged strays of non-running tasks. Reaper deadline is per-task (max(900s, timeout_sec + 120s)). macOS gives no session/env signal (ps sess=is 0 everywhere,ps -Eshows no env), so ppid walk + argv marker are the whole toolkit — reparented-to-1/setsid grandchildren are the known residual. NOTE: never pass--sessionto the CLI: it makes free-tier models refuse to run.No banners: macOS only. Set
WORKER_NOTIFY=0to silence intentionally; full output is always intasks.db+worker.log.Reverse bridge fails fast (~1s): run
claude loginonce or setANTHROPIC_API_KEY.opencodenot found: put it onPATHor setOPENCODE_BIN=/path/to/opencode.
Limitations
Token counts aren't exposed by the
opencodeCLI —usagereports model, latency, attempts, and sandbox status, not tokens.no-network/no-shellare prompt-level restrictions, not OS-enforced sandboxes (documented inworker.py).Desktop banners and launchd scheduling are macOS-specific; Linux needs its own scheduler (systemd/cron) +
worker.pystill runs manually.Long tasks (up to 1800s
timeout_sec) are supported, but the 60s launchd cadence means pickup latency averages ~30s.
Verified
task_storesubmit → claim → complete round-trip: OKMCP
submit_task/get_task/list_tasksviacall_tool: OKCLI
pending/show/claim/complete: OKsubmit_task→ auto-picked-up in ~60s →get_task_resultwith zero manual steps: OK
License
Apache-2.0 — see LICENSE. Fork it, self-host it, build on it.
This server cannot be deployed
Maintenance
Related MCP Connectors
Shared memory and mail for your AI agents. Verified with Claude Code; other MCP clients in testing.
Real-time chat for AI agents. Claude Code, Cursor, Cline and Codex join channels over MCP.
An agent-first office suite Claude & ChatGPT read and write over one MCP URL.
Persistent AI memory shared across Claude, ChatGPT, coding agents, and compatible MCP clients.
Related MCP Servers
- AlicenseAqualityDmaintenanceCost-aware, multimodal OpenCode task router and sub-agent MCP server for Claude Code, providing tools for delegation, status, review, revision, abort, models, and usage.7MIT
- AlicenseNot gradedqualityBmaintenanceEnables orchestrating multiple AI CLI agents (Codex, Grok, Claude, etc.) via Claude Code, providing tools for dispatching tasks, broadcasting, debating, and managing jobs through a local MCP server.MIT
- FlicenseNot gradedqualityBmaintenanceEnables MCP clients like Claude Code to delegate coding tasks to a local model through a configurable coding-agent CLI backed by any OpenAI-compatible endpoint, with tools for health checks, task execution, and context-aware file modifications.-
- AlicenseNot gradedqualityBmaintenanceEnables multiple AI coding agents to work concurrently on the same repository by coordinating task ownership, file locks, architectural decisions, investigation gaps, handoffs, and audit activity through a local SQLite-backed MCP interface.15 npmMIT