For AI agents: a documentation index is available at /llms.txt. A markdown version of this page is available at /guide/mcp/authentication.md.
Authentication
How MCP clients authenticate with OAuth 2.1 and PKCE: discovery, consent, the scope vocabulary, token lifetimes and what each error means.
/mcp/partner authenticates with OAuth 2.1 + PKCE. Your client obtains its
own bearer token through a browser sign-in; there is no key to copy into a
config file.
This replaced X-API-KEY
Earlier releases authenticated MCP with the X-API-KEY header. The primary
endpoint no longer accepts it. See Legacy key path if you
have an integration still on the old header.
#What you need before connecting
Two things, both handled once:
MCP enabled for your workspace
An administrator has to switch MCP on for the company and choose which scopes it may ever grant. Until that happens every authorization attempt is refused, regardless of who signs in. Contact support@orangescrum.com or your account manager to have it enabled.
An Orangescrum sign-in
You authorize as yourself, with email and password or Google sign-in. The assistant then acts with your permissions inside the workspace you picked. It cannot see projects you cannot see.
#The flow
Most clients run all of this for you after you paste the URL. It is worth knowing what the steps are when one of them fails.
Discovery
The client fetches the two well-known documents to learn where to send people and what scopes exist:
GET https://v4-api.orangescrum.com/.well-known/oauth-protected-resource GET https://v4-api.orangescrum.com/.well-known/oauth-authorization-serverThe second advertises
authorization_endpoint,token_endpoint,registration_endpoint,scopes_supported, and PKCE support (S256).Dynamic client registration
The client registers itself and receives a
client_id: no client secret, because it is a public client protected by PKCE:POST https://v4-api.orangescrum.com/oauth/registerThis is RFC 7591. You never do it by hand, and there is nothing to pre-provision on the Orangescrum side.
Sign in and consent
The client opens
/oauth/authorizein your browser. You sign in if you do not already have a session, then land on a consent screen that shows the connecting client, the scopes it is asking for, and the MCP-specific part: a workspace picker listing every workspace you belong to that has MCP enabled.Pick one and authorize. The grant is bound to that single workspace.
Token exchange
The client exchanges its authorization code at
/oauth/tokenwith the PKCE verifier and receives an access token plus a refresh token.Calls
Every subsequent MCP request carries the token:
Authorization: Bearer <access-token>
#Token lifetimes
| Token | Lifetime | Notes |
|---|---|---|
| Access token | 1 hour | Short on purpose, so revoking access takes effect quickly |
| Refresh token | 30 days | Rotated on every exchange; keeps you from re-consenting daily |
Clients refresh silently. You will only see the browser again if you go 30 days without using the connection, or if access is revoked.
#Scopes
Two things have to agree before a scope is usable: your workspace must allow it, and you must approve it on the consent screen. A client asking for more than the workspace allows is clamped down to the allowed set rather than refused.
mcp:use is the base gate. Every request needs it, and it is what a client
falls back to when it does not know the granular vocabulary.
| Scope | Grants |
|---|---|
mcp:use | Connect at all, for the selected workspace. Required by every request |
mcp:projects.read | Read projects and project metadata |
mcp:projects.write | Create and update projects |
mcp:tasks.read | Read tasks, task lists, statuses and types |
mcp:tasks.write | Create, update, assign and close tasks |
mcp:epics.write | Create epics, features, stories and subtasks |
mcp:sprints.read | Read sprints and sprint plans |
mcp:sprints.write | Create, update, start and complete sprints; assign tasks to them |
mcp:timelogs.read | Read time entries and timesheets |
mcp:timelogs.write | Create and update time entries |
mcp:users.read | Read workspace members and user profiles |
mcp:tests.read | Read test cases, scenarios, steps and defects |
mcp:tests.write | Create, update, link and archive test cases, scenarios, steps and defects |
mcp:checklists.read | Read checklists, checklist groups and templates |
mcp:checklists.write | Create, update, complete and delete checklist items, groups and templates |
mcp:context.read | Read saved project/company context ("memory") |
mcp:context.write | Save project/company context ("memory") |
mcp:documents.read | Search uploaded documents |
Reserved scopes in the discovery document
scopes_supported also advertises scopes with no tools behind them yet,
mcp:users.write, mcp:teams.*, mcp:wiki.*, mcp:tickets.*,
mcp:reports.read and others. They are registered ahead of the features that
will use them. Granting one today grants nothing, and they are deliberately
not offered in the workspace scope picker.
Users stay read-only
There is no tool to invite, deactivate or re-role a member. mcp:users.write
exists in the vocabulary but nothing dispatches on it. Changing who has access
to your workspace stays in the admin UI deliberately.
#Errors
Every failure carries a WWW-Authenticate header alongside a JSON-RPC error
body. Clients that follow the OAuth challenge restart the flow automatically on
invalid_token.
| Status | error | What happened | Fix |
|---|---|---|---|
401 | invalid_request | No bearer token was sent | Let the client run the OAuth flow; check it is not still sending X-API-KEY |
401 | invalid_token | Token expired, revoked or signature invalid | Reconnect, normally automatic on refresh |
401 | invalid_token | No consent recorded for this token | Re-authorize; the workspace selection never completed |
403 | insufficient_scope | Token lacks mcp:use | Re-authorize and approve the base scope |
403 | invalid_token | Audience mismatch | The token was issued for a different resource. Reconnect against this URL |
403 | invalid_token | Workspace entitlement disabled or revoked | Ask an administrator to re-enable MCP for the workspace |
403 | n/a | Tool called without its scope | Re-authorize with the scope named in the error |
429 | n/a | Rate limited | See rate limits |
A per-tool scope failure names the scope it wanted, for example "requires the
mcp:sprints.write scope". That is the signal to re-authorize with a wider
grant, or to ask an administrator to widen what the workspace allows, if the
scope is not on offer.
#Rate limits
120 requests per minute and 5,000 per day, returned as JSON-RPC error
code -32500 with HTTP 429.
The MCP limit is counted per IP address
Unlike the REST limits, which are counted per API key, the MCP limiter keys on the calling IP, MCP clients do not always present a credential during the initialize handshake. Everyone connecting from the same office NAT or VPN egress shares one bucket, so a colleague's bulk run can rate-limit you.
#Protocol versions
The server negotiates these MCP spec revisions during initialize:
2025-11-25 · 2025-06-18 · 2025-03-26 · 2024-11-05
A client offering something newer will fail the handshake immediately after OAuth succeeds, which looks like an auth problem but is not. If you see that after a client update, say so when you report it.
#Legacy key path
A second endpoint still accepts the old header, for integrations mid-migration:
POST https://v4-api.orangescrum.com/mcp/partner-legacy
X-API-KEY: YOUR_KEY
It serves the identical tool set. Two things to know before you reach for it:
- It is feature-flagged and not guaranteed to stay available. OAuth is the supported path going forward.
- A partner key has no scope vocabulary and no consent screen, so the per-tool safety boundary described above does not apply to it in the same way.
Do not build new integrations against it
If you are connecting a client today, use /mcp/partner and OAuth. Treat
/mcp/partner-legacy as a migration aid with a limited life.