Skip to main content
The Bizzy MCP server is a protected resource. Clients authenticate using OAuth 2.1 with PKCE, following the MCP authorization specification. A client identifies itself with a Client ID Metadata Document, or with Dynamic Client Registration when it cannot. Modern MCP clients — Claude Desktop, Claude Code, Cursor, Windsurf, and the MCP Inspector — run the entire flow automatically. As an end user you only need to:
  1. Point the client at https://mcp.bizzyco.ai/mcp.
  2. Sign in to Bizzy when the consent screen opens in your browser.
  3. Choose an agent on the consent screen and review its allowed tools before approving the connection.
The rest of this page describes the flow in detail for client developers and for anyone debugging a connection.

How the flow works

The handshake is plain OAuth 2.1; no Bizzy-specific extensions are involved.

Discovery

The server publishes two metadata documents. A client discovers everything else from these. You can fetch them directly:

401 response shape

A request to /mcp without a valid Bearer token returns HTTP 401 with a WWW-Authenticate header pointing back to the protected-resource metadata URL on the same host and naming the scope to request:
The 401 — not a JSON-RPC error envelope — is the canonical signal that the client should run discovery and the OAuth flow. A host-level metadata document is also available at /.well-known/oauth-protected-resource for clients that prefer it.

When a working connection starts returning 401

A token is bound to one agent at consent time. If that agent is later deleted, deactivated, or moved to another organization, the token stops working and every request returns a 401 that names the reason:
Retrying and refreshing cannot recover it — the binding is what expired, not the credential. Run the OAuth flow again and the consent screen issues a token bound to an agent that still exists. Clients that re-authorize automatically on a 401 recover on their own.

When a disabled account is refused

If your Bizzy account is disabled, the server stops serving your connection. A new connection is refused with HTTP 403 and no WWW-Authenticate header:
A connection that was already open keeps its transport, so the refusal arrives in the JSON-RPC envelope instead, on tools/call and on every other method except ping:
Running the OAuth flow again does not clear either one — a fresh token for the same account is refused the same way — so treat both as terminal and show the reason rather than re-authorizing. Nothing is revoked: once the account is enabled again the same connection resumes within a minute, with no new consent and no reconnect.

When the business agreement isn’t accepted

The consent screen offers only businesses whose owner or admin has accepted the business agreement. If none of your businesses has, the consent screen shows Business agreement not accepted instead. An existing connection is refused the same way while its business still has to accept, including after a new version needs accepting:
Re-authorizing does not clear it. Once an owner or admin accepts the agreement in Bizzy, the same connection works again on its next request.

Client registration

Client ID Metadata Documents

Use an https:// URL as your client_id. The URL must have a path and serve a JSON document whose client_id is that exact URL, with client_name and redirect_uris (the redirect URI you send on /oauth/authorize must be listed there). No registration step is needed, the same client_id works with every server that supports this, and the consent screen shows your document’s domain so users can tell who is asking.
If the document cannot be fetched or does not validate, the authorize step fails with Client metadata unavailable and names the URL.

Dynamic Client Registration

The MCP specification deprecates RFC 7591 registration but keeps it for clients that cannot host a metadata document. Register at POST /oauth/register. Registration is open (no admin approval required) but rate-limited to 10 requests per 60 seconds per IP, so cache the returned client_id (and any client_secret) and reuse it across launches rather than re-registering every time. Prefer the OS credential store (Keychain on macOS, Credential Manager on Windows, libsecret on Linux) over a plaintext file on disk, especially for client_secret values.

PKCE

The server requires PKCE on every authorization request and only accepts the S256 code-challenge method. Plain PKCE is rejected — clients that send code_challenge_method=plain will fail the authorize step.

Resource indicator

Send the RFC 8707 resource parameter on every authorization and token request with the value https://mcp.bizzyco.ai/mcp — exactly the value in the protected-resource metadata, path included. This binds the issued access token to Bizzy so it can’t be replayed against another server. A request naming any other resource is refused with invalid_target, sent back to your redirect URI with your state. Modern MCP clients read the value from the metadata and send it automatically; custom clients must include it. The redirect back to your client carries an iss parameter (RFC 9207). Compare it with the issuer from the authorization-server metadata before exchanging the code.

Scopes

Two scopes are advertised: Choose an agent during consent. Its current resource permissions determine which supported tools the client can use. Only allow actions are available; ask and deny actions are unavailable because MCP cannot request chat approval. Change the agent’s resource permissions to change the connection’s access. Changes apply on the next MCP request, including within an existing connection. A request already in progress keeps its starting permissions.

Token lifetime

Access tokens are refreshed via POST /oauth/token with grant_type=refresh_token. Refresh tokens rotate on every use per OAuth 2.1. The token endpoint is rate-limited to 10 requests per 60 seconds per IP; cache the access token for its lifetime rather than re-exchanging on every call.

Rate limits

Two limits apply to authenticated traffic, and they surface differently.

Tool calls: your plan’s per-minute limit

Every tools/call spends one request from your account’s MCP allowance: The limit is also the burst capacity: you can spend your full per-minute allowance at once, and it replenishes continuously over the following minute. MCP and API allowances are independent — heavy API traffic never consumes your MCP capacity. See Understanding Limits for how rate limits fit into your plan. A throttled tool call is not an HTTP error. The request succeeds at the transport level and the throttle is reported in the JSON-RPC envelope, so clients must inspect the response body rather than the status code alone:
Wait data.retryAfter seconds before retrying that call. Other methods (tools/list, ping, and the rest of the protocol) do not spend from this allowance.

Transport: per-(user, client) backstop

Independently, /mcp accepts at most 600 requests per 60 seconds per (user, client) as an abuse backstop. Its ceiling sits above every plan’s tool-call limit, so ordinary use never reaches it. A throttled request here is HTTP 429 with the same JSON-RPC error body and a Retry-After header. The server does not emit X-RateLimit-* headers on either surface.

Reference

Last modified on October 3, 2026