Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 46 additions & 83 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,130 +1,93 @@
# freebuff-mcp
# Freebuff MCP

A production MCP bridge for a locally installed, signed-in Freebuff Desktop or CLI installation. It gives MCP clients (Codex, Claude Code, and others) bounded access to Freebuff projects, threads, live turn progress, safe project-file reads, and full coding turns.
![Freebuff MCP connects an MCP app to Freebuff on your computer](docs/media/freebuff_mcp_overview.svg)

## Requirements
Watch the [short video](docs/media/freebuff-mcp-explainer.mp4) to see the path from request to finished work.

- Windows, macOS, or Linux
- Node.js 20 or newer
- Freebuff Desktop or the Freebuff CLI installed and signed in
Freebuff MCP lets Codex, Claude Code, plus other MCP apps work with Freebuff Desktop plus its command line app on your computer. It can find projects, read threads, send a request, show progress, read ordinary project files, plus stop work when the app asks.

The bridge runs entirely on your machine. It does not dump process memory, steal credentials, or expose your auth tokens. See SECURITY.md.
MCP is a shared way AI apps connect to tools on your computer.

## What it does
Your computer runs the bridge. Your Freebuff installation controls access to your projects. The bridge does not read process memory. It does not remove Freebuff approval steps. Text returned to an MCP app has common secret patterns masked. Pattern checks can miss unusual secrets. Do not treat them as a complete security boundary.

- **Canonical sessions and turns.** Every interaction is a bridge session/turn with its own identity, mapped explicitly to the real Freebuff thread or conversation id. Bridge ids are never passed to Freebuff as conversation ids. MCP v2, HTTP, and ACP all run on this one implementation (`CompositeBackend + SessionManager + TurnManager`); discovery, SSE parsing, and the event store are never duplicated. The legacy `serve-v1` surface keeps its own runtime adapter for backward compatibility and is covered by its own contract tests.
- **Deterministic backend selection.** 1) Desktop with verified write authorization, 2) Desktop read-only, 3) Freebuff CLI via a managed PTY (fallback), 4) a structured unavailable state. A port being open is never enough: `/api/projects` must answer correctly and the launch-ID health check must pass for writes.
- **`run_turn` with live progress.** A first-class long-running MCP tool that streams coalesced, request-scoped progress notifications and honors transport-native MCP cancellation (including per-request abort/response-stream close on modern HTTP) and propagates it to the backend.
- **Resilient Desktop connection.** Handoff-file-first discovery (no broad port scanning in the normal path), SSE with `Last-Event-ID`, `retry:`, bounded backoff with jitter, and recovery from 401/403/404, 5xx, ECONNREFUSED, timeouts, and Desktop restarts/port rotation.
- **Bounded event store.** Per-thread sequences and cursors, count/byte/TTL retention, per-thread staleness, terminal states clear running state. Events past 100 are readable with `afterSequence`.
- **Accurate phases.** `read_files`/`code_search` → reading files; `change_file`/`apply_patch` → editing files; terminal commands → running a command; only actual test commands (`pnpm test`, `pytest`, `cargo test`, …) are classified as running tests.
## Start here

## Install
Node.js 20 is the minimum. Install Freebuff Desktop. The command line app works too. Sign in before connecting an MCP app.

```bash
```sh
npm install --global freebuff-mcp
freebuff-mcp doctor
```

`doctor` prints (or `--json` emits) package version, platform, selected backend, Desktop detection/authorization, event-stream state (including the timestamp of the most recent live event), CLI detection, PTY/node-pty version, handoff status, capabilities, and recent safe diagnostic errors.
The doctor report shows whether Desktop is found, whether it allows changes, whether the command line app is available, plus whether its terminal component works. A found app can still be signed out. A missing terminal component can block command line sessions. Check the report before setting up an MCP app.

## Configure Codex
## Connect an MCP app

```bash
freebuff-mcp install codex # print config
freebuff-mcp install codex --write # append to ~/.codex/config.toml (refuses to overwrite an existing entry)
```

Generated entry (note `tool_timeout_sec` — long coding turns exceed Codex's default tool timeout):
Codex setup prints its settings entry.

```toml
[mcp_servers.freebuff]
command = 'node'
args = ['/path/to/freebuff-mcp/dist/src/cli.js', 'serve']
startup_timeout_sec = 20
tool_timeout_sec = 3600
enabled = true
```sh
freebuff-mcp install codex
```

## Configure Claude Code
Claude Code setup prints its instructions.

```bash
freebuff-mcp install claude # print instructions
freebuff-mcp install claude --write # merge into ~/.claude.json (user scope)
freebuff-mcp install claude --write --project # write ./.mcp.json (project scope)
```sh
freebuff-mcp install claude
```

The writer merges into the `mcpServers` object, preserves unrelated keys, and refuses to clobber a differing existing `freebuff` entry. Equivalent manual command:
The automatic write option adds the entry to your app settings. It preserves other settings. It refuses to replace a different Freebuff entry.

```bash
claude mcp add --scope user freebuff -- node /path/to/freebuff-mcp/dist/src/cli.js serve
```
## What you can ask it to do

## Tools (MCP v2, `freebuff-mcp serve`)
The bridge can find projects plus threads, read thread messages, start a request, continue earlier work, show live progress, stop a turn, resume a paused thread, change model settings, inspect changed files, read project files, plus list attachments.

The catalog is stable: tools are always registered and return structured actionable errors (`{ ok:false, code, message, recovery }`) when Freebuff is unavailable — availability never depends on the client processing dynamic tool-list updates.
`run_turn` stays open while Freebuff works. It reports progress while the turn runs. When the MCP app cancels the request, the bridge asks the owning Freebuff backend to stop. A local cancel alone does not prove the work stopped.

- Status/discovery: `freebuff_status`, `list_projects`, `list_threads`, `get_thread`, `get_thread_messages`, `get_active_work`, `search_history`, `list_models`
- Progress: `get_turn`, `watch_turn`, `get_thread_progress`, `watch_thread`, `get_thread_progress_summary`, `watch_active_threads`, `get_changed_files`
- Changes/diff: `get_changes` (Desktop change summary), `get_diff` (real per-file patches; reports `binary`/`tooLarge`/`error` rather than inventing a diff)
- Sessions/turns: `start_thread`, `send_message` (async, returns `turnId`), `run_turn` (synchronous with progress + cancellation), `stop_turn`, `stop_thread`, `resume_thread`, `set_model`, `set_reasoning`
- Files/attachments: `list_project_files`, `read_project_file`, `list_thread_attachments`
Freebuff can ask you to approve a step. The turn stays marked as waiting. Resume checks the same thread. The bridge marks the turn complete only after Desktop confirms a finish. Use `stop_turn` to stop a waiting turn. Command line resume may not prove that the original work finished. The bridge keeps that turn open when its result is uncertain.

### `run_turn` and cancellation
Progress arrives in pages. Each returned cursor points to the last event in that page. Use it to read the next page without skipping events. Page size is limited to keep replies manageable.

`run_turn` keeps the MCP request open for the whole Freebuff turn, emits request-scoped progress notifications (coalesced, human-meaningful — never token spam), aborts the backend when the MCP client cancels the request, and returns structured output (`turnId`, `state`, `result`/`error`) when the turn is terminal.
## Local connection plus remote connection

### Resources
The default connection uses standard input plus output. This works well when your MCP app runs on the same computer.

`freebuff://projects`, project threads, thread messages, and per-thread progress resources are available. Resource updates are throttled (max one per thread per 2 s) and are supplementary to progress tools.
An optional remote web connection is available through Streamable HTTP.

## ACP (experimental)
```sh
freebuff-mcp serve-http
```

`freebuff-mcp serve-acp` implements the ACP v1 wire contract on the canonical bridge: ACP session ids map to real Freebuff identities, prompts complete only at terminal turn state, progress uses an advancing cursor, assistant text comes only from structured deltas, and infrastructure errors are reported as errors (never "refusal"). Only implemented capabilities are advertised.
It listens on `127.0.0.1` port `8788`. Requests need the token in `FREEBUFF_MCP_TOKEN`. Remote binding also needs `FREEBUFF_MCP_ALLOW_REMOTE=1`. Remote use needs trusted HTTPS. A private network also works. Keep the access token private. The remote server still needs access to Freebuff on the computer where the bridge runs.

## HTTP transport (optional, local-first)
ACP is another tool connection format. This project's ACP support is experimental. Use MCP to do normal work.

Stdio is the safer default. `freebuff-mcp serve-http` binds `127.0.0.1:8788`, requires `Authorization: Bearer $FREEBUFF_MCP_TOKEN` on `/mcp`, validates Origin, bounds request bodies, and refuses non-loopback binding unless `FREEBUFF_MCP_ALLOW_REMOTE=1`. Remote use requires trusted HTTPS/private networking.
## When a connection fails

The HTTP server uses `@modelcontextprotocol/server`'s `createMcpHandler` with `@modelcontextprotocol/node`'s `toNodeHandler`, which together implement the full MCP 2026-07-28 protocol:
- Modern MCP 2026-07-28 requests via `server/discover` + per-request `_meta` for progress/cancellation
- Legacy 2025-era `initialize`/`tools/call` traffic through the `legacy: 'stateless'` compatibility path
- Transport-native HTTP cancellation via client-disconnect abort propagation
Run the doctor first. Desktop can be visible while change access remains unavailable. Restart Freebuff Desktop, reopen the project, then run the doctor again if its permission is missing. Check that the command line app is installed plus signed in if Desktop cannot accept changes. Managed command line sessions need the terminal component.

Both paths are tested and share the same canonical v2 tool surface.
## Security plus privacy

## CLI fallback mode
File reads stay inside the selected project. Credential files are denied. Binary content is denied. Reads stop at one megabyte. Common passwords, access tokens, authorization headers, URLs, plus private key text are masked before they reach the AI app. Fields named password, token, secret, API key are masked too. No text pattern can find every possible secret. Review sensitive project data before sharing it with a model.

Set `FREEBUFF_MCP_CLI_MODE=pty` to force the CLI backend. New-session creation is serialized per project so conversation identity is never misattributed; `--continue` only receives conversation ids verified to exist in the CLI chat store; cancellation is verified and stuck children are cleaned up. Readiness relies on multiple signals, and UI scraping stays isolated here as fallback behavior.
Read [the security notes](SECURITY.md) plus [the privacy notes](PRIVACY.md) before using the bridge with private work.

## Environment reference
## Project health

| Variable | Purpose |
| --- | --- |
| `FREEBUFF_PROJECT_ROOT` | Project root for CLI-mode sessions |
| `FREEBUFF_MCP_CLI_MODE=pty` | Force the CLI PTY backend |
| `FREEBUFF_ORCHESTRATOR_URL` | Explicit Desktop URL (skips discovery) |
| `FREEBUFF_MCP_HANDOFF_FILE` | Explicit Desktop handoff file path |
| `FREEBUFF_CLI_PATH` | Explicit Freebuff CLI executable path |
| `FREEBUFF_MCP_TOKEN` | Bearer token for `serve-http` |
![Automated project checks](docs/media/freebuff_mcp_health.svg)

## Development
The figures above come from the local suite run on this source revision. They describe automated checks. They do not prove live compatibility with every Freebuff version. The Desktop plus command line acceptance steps are in [the acceptance checklist](docs/acceptance_checklist.md).

```bash
## Build from source

```sh
pnpm install --frozen-lockfile
pnpm typecheck # src
pnpm typecheck:test # src + tests
pnpm typecheck
pnpm test
pnpm build
pnpm pack:check
```

The suite (180 tests) covers the event store (cursors past 100 events, retention, per-thread staleness), SSE parsing/reconnect/Last-Event-ID/retry, handoff validation matrix, Desktop restart recovery, session/turn lifecycle and cancellation, phase classification, live-progress honesty, redaction classes, installers on existing/missing configs, and MCP integration tests that drive the real server through the MCP SDK client for both the v2 (`serve`) and legacy v1 (`serve-v1`) surfaces.

Because CI has no Freebuff Desktop, `test/helpers/fake-desktop.ts` serves the Desktop HTTP contract (payload shapes first captured from a live installation): `test/desktop-wire.test.ts` pins the exact payload shapes, `test/desktop-http-integration.test.ts` drives real sockets including turn completion/cancellation, and `test/http-transport.test.ts` / `test/acp-wire.test.ts` spawn the real `serve-http` and `serve-acp` processes to verify auth, rate limiting, capability advertisement, and prompt semantics on the wire.

These are contract and fault-injection tests against fixtures — they prove the bridge honors the pinned shapes and failure semantics, not that a given release passes against real software. The 0.2.0 release gate additionally requires real smoke tests outside CI: real Desktop on Windows + macOS, real CLI long-turn + cancellation runs, an ambiguous-POST run proving no duplicate prompt/thread, and long `run_turn` runs through Codex and Claude Code.
The automated suite uses fake Desktop plus command line services. It checks protocol behavior, event paging, cancellation, redaction, setup, plus error handling. It cannot prove that a signed in installation works on your computer. Use the acceptance checklist to record that separately.

## Security
## Learn more

The bridge never scrapes process memory, attaches debuggers, dumps credentials, or bypasses Freebuff permission boundaries. Desktop writes require the Desktop's own launch-ID health check; the handoff file contains only a loopback URL and a short-lived launch id, lives in the current user's config directory, and is validated (version, loopback, live PID, expiry) before use. See SECURITY.md and PRIVACY.md.
Read [the changelog](CHANGELOG.md) to see release history. Read [the license](LICENSE) before you share changes to this project.
44 changes: 44 additions & 0 deletions docs/acceptance_checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Freebuff acceptance record

Use this checklist on a disposable project. Complete it separately for Freebuff Desktop plus the command line app. Record the date, operating system, Freebuff version, bridge version, MCP client version, plus the outcome of each step.

No live acceptance run is included with this source change. The local automated tests use synthetic backends. Do not copy their results into this record as live proof.

## Run record

Date

Operating system

Freebuff version

Bridge version

MCP client version

Backend under test

## Steps

1. Create a disposable project plus start one bridge session.
2. Send a harmless request that does not change files.
3. Confirm that progress appears, then confirm a terminal result.
4. Trigger an approval request. Confirm the turn remains visibly waiting.
5. Approve it in Freebuff. Confirm the same turn reaches a terminal state without a duplicate prompt.
6. Start another harmless request, cancel it, then confirm that Freebuff stopped it.
7. Restart the MCP client or bridge. Reconnect to the thread plus confirm that no duplicate request was sent.
8. Record any step that could not be completed, including the exact version plus a short error message with secrets removed.

## Results

Progress and completion

Approval and resume

Cancellation

Restart and reconnect

Duplicate work check

Notes
Binary file added docs/media/freebuff-mcp-explainer.mp4
Binary file not shown.
14 changes: 14 additions & 0 deletions docs/media/freebuff_mcp_health.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading