# MCP server

The PlentyLabs MCP server allows AI clients to work with your data in the same way as you would through the app.

## Server

```
https://mcp.plentylabs.com/mcp
```

- Transport: streamable HTTP. Every message is a JSON-RPC `POST` to the server URL.
- Sessions: none. Each request stands alone and responses are JSON.
- Authentication: OAuth 2.1. API keys are not accepted.
- Tools and prompts: the client lists them after connecting. They cover boards, the asset library, Brand kits and image, video and audio generation. Clients that support MCP Apps also get tools that open views in the chat.

## Connect

Add the server as a remote HTTP server, then sign in.

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

### Sign-in

1. The client calls the server without a token and gets `401` with a `WWW-Authenticate` header.
2. The header points to the protected resource metadata at `https://mcp.plentylabs.com/.well-known/oauth-protected-resource/mcp`, which names the authorization server.
3. The client reads the authorization server's metadata and registers itself with dynamic client registration.
4. The person signs in to PlentyLabs and approves the client. The client gets an access token with PKCE.
5. The client sends the token as `Authorization: Bearer` on every request, and refreshes it when it expires.

The client has the signed-in person's access in every workspace they belong to. `ListMyWorkspaces` returns their workspace ids.

## Limits and errors

- `GenerateImage`, `GenerateVideo` and `EditImage` take 1 to 12 entries per call.
- A request body can be at most 10 MB.
- Tools spend the signed-in person's [request and complexity budgets](https://plentylabs.com/developers/rate-limiting) and the same credits as the app. Generation tools share the workspace's generation limits, and `ImportImageFromUrl` and `RefinePrompt` have their own per-person limits, as do tools that open a view in the chat.
- A tool that fails returns `isError: true`; its text holds the GraphQL response with the API's error codes. `GenerateImage`, `GenerateVideo` and `EditImage` set `isError` only when no entry succeeded, and list each failed entry's message by index.
- A request with no valid token gets `401`. An unsupported `MCP-Protocol-Version` gets `400` with JSON-RPC error `-32022` listing the supported versions. `initialize` negotiates the version instead.
- A request that takes longer than 15 seconds gets `408`. `GET` and `DELETE` get `405`.
