# MCP Connect (OAuth 2.1) — Finradar API > Version: 3.61.0 | Generated: 2026-06-20 | Content Hash: 67d6f5c2 > Fetch this file at: https://uat.finradarapi.com/llms/mcp-connect-oauth-2-1.txt ## Authentication All endpoints require an API key. Pass it via query parameter `?apiKey=YOUR_KEY` or header `X-API-Key: YOUR_KEY`. WebSocket endpoints accept the key in the `token` auth payload or query parameter. --- ## MCP Connect (OAuth 2.1) One-click **Connect** for MCP clients (Cursor, Claude Desktop): instead of pasting an X-API-Key, the client runs the OAuth 2.1 authorization-code + PKCE flow against FinRadar's own login and gets a short-lived token. Discovery follows RFC 9728 (protected-resource) + RFC 8414 (authorization-server); the resource is `/api/mcp`. Both auth methods work side-by-side (dual auth) — existing X-API-Key clients are unaffected. Select FinRadar's MCP server in your client and click Connect to use it. ### GET /.well-known/oauth-protected-resource/api/mcp Served by the MCP server (the resource server), NOT main_api. Returns `{ resource: , authorization_servers: [], scopes_supported: ['mcp'], bearer_methods_supported: ['header'] }`. An unauthenticated MCP call returns 401 with `WWW-Authenticate: Bearer ... resource_metadata=` — how a client discovers where to authorize. **Token cost:** 0 (EXEMPT — auth / billing / account / admin / health) ### GET /.well-known/oauth-authorization-server FinRadar AS metadata: `issuer`, `authorization_endpoint` (/oauth/authorize), `token_endpoint` (/oauth/token), `jwks_uri`, `code_challenge_methods_supported: ['S256']` (PKCE S256 required), `scopes_supported: ['mcp']`, `grant_types_supported: ['authorization_code','refresh_token']`. **Token cost:** 0 (EXEMPT — auth / billing / account / admin / health) ### GET /.well-known/jwks.json The AS's RS256 public keys. The MCP server verifies access tokens against these (it holds no signing secret). Access tokens are RS256 JWTs with `iss`, `aud` (the canonical resource), `sub` (user uuid), `scope: mcp`, `token_use: mcp_access`, short `exp` (≤15 min), and `kid`. **Token cost:** 0 (EXEMPT — auth / billing / account / admin / health) ### POST /oauth/register Open registration endpoint (advertised as `registration_endpoint` in the AS metadata). An MCP client POSTs its metadata as JSON and receives a `client_id`. **Public clients only**: `token_endpoint_auth_method` is forced to `none` (no secret — authenticate with PKCE), `scope` is forced to `mcp`, `grant_types` is filtered to `authorization_code`(+`refresh_token`) and `response_types` to `code`. `redirect_uris` (required, 1-5) must each be `https` or a loopback `http://127.0.0.1[:port]` URI with no fragment (RFC 8252; `localhost` is rejected — register the 127.0.0.1 IP literal). Guarded by per-IP + global daily caps. Returns 201 `{ client_id, client_id_issued_at, redirect_uris, grant_types, response_types, token_endpoint_auth_method, scope }` — no `client_secret` (public client). **Token cost:** 0 (EXEMPT — auth / billing / account / admin / health) **Parameters:** - `redirect_uris` (body, required): JSON array (1-5) of allowed redirect URIs. Each must be `https` or loopback `http://127.0.0.1[:port]`, no fragment. - `client_name` (body, optional): Human-readable client name shown on the consent page (escaped). - `grant_types` (body, optional, default: authorization_code refresh_token): JSON array; filtered to the supported set (`authorization_code` required). - `token_endpoint_auth_method` (body, optional, default: none): Public clients only — must be `none` (or omitted). ### GET /oauth/authorize OAuth 2.1 authorization endpoint. GET renders a login + consent page (PKCE S256 required; CSRF-protected; framebusting). POST authenticates the user against the FinRadar login and, on Allow, redirects to `redirect_uri?code=...&state=...`. Loopback `redirect_uri` (http://127.0.0.1:/...) is allowed for native clients (RFC 8252). **Token cost:** 0 (EXEMPT — auth / billing / account / admin / health) **Parameters:** - `response_type` (query, required): Must be `code`. - `client_id` (query, required): Registered client id. - `redirect_uri` (query, required): Must match a registered redirect (loopback any-port allowed). - `scope` (query, optional, default: mcp): Single `mcp` scope. - `state` (query, required): CSRF/correlation value echoed back. - `code_challenge` (query, required): PKCE S256 challenge (base64url SHA-256 of the verifier). - `code_challenge_method` (query, required): Must be `S256` (plain is rejected). ### POST /oauth/token OAuth 2.1 token endpoint (public client, `token_endpoint_auth_method: none`). `grant_type=authorization_code` exchanges a one-time code + `code_verifier` for `{ access_token (RS256 JWT), token_type: Bearer, expires_in, refresh_token, scope }`. `grant_type=refresh_token` rotates the refresh token (reuse of a rotated token revokes the whole family). **Token cost:** 0 (EXEMPT — auth / billing / account / admin / health) **Parameters:** - `grant_type` (body, required): `authorization_code` or `refresh_token`. - `code` (body, optional): Authorization code (authorization_code grant). - `code_verifier` (body, optional): PKCE verifier (authorization_code grant). - `redirect_uri` (body, optional): Must match the authorize request. - `refresh_token` (body, optional): Refresh token (refresh_token grant). - `client_id` (body, required): Client id. ### POST /oauth/revoke Revokes the presented refresh token and its whole rotation family. Always returns 200 per RFC 7009. **Token cost:** 0 (EXEMPT — auth / billing / account / admin / health) **Parameters:** - `token` (body, required): The refresh token to revoke.