Authentication

Platica's MCP server accepts two Bearer credentials. Both travel in the same header; what changes is who issues them and what authority they carry.

Authorization: Bearer <credential>
CredentialPrefixWho uses itAuthority
OAuth 2.1pl_at_Cursor, Claude, VS Code, and any MCP client that speaks the specYou: the workspaces you authorized and your role's permissions
API Keypl_key_Scripts, CI, Postman, and clients without OAuthThe key's workspace, with full access to its modules

Every MCP tool internally makes the same authenticated call you would make to the corresponding REST endpoint. Rate limits, validation, and errors are identical. There is no separate "MCP mode".


OAuth 2.1

This is the method recommended by the MCP authorization spec . Platica is both the resource server (POST /mcp) and the authorization server that issues tokens for it.

How the connection works

  1. Paste the URL — In your MCP client, set https://api.platica.mx/mcp without an Authorization header. See Setup .

  2. The client discovers on its own — The first call to /mcp returns 401 with a WWW-Authenticate header pointing at the discovery documents. The client reads the authorization server, registers itself (Dynamic Client Registration), and opens the browser.

  3. Sign in to Platica — Authorize with the same account you use in the dashboard. If you already have a session, you won't type a password again.

  4. Pick workspaces — Choose which ones this connection can reach. The client stores the tokens and refreshes them on its own.

You don't register an OAuth App by hand. The client registers itself the first time; a client_id grants nothing until a person approves the connection.

Scopes

ScopeWhat it allows
platica:readReads (GET). The minimum to get in the door.
platica:writeCreates, updates, and deletes. Without it, those tools return 403 with an insufficient_scope challenge so the client can step up.
offline_accessRefresh token. The client uses it to renew the access token without asking you to consent again.

If the client omits scope, Platica grants platica:read and platica:write. Modern MCP clients usually also request offline_access.

Role permissions

Scopes open the door; your role in the workspace decides what's behind it. An operator who connects Claude does not become an admin: if they can't manage integrations in the product, connect_mcp_server returns the same 403.

That lookup is live. If you're removed from a workspace on Monday, the token stops reaching it on the next call — nothing has to be revoked by hand.

An API Key is different: it's a service credential an admin deliberately issued, and it still grants full module access to its workspace for as long as the owner remains a member.

Workspaces

At consent you pick one or more workspaces. The model doesn't know those IDs: the first tool it should call is list_workspaces .

  • A single workspace: the other tools infer the ID. You don't need to pass workspace.
  • Several workspaces: write tools require workspace: "<id>". If you omit it, they respond 400 Must specify a valid workspace... so the model can correct itself.

The same workspace argument exists in REST as ?workspace=.

Tokens

TokenPrefixLifetime
Access tokenpl_at_1 hour
Refresh tokenpl_rt_60 days of inactivity; every use extends it

The client stores and rotates them. Don't copy them into a config or paste them into a header by hand: if the access token expires, the client refreshes it; if you paste a stale one, you get 401.

The access token also works as a Bearer on the REST API (/v1/*). It still carries your role and scopes, not the full access of an API Key.

How access is cut off

  • Disconnect the server in the MCP client. Clients that follow the spec call POST /oauth/revoke.
  • Leaving a workspace in Platica cuts that workspace on the next request.
  • A read-only token cannot write: the client must re-authorize requesting platica:write.

API Key management (create / revoke) is not exposed as an MCP tool. A model cannot trade an OAuth session for a permanent key.

Discovery, per RFC 9728 and RFC 8414. Clients try both path spellings:

GET https://api.platica.mx/.well-known/oauth-protected-resource
GET https://api.platica.mx/.well-known/oauth-protected-resource/mcp
GET https://api.platica.mx/.well-known/oauth-authorization-server
GET https://api.platica.mx/.well-known/oauth-authorization-server/mcp

The canonical resource — the resource value on authorize/token — is https://api.platica.mx/mcp. The bare origin (https://api.platica.mx) is also accepted. Any other audience is rejected.

EndpointUse
GET /oauth/authorizeAuthorization Code + PKCE S256. A response_type other than code is not supported.
POST /oauth/tokenauthorization_code and refresh_token. Accepts form-urlencoded or JSON.
POST /oauth/registerDynamic Client Registration (RFC 7591). Open: a client_id grants no access.
POST /oauth/revokeRevocation (RFC 7009). Answers 200 even if the token does not exist.

PKCE is required and only S256 is advertised (plain is not offered: OAuth 2.1 forbids it). MCP clients are public (token_endpoint_auth_method: none); if you registered a secret, you must present it.

The 401 from /mcp with no credential carries the challenge that starts the flow:

WWW-Authenticate: Bearer resource_metadata="https://api.platica.mx/.well-known/oauth-protected-resource/mcp", scope="platica:read platica:write"

Redirect URIs allowed at registration: https, loopback (http://127.0.0.1, localhost, [::1]), or a private scheme (cursor://…). Public-host http and any URI with a fragment are rejected.


API Key

Still valid. Use it for cron, CI, curl, and any client that doesn't speak OAuth.

API Keys are created from the dashboard, not from the MCP server:

  1. Open settings — In the dashboard, Settings → API Keys.

  2. Create a Key — Give it a descriptive name (e.g. cursor-personal or ci-prod).

  3. Copy it — Format pl_key_KEY_ID_SECRET. It's shown only once.

  4. Paste it in the client — Authorization: Bearer pl_key_... in the config. See Setup .

The key covers the workspace it was created in (or the ones assigned to it, if it's multi-workspace) with access to every module. It does not inherit the role of whoever created it.


Multi-workspace

CredentialHow the workspace is chosen
OAuth with one workspaceInferred. Don't pass workspace.
OAuth with severalCall list_workspaces and pass workspace on every write tool.
Single-workspace API KeyInferred.
Multi-workspace API KeySame: if you omit workspace on a write, 400 Must specify a valid workspace....

list_workspaces also tells you whether the credential is oauth or apiKey, which scopes it has, and which modules your role can reach in each workspace. Call it first when the client has just connected.