> ## Documentation Index
> Fetch the complete documentation index at: https://docs.peeve.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP server

> A live Model Context Protocol endpoint over your product's verified capabilities — and what it deliberately will not do.

Peeve runs a live [Model Context Protocol](https://modelcontextprotocol.io)
server for your workspace. External assistants — Claude, ChatGPT, Cursor — connect
to it to discover what your product can do.

Two things determine whether it is useful to you, and both are on this page.

<Warning>
  **`tools/call` returns a guide, not a result. The MCP server never executes a
  write.**

  Calling a tool tells the assistant *where the capability lives in your product
  and how to complete it*. It does not perform the action. Writes are completed
  by the person, in your product.

  This is a deliberate security decision, not a missing feature. Do not build on
  the assumption that an assistant can change something through this endpoint,
  and do not describe it to your users that way — someone who believes MCP can
  mutate their account will be badly misled.
</Warning>

<Warning>
  **The agent channel requires Growth or above.**

  Both MCP endpoints check the `agent_write` entitlement. On Starter, or during
  a trial, or with a lapsed subscription, they return "agent channel not
  available for this workspace". The same gate applies to
  [agent artifacts](/artifacts/overview) and to the agent executing writes.

  It also requires the agent channel to be enabled for the workspace, and the
  [kill switch](/authentication/keys#the-kill-switch) to be off.
</Warning>

## What it exposes

Tools are projected from your workspace's **verified** capabilities — the ones
Peeve has confirmed exist in your product by mapping it. A capability appears as
a tool only when all of the following hold:

* it belongs to the current production version of your product map;
* its status is verified — not draft, stale or broken;
* its agent access is set to allowed — not human-only or blocked;
* it has not been disabled by a builder.

Everything else is invisible to an assistant. Nothing is hand-written; the
projection is generated from the same graph that grounds the in-product agent,
so the two can never disagree about what your product does.

## The two endpoints

<CardGroup cols={2}>
  <Card title="Workspace-level" icon="building" href="/mcp/workspace-endpoint">
    `/api/mcp/{workspaceId}`

    Unauthenticated, CORS `*`. Anyone with the URL can list and call tools. Safe
    because it is read-only and guide-only.
  </Card>

  <Card title="Per-user" icon="user" href="/mcp/per-user-grants">
    `/api/mcp/{workspaceId}/u/{contactId}`

    The same tools, behind a `pv_grant_…` bearer token bound to one contact.
    Revocable per person.
  </Card>
</CardGroup>

## Protocol

JSON-RPC 2.0 over HTTP. Protocol version `2024-11-05`, negotiated in the
`initialize` handshake.

| Method       | Behaviour                                                           |
| ------------ | ------------------------------------------------------------------- |
| `initialize` | Returns the protocol version, server info and instructions.         |
| `ping`       | Returns `{}`.                                                       |
| `tools/list` | Lists the projected tools with their input schemas and annotations. |
| `tools/call` | Returns a **grounded guide** for the named capability.              |

Anything else returns `-32601 Method not found`.

Notifications — a message with no `id`, or any method in the `notifications/*`
namespace — get no reply. A batch consisting only of notifications is answered
`202` with no body.

Batches are supported: send an array, get an array back.

<Note>
  There is no version segment in the URL, on purpose. MCP negotiates its
  protocol version in the handshake and tool changes are additive, so the URL
  you paste into an assistant stays valid indefinitely.
</Note>

## What a `tools/call` actually returns

```json theme={null}
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Invite a teammate to the workspace\n\nWhere in Example Corp: /settings/team\nPermission: write — needs the user's confirmation\n\nThis changes data. Guide the user to complete it themselves in the product — do not assume it was executed here."
      }
    ],
    "isError": false
  }
}
```

The guide names the capability's purpose, where it lives (a deep link, or the
route path), and its permission class. For anything that changes data it says so
explicitly. For a read or navigation capability it says the assistant is safe to
walk the user there directly.

Permission classes: `read`, `write`, `write — needs the user's confirmation`,
and `destructive — needs the user's confirmation`.

## Auditing

Every `tools/call` and every `initialize` lands in your activity log, recorded
after the response so it never slows a call.

The record carries the capability key, the method and the outcome — **never the
arguments**. On the per-user endpoint it is attributed to the granted contact,
so you can see which person's assistant did what.

## Next

<CardGroup cols={2}>
  <Card title="Workspace endpoint" icon="building" href="/mcp/workspace-endpoint">
    Full request and response shapes.
  </Card>

  <Card title="Per-user grants" icon="key" href="/mcp/per-user-grants">
    Issuing and revoking `pv_grant_…` tokens.
  </Card>

  <Card title="Connect a client" icon="plug" href="/mcp/connect-a-client">
    Claude, Cursor and generic MCP client configuration.
  </Card>

  <Card title="Agent artifacts" icon="file-code" href="/artifacts/overview">
    The static alternative, for agents that do not speak MCP.
  </Card>
</CardGroup>
