# Connect your agent (MCP)

> Connect Claude Code, Cursor, VS Code or any MCP client to Synento, and let it build and verify your video integration.

Synento runs a remote [MCP](https://modelcontextprotocol.io) server. Connect
your coding agent to it and the agent can set up a project, write your
integration, and then **prove the video works** by reading back what was
actually recorded — without you opening a dashboard.

The server is at:

```
https://api.synento.com/mcp
```

It speaks Streamable HTTP and authenticates with OAuth 2.1. The first time your
agent uses it, your browser opens so you can sign in and choose what the agent
may do.

## Connect

### Claude Code

```bash
claude mcp add --transport http synento https://api.synento.com/mcp
```

Then run `/mcp` in Claude Code and choose **synento** to sign in.

### Cursor

Add to `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project):

```json
{
  "mcpServers": {
    "synento": { "url": "https://api.synento.com/mcp" }
  }
}
```

### VS Code

Add to `.vscode/mcp.json`:

```json
{
  "servers": {
    "synento": { "type": "http", "url": "https://api.synento.com/mcp" }
  }
}
```

### Other clients

Any client that supports remote MCP servers over Streamable HTTP with OAuth
will work: point it at `https://api.synento.com/mcp`. It discovers everything
else itself — the server answers an unauthenticated request with a `401` whose
`WWW-Authenticate` header points to
[`/.well-known/oauth-protected-resource/mcp`](https://api.synento.com/.well-known/oauth-protected-resource/mcp).
Clients may register dynamically (RFC 7591) or identify themselves with a
client ID metadata document.

For a client that can't sign in through a browser (a CI job, a headless
agent), create an **agent token** in the dashboard under **Agents** and send
it as a header:

```bash
claude mcp add --transport http synento https://api.synento.com/mcp \
  --header "Authorization: Bearer sat_…"
```

## What you approve

When the agent connects, Synento shows you who is asking and lets you choose:

- **Projects** — the agent can only see and act in the projects you tick.
- **Permissions** — one or more of:

| Permission | Lets the agent |
|---|---|
| `mcp:read` | Read projects, sessions, usage and session manifests |
| `mcp:write` | Create sessions and connection tokens, and run media checks |
| `keys:mint` | Create restricted server keys for your app's environment |
| `projects:create` | Create new projects, which it can then use |

Whatever you tick, an agent can never see your owner API keys, change billing,
invite people, or delete anything. You can disconnect it at any time from the
dashboard under **Agents**; its access ends on its next request.

## Tools

| Tool | What it does |
|---|---|
| `get_account` | The organisation, the projects this connection may use, plan limits, and next steps. |
| `list_projects` | The projects this connection may use. |
| `create_project` | Create a project; the connection can use it straight away. |
| `create_session` | Create a session. Accepts an `idempotency_key`, so a retry never makes a second one. |
| `create_connection_token` | A short-lived token for one participant to join from a browser — for trying things locally. |
| `list_sessions` | Recent sessions in a project. |
| `create_server_key` | A restricted `rk_live_` key for your app's server-side environment, returned once. |
| `get_session_manifest` | Every participant and track that actually holds recorded media. |
| `verify_session` | Checks a session's recording against what you expected, and says what is missing and why. |
| `run_media_check` | Publishes a synthetic two-person call through Synento and verifies it from the recording. |
| `get_guide` | Any page of these docs. The same pages are available as MCP resources. |

## The loop your agent follows

1. **`get_account`** — see which projects it may use.
2. **`create_server_key`** — mint a restricted key and write it to your app's
   server-side environment (`.env`, which must be gitignored):

   ```bash
   SYNENTO_API_KEY=rk_live_…
   SYNENTO_API_URL=https://api.synento.com
   SYNENTO_PROJECT_ID=…
   ```

3. **Write the integration** — the server creates sessions and mints
   connection tokens with [`@synento/node`](https://synento.com/docs/guides/sdk.md); the browser joins with
   `@synento/client` using only the short-lived connection token. See
   [Getting Started](https://synento.com/docs/getting-started.md).
4. **Run the app** and publish camera and microphone into a session.
5. **`verify_session`** on that session. It passes only when each participant's
   tracks actually hold recorded media. If it fails, it tells the agent what is
   missing and the usual cause — no audio track in the stream, publishing
   before `connect()` resolved, a token for the wrong session.

An agent should not report the integration as working until `verify_session`
passes. If it keeps failing, `run_media_check` tells a Synento problem from an
integration problem: it sends a synthetic call through the same WebSocket
endpoint and recording path your app uses. It does not run your code, so it
cannot prove your integration works — only `verify_session` on your app's own
session can.

## Restricted server keys

The key an agent writes into your environment is a **restricted key**
(`rk_live_…`), not an owner API key. It belongs to one project and works on
exactly four routes:

- `POST /v1/sessions` and `POST /v1/projects/{projectId}/sessions`
- `POST /v1/sessions/{sessionId}/connection` (live and replay tokens)
- `GET /v1/sessions/{sessionId}/manifest`

Every other route refuses it. `@synento/node` works with it unchanged. Keys
an agent created are marked as such under **Agents** in the dashboard, where
you can revoke them.

## Security

- **Tokens are bound to this server.** Access tokens are opaque, last an hour,
  and are issued for exactly one audience, `https://api.synento.com/mcp`.
- **PKCE is required** for every authorization, and only the authorization-code
  flow is supported.
- **Refresh tokens rotate** on every use. Presenting one that was already used
  revokes the whole connection.
- **Nothing a token grants outlives its grant.** Each request re-checks that the
  connection is still approved, the person is still in the organisation, and
  each project still belongs to it.
- **Every tool call is recorded.** The dashboard's **Agents** page shows recent
  activity: which tool, which project, and whether it worked.
- **Scope is enforced on every call.** Calling a tool without the permission it
  needs returns `403` with `error="insufficient_scope"`, so the client can ask
  you for more.

## Troubleshooting

### The browser says the request has expired

The sign-in link is valid for 30 minutes. Go back to your agent and connect
again.

### A tool fails with "requires the … scope"

The connection wasn't granted that permission. Reconnect (in Claude Code:
`/mcp`, then re-authenticate **synento**) and tick it.

### "Project … is not available to this connection"

The agent is using a project you didn't approve. Reconnect and tick it, or
allow `projects:create` and let the agent make one.
