# Connect an MCP client (/mcp/connect)



Add one URL to your client. Sign in once in a browser. Your agent gets up to 17 RiffAds tools.

```text title="Server URL"
https://mcp.riffads.com
```

* **No API key.** MCP is OAuth 2.1 only. Keys (`sk_live_...`) are for the [REST API](/api/authentication) and the CLI.
* **The workspace needs a paid plan.** Without one, tools refuse with `required_plan`.
* Want a first video right away? Go to the [MCP quickstart](/quickstart/mcp).

## Add the server [#add-the-server]

<Tabs items="['Claude','Claude Code','Cursor','VS Code','ChatGPT','Any client']">
  <Tab value="Claude">
    Open this link to get the add dialog prefilled:

    ```text title="Prefilled connector dialog"
    https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=RiffAds&connectorUrl=https%3A%2F%2Fmcp.riffads.com
    ```

    By hand: **Settings**, **Connectors**, **Add custom connector**. Paste `https://mcp.riffads.com`. Save.
  </Tab>

  <Tab value="Claude Code">
    ```bash title="Terminal"
    claude mcp add --transport http riffads https://mcp.riffads.com
    ```

    Or commit it for the whole repo:

    ```json title=".mcp.json"
    {
        "mcpServers": {
            "riffads": {
                "type": "http",
                "url": "https://mcp.riffads.com"
            }
        }
    }
    ```

    Each person signs in as themselves on the first tool call. Want the procedure too? Install the [Agent Skills plugin](/skills/overview).
  </Tab>

  <Tab value="Cursor">
    ```text title="Cursor install link"
    https://cursor.com/en/install-mcp?name=riffads&config=eyJ0eXBlIjoiaHR0cCIsInVybCI6Imh0dHBzOi8vbWNwLnJpZmZhZHMuY29tIn0%3D
    ```

    By hand: add an HTTP MCP server named `riffads` with this config:

    ```json title="Cursor MCP config"
    { "type": "http", "url": "https://mcp.riffads.com" }
    ```
  </Tab>

  <Tab value="VS Code">
    Copilot agent mode.

    ```text title="VS Code install link"
    vscode:mcp/install?%7B%22name%22%3A%22riffads%22%2C%22type%22%3A%22http%22%2C%22url%22%3A%22https%3A%2F%2Fmcp.riffads.com%22%7D
    ```

    By hand:

    ```json title="VS Code MCP config"
    { "name": "riffads", "type": "http", "url": "https://mcp.riffads.com" }
    ```
  </Tab>

  <Tab value="ChatGPT">
    No install link. Open connector settings, add a custom connector, paste `https://mcp.riffads.com`.

    ```text title="ChatGPT connector settings"
    https://chatgpt.com/#settings/Connectors
    ```
  </Tab>

  <Tab value="Any client">
    ```json title="Generic MCP config"
    {
        "mcpServers": {
            "riffads": {
                "type": "http",
                "url": "https://mcp.riffads.com"
            }
        }
    }
    ```

    | Setting                | Value                                              |
    | ---------------------- | -------------------------------------------------- |
    | Transport              | Streamable HTTP, stateless                         |
    | Method                 | `POST` with a JSON-RPC 2.0 body                    |
    | `Content-Type`         | `application/json`                                 |
    | `Accept`               | `application/json, text/event-stream`              |
    | Auth                   | `Authorization: Bearer <access token>` (OAuth 2.1) |
    | Wall clock per request | 60 seconds                                         |

    * Old HTTP+SSE-only clients cannot connect.
    * A reply can be a one-frame event stream. Accept both types.
    * Authenticated `GET` answers `405`. There is no session.
  </Tab>
</Tabs>

<Callout type="warn" title="Use the URL exactly">
  `https://mcp.riffads.com`. No path, no trailing slash. A wrong URL means no sign-in window.
</Callout>

## Sign in [#sign-in]

1. The first tool call opens a browser on `app.riffads.com`.
2. Sign in with Google, or email and password.
3. Approve. You only see a consent screen if the client sends `prompt=consent` (Claude does not). There you pick the workspace and **spend** or **read only**.

## Check the connection [#check-the-connection]

Call `riffads_ping`. No arguments. Spends nothing.

```json title="riffads_ping result"
{
    "ok": true,
    "user_id": "...",
    "organization_id": "org_...",
    "workspace": "Acme",
    "plan": "launch",
    "mode": "spend",
    "can_spend_credits": true,
    "server_time": "2026-09-17T10:28:41.002Z"
}
```

* `workspace`: the workspace this connection uses.
* `can_spend_credits: false`: read only. The 5 spend tools are missing.

## Which workspace it uses [#which-workspace-it-uses]

An MCP token is a **person**, not a workspace. The connection holds the workspace.

| Your account                     | What happens                                                        |
| -------------------------------- | ------------------------------------------------------------------- |
| One workspace                    | Binds on first use.                                                 |
| More than one, no consent screen | Nothing binds. Every call refuses with `connection_not_configured`. |
| Client showed a consent screen   | You picked it there.                                                |
| No workspace                     | Every call refuses with `no_workspace`.                             |

```json title="connection_not_configured"
{
    "ok": false,
    "code": "connection_not_configured",
    "message": "This RiffAds account has more than one workspace, so this connection does not know which one to spend from. Choose one at https://app.riffads.com/connections, then try again.",
    "retryable": false,
    "credits_charged": 0,
    "connect_url": "https://app.riffads.com/connections"
}
```

Retrying changes nothing. Pick the workspace at [app.riffads.com/connections](https://app.riffads.com/connections), then call again.

## Read or spend [#read-or-spend]

| Mode    | Tools | Can do                                                                                                  |
| ------- | ----- | ------------------------------------------------------------------------------------------------------- |
| `read`  | 12    | Browse, estimate, read generations and runs.                                                            |
| `spend` | 17    | Plus `submit_generation`, `generate_talking_actor`, `run_workflow`, `create_upload`, `finalize_upload`. |

* New connections can spend, unless you chose read only.
* Uploads count as spend tools.
* Change the mode at [app.riffads.com/connections](https://app.riffads.com/connections). Anyone can narrow their own. Only owners and admins can widen.
* After a change, refresh the client's tool list. A stale list calling a spend tool gets `read_only_connection`.

## OAuth discovery (custom clients) [#oauth-discovery-custom-clients]

Most clients do this for you. Building your own:

1. Call with no token. You get `401`:

```text title="WWW-Authenticate"
Bearer error="invalid_token", error_description="Missing Authorization header", resource_metadata="https://mcp.riffads.com/.well-known/oauth-protected-resource"
```

2. Fetch `resource_metadata`:

```json title="GET https://mcp.riffads.com/.well-known/oauth-protected-resource"
{
    "resource": "https://mcp.riffads.com",
    "authorization_servers": ["https://app.riffads.com"],
    "scopes_supported": ["openid", "profile", "email", "offline_access"],
    "bearer_methods_supported": ["header"],
    "resource_name": "RiffAds"
}
```

3. Read `authorization_servers[0]`. Do not hardcode it. Fetch its `/.well-known/oauth-authorization-server` for the authorize, token and registration endpoints.
4. Register (dynamic registration works), authorize in a browser, exchange the code.
5. Send `Authorization: Bearer <access token>` on every call.

Scopes gate nothing on MCP. The connection mode decides what a token can call.

<Callout type="warn" title="Register once, not in a loop">
  Per address, before any token: 10 registrations per 10 minutes, 120 requests a minute on the MCP endpoint. Over either: `429` with `Retry-After` and no JSON-RPC body.
</Callout>

Token problems answer `401` with a plain OAuth body:

| `error_description`                                            | Fix                          |
| -------------------------------------------------------------- | ---------------------------- |
| `Missing Authorization header`                                 | Send the token.              |
| `Invalid Authorization header format, expected 'Bearer TOKEN'` | Use the `Bearer` scheme.     |
| `Unknown, revoked or expired access token`                     | Authorize again.             |
| `Token has expired`                                            | Refresh, or authorize again. |
| `Access token has no usable expiry`                            | Authorize again.             |
| `Access token is not bound to a client`                        | Authorize again.             |

## Troubleshooting [#troubleshooting]

| Symptom                                        | Cause                                      | Fix                                                                            |
| ---------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------ |
| No sign-in window                              | Wrong URL, or not a streamable HTTP client | URL exactly `https://mcp.riffads.com`                                          |
| Every tool answers `connection_not_configured` | Several workspaces, none picked            | Pick one at [app.riffads.com/connections](https://app.riffads.com/connections) |
| Only 12 tools                                  | Read only connection                       | Allow spending, refresh the tool list                                          |
| `not_authorized`                               | Token revoked or bad, or account blocked   | Reconnect and sign in again                                                    |
| `workspace_unavailable`                        | Workspace deleted, or you left it          | Reconnect, pick a workspace you are in                                         |
| `no_workspace`                                 | Account has no workspace                   | Finish setup at [app.riffads.com](https://app.riffads.com), reconnect          |
| `required_plan`                                | Plan does not include the agent API        | The message names the plan that does                                           |
| `429` with `Retry-After` during setup          | Per-address limit                          | Wait, register once                                                            |

* Disconnecting deletes the tokens. The agent must reconnect from scratch. Work already running finishes.
* Switching workspace in the browser does not move a connection.
* Tool refusals are JSON with `code`, `message`, `retryable`, `credits_charged`. Branch on `code`. See [errors](/reference/errors).
