mcpField
F
FerryCat

FerryCat

Local
github.com/GuoBugAI & Agents2Updated 1d ago

About FerryCat

FerryCat is a local handoff and review bus for AI agents running in separate desktop IDE hosts. It uses an MCP server and SQLite WAL to route contract-validated tasks while checking file fingerprints to detect stale review context.

Key features

  1. 01Cross-host task handoff
  2. 02Contract-based output validation
  3. 03SHA-256 file integrity checks
  4. 04Transactional SQLite task states
  5. 05CLI for inspection and verification

Use cases

  1. 01Send a code review task between IDE agents
  2. 02Check that files remain unchanged before review delivery
  3. 03Validate structured results from a worker agent
  4. 04Inspect or verify local handoff contracts

MCP support

FerryCat runs as a local MCP server and exposes tools to dispatch, claim, verify, fulfill, and inspect task contracts. Separate MCP hosts share the same local SQLite WAL database and workspace files.

Configuration

Local server config is the same for every client. Copy it into your client’s MCP config file.

mcp.json · Universal config
{
"mcpServers": {
"guobug-ferrycat": {
"command": "npx",
"args": [
"-y",
"ferrycat"
]
}
}
}
Run commandnpx -y ferrycat

Local servers need a runtime on your machine (e.g. Node.js 18+). Config file locations differ by client; see your client’s docs.

Packages
npmferrycat0.4.0

Tools

8

Saved tool list · updated 2d ago

ParameterTypeRequiredDescription
titlestringYesConcise contract title (1-120 chars) summarizing the goal of the request.
pointersarrayYesArray of 1 to 50 target file pointers hashed with full-file SHA-256 and snapshot boundaries for tamper detection.
task_typeenumYesType of contract task. Tiered default execution TTL: 1800s for code_review/architecture_audit, 300s for implementation/test_generation.code_review | architecture_audit | implementation | test_generation
exec_ttl_secintegerNoExecution TTL in seconds once CLAIMED (default: 1800s for review/audit, 300s for implementation/test). Worker must fulfill, extend, release, or fail within this window.
target_agentstringYesTarget worker agent identifier expected to claim and execute this contract (e.g., "workbuddy", "antigravity").
queue_ttl_secintegerNoQueue expiration TTL in seconds while status is SUBMITTED (default: 1800s / 30m). Transitions to TIMED_OUT if unclaimed before expiry.
workspace_rootstringYesAbsolute canonical path to the shared local workspace directory accessible by both hosts (e.g. "F:/git/FerryCat"). Path escapes and sensitive files are blocked.
context_summarystringYesDetailed task instructions, audit focus areas, architectural constraints, and background context for the worker agent (1-20000 chars).
contract_schemaobjectNoOptional Draft-07 JSON Schema that structured_output must validate against. Bounded to 1MB and max 32 depth (FC-302).
requester_agentstringNoRequester agent identifier. Defaults to AGENT_NAME env var (e.g., "antigravity", "workbuddy").

Details

From the project README

FerryCat: Contract-Driven Cross-Host AI Agent Handoff Bus

English • 中文

npm version MCP Registry Node.js Version Native Addons Protocol Glama License

FerryCat (ferrycat) is a lightweight, deterministic cross-host AI agent handoff and code review bus built on the Model Context Protocol (MCP) and Node.js built-in node:sqlite (WAL mode).
Purpose-built to safely bridge isolated desktop IDE agent hosts (such as Google Antigravity, WorkBuddy, Claude Code, and Cursor) across separate OS processes without context drift or blind reviews on stale files.

FerryCat Architecture and Workflow

📖 Deep Dive: Why I Started Building FerryCat: When Two AI Coding Hosts Live on the Same Desktop


Core Pain Points & Engineering Solutions

While the official MCP Tasks specification (2025-11 / 2026-07) addresses long-running operations within a single Client ↔ Server connection, it does not solve cross-host collaboration on a developer workstation:

  1. stdio Process Isolation: Desktop IDEs spawn local MCP servers as independent child processes with isolated memory spaces and distinct Node.js runtimes.
  2. Silent Blind Reviews on Stale Code (Stale Context): When handing off a task from Host A to Host B, unushed IDE buffers, branch switches, or mid-review edits cause the receiving agent to audit outdated code and produce plausible but invalid conclusions.
  3. Context Window Bloat: Pasting hundreds of lines of source code across chat windows duplicates token consumption on both ends.
  4. Unstructured Handoff Outputs: Free-form prose responses lack deterministic schema enforcement, making downstream consumption unreliable and prone to infinite retry loops.

FerryCat resolves these failure modes through a human-scheduled, contract-driven SQLite WAL bus:

[Developer]             [Host A: Antigravity]            [~/.ferrycat/mesh.db]            [Host B: WorkBuddy]
     |                            |                                |                               |
     |-- 1. "Dispatch review" --->|                                |                               |
     |                            |-- dispatch_contract() -------->| Write status = SUBMITTED      |
     |                            |   (Full SHA-256 + Line Bounds) | Store size / sha256 snapshot  |
     |                            |                                |                               |
     |-- 2. Switch IDE: "Poll" ---|--------------------------------|------------------------------>|
     |                            |                                |<-- poll_next_task() ----------|
     |                            |                                |    (Atomic claim changes===1  |
     |                            |                                |     + Verify disk SHA-256)    |
     |                            |                                |                               |-- Read local files
     |                            |                                |<-- fulfill_contract() --------|-- Re-verify SHA-256
     |                            |                                |    (Validate Ajv JSON Schema  |   & submit JSON
     |                            |                                |     -> status = COMPLETED)    |
     |                            |                                |                               |
     |-- 3. Switch IDE: "Inspect" |                                |                               |
     |                            |-- inspect_mesh_state() ------->| Read-only query of COMPLETED  |
     |<-- Present structured res -|                                |                               |

Key Architectural Pillars

1. Deterministic 7-State Machine

Every state transition is bound to an explicit SQL transaction with optimistic concurrency control (changes === 1), eliminating phantom or dangling states:

                  dispatch_contract()
                          │
                          ▼
                    ┌───────────┐
                    │ SUBMITTED │ (Queue TTL: default 1800s)
                    └─────┬─────┘
                          │
                 poll_next_task()
         ┌────────────────┼────────────────┐
         │ (Queue TTL)    │ (Hash Match)   │ (Missing / Size Diff / SHA-256 Mismatch)
         ▼                ▼                ▼
   ┌───────────┐    ┌───────────┐   ┌───────────────┐
   │ TIMED_OUT │    │  CLAIMED  │   │ POINTER_STALE │ (Terminal: Rejects blind review)
   └───────────┘    └─────┬─────┘   └───────────────┘
      ▲                   │ (Exec TTL: default 300s)
      │          fulfill_contract()
      │  ┌────────────────┼────────────────┬────────────────┐
      └──┤ (Exec TTL)     │ (Schema Valid) │ (Retries > 2)  │ (Mid-Review File Edit)
         │                ▼                ▼                ▼
         │          ┌───────────┐   ┌───────────────────┐ ┌───────────────┐
         └──────────│ COMPLETED │   │ VALIDATION_FAILED │ │ POINTER_STALE │
                    └───────────┘   └───────────────────┘ └───────────────┘

Holder-side lifecycle controls on a CLAIMED contract (all require agent_id === target_agent):

CallTransitionGuard rails
release_contractCLAIMED → SUBMITTED (tail of queue, fresh queue window)Resets extend_count (renewal budget is per holder) but preserves retry_count: the schema-failure circuit breaker is a contract-level quota, so releasing cannot launder retry budget. Refused past the absolute lifetime deadline. Max 3 releases per contract.
extend_ttlCLAIMED → CLAIMED (claimed_at = now)Must be called inside the active window; max 5 renewals per holder; refused once now ≥ created_at + 4 × queue_ttl_sec.
fail_contractCLAIMED → FAILED (terminal)Requires a reason, stored as WORKER_FAILED: <reason>. A report arriving after the window closed becomes TIMED_OUT with the reason attached.
2. Full-File SHA-256 Fingerprinting, Pre-Flight Verify & TOCTOU Soft-Failure Buffering (ADR-0004)
  • Dispatch Snapshot: dispatch_contract reads target files on disk, recording byte size, full-file sha256 (64 hex chars), first_line, and last_line. If a file was modified within the last 3 seconds, a warning is emitted to alert the requester of potential unsaved IDE buffers.
  • Claim Verification: poll_next_task verifies Existence -> Byte Size -> Full-File SHA-256 (never rejecting on mtime_ms alone to tolerate no-op IDE saves). On mismatch, it waits 150ms and retries once to rule out transient IDE flushes before marking the contract POINTER_STALE.
  • Pre-Flight Verify (verify_contract): A strictly read-only check allowing workers or scripts to audit pointer health (valid: true vs valid: false with dirty files list) before submitting.
  • TOCTOU Soft-Failure Buffering: fulfill_contract checks on-disk pointer fingerprints. If dirty pointers are detected:
    • Strike 1 returns RETRY_NEEDED, leaves the contract CLAIMED, renews the execution window, and lists dirty files with recovery instructions (git stash / git checkout -- <file>).
    • Strike 2 transitions to terminal POINTER_STALE and saves the full submitted review payload into salvaged_result_json so review effort is never lost.
  • TOCTOU Race Narrowing: While no file-based system can eliminate the microsecond race between reading disk bytes and committing a database row, FerryCat's dual-verification (at poll and at fulfill) drastically narrows the TOCTOU window from minutes of blind review down to the sub-millisecond atomic SQL transition boundary.
3. Bounded Schema Validation (RETRY_NEEDED $\le 2$)
  • Outputs are validated against the contract's JSON Schema via cached Ajv validators, with errors flattened into concise single-line paths (e.g., ["/passed: must be boolean"]).
  • Up to 2 validation failures return RETRY_NEEDED while keeping the contract CLAIMED for immediate self-correction (each rejection also renews the execution window); a 3rd failure transitions the contract to terminal VALIDATION_FAILED.
4. Dual-Stage TTL & Read-Before-Write Sweeping
  • Separates queue_ttl_sec (default 1800s for SUBMITTED) from exec_ttl_sec (measured from claimed_at), preventing tasks claimed late in the queue window from timing out prematurely during execution.
  • exec_ttl_sec defaults are tiered by task_type: code_review / architecture_audit → 1800s (deep reasoning or human-in-the-loop), implementation / test_generation → 300s. An explicit exec_ttl_sec always wins.
  • poll_next_task executes a lock-free SELECT COUNT(*) probe before attempting any UPDATE on expired rows; inspect_mesh_state is strictly read-only.
5. Defense-in-Depth Path Security
  • Enforces path containment within workspace_root and blocks sensitive file patterns (.env*, *.pem, *.key, id_rsa*, *credentials*, *secret*, .npmrc, .git/config) on both dispatch and worker verification paths.
  • Path Resolution: workspace_root is strongly recommended to be passed as an absolute path. If a relative path is provided, it is deterministically resolved against process.cwd() via path.resolve.
6. Threat Model & Security Assumptions (Local Workstation IPC)
  • Assumed Trust Environment: FerryCat is intentionally designed as a Trusted Local Workstation Bus bridging isolated IDE hosts operating under the same OS user account. Callers and workers share the local file system (workspace_root) and SQLite database (~/.ferrycat/mesh.db).
  • Defense Scope: Path containment (assertSafePointerPath) and sensitive file pattern filters prevent unintentional workspace escapes, symlink traversals, or accidental leakage of credentials/secret files during handoffs.
  • Out of Scope (Non-Goals): FerryCat does not provide adversarial sandboxing, multi-tenant isolation, or network authorization against malicious local processes or adversarial agents spoofing AGENT_NAME.

Applicability Boundaries (When NOT to Use FerryCat)

  1. Disjoint File Systems: FerryCat offloads context by file reference; both hosts must share access to the same local workspace_root.
  2. Trivial Single-Turn Queries: Each cross-host handoff involves 3 explicit human window switches (~15–25s overhead).
  3. Unattended Background Pipelines: Desktop IDE hosts follow a request-response model and cannot be woken up asynchronously by an idle MCP server. For unattended multi-step pipelines, use a standalone DAG workflow engine such as PatchCat.

Quickstart

1. Recommended: Zero-Install MCP Mounting (via npx)

No local clone or manual compilation required. Mount directly into your IDE's MCP configuration using npx -y ferrycat:

Antigravity Configuration

Edit %USERPROFILE%\.gemini\antigravity\mcp_config.json (or ~/.gemini/antigravity/mcp_config.json on macOS/Linux):

{
  "mcpServers": {
    "ferrycat": {
      "command": "npx",
      "args": ["-y", "ferrycat"],
      "env": {
        "AGENT_NAME": "antigravity"
      }
    }
  }
}
WorkBuddy / Claude Code / Cursor / Codex Configuration

Configure the target host's MCP settings with its respective AGENT_NAME:

{
  "mcpServers": {
    "ferrycat": {
      "command": "npx",
      "args": ["-y", "ferrycat"],
      "env": {
        "AGENT_NAME": "workbuddy"
      }
    }
  }
}
2. Global Installation & Source Build
  • Global CLI Installation:
    npm install -g ferrycat
    
    Then simply set "command": "ferrycat" in your MCP config.
  • Local Source Build (For Contributors):
    git clone https://github.com/GuoBug/FerryCat.git
    cd FerryCat
    npm install
    npm run build
    npm test
    
    Mount using your local path: "command": "node", "args": ["--experimental-sqlite", "/path/to/FerryCat/dist/index.js"].

First-Class CLI Experience (ferrycat-cli)

Beyond serving as an in-IDE MCP Server, FerryCat provides a first-class CLI utility (ferrycat-cli or npx ferrycat-cli). Sharing the same ~/.ferrycat/mesh.db SQLite WAL database and Zod validation contracts, the CLI allows developers to inspect mesh health, verify working tree safety, and hook into automated CI/Git scripts without leaving their terminal:

1. Terminal Visual Inspection (ASCII Status Table)

Inspect all cross-host handoffs and error reasons formatted as an ASCII table:

# View all contracts in an ASCII table
npx ferrycat-cli inspect

# Filter by target agent (e.g., only tasks for antigravity)
npx ferrycat-cli inspect --target antigravity
2. Pre-Flight Verification (Auditing Before Mutation)

Audit on-disk pointer file integrity against the contract's baseline SHA-256 before committing review work (ADR-0004), eliminating false-positive deliveries:

npx ferrycat-cli verify <CONTRACT_ID>
3. Local CI & Headless Worker Execution

Poll the queue, claim tasks, and execute local review/test scripts with automatic failure closure:

# Safely run a script upon task arrival (no shell quotation hazards)
npx ferrycat-cli worker --agent codex --mode=exec --exec-file ./scripts/review.sh

Exposed MCP Tools

Tool NameRoleTransactional Behavior
dispatch_contractRequesterEnforces path blacklist $\to$ computes full-file SHA-256 & line bounds $\to$ inserts SUBMITTED.
poll_next_taskWorkerSweeps expired TTLs (read-before-write) $\to$ claims via changes === 1 (CLAIMED) $\to$ verifies disk SHA-256 (or marks POINTER_STALE).
fulfill_contractWorkerRe-verifies SHA-256 (TOCTOU guard) $\to$ validates Ajv JSON Schema ($\le 2$ retries via RETRY_NEEDED, 3rd marks VALIDATION_FAILED) $\to$ marks COMPLETED.
release_contractWorker (holder)Hands a CLAIMED contract back to the queue tail as SUBMITTED. retry_count is preserved (contract-level circuit breaker); extend_count is reset. Max 3 releases; refused once past the absolute lifetime deadline.
extend_ttlWorker (holder)Heartbeat: restarts the execution window (claimed_at = now), max 5 renewals and bounded total lifetime.
fail_contractWorker (holder)Marks a CLAIMED contract terminal FAILED with a mandatory reason.
verify_contractWorker / Any (Read-Only)Pre-flight check: validates on-disk pointer files against the baseline SHA-256 without mutating contract state (ADR-0004).
inspect_mesh_stateAny (Read-Only)Pure read-only query of contract states, outputs, and dynamic is_logically_expired flags.

💡 Architecture Decision Records & Engineering Verification:


About the Author
Guo Qiang (GuoBug), Product Engineer specializing in platform engineering and growth. Currently focused on AI workflow orchestration, DAG state machines, and deterministic system architectures.
Open Source & Homepage: https://github.com/GuoBug · https://guobug.github.io
Inquiries and discussions on workflow engine architecture, topological scheduling, and developer experience are warmly welcomed.

Comments

Markdown supported

New to MCP?

From what the protocol is to installing your first server, these answers cover most first questions.

An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.