Skip to content

Repository files navigation

Computer Access MCP v2.1

v2.1.0 β€” Give cloud AI agents hands on your local machine β€” hardened, modular, injection-proof β€” plus an orchestrator for the local coding agents you already use


🎯 Who this is for

This bridge exists for cloud-side AI agents that speak MCP but have no access to your machine β€” platforms where the agent lives in someone else's product and reaches out through an MCP connector:

  • Notion Custom Agents (the original use case β€” a scheduled agent driving a task board)
  • Claude.ai custom connectors (web/desktop/mobile, not Claude Code)
  • ChatGPT with MCP connectors / custom GPTs
  • Microsoft Copilot Studio agents
  • Mistral Le Chat connectors, Zapier/agent-builder platforms, or anything else that can call a remote MCP server

It is not needed by AI tools that already run natively on your machine β€” Claude Code, OpenAI Codex CLI, Gemini CLI / Antigravity, GitHub Copilot CLI, opencode, Cursor, Aider β€” those have their own local access. Here they play a different role: they're the workforce this bridge orchestrates.

The control surface is pluggable too. The bridge knows nothing about any particular board: a dispatcher β€” Notion custom agent, an Obsidian plugin, a cron script, any MCP client β€” supplies which repo, which local agent, which brief through the MCP tools, and the bridge does the rest. Notion is the worked example throughout these docs, not a dependency: the bridge is a generic build executor whose entire vocabulary is directory + agent + mode + prompt + jobId β€” grep -ri notion src/ returns nothing. Whatever holds your queue (a Notion board, an Obsidian vault, a cron script) polls and dispatches through the six MCP tools.

🧠 Two roles in one server

  1. Hands β€” 19 master tools give a cloud agent direct control of the machine: terminal, filesystem, git, macOS system control, browser automation, media processing, documents, networking. The cloud agent is the brain; these tools are the hands.
  2. Orchestrator β€” the build bridge (plan / start / get_status / answer / cancel / merge) turns those local coding agents into dispatchable workers. A cloud agent doesn't have to write code through raw tool calls β€” it hands the task to Claude Code, Codex, opencode, or any CLI in the registry, and the bridge runs the whole engagement: isolated worktree, build, verify, local commit, human-gated delivery (merge to main on owned repos, a real PR on anyone else's), revert window.

Example β€” end-to-end development from a task board: a Notion Custom Agent (mine is named Dispatcher Assistant) wakes on a schedule, reads project tasks from the board, plans them (plan), dispatches each to the coding agent named on the card (start), posts progress and failures back as board comments (get_status), and β€” after a human approves β€” merges to main (merge). One agent in Notion, every coding CLI on your machine, a full development cycle with two human gates and no terminal in sight.

Notion board ──> Dispatcher Assistant (cloud, MCP connector)
                      β”‚ ngrok HTTPS + Bearer token
                      β–Ό
             Computer Access MCP (this repo, local)
              β”œβ”€ hands: fs / shell / git / browser / macOS …
              └─ orchestrator: Build Board bridge
                     β”œβ”€ claude-code ─┐
                     β”œβ”€ codex        β”œβ”€ isolated worktrees β†’ branch β†’ PR β†’ gated merge
                     └─ opencode …  β”€β”˜

✨ Features

  • Build Bridge β€” plan / start / get_status / answer / cancel / merge: durable, dispatcher-agnostic coding-agent orchestration (SQLite job store, FIFO queue, isolated git worktrees, question relay, heartbeat crash detection, local-only builds with human-gated delivery: --no-ff merges on owned repos, real PRs on anyone else's)
  • 8 Master Tools β€” Consolidated tool architecture for deep machine control
  • Multi-Agent Parallelism β€” Session-isolated state allows multiple AI models to work together
  • 19 Master Tools β€” Consolidated tool architecture for deep machine control
  • Two transports β€” Legacy SSE (/sse) and modern Streamable HTTP (/mcp)
  • Multi-Agent Parallelism β€” Session-isolated state lets multiple models work together
  • Ngrok HTTPS Tunneling β€” Auto-tunnels localhost for cloud agent access
  • Ripgrep-Powered Search β€” Fast recursive search with graceful grep/fast-glob fallback
  • Session-Aware Auditing β€” Every action logged (with rotation) with session ID and CWD
  • Safety & Guardrails β€” Path sandboxing (symlink-aware), shell-free execution, feature toggles, kill switch

πŸš€ Getting Started

Prerequisites

Installation

npm install

Configuration

cp .env.example .env
# Edit .env with your NGROK_AUTHTOKEN, BRIDGE_AUTH_TOKEN, and ALLOWED_DIRS

MCP_TOKEN is required β€” the server refuses to open a tunnel without it (override for trusted local testing only via ALLOW_UNAUTHENTICATED_TUNNEL=true).

Usage

npm start        # build + boot server + ngrok tunnel
npm test         # run the unit tests (vitest)
npm run lint     # eslint
npm run typecheck

npm start prints two connection URLs β€” paste the one your agent supports:

  • Streamable HTTP β†’ <url>/mcp (preferred for new clients)
  • Legacy SSE β†’ <url>/sse

πŸ› οΈ Tool Surface (19 Master Tools)

Each tool is action-dispatched: pass an action plus the fields that action needs.

Tool Purpose Key actions
fs-manage Filesystem read, read-media, batch-read, write, smart-edit, patch, list, list-with-sizes, tree, file-info, move, copy, delete, mkdir
fs-search Codebase search regex-search, file-search, code-definitions
sys-manage System & macOS exec, info, ps-list, ps-kill, list-apps, open-app/url/file, clipboard-read/write, screenshot, notification, say, volume, brightness, caffeinate, lock-screen, active-app, window-list, test-run, lint
git-manage Version control status, add, commit, push, pull, branch, log, diff, stash, merge, tag, raw
media-manage FFmpeg/FFprobe transcode, convert-image, extract-audio, metadata
doc-manage Documents pdf, docx, spreadsheet, csv, markdown-preview
browser-manage Headless browser navigate, click, type, get-text, get-html, screenshot-page, pdf, evaluate, wait
net-manage Network http-request, download, web-search, port-check
task-manage Background jobs run, status, logs, cancel, list
watch-manage FS watch / log tail watch, poll, unwatch, list-watchers, tail-log
secret-manage macOS Keychain (off by default) get, set, delete, list
archive-manage Archives zip, unzip, tar, untar, list-contents
db-manage SQLite query, execute, schema, list-tables
diff-manage Diff & patch file-diff, dir-diff, apply-patch, three-way-merge
code-format Formatters format, check, list-formatters
test-manage Structured tests run, run-file, coverage
audit-manage Audit log explorer tail, search, stats, session-history
env-manage .env files read, set, unset, validate, diff
window-manage macOS windows list, focus, resize, move, screenshot-window, applescript

πŸ—οΈ Build Bridge

Six MCP tools that let any dispatcher (a Notion custom agent, an Obsidian plugin, a cron script β€” anything that speaks MCP) drive local coding-agent CLIs β€” the orchestrator role described above. The bridge's entire vocabulary is jobId + repoPath + agent + mode + prompt; it knows nothing about whichever tool dispatches the work. Every response uses the generic states planning Β· planned Β· queued Β· running Β· awaiting_input Β· paused Β· in_review Β· failed Β· merged Β· cancelled. State is durable (SQLite at data/jobs.sqlite + per-job logs at data/logs/<jobId>.log) and survives restarts.

Tool Description
plan Dispatch a READ-ONLY plan job (no branch, no worktree, no writes) and return immediately β€” a slow plan never hangs the caller. Every provider plans in its cheapest viable mode (planMode in the registry): headless (flags, plan on stdout), oneshot (plan captured from a generated file like plan.md, artifact cleaned so the repo stays pristine), or interactive (the CLI's TUI driven through a pty β€” mode toggles, slash-commands, the brief). Thin/empty one-shot plans (< PLAN_MIN_CHARS) escalate to an interactive session for the same provider, and complex: true skips straight there. Plans are jobs in the same store as builds (state planning β†’ planned, result in plan) sharing the concurrency pool, heartbeat/stale-kill, a PLAN_TIMEOUT_MS ceiling, and orphan-on-restart recovery. PLAN_FALLBACK_AGENT is last-resort only β€” it plans when a provider's mode can't be driven at all (pty failure, unknown flags, no mode), attributed in the plan text; the job's own agent always does the build. planUnsupported only when neither the provider nor a valid fallback can plan.
answer Relay a human's reply into a job paused on awaiting_input. A live interactive session gets the answer written straight into its pty (the session continues); a dead session (or one lost to a bridge restart, or a headless question) gets the answer folded into the brief and the job cleanly re-runs. Loop until planned.
start Dispatch a build: creates branch job/<jobId> (or a caller-supplied branch) in an isolated worktree under WORKTREE_ROOT, runs the agent CLI asynchronously, returns immediately. On success: verify β†’ local commit only β†’ in_review with a diffStat. Nothing leaves the machine at build time β€” no push, no PR (localOnly: true); the work is reviewed from the diff and delivered by merge after human approval. Structured returns: alreadyRunning (idempotent on jobId), queued: true (capacity full β€” waits in a durable FIFO queue and starts itself when a slot frees), invalidRepo (exact reason, never a guessed path), and awaiting_input when the directory has no git repo β€” the bridge asks permission and answer("yes") runs git init and continues. Empty diff after a build β†’ in_review with an empty diffStat so the caller sees nothing changed. Re-dispatch of a failed/in_review/paused/cancelled job re-runs on the same branch/worktree.
get_status Always an array: one job (with log excerpt) or the 50 most recent. Key fields: state, question (on awaiting_input), pausedReason (quota auto-retries; session/blocked wait for a human), deliveryMode (merge/pr, resolved at merge time), prUrl (pr-mode deliveries), localOnly, diffStat, plan, error, lastHeartbeat.
cancel Kills a running/held job, removes the worktree, keeps the branch β€” later re-dispatch resumes from it.
merge Deliver an approved (in_review) job. Ownership decides the mode, not push capability β€” resolved per repo at merge time (deliveryMode in get_status): a .bridge.json {"deliver": "merge" | "pr"} override wins; else gh decides β€” viewerPermission ADMIN or the authenticated gh user owning the repo β†’ merge mode; MAINTAIN/WRITE/TRIAGE/READ/none β†’ pr mode (a WRITE collaborator who could technically push still goes through a PR); gh missing/unauthenticated or no origin β†’ merge mode (local merge, push skipped without origin). merge mode (owned repo): sync main (--ff-only β€” a diverged local main returns {error:"mainDiverged"}, never guessed), rebase the job branch onto main in the worktree (conflict β†’ {conflict:true, conflictFiles} with the worktree intact β€” the dispatcher re-dispatches the agent to reconcile), --no-ff merge, push only main, delete the branch + worktree immediately (no retention window). A rejected main-push (protected branch) resets main to origin/<main> and falls back once to pr mode. pr mode (anyone else's repo): local main is never checked out or modified; the job branch is rebased onto origin/<main>, pushed (to origin, or to a fork created idempotently via gh repo fork when the viewer can't push branches), and a real PR is opened via gh with the repo's PR template filled by the job's own provider (structured Summary/Changes/Testing fallback) β†’ {merged:true, deliveredVia:"pr", prUrl}. Branch + worktree are kept while the PR is open; the sweep polls the PR state and cleans up on MERGED/CLOSED. Refuses when tracked files have uncommitted changes (untracked junk like .DS_Store never blocks) or gh is unauthenticated in pr mode (ghUnauthenticated). action:"revert" reverts a merge-mode delivery's merge commit within REVERT_WINDOW_HOURS (works after branch deletion; operator use) β€” pr-mode deliveries are reverted upstream.

πŸ”Œ Always-on service (macOS)

The bridge runs forever as a per-user launchd service β€” starts at login, auto-restarts on crash β€” with sleep/wake resilience built to how macOS actually behaves: sleep freezes the process and it resumes on wake (no relaunch needed), so the bridge (a) holds a caffeinate power assertion only while jobs are running, (b) detects wake via a monotonic-clock gap and immediately runs tunnel check β†’ reconcile in-flight jobs β†’ drain the queue.

npm run build && ./scripts/install-service.sh   # bridge (+ ngrok tunnel service if NGROK_DOMAIN set)
./scripts/buildboard status|logs|stop|start     # stop = real stop (bootout); KeepAlive won't fight you
./scripts/uninstall-service.sh
  • Stable URL: ngrok runs as its own KeepAlive service (com.buildboard.tunnel) on your reserved domain, so the MCP URL registered in your dispatcher never changes; the bridge monitors it via the ngrok local API and reports it in /status β€” a tunnel blip never crashes anything.
  • Durable FIFO queue: dispatches beyond MAX_CONCURRENT_JOBS wait in SQLite (state: queued) and are drained at boot, by the sweep, and by the wake routine β€” jobs queued while the Mac slept start within seconds of wake, and the dispatcher never has to re-call start.
  • Recovery, not routine resume: on bridge start, non-terminal jobs are triaged β€” provider pid still alive β†’ reattach (pid-liveness becomes the heartbeat; the pipeline finishes when it exits); pid dead β†’ RESUME_STRATEGY: resume (provider session via resumeArgsTemplate β€” claude/opencode/grok/agy --continue, worktree-scoped), rerun (original brief, same worktree), or rework (fail with a note).
  • Service logs live in ~/.bridge/logs/ with copy-truncate rotation at 10 MB.

Per-job Mode (mode param β†’ build posture): auto (default, configurable via DEFAULT_MODE) runs the agent in its skip-permissions posture β€” full autonomy, installs allowed. accept_edits runs the agent's buildAcceptEditsArgs posture under a pty: file edits auto-apply, but higher-risk actions (shell/installs/deletes/network) pause the CLI β€” the bridge captures the exact prompt, parks the job in awaiting_input, and answer feeds the human's reply back into the live session. Both postures are data in providers.json.

Package installs are user-authorized by design (ALLOW_PACKAGE_INSTALLS, default true): these are your own repos, so npm/pnpm/yarn/bun/pip/cargo/brew install run freely inside allowlisted repo paths β€” nothing classifies them as dangerous. Setting it false refuses install commands on the bridge's exec surfaces (verifyCommand, sys-manage exec, task-manage); the allowlist and prompt-injection scoping are unchanged either way.

Launch-context-proof: the bridge augments its PATH at startup with the well-known agent install dirs (~/.local/bin, ~/.claude/local, ~/.opencode/bin, homebrew, …), so providers resolve identically whether it was launched from a login shell, an IDE terminal, or launchd β€” and a boot agent preflight line reports exactly where each configured CLI resolves (or that it's missing) so a broken agent shows up at startup, not as a failed job.

Optional pty upgrade: interactive/supervised sessions ship on a dependency-free expect(1) relay. If you want the more robust native pty, run npm install node-pty yourself β€” the bridge auto-detects and prefers it. The bridge never installs it for you.

Hold & auto-retry: provider output is classified on failure β€” rate-limit/quota β†’ paused(quota) and the sweep auto-retries after HOLD_RETRY_MS, restoring the previous state; auth/session errors β†’ paused(session) (human re-login needed); a trailing question β†’ awaiting_input with the question captured. Builds never push, so push failures can only happen at merge time β€” where they surface as structured results (mainDiverged, the once-only pr fallback, ghUnauthenticated), never a silent success.

Providers are data, not code β€” providers.json maps an agent name to {command, buildAutoArgs, buildAcceptEditsArgs, planMode, planArgs, resumeArgsTemplate, promptVia} with {brief}/{workspace}/{nudge} placeholders. Shipped: claude-code, codex, opencode, antigravity-agy, grok-build, github-copilot-cli β€” each with auto, accept-edits, and plan postures. Adding a provider = one JSON entry (see the _TODO notes in the file for what's verified vs. per-spec).

⚠️ Unattended-run flags: the shipped entries run fully auto-approved (claude --dangerously-skip-permissions, codex exec --dangerously-bypass-approvals-and-sandbox) β€” otherwise a bash prompt or sandbox denial stalls/fails the job until the stale-kill fires. Containment comes from the bridge, not the CLI: allowlisted repos (ALLOWED_DIRS), isolated worktrees, two human gates before main, and the revert window. To tighten codex later, swap the flag for --sandbox workspace-write (note: its sandbox blocks network, so dep installs fail). opencode run is non-interactive with allow-by-default permissions; if your opencode config sets permissions to "ask", switch them to "allow" for headless use.

Crash safety: heartbeat bumps on every output chunk (stdout and stderr); jobs silent past HEARTBEAT_TIMEOUT_MS or running past JOB_MAX_RUNTIME_MS are killed and marked failed; jobs interrupted by a bridge restart are marked failed on boot.

Verification: verifyCommand param > .bridge.json {"verifyCommand": "..."} in the repo > skip. A failing verify commits the work locally (not pushed) and fails the task for Rework.

Per-repo config (.bridge.json in the repo root): {"verifyCommand": "...", "deliver": "merge" | "pr"} β€” the optional deliver key overrides the delivery-mode resolution for that repo: "merge" forces a direct main merge, "pr" forces PR delivery regardless of ownership.


πŸ›‘οΈ Security & Guardrails

  • Path isolation (symlink-aware) β€” All file operations are validated against ALLOWED_DIRS. Paths are fully symlink-resolved, so a symlink inside an allowed directory that points outside it is rejected.
  • Shell-free execution β€” Tools invoke binaries via execFile with explicit argument vectors, so filenames/queries containing shell metacharacters cannot inject commands.
  • Bearer token auth β€” Every MCP request requires MCP_TOKEN in the Authorization header (constant-time comparison; never accepted as a query parameter).
  • Kill switch β€” Create ~/.mcp_kill to block all tool calls (GET and POST) with a 503 until removed.
  • Feature toggles β€” Disable write, shell, git, media, browser, net, db, or keychain independently.
  • Confirmation gate β€” With ENABLE_CONFIRMATION_GATE=true, actions marked dangerous must be re-called with confirm:true.
  • Tool allowlist β€” TOOLS=fs-manage,fs-search registers only those tools (least privilege).
  • Audit logs β€” Every tool execution is recorded in audit.log (JSONL, auto-rotated) with session ID.

⚠️ Honest limitation: the command blocklist (rm -rf /, curl … | sh, …) is a tripwire, not a boundary. Once ENABLE_RUN_COMMAND is on, the sys-manage exec and task-manage tools can run anything your user account can, anywhere on disk β€” ALLOWED_DIRS only sandboxes the structured file tools and the command working directory. For real containment, disable shell execution or scope TOOLS.


πŸ”§ Configuration

Variable Default Description
PORT 8123 Local MCP server port (shared by server and ngrok)
NGROK_DOMAIN β€” Ngrok static domain (optional, for stable URLs)
NGROK_AUTHTOKEN β€” From dashboard.ngrok.com
ALLOWED_DIRS ~/Documents Repo allowlist. Add via --add-dir <path> / buildboard add-dir or allowed-dirs.txt (hot-reloaded); remove/edit via the file only
COMMAND_TIMEOUT 30000 Shell command timeout in ms
BRIDGE_AUTH_TOKEN β€” Required bearer for the internet-exposed MCP endpoint (MCP_TOKEN legacy alias; BRIDGE_ALLOW_NO_AUTH=true for local-only testing)
CORS_ORIGINS β€” Comma-separated allowlist; permissive if unset
ENABLE_SECRETS false Keychain access (largest exfiltration surface) β€” off by default
TOOLS β€” Optional least-privilege allowlist: only register these tools
MAX_EXEC_BUFFER 64 MB Child-process stdout/stderr buffer cap
AUDIT_LOG_MAX_BYTES 10 MB Audit log rotation threshold
ENABLE_WRITE_EDIT true Allow file write/edit operations
ENABLE_RUN_COMMAND true Allow shell command execution
ENABLE_GIT true Allow git operations
ENABLE_FFMPEG true Allow FFmpeg media processing
DEFAULT_AGENT claude-code Agent used when a job doesn't name one (DEFAULT_PROVIDER legacy alias)
WORKTREE_ROOT ~/.bridge/worktrees Where task worktrees are created (outside repo trees)
MAX_CONCURRENT_JOBS 2 Parallel job cap; excess dispatches queue FIFO and start themselves
HEARTBEAT_TIMEOUT_MS 900000 Kill + fail a job with no output for this long (15 min)
JOB_MAX_RUNTIME_MS 7200000 Hard kill for any job running longer (2 h)
REVERT_WINDOW_HOURS 168 How long after a merge-mode delivery revert stays eligible (time since the merge commit). No longer implies branch retention: merge-mode branches are deleted at merge; pr-mode branches live until their PR closes
PLAN_FALLBACK_AGENT claude-code Last-resort planner, used only when a provider's plan mode can't be driven (empty = disable)
PLAN_MIN_CHARS 200 One-shot plans shorter than this escalate to an interactive session
PLAN_IDLE_MS 20000 Interactive session idle window before question/completion detection
PLAN_TIMEOUT_MS 600000 Hard runtime ceiling for plan jobs (the plan call itself never blocks)
HOLD_RETRY_MS 1800000 Delay before a paused(quota) job auto-retries
RESUME_STRATEGY resume Dead-job recovery: resume | rerun | rework
WAKE_GAP_MS 120000 Wall-clock gap treated as a wake from sleep
TUNNEL_API_URL http://127.0.0.1:4040/api/tunnels ngrok local API for tunnel liveness
ALLOW_PACKAGE_INSTALLS true User-authorized installs in allowlisted repos; false refuses them on exec surfaces
DEFAULT_MODE auto Posture when a card has no Mode: auto | accept_edits
ENABLE_CONFIRMATION_GATE false Break-glass: when true, merge refuses outright (autonomous merges disabled)

πŸ“¦ Project Structure

computer-access/
β”œβ”€β”€ .env                    # Active config (secrets, gitignored)
β”œβ”€β”€ .env.example            # Configuration template
β”œβ”€β”€ .github/workflows/ci.yml
β”œβ”€β”€ package.json
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ providers.json          # Coding-agent CLI registry (auto/accept-edits/plan/resume postures)
β”œβ”€β”€ allowed-dirs.txt        # Optional allowlist additions (gitignored, hot-reloaded)
β”œβ”€β”€ agent-instructions.md   # Example dispatcher instructions (Notion custom agent)
β”œβ”€β”€ README.md
β”œβ”€β”€ data/                   # Bridge state: jobs.sqlite + logs/ (gitignored)
β”œβ”€β”€ scripts/                # install-service.sh Β· uninstall-service.sh Β· buildboard CLI
β”œβ”€β”€ service/                # launchd plist templates (bridge + ngrok tunnel)
β”œβ”€β”€ tests/                  # bridge-smoke.ts (184 assertions) Β· service-smoke.sh
└── src/
    β”œβ”€β”€ start.ts            # Ngrok boot orchestrator (embedded-tunnel mode)
    β”œβ”€β”€ server.ts           # Composition root: transports (SSE + /mcp), auth, guarded registrar
    β”œβ”€β”€ config.ts           # Environment parsing + allowed-dirs machinery (single source of truth)
    β”œβ”€β”€ security.ts         # Symlink-aware sandbox, blocklists, confirmation gate
    β”œβ”€β”€ audit.ts / exec.ts / runtime.ts   # Rotating audit log Β· shell-free exec Β· shared state
    β”œβ”€β”€ tools/              # One module per master tool (19) + bridgeTools.ts (the 6 bridge tools)
    β”œβ”€β”€ bridge.ts           # Job orchestration: dispatch, queue, sessions, recovery, sweeps
    β”œβ”€β”€ jobs.ts             # Durable SQLite job store (self-healing schema)
    β”œβ”€β”€ providers.ts        # Provider registry loader/validator
    β”œβ”€β”€ pty.ts              # Dependency-free pty layer (expect(1); node-pty auto-preferred)
    β”œβ”€β”€ power.ts            # caffeinate assertion, held only while jobs run
    └── wake.ts             # Monotonic-clock wake detection

πŸ“‹ Changelog

v2.1.0 β€” 2026-07-18

Workflow v2: local-only builds + delivery modes

  • Nothing leaves the machine until the human approves: a finished build is committed locally on its job branch and ends in_review with a diffStat (localOnly: true) β€” no push, no PR at build time, ever. The build-time paused(blocked) push-failure path is gone (builds no longer push)
  • Delivery happens at merge time, and ownership decides the mode β€” not push capability: repos the user owns/administers (gh viewerPermission ADMIN or repo owner) β†’ merge mode (sync main --ff-only, rebase, --no-ff merge, push only main, delete the branch immediately); anyone else's repo β€” even with write/push access β€” β†’ pr mode (rebase on origin/<main>, push the branch β€” to origin or an idempotently-created fork β€” fill the repo's PR template via the job's own provider, open a real PR with gh). .bridge.json {"deliver": "merge" | "pr"} overrides per repo; resolved mode exposed as deliveryMode in get_status
  • Main is sacred in both directions: on owned repos only main is ever pushed (a rejected main-push resets main to origin/<main> and falls back once to pr mode); on others' repos local main is never even modified. Diverged local main β†’ {error: "mainDiverged"}; rebase conflicts β†’ {conflict: true, conflictFiles} with the worktree intact for agent-driven reconciliation; unauthenticated gh in pr mode β†’ {error: "ghUnauthenticated"}
  • Branch lifecycle: merge-mode branches are deleted at merge (no retention window β€” REVERT_WINDOW_HOURS now only bounds revert eligibility, and revert works from the stored merge commit after deletion); pr-mode branches + worktrees are kept while the PR is open and cleaned by the sweep once gh pr view reports MERGED/CLOSED. The sweep never deletes branches on origin

v2.0 β€” 2026-07-06

The build bridge (dispatcher-agnostic orchestration):

  • Build bridge: plan / start / get_status / answer / cancel / merge MCP tools β€” a generic, dispatcher-blind build executor (vocabulary: jobId + repoPath + agent + mode + prompt; states: planning/planned/queued/running/awaiting_input/paused/in_review/failed/merged/cancelled). All calls return immediately; nothing blocks on a slow run
  • Durable SQLite job store with a self-healing schema guard, FIFO queueing past the concurrency cap (drained at boot, sweep, and wake), and per-job log files
  • Provider registry (providers.json): per-agent auto / accept-edits / plan / resume postures for claude-code, codex, opencode, antigravity-agy, grok-build, github-copilot-cli; plan modes headless / oneshot (generated-file capture) / interactive (pty-driven TUI) with thin-plan escalation and last-resort PLAN_FALLBACK_AGENT
  • Question relay: supervised (accept_edits) builds and interactive plans pause as awaiting_input with the CLI's exact prompt; answer feeds the reply into the live pty session or cleanly re-runs. A directory without a git repo parks the job asking permission to git init β€” never initialized silently
  • Isolated per-job git worktrees under WORKTREE_ROOT, branch job/<jobId> kept through a configurable revert window; empty diffs finish in_review with an empty diffStat; merge guard ignores untracked files; push failures pause with the commit kept local (localOnly)
  • Always-on service: launchd LaunchAgents (bridge + ngrok reserved-domain tunnel) with the buildboard CLI, power assertion held only while jobs run, monotonic-clock wake detection β†’ tunnel check / reconcile / queue drain, and pid-liveness recovery (reattach alive orphans; RESUME_STRATEGY resume/rerun/rework via per-provider --continue templates)
  • Hardening: BRIDGE_AUTH_TOKEN required on the internet-exposed endpoint; ALLOWED_DIRS defaults to ~/Documents with non-interactive --add-dir and a hot-reloaded allowed-dirs.txt (removals file-only); launch-context-proof PATH augmentation + boot agent preflight; user-authorized package installs (ALLOW_PACKAGE_INSTALLS); heartbeat stale-kill on stdout+stderr; break-glass ENABLE_CONFIRMATION_GATE The hardened core (security & structure):
  • Security: shell-free execution across all tools (execFile + argv), symlink-aware path sandbox, constant-time token check (header only), kill switch on POST routes, keychain off by default, tunnel refuses to start without MCP_TOKEN, confirmation gate wired into dispatch.
  • Robustness: JSON body parsing (webhook tool names, pre-parsed transport bodies), single /health route, smart-edit uniqueness check without $-corruption, patch via system patch(1), depth-capped/symlink-safe tree, background-task buffer caps + eviction + process-group kill, size caps on media reads, browser crash recovery, larger exec buffer.
  • Structure: extracted config/security/exec/audit/runtime modules and split the 19 tool handlers into one module each under src/tools/ (server.ts is now a ~350-line composition root); added vitest tests, eslint, and CI.
  • Enhancements: Streamable HTTP transport (/mcp) alongside SSE, audit-log rotation, per-tool allowlist (TOOLS).
  • Dependencies: replaced abandoned xlsx@0.18.5 (ReDoS / prototype-pollution CVEs) with the vendor-distributed SheetJS 0.20.3 (same API, patched); dropped dead @types/axios and @types/express-rate-limit.

v1.0 β€” 2026-04-24

  • Standardized terminal print pattern; tunnel health check monitoring; renamed to "Computer Access".

πŸ“„ License

MIT

About

MCP server to access your computer to run terminal commands through any LLMs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages