Authorize a tool account
An enrolled OAuth profile lets you authorize a tool account without pasting a provider token into the application. The service exchanges the authorization code and stores the resulting credentials for authorized execution. Access tokens, refresh tokens and client secrets are never returned to the SDK.
Use the current human session in the selected organization and environment. Organization-owned connections require owner or admin authority. Personal connections remain bound to their user. The enrolled profile fixes the issuer, resource, permissions, redirect URI and client configuration; the callback cannot choose a different provider or destination.
Begin an authorization
Section titled “Begin an authorization”List profiles through client.toolCredentialsOAuth.profiles(scope) in TypeScript
or client.tool_credentials_oauth.profiles(scope) in Python. Supply the exact
organization, environment, mode and reset generation.
Select the profile, connection owner and one to 32 sorted, unique permitted agent
IDs. Choose an explicit authorization_expires_at in UTC and review that deadline.
The service requires it to be in the future and within the selected profile’s
max_authorization_seconds limit, between 60 and 2,592,000 seconds.
Call begin(scope, request, profile, key) with a caller-chosen idempotency key.
The selected profile summary is a separate argument so the SDK can check the
returned authorization URL against its issuer origin, audience and permissions.
It also checks the response’s scope, profile and exact authority-deadline pins, the authorization-code flow
and the S256 PKCE parameters before returning the URL.
Show the selected provider and permissions, then navigate only after the person’s
explicit action. The SDK does not open a browser. The authorization URL contains
sensitive state: use it transiently and do not log or persist it. Do not send it to
analytics or include it in a recovery record. Check expires_at before navigation: it is the separate ten-minute setup/review
window, not the connection authority deadline.
Complete the callback once
Section titled “Complete the callback once”Your application callback must match the redirect URI enrolled for the profile. Capture the callback’s code, state and issuer without altering them. Remove sensitive query parameters from the visible URL before application scripts, analytics or error reporting process the page. Use a no-referrer policy.
Call complete(scope, authorizationID, {state, issuer}, codeBytes) once. Python
uses the same method name and accepts bytes. Code bytes are a separate transient
argument, containing one to 4,096 printable, non-space ASCII bytes. HTTP uses
{state, issuer, code_base64}; base64 does not provide encryption.
Complete does not take an idempotency key. The authorization ID controls the one-use exchange. A lost response is not permission to repeat that exchange. Clear callback inputs after submission, failure or navigation. Keep state, codes, authorization URLs and token responses out of persisted recovery data and logs. The SDK sanitizes failures rather than returning original sensitive transport errors or response details.
Inspect the result, then activate
Section titled “Inspect the result, then activate”Use review(scope, authorizationID) to inspect the current result. The optional
last argument is the original Begin request, which binds the returned profile,
owner, agent allowlist and reconnect reference to that request.
| Status | Next action |
|---|---|
pending | Authorization has not completed. Check its expiry before continuing. |
exchanging | Inspect status again; do not resend the callback. |
review | Show the verified account, permissions, expiry and account digest for explicit review. |
activated | Read the recorded credential version; do not treat another activation as a new connection. |
rejected | The authorization was refused. Start a new authorization after reviewing the cause. |
uncertain | Inspect the recorded status and reconcile the uncertain exchange; do not repeat it automatically. |
expired | This authorization can no longer proceed. A previous account preview may remain as metadata. |
oauth_exchange_uncertain is an HTTP 409 requiring inspection, not a retry action.
oauth_authorization_rejected is an HTTP 403. Neither response tells the client to
repeat the provider exchange.
After the person reviews the verified account and permitted agents, call
activate(scope, review, key) with a new explicit idempotency key. Activation
independently checks the reviewed account digest and current authority. It returns
the normal credential connection and exact version reference.
The connection version’s expires_at equals the reviewed authorization_expires_at.
Shorter access-token expiry and serialized token refresh are private service state;
refresh never extends that authority deadline. Read the connection’s current
availability; refresh_required, refreshing and reconnect_required are not
ready states even when record state remains active. Revocation and current-authority checks
still apply. A successful provider authorization alone does not activate a credential, approve
an action or authorize spending.
Access-token renewal
Section titled “Access-token renewal”Before authorized execution, the service can renew an expired access token using the connection’s private refresh token. Concurrent callers share a serialized refresh attempt. They cannot start competing exchanges for the same generation. The resulting token must still represent the same verified account, exact permissions and current enrolled provider. Renewal never changes the connection owner, agent allowlist or reviewed authorization deadline.
A lost exchange or completion result does not make the previous refresh token
safe to reuse. A refused or uncertain renewal requires reconnect rather than an
automatic repeat of that provider exchange. While renewal is underway,
availability is refreshing; read current connection metadata before deciding
what to show. A successful earlier authorization does not guarantee that renewal
or execution remains available.
For reconnect, Begin includes reconnect: {connection_id, expected} using the
current connection’s exact reference. The profile, owner and permitted agents
must match the existing connection. The service verifies the same account and
activation creates the next immutable credential version.
Retain only recovery metadata
Section titled “Retain only recovery metadata”No SDK method automatically retries. Recovery records may retain the original request, caller key, authorization ID and selected account/environment scope. They must omit the authorization URL, state, callback code and provider tokens. Keep records bound to the same signed-in account, mode and reset generation.
After an uncertain Begin result, an explicit recovery must use its original key and exact metadata. After an uncertain Complete result, inspect Review instead of resending the exchange. After uncertain activation, inspect the authorization and its credential reference; an explicit retry must retain the same activation key and reviewed account digest.
const api = client.toolCredentialsOAuth;const profiles = await api.profiles(scope);const profile = profiles.data[0];const request = { profile: profile.profile, owner_kind: 'user' as const, agents: selectedAgentIDs, authorization_expires_at: reviewedAuthorityDeadline,};const start = await api.begin(scope, request, profile, beginKey);// Use start.authorization_url only for the person's explicit navigation.// After the callback, submit transient code bytes once:const review = await api.complete(scope, start.id, callback, codeBytes, request);// Inspect review.status and require explicit account approval before activation.const connection = await api.activate(scope, review, activationKey);All OAuth SDK methods use a human session and a 40-second request timeout. Profiles and credential services must be enabled for the environment. Synthetic contract fixtures test scope, redirect and callback boundaries; they do not establish live provider authorization or successful external tool execution.
Authorization deadlines use UTC timestamps with microsecond precision. Nonzero digits beyond six fractional decimal places are rejected rather than rounded. Trailing zero digits do not change the instant.
Refresh access before catalog maintenance
Section titled “Refresh access before catalog maintenance”An owner can explicitly ensure current OAuth access before an authenticated MCP catalog probe or publication. Read the exact connection, review its current availability and submit its immutable reference:
const refreshed = await client.refreshToolCredentialOAuth(scope, connection.reference);Python uses refresh_tool_credential_oauth(scope, connection_reference). The nested
toolCredentialsOAuth.refresh / tool_credentials_oauth.refresh methods are
equivalent. The request requires a fresh human session with locus:tools:write;
API keys and workloads cannot perform this maintenance. It sends no tokens and
needs no idempotency key. The server serializes token-generation exchange; it does
not change the credential version or extend the reviewed authorization deadline.
The SDK never retries this request automatically. After a lost response, use
toolCredentials.get / tool_credentials.get to inspect the exact connection.
refreshing requires inspection; reconnect_required requires a newly reviewed
authorization. Neither status authorizes repeating a provider exchange. A later
explicit maintenance request can refresh a newly near-expiry generation, so this
is not a permanently replayed operation receipt.