Discovery
MCP-compatible clients automatically discover the authorization server via the RFC 8414 metadata document:authorization_endpoint— where the user grants consenttoken_endpoint— where clients exchange codes / refresh tokensregistration_endpoint— RFC 7591 Dynamic Client Registration (no manual setup needed)- Supported scopes, grant types, PKCE methods (S256 mandatory), and signing algorithms
The flow
1
Client registration (one-time, automatic)
On first connection, your MCP client posts to the registration endpoint
and receives a
client_id. No human action required.2
Authorization request
The client opens a Propal-hosted consent page in the user’s browser, with
a PKCE challenge. The user is asked to log in (if not already), pick the
organization to grant access to, and confirm the scopes requested.
3
Code exchange
Once consent is granted, Propal redirects to the client with an
authorization code. The client exchanges it for a short-lived access
token + a refresh token, sending the PKCE verifier.
4
Authenticated calls
Every MCP call carries the access token as
Authorization: Bearer <token>.
The token includes the user’s identity and the organization context.5
Refresh
When the access token expires, the client uses the refresh token silently
— no user prompt.
The mcp:use scope
Every MCP call requires the mcp:use scope. This is granted by default when
the user authorizes a client. Without it, you’ll get:
Organization context
The MCP is scoped to a single organization per session. When the user consents, they pick which organization to grant access to. All subsequent calls operate inside that organization — there’s no cross-org access. To switch organizations, the user re-authorizes the client (most clients expose a “Reconnect” or “Sign in again” action).Revoking access
Users revoke connectors from Settings → Integrations in the Propal app. After revocation, the client’s refresh token is invalidated — the next API call returns401 Unauthorized and the client can re-trigger the OAuth flow.
Security notes
- PKCE S256 is mandatory for all clients. We reject
plainPKCE. - Tokens are short-lived (1h access, 30d refresh). Refresh tokens rotate on each use.
- No client secrets are issued — Dynamic Client Registration produces public clients with PKCE binding.
- Organization scoping is enforced server-side at every tool call. The token alone doesn’t grant access; the user’s membership is re-checked.
Troubleshooting
"invalid_grant" on token refresh
"invalid_grant" on token refresh
The refresh token has been revoked (the user disconnected the client) or
expired (>30 days). Re-trigger the OAuth flow.
"forbidden — missing scope: mcp:use"
"forbidden — missing scope: mcp:use"
The client requested fewer scopes than required. Reconnect with the
default scope set; the user will be re-prompted to consent.
claude.ai shows a 'Connection failed' state
claude.ai shows a 'Connection failed' state
The most common cause is a server discovery glitch — wait 30s and click
‘Retry’. If it persists, check that
https://api.propal.io/v1/.well-known/oauth-authorization-server
returns 200.ChatGPT can't add the connector ('not supported on your plan')
ChatGPT can't add the connector ('not supported on your plan')
Custom MCP connectors require a Plus, Pro, Team, or Enterprise plan.
Free accounts can use the public REST API instead — see the
API quickstart.
Codex / IDE refuses to open the browser
Codex / IDE refuses to open the browser
Headless or CI environments often can’t pop a browser. Run an
interactive
codex (or IDE) session once on a machine with a browser to
complete the OAuth flow — the refresh token is cached locally
(~/.mcp-auth/ for mcp-remote, ~/.codex/auth/ for Codex) and reused
silently afterwards.Tools appear without a 'propal_' prefix
Tools appear without a 'propal_' prefix
Some clients (notably Codex CLI) prefix tool names with the connector
name, e.g.
propal__list_propal_components. Others (Claude Desktop,
ChatGPT) keep the original name. The behavior is fully client-side —
the MCP server registers them as list_propal_components, etc.