---
title: "MCP: file, scope and drive work in-session | CommitCycle"
description: "Two MCP surfaces — a plugin server that never moves a task, and a connector that drives the board. What each carries, and the lines neither crosses."
url: https://commitcycle.com/docs/reference/mcp/
language: en
---

# MCP server

> Two MCP surfaces — a plugin server that never moves a task, and a connector that drives the board. What each carries, and the lines neither crosses.

Filing a task and answering the four questions used to mean leaving the session for a browser. On 2026-08-05 an agent spent roughly a hundred browser calls doing that by hand, which made the diagnosis hard to argue with: the gate was never the friction, the walk to it was. Risk #1 in the spec is “uninstalled through friction”.

So CC ships MCP. The assistant you are already talking to can read the zone map, file a request, draft the four fields and save them — in the session, where the work is being discussed.

## Two servers, and they are not the same size

|               | Where it comes from                            | Tools | Can it move a task?                               |
| ------------- | ---------------------------------------------- | ----- | ------------------------------------------------- |
| **stdio**     | Inside the plugin, or `cycle mcp` from the CLI | 7     | No — it reads the board and files or scopes tasks |
| **connector** | An HTTP URL the board issues, per machine      | 11    | Yes, by asking the gate                           |

Which one you have decides what your assistant can do, so it is worth knowing which one is wired. The counts are the two lists on the trunk on 2026-10-31: `apps/mcp/src/tools-list.ts` for the stdio server, and that list plus the connector’s own four in `apps/api/src/mcp-http.ts` — and the site’s build fails when this page’s counts or tables disagree with them (CC-1384). The stdio server you install today has six: `cc_search` reached it after the newest release, 0.1.25 — [what the newest release does not carry yet](https://commitcycle.com/docs/start/install/#what-the-newest-release-does-not-carry-yet).

### Every tool description says which board it answers for

Read the end of any CC tool’s description and you will find a `SCOPE:` line naming the tenant and repository that server resolved, and where it resolved them from.

It is there because **task ids are shaped the same on every board**. Ids are numbered per board, so every board’s first task is `CC-1` (CC-71): `CC-42` is a valid id on yours and on every other board, so an assistant holding two CC servers in one session — a local one and a connector, or two projects — has nothing in a payload to tell them apart. The suffix is what makes the answer attributable to a board instead of merely plausible. When a server has not resolved a board at all, the same line says that instead, rather than letting the tool answer as if it had.

Worth reading before trusting a payload, and worth checking first when a task “does not exist” that you are certain exists. `cc_intake`’s reply names the board too — “Filed CC-n in Triage on `<tenant>/<repo>`” — because a client reads the descriptions once and a misfiled task is seen in the reply or not at all (CC-749).

### The seven, on both

| Tool           | Does                                                                                                                                                                                                                                                          | Writes? |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `cc_zones`     | The zone map: which areas are protected, at what risk, and who owns each                                                                                                                                                                                      | no      |
| `cc_intake`    | File a request in one line. Lands in **Triage**, and the reply names any task already on the board that looks like the same work                                                                                                                              | yes     |
| `cc_interview` | The four fields drafted for a task. The stdio server returns the board’s draft, validated against the real zone map; the connector hands back a drafting brief and your assistant does the drafting                                                           | no      |
| `cc_scope`     | Save the four answers onto a task, and the files it expects to touch (`expected_files`). The reply names open tasks that expect or touched the same files. Over the connector this is also the Triage → **Todo** move; the stdio server saves and stops there | yes     |
| `cc_status`    | One task by id, or everything in flight — and any **mentions** on it still waiting to be acknowledged                                                                                                                                                         | no      |
| `cc_why`       | Which tasks changed a file or a folder, newest first, with the goal each was opened for — the same answer as `cycle why`                                                                                                                                      | no      |
| `cc_search`    | Up to five tasks on this board related to a request, to the files it will touch, or both — matched by meaning where the board has that on, by shared files and by words, each with its state and what it was opened for                                       | no      |

`cc_status` carries the board’s count of **unacknowledged mentions** on a task — a note somebody left for whoever is working it, which nothing else in the session would surface. It is an annotation on the answer, not a second call: an assistant that reads `cc_status` at all has already been told there is something waiting. Acknowledging one is a separate act, so reading the count never discharges it.

`cc_search` is told to run **before** filing or starting work, and it is the same search `cc_intake` and `cc_scope` append to their answers: the point is to continue a task that already exists instead of filing its duplicate, and to keep what earlier work decided. The meaning half is an embedding search on the board’s side, not a generative model (`apps/api/src/search.ts`), and a board without it still answers from files and words. The hook treats it as a read wherever it runs, inside a task or outside one, as it treats `cc_why`, `cc_status` and `cc_zones`, so the paths you pass it are never mistaken for a write (CC-1345).

`cc_interview` is told, in its own description, to present its draft **as choices rather than as a fait accompli** — each suggestion offered as a selectable option next to a free-text alternative. A drafting tool that hands back a finished spec produces specs nobody read, which is the failure mode the four fields exist to prevent.

`cc_interview` also tells the assistant to settle the four answers **in rounds** (CC-1361). Both servers carry the same text: in the connector’s drafting brief, and after the stdio server’s draft. Each round asks only the questions whose prerequisites are settled. The goal comes first, then what the work must not do and which zones it touches, then how you will know it worked. Each question is numbered and carries the assistant’s recommended answer, worded so a plain “yes” accepts it. A fact the codebase can answer, such as which files hold the code, the assistant looks up instead of asking. A task with no zone and nothing unknown keeps a single round, so one “yes” settles all four. Whatever the number of rounds, `cc_scope` saves the same four fields.

### The four more, on the connector only

| Tool        | Does                                                                                                                                                                                                                                                                                                                                                                                                            |
| ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cc_setup`  | Returns the files to write for a repository with nothing installed. It deliberately never returns a hook configuration — see the [quickstart](https://commitcycle.com/docs/start/quickstart/) for why that would be worse than nothing                                                                                                                                                                          |
| `cc_start`  | Todo → In Progress. **The gate decides**, and its refusal comes back verbatim: no four fields, or a high-risk zone nobody approved, and it says no                                                                                                                                                                                                                                                              |
| `cc_submit` | In Progress → In Review. Access closes in the same breath. It takes `files` (every path the work changed, kept as the task’s files so the next request learns what this one touched), `note` (the hand-in report, below) and `pr` (the pull request, so the reviewer sees it on the task). With the repository’s `pr.open` policy on (off by default), it also opens the task’s pull request                    |
| `cc_close`  | In Review → Done, and writes the audit record. It takes every path the work changed and the closing gate compares that list against what the task declared. The list is the agent’s report, and the audit record labels it as reported. It also requires `learned` — what the work taught, where an empty list is a legitimate answer — and hands back each lesson as a playbook append for your agent to write |

`cc_submit`’s `note` is the agent’s final report, kept on the ticket. The board reads the note’s headed sections into the reviewer’s view; the headings it reads are listed in `cc_submit`’s own tool description and in `cycle submit --help`. It is the same note `cycle submit --note` sends (CC-1243). Secrets are redacted before the board stores it.

`cc_close`’s own description tells the assistant not to guess or summarise the file list — run `git diff --no-renames --name-only <base>...HEAD` and pass exactly that, with the paths that no longer exist passed again as `deleted`. `--no-renames` lists a renamed file under its old path and its new one, because moving a file out of a zone changes that zone as much as moving one in (CC-1382). A manifest that omits a file is a close that certifies work nobody checked, and the audit record is what somebody reads six months later to find out what happened.

Files the connector hands back for your agent to write — a task record, a grant, an audit record, a playbook append — sit between fences drawn fresh for each reply. Text other people wrote, such as a task’s goal, cannot carry the fence, so it cannot pose as another file or as an instruction from the server (CC-1310).

## What no MCP tool does

These hold on both servers, and they are the interesting part:

- **Nothing approves an access request.** An approval reaching the board through MCP would be authenticated by a token the _agent_ holds, so the board could not tell your yes from the agent’s own — and an agent that can approve its own request is the end of the claim, not a convenience. So the request travels into the session and the decision travels out of it: the link opens a browser where you are already signed in, and that session is the credential.
- **No tool talks to the hook.** `cc_start` and `cc_submit` ask the gate, which issues or revokes a grant; the hook reads that grant only once `cycle sync` brings it to the machine, and no tool can widen it. Enforcement is a capability ([Layer 2](https://commitcycle.com/docs/concepts/three-layers/)), not a request. An agent _chooses_ whether to call an MCP tool, and a boundary you can decline to call is not a boundary.
- **Nothing decides a transition.** `cc_start` asks the gate; the gate answers. The tool is a client of the same rules the console obeys, not a second door with easier locks.
- **Nothing reads the grant file on your machine.** `cc_start` hands back the grant the board issued, but the copy the hook decides against is a local file, and `cycle status` is what reads it.

`cc_start` can tell you access was opened. Nothing is stopping a write on that machine unless the CC binary is installed there — and the tool’s own description orders the assistant to say so rather than imply the zones are guarded.

The activation is a handshake across two machines: the board flips the state, and the grant only takes effect where something local reads it. The trusted way to collect it is `cycle sync`, which pulls it authenticated. Writing the grant file by hand is offered only as a fallback for machines with nothing enforcing — on a machine that _is_ enforcing, the hook refuses that write, correctly, because an agent hand-writing grant state is an agent handing itself access, and the hook cannot tell a faithful copy from a forgery.

## Connecting it

**The connector** is the path the quickstart uses — nothing to download. Open **Settings → Connect a machine** in the console, choose **Connector**, copy the URL, and:

```bash
claude mcp add --transport http commitcycle "<your connector URL>" --scope local
```

The URL contains a key. `--scope local` keeps it out of anything you would commit, and the machine shows up in the console’s machines table where you can revoke it.

**The stdio server** arrives with the [plugin](https://commitcycle.com/docs/start/install/) already wired — there is nothing to configure. To point a different client at it, or to use the npm CLI:

.mcp.json

```json
{
  "mcpServers": {
    "commitcycle": {
      "command": "cycle",
      "args": ["mcp"]
    }
  }
}
```

It resolves the board exactly as every other `cycle` command does: the environment wins, and when the environment says nothing, the committed `.zones/board.json` answers. So a cloned repository usually needs no configuration at all.

| Variable     | Notes                                                                                                                                                                      |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CC_API_URL` | The board this repository reports to                                                                                                                                       |
| `CC_TENANT`  | **No default, ever.** The first half of the address in the console — `pow/commitcycle` means `CC_TENANT=pow`                                                               |
| `CC_REPO_ID` | Falls back to the repository’s directory name                                                                                                                              |
| `CC_TOKEN`   | One command, one credential, nothing stored. Used only when `CC_API_URL` is set too — see [two accounts on one machine](https://commitcycle.com/docs/operations/accounts/) |

`CC_TENANT` has no fallback on purpose: a guessed tenant writes zones, events and grants into an organization nobody created, and it fails silently rather than loudly.

## A normal exchange

1. Someone asks for something in chat. `cc_search` checks whether the board already holds it; if not, `cc_intake` files it in one line — a request that has not been scoped is not work in progress.
2. `cc_zones`, then `cc_interview`, drafts what it should do, what it must **not** do, which zones it touches, and how you will know it worked.
3. The person corrects the draft, in rounds of numbered questions, each with a recommended answer that a plain “yes” accepts. A task with no zone and nothing unknown takes one round. This is the step that matters; the rest is transcription.
4. `cc_scope` saves it. The task is now startable.
5. On the connector, `cc_start` asks the gate to open it and hands back the branch to create. With only the stdio server, that step is `cycle start` in a terminal — which is also where the enforcing machine collects the grant either way.

MCP over stdio is newline-delimited JSON-RPC 2.0, and the server answers `initialize`, `tools/list`, `tools/call` and `ping` from one file it owns (`apps/mcp/src/server.ts`). Both servers negotiate the protocol version a client asks for — `2025-06-18`, `2025-03-26` or `2024-11-05` — and check each call’s arguments against the tool’s own schema before running it (CC-1336). A workspace with an anti-dead-code policy is better served by code it owns than by a dependency tree it does not read.
