Skip to main content
Glama

Rig Bridge

A small MCP server for working on your computer from an AI assistant. The assistant holds the conversation and decides what to do. The server calls Pi's actual file and shell tools and returns their results, without starting another model session.

One OS account, one computer, one server process. Persistent workspaces group projects and their conversation threads. Temporary execution handles select directories so several threads can share that process.

Install and run

Requires Node.js 24+, npm, Git, and a working bash installation. Install the checkout's pinned dependencies:

git clone https://github.com/dna113p/rig-bridge.git
cd rig-bridge
npm ci --ignore-scripts
npm run check
npm run serve

Pi is installed as a dependency. A separate Pi CLI installation or model API key is unnecessary for the server's own tool execution.

HTTP listens at http://127.0.0.1:8767/mcp. On first start, it generates an owner-only bearer file at ~/.local/state/rig-bridge/http-authorization (or under XDG_STATE_HOME). The credential is never printed. The file contains the complete value to send in the Authorization header, including Bearer.

Connect your MCP client or authenticated tunnel/proxy to that HTTP endpoint and supply the header. The proxy must preserve the local target's Host and omit browser Origin. A remote assistant needs a connection that can reach this local endpoint. Tunnel provisioning is separate from this package.

Optional flags:

npm run serve -- --port 9000 --state-dir /absolute/private/state
npm run serve -- --token-file /absolute/existing/bearer-file

An explicitly supplied bearer file must already exist, have owner-only permissions, and contain Bearer followed by at least 43 base64url characters. Keep it outside the checkout.

For a client that launches a local stdio MCP server, use the absolute Node executable and src/cli.ts paths in its configuration:

{
  "mcpServers": {
    "rig-bridge": {
      "command": "/absolute/path/to/node",
      "args": ["/absolute/path/to/rig-bridge/src/cli.ts"]
    }
  }
}

Stdio uses the local client's process access. Use HTTP when multiple clients should share one server. This checkout runs TypeScript directly under Node 24; global npm installation is not an advertised installation path.

Related MCP server: lnwjud

Live Status & Workspace Viewer

When using Rig Bridge with remote assistants like ChatGPT web, it can be difficult to see which workspace the assistant is operating in or whether a command is actively running.

Rig Bridge includes both a real-time web dashboard and a terminal monitor.

Web Dashboard

Open in your browser:

  • http://127.0.0.1:8767/ (or http://127.0.0.1:8767/ui)

Features:

  • Project Workspaces & Threads: Groups repeated opens, repository subdirectories, and Git worktrees under one project. Named threads retain their checkout and run history across restarts.

  • Your Turn Inbox: Shows explicit assistant handoffs, outcome summaries, and unread badges. Opening a handoff selects its thread and marks it read.

  • Notifications: Per-project desktop alerts and browser alerts with click-to-open thread navigation.

  • Running Commands: Shows commands actively executing with a live ticking timer.

  • Last Command & Recent Activity: Shows tool name, command or target path, duration, relative time, and success/error status.

  • Abort Action: Stop hanging or runaway commands directly from the dashboard.

  • Live Updates: Automatically refreshes every second with connection health monitoring.

CLI Monitor

Inspect status from your shell:

npm run status

Options:

  • npm run status -- --watch : Live updating terminal monitor.

  • npm run status -- --json : Dump raw JSON status.

  • npm run status -- --port 8767 : Connect to a non-standard port.

Thirteen tools

Tool

Purpose

workspace_open

Open a checkout in a persistent project workspace. Returns an execution handle (workspace_id), project_id, thread_id, account, Git state, project instructions, and skills. Give a new thread a title; supply thread_id to resume.

workspace_list

List saved projects, threads, runs, and live execution handles.

run_start

Start and name a stretch of work, including a follow-up that needs no execution tools.

work_handoff

Report that the assistant is about to return control to the user, with an outcome and summary. Records a durable notification without closing the thread.

workspace_close

Close an execution handle and cancel its active calls. The saved project and thread remain. Repeating close is harmless.

read

Read text or supported images through Pi. Returns a file revision.

ls

List directory contents.

find

Find files by glob.

grep

Search file contents.

write

Create or replace a file.

edit

Apply Pi's targeted text replacements and return its diff.

bash

Run a command and return output, exit status, and truncation details.

skill_info

Inspect available Pi skills or get the full instructions and metadata for a specific skill.

Text results are available in both MCP content and structuredContent.output, alongside structured metadata such as revisions and exit codes. Clients consuming only structured results can read file contents, search matches, command output, and error messages from output. Pi's truncation notices and output-file references are preserved. Images remain native MCP image blocks in content; their base64 data is not duplicated into structured results.

When an assistant opens a workspace via workspace_open, the bridge automatically discovers and inlines relevant project context (AGENTS.md, CLAUDE.md, etc.) and formats an <available_skills> catalog into the initial response. Assistants can query skill_info with a skill's name to view its complete prompt instructions, parameters, and frontmatter. Opening a workspace does not automatically execute project instructions or run arbitrary extensions.

cwd is fixed for the lifetime of a thread's execution handle. Relative paths resolve there; absolute paths, ~/, and ../ can read or modify other locations. Shell commands have the account's normal access, including existing noninteractive elevation. There is no directory allowlist or filesystem sandbox. A shell cd affects that command only. The server never changes its process-wide working directory.

Project workspaces, threads, runs, notification preferences, and handoff summaries persist in the private work.sqlite database under the state directory. Conversation transcripts and tool output are not stored there. Opening a repository or its subdirectories finds the same project; Git worktrees share the common Git directory identity. Independent clones stay separate unless project_id explicitly groups them. For non-Git projects, pass project_root to group directories under a chosen root. Project grouping does not isolate files or create worktrees.

Each new workspace_open creates a separate thread and temporary execution handle, even for the same directory. Passing a saved thread_id resumes that thread at its fixed checkout path; an existing live handle is reused only for that explicit resume. title names or renames the thread. workspace_list finds saved threads after restart. Do not give two independent conversations the same thread ID.

The compatibility parameter workspace_id is an execution handle, not the persistent project ID. At most 64 handles can be open. The server reclaims the least recently used idle handle when a new open needs room, protecting active tool calls. Handles survive HTTP reconnection and transport-session closure, but expire on explicit close, LRU reclamation, or restart. Cancellation and mutation retry scopes remain independent between threads. Closing a handle preserves the project/thread history and marks unfinished work interrupted; it does not report a successful handoff. All authenticated clients share the same owner's access.

HTTP protocol sessions are separate from workspaces. The server keeps at most 64, reclaiming the least recently used idle session when a new connection needs room. Active requests remain protected, including commands whose HTTP caller disconnected; an idle notification stream does not reserve a slot. Clients receiving HTTP 404 for an expired session must initialize again and can continue using their workspace IDs. If all sessions are busy, new connections receive HTTP 503 until a request finishes.

Agent handoffs and notifications

The bridge's MCP instructions, workspace_open response, and work_handoff description tell the assistant to call work_handoff immediately before a final reply that returns control to the user. This is an explicit report that the assistant is about to hand back the conversation; it does not confirm that the final chat message appeared. Empty command queues and inactivity never imply completion.

Example tool arguments:

{
  "workspace_id": "<execution handle from workspace_open>",
  "request_key": "handoff-unique-for-this-line-of-work",
  "reason": "completed",
  "summary": "Implemented project grouping and notifications. Checks passed."
}

Supported reasons are completed, needs_input, blocked, failed, and cancelled. Wait for this thread's active calls before handing off. Other threads can continue working. A run starts automatically on the first execution tool; use run_start to give it a title or start a follow-up that requires no file/shell tools. A handoff finishes that run and keeps the thread available. Optional run_id verifies that the handoff belongs to the current run.

Retry a control request with the identical arguments and request_key: the saved response is returned without another handoff or notification, even after the old handle closes or the service restarts. A new key cannot hand off an already finished run; start new work first. Retries of old mutation results do not start a new run. Unfinished runs show interrupted status after restart.

The dashboard inbox always records handoffs, including while it is closed. Browser alerts are enabled per project and browser using Browser alerts; grant the browser's notification permission when prompted. Clicking a browser alert opens its thread. Browser alerts require an open dashboard tab; preferences and delivered event IDs are retained locally to avoid repeats on refresh or reload. Enabling browser alerts starts with future handoffs; existing events remain in the inbox.

Desktop alerts are enabled per project and saved by the bridge. On Linux, the bridge sends through the desktop session's notification service using busctl, with notify-send as a fallback. These alerts work with the dashboard closed and include the thread's dashboard URL. The bridge must run in a user session with access to the notification service. Delivery errors stay visible in the inbox. Events interrupted during desktop delivery are marked unknown and are not automatically resent, avoiding duplicates. Desktop delivery on Windows/macOS is not implemented.

Assistant compliance is required: the bridge cannot infer a conversation handoff when the calling assistant omits the MCP signal. It also cannot observe detached jobs that were launched outside its tracked tool calls.

Editing and retries

Read before editing. write and edit require the returned revision as expected_revision, or "missing" to create a file. Pi 0.85.1's edit input is edits: [{oldText, newText}], with all replacements matched against the original file.

Every write, edit, and bash requires a request_key, unique within its execution handle. The control tools run_start and work_handoff also require unique keys. Retry an interrupted request with exactly the same arguments and key. The server returns its cached result, waits for the original call, or returns a durable receipt; it does not dispatch that key again. Reusing a key with different arguments returns REQUEST_KEY_CONFLICT. This still works with an expired workspace ID after closure or restart.

After a crash, an unfinished receipt reports OUTCOME_UNCERTAIN. Inspect the actual files or processes before deciding what to do next. A failed or cancelled command may already have produced effects. Changing the request key authorizes a new operation; it is not a safe automatic retry.

Receipts store metadata in a private SQLite database: tool, workspace, paths, revision, exit status, and output-file reference where available. They do not store command text, file contents, or conversations. The last 64 mutation results are cached in memory; after eviction/restart only the receipt remains. Keep the state directory to retain retry protection. Receipt metadata is retained until you maintain it locally.

File operations share path locks and use atomic replacement with revision checks. They preserve permission bits and follow symlink targets. Replacement creates a new inode, so ownership, ACLs, extended attributes, and hard-link relationships are not preserved. Arbitrary shell commands and external programs do not participate in these locks. The workspace is not protection against two conversations changing the same files. Use worktrees or coordinate changes when needed.

Commands and lifecycle

Commands default to a 120-second timeout, with a maximum of 3600 seconds. The client/tunnel may impose a shorter deadline. Shell stdin is closed; interactive prompts cannot be answered through bash. Pi bounds output and reports a temporary full-output file when truncated. read snapshots regular files up to 32 MiB; use a bounded command for larger files or special devices.

MCP cancellation and execution-handle closure abort the affected active calls. Graceful server shutdown aborts all active calls. None of these undo completed effects. A forced process kill or deliberately detached job can leave work running. For long jobs, use the OS's existing process supervisor and inspect/stop those jobs explicitly.

File locks live under the state directory. A forced crash during a write can leave a stale lock; inspect it and verify no writer remains before removing it. Locks never expire automatically while a writer may still be active.

Optional Linux startup service

npm run install:service -- --start
systemctl --user status rig-bridge.service
journalctl --user -u rig-bridge.service -n 50
systemctl --user stop rig-bridge.service

Without --start, the installer writes and validates the unit without enabling or starting it. --print prints the unit without installing it. It captures this checkout's absolute path, Node executable, and current PATH; rerun after moving the checkout or changing Node. The installer does not configure a tunnel or enable user lingering. Boot/login behavior follows the user's existing systemd configuration. Other platforms can launch the Node command with their preferred supervisor.

ChatGPT / OpenAI Secure MCP Tunnel

To connect ChatGPT to your local MCP tools using OpenAI's Secure MCP Tunnel (e.g. tunnel_your_id_here):

  1. Set your tunnel runtime key (from OpenAI Platform > Tunnels) in .env or your shell:

    cp .env.example .env
    # Edit .env and set CONTROL_PLANE_API_KEY=...
  2. Run the tunnel (auto-downloads tunnel-client if not found):

    npm run tunnel

    Or specify options:

    npm run tunnel -- --tunnel-id tunnel_your_id_here --api-key <key>
  3. To run as a background service alongside rig-bridge.service in Linux / WSL systemd:

    npm run install:tunnel-service -- --start
    systemctl --user status rig-bridge-tunnel.service

Network roaming and auto-recovery

When switching between Wi-Fi networks, tethering to a mobile hotspot, or resuming after system sleep, long-polling tunnel sockets can hang on stale network routes.

npm run tunnel and rig-bridge-tunnel.service include an automatic supervisor by default:

  • Route Monitoring: Tracks default IP route and gateway changes (ip route show default). If a network switch occurs and internet is reachable, the tunnel is automatically restarted with fresh sockets.

  • Stall Detection: Monitors health metrics on 127.0.0.1:8081/metrics. If a long-poll request stalls (>65s without a successful poll) while internet is up, it triggers a clean restart.

  • Pass --no-watchdog to disable the supervisor if desired.

  • For external or existing tunnel services (e.g. pi-mcp-bridge-tunnel.service), a standalone watchdog script is provided at scripts/tunnel-watchdog.sh.

Development and verification

npm run check        # lint, typecheck, tests, and the serve smoke check
npm run test:tunnel  # Optional: requires tunnel-client 0.0.14 with dev proxy

npm run lint runs oxlint and fails on warnings. npm run smoke:serve starts src/cli.ts serve on a free port with a temporary state directory, then checks the generated owner-only bearer file, the health, dashboard, and status endpoints, MCP authentication, one authenticated tool call, and a clean SIGTERM shutdown. It never uses port 8767 or the default state directory.

Delegated work runs through the Machines catalog in .machines/; see .machines/README.md.

Tests use real MCP clients and Pi implementations: project routing, unrestricted paths, image reads, edits/revisions, concurrent HTTP calls, cancellation, close/shutdown, authentication, restart receipts, and uncertain outcomes after a forced server crash. The optional test routes two clients through a real tunnel-client development proxy. It uses disposable local control infrastructure, not a deployed remote assistant connection.

Linux is the tested platform. Windows/macOS runtime behavior and an actual remote assistant round trip still require validation before claiming those environments are supported.

Available Tools

10 tools
bashA
Destructive

Run a real command on this workspace's computer using Pi, without another model. Full account access; sudo -n uses existing elevation. cd affects this command only. On timeout, cancellation, or lost connection inspect effects before retrying.

Inputs: command (required), request_key (required), workspace_id (required), timeout.

editA
Destructive

Precisely edit a file using Pi's real edit implementation. All oldText entries match the original file. Read first and provide expected_revision; returns the actual diff.

Inputs: path (required), edits (required), request_key (required), workspace_id (required), +1 more.

findB
Read-only

Find files by glob using Pi. Use a bounded path to avoid scanning unrelated mounts.

Inputs: pattern (required), workspace_id (required), path, limit.

grepC
Read-only

Search file content using Pi and return matching lines.

Inputs: pattern (required), workspace_id (required), glob, path, +4 more.

lsB
Read-only

List directory contents using Pi.

Inputs: workspace_id (required), path, limit.

readA
Read-only

Read actual file content using Pi. Returns a file revision for subsequent edit/write preconditions. Use offset/limit for more context.

Inputs: path (required), workspace_id (required), limit, offset.

skill_infoA
Read-only

Inspect available Pi skills or get the full instructions and metadata for a specific skill.

Inputs: workspace_id (required), name.

workspace_closeB
Read-onlyIdempotent

Close this workspace and cancel its active calls. Does not undo changes or stop separately supervised jobs. Repeating close is harmless.

Inputs: workspace_id (required).

workspace_openA
Read-only

Open a local working directory and return a workspace_id, account, Git state, inlined project instructions, and available skills. Omit cwd for home. This is directory routing, not a sandbox; absolute and parent paths remain usable.

Inputs: cwd.

writeA
Destructive

Create or replace a file using Pi. expected_revision must be the last read revision, or 'missing' to create a new file. Returns its new revision.

Inputs: path (required), content (required), request_key (required), workspace_id (required), +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 10 tools

    Disambiguation5/5

    Each tool has a clear, distinct purpose: workspace lifecycle, file listing/searching/reading, content modification, shell execution, and skill inspection are cleanly separated. Write vs. edit is explicitly differentiated by whole-file replacement versus precise text edits.

    Naming Consistency4/5

    Most tools use simple lowercase command-style names like read, ls, grep, and write, which is consistent and readable. workspace_open, workspace_close, and skill_info are minor deviations from the bare-command pattern but remain predictable and intuitive.

    Tool Count5/5

    Ten tools is a well-scoped count for a workspace/file/shell bridge. Each tool earns its place and the set covers the core operations without bloating the surface.

    Completeness4/5

    The toolset covers workspace open/close, file reading, listing, searching, writing, editing, shell execution, and skill inspection. Dedicated delete/move or workspace-list tools are absent, but bash and the workspace tools provide reasonable workarounds.

    Maintenance

    ActivityActive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI clients to securely control and interact with a local Windows machine through 218 configurable tools for files, Git, processes, Windows UI, browser automation, WSL, Office, recovery, skills, and child MCP servers.
      8 npm
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI agents to securely access local development capabilities such as files, Git, processes, browser control, Windows automation, WSL, and observability through MCP on Windows and macOS.
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables ChatGPT and other MCP clients to browse, search, edit and upload files, run commands and interactive terminals, inspect Git history and worktrees, dispatch coding agents, and install composable plugins within locally registered workspaces. Requests execute under the user's own machine with per-request approval or auto-approval, keeping files, tasks and results local unless explicitly returned.
      1
      MIT