# MCP server

> Let Claude Code, Cursor and other AI agents read StoryShelf builds, diffs and AI triage and comment on reviews. Read-only plus comments; approving stays a human decision.

Source: https://storyshelf.js.org/ai/mcp/

The StoryShelf [MCP](https://modelcontextprotocol.io) server gives AI agents the same view of a build that a reviewer has: which stories changed, how much, what the capture logs say, and what the [AI triage](https://storyshelf.js.org/ai/triage/) concluded. An agent can then explain a failing build, point at the likely regression, or leave a comment on the review.

It is a thin client over the [REST API](https://storyshelf.js.org/guides/api/): it uses your existing tokens and roles, and needs no changes to your server.

## What agents can do

Read

Projects, builds, snapshots with diff metrics, capture attempts and logs, comments, cached build triage and project health.

Comment

Add a comment to a build, a story or a snapshot, reply, and resolve threads. Needs a token with the developer role or above. A project with review off has no comments.

Never approve

There is no approve, reject, build-verdict, retry or generate tool. A human signs off in StoryShelf, and agents cannot spend your AI budget.

Tools that read snapshots, capture logs or AI insights (`list_snapshots`, `get_capture_logs`, `get_build_insight`, `get_project_health`) call routes that only exist with `testing`, so the server advertises them only when the StoryShelf instance has it. It asks the open `GET /api/v1/health` (its `testing` field) when it starts; over HTTP the answer is reused for a minute. An instance that does not answer counts as having `testing`.

| Tool                                              | Purpose                                                                                              |
| ------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `list_projects`, `get_project`                    | Projects (listing needs a site-admin token) and one project’s settings                               |
| `list_builds`, `get_build`                        | Recent builds, filtered by branch or status, and one build’s counts                                  |
| `list_snapshots`                                  | Changed, new, pending and rejected snapshots with diff pixels and ratio (`includeUnchanged` for all) |
| `get_capture_logs`                                | Capture attempts and the tail of an attempt’s logs                                                   |
| `get_build_insight`, `get_project_health`         | Latest cached AI triage and health digest (never generates one)                                      |
| `list_comments`, `add_comment`, `resolve_comment` | Review comments on a build, a story (`storyId`) or a snapshot                                        |

A `review-build` prompt chains these into a short review summary.

## Connect an agent

1. **Create a token.** In **Project settings → Tokens**, create a project token. Viewer is enough to read; developer or above is needed to comment. See [Roles and tokens](https://storyshelf.js.org/concepts/roles/).

2. **Scaffold the server** (or skip this and use the `npx` config below):

   ```sh
   npx storyshelf mcp init
   ```

   It asks how agents connect (stdio or HTTP), your server URL and a default project, and writes a ready `.mcp.json`.

3. **Add it to your agent.** For Claude Code, over stdio:

   ```json
   {
     "mcpServers": {
       "storyshelf": {
         "command": "npx",
         "args": ["-y", "@storyshelf/mcp"],
         "env": {
           "STORYSHELF_URL": "https://shelf.example.com",
           "STORYSHELF_SLUG": "web",
           "STORYSHELF_TOKEN": "${STORYSHELF_TOKEN}"
         }
       }
     }
   }
   ```

   Cursor takes the same block in `.cursor/mcp.json`.

Then ask your agent, for example: *“Review the latest build on `feat/header` and tell me which changes look unintended.”*

## stdio or HTTP

|          | stdio                                    | Streamable HTTP                                                                              |
| -------- | ---------------------------------------- | -------------------------------------------------------------------------------------------- |
| Best for | One developer’s local agent              | A shared or remote agent                                                                     |
| Start    | The agent launches `npx @storyshelf/mcp` | `npx storyshelf mcp serve` (scaffolded with `--http`) or `storyshelf-mcp --http --port 3333` |
| Token    | `STORYSHELF_TOKEN` in the process env    | Each client sends `Authorization: Bearer <token>`; none is stored on the MCP server          |
| Roles    | The token’s role                         | Per caller, so different people get different permissions                                    |

The HTTP endpoint is `/mcp`. It is stateless, answers `401` without a token, and rejects requests that carry a browser `Origin` unless you allow it with `--origin`. Bind it to `127.0.0.1` (the default) or put it behind TLS and your own network controls before exposing it.

You can also mount the handler in your own server:

```ts
import { createMcpHttpHandler } from "@storyshelf/mcp/http";

const handler = createMcpHttpHandler({ url: "https://shelf.example.com", slug: "web" });
// handler(request: Request) => Promise<Response>, e.g. app.all("/mcp", (c) => handler(c.req.raw))
```

## Privacy and safety

An agent sees exactly what its token’s role can see, and what it reads goes to *its* model, so give agents tokens scoped to the projects they need. See [Privacy and safety](https://storyshelf.js.org/ai/privacy/) for how StoryShelf itself treats AI data.

## Reference

Configuration: `STORYSHELF_URL` (required), `STORYSHELF_TOKEN` (or `SHELF_TOKEN`), `STORYSHELF_SLUG`, and the flags `--url`, `--slug`, `--token`, `--http`, `--port`, `--host`, `--origin`. Package details: [@storyshelf/mcp](https://storyshelf.js.org/packages/mcp/).
