Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Prizmad OAuth 2.1 — Authorization Code + PKCE + Dynamic Client Registration is the primary path (powers Claude Desktop / Claude.ai / ChatGPT / Cursor "Connect" flow). client_credentials remains for headless / programmatic clients.
.claude/skills/prizmad-oauth/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 19% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 11% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 26% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 9% | 0% |
| case-08 | ✗→✓ | ▲ Improved | -19% | 0% |
Prizmad publishes a full OAuth 2.1 authorization server with Dynamic Client Registration. Three grant types are supported, each for a different audience:
| Grant | When | Output | |---|---|---| | authorization_code (PKCE S256, public client) | Interactive MCP / connector flow — Claude Desktop, Claude.ai, ChatGPT, Cursor, Zed | RS256 JWT, audience https://prizmad.com/api/mcp, 1 h, refresh-rotated | | refresh_token | Companion to authorization_code | Same shape; old refresh is single-use, reuse revokes the chain | | client_credentials | Headless / server-to-server using an API key as client_secret | HS256 JWT, audience https://prizmad.com/api, 1 h |
The MCP server also accepts the raw API key (przmad_sk_live_...) as a Bearer token directly, without going through OAuth at all.
This is what runs when a user clicks Add custom connector → enter https://prizmad.com/api/mcp in Claude Desktop, Claude.ai, ChatGPT, Cursor, etc. The client implements RFC 7591 / 8414 / 9728 / 7636 / 8707; no manual app registration is needed.
text1. POST /api/mcp without auth ← 401 + WWW-Authenticate: Bearer resource_metadata="…" 2. GET /.well-known/oauth-protected-resource GET /.well-known/oauth-authorization-server 3. POST /oauth/register Body (RFC 7591): { "client_name": "<your app>", "redirect_uris": ["<your callback URL>"], "grant_types": ["authorization_code", "refresh_token"], "response_types": ["code"], "token_endpoint_auth_method": "none" } ← 201 { "client_id": "mcp_…", … } (no client_secret — public client) 4. Browser to /oauth/authorize? response_type=code & client_id=<from step 3> & redirect_uri=<from step 3> & code_challenge=<S256(verifier)> & code_challenge_method=S256 & scope=videos:read videos:write & resource=https://prizmad.com/api/mcp & state=<csrf> User signs in (NextAuth) and approves on the consent screen. ← 302 redirect_uri?code=…&state=… 5. POST /oauth/token grant_type=authorization_code code=<from step 4> redirect_uri=<from step 3> client_id=<from step 3> code_verifier=<original PKCE verifier> resource=https://prizmad.com/api/mcp ← 200 { "access_token": "<RS256 JWT>", "refresh_token": "…", "expires_in": 3600, "token_type": "Bearer" } 6. POST /api/mcp with Authorization: Bearer <access_token> ← MCP traffic.
Refresh:
bashcurl -X POST https://prizmad.com/oauth/token \ -d grant_type=refresh_token \ -d refresh_token=<previous refresh_token> \ -d client_id=<client_id>
Returns a fresh access token + a new refresh token; the previous refresh is single-use. Reusing a revoked refresh token revokes the entire chain (defence against token theft).
Quickest way to turn a long-lived API key into a short-lived bearer for server-to-server calls.
bashcurl -X POST https://prizmad.com/oauth/token \ -d grant_type=client_credentials \ -d client_id=my-app \ -d client_secret=przmad_sk_live_...
bashcurl -X POST https://prizmad.com/oauth/token \ -H "Content-Type: application/json" \ -d '{"grant_type":"client_credentials","client_id":"my-app","client_secret":"przmad_sk_live_..."}'
bashcurl -X POST https://prizmad.com/oauth/token \ -u "my-app:przmad_sk_live_..." \ -d grant_type=client_credentials
json{ "access_token": "eyJhbGciOiJIUzI1NiIs...", "token_type": "Bearer", "expires_in": 3600, "scope": "videos:read videos:write" }
| Scope | Description | |-------|-------------| | videos:read | Read video status, projects, assets | | videos:write | Create videos, upload images, mutate projects |
/oauth/authorize, /oauth/token, /oauth/register) live on the same origin as the MCP server (https://prizmad.com). This sidesteps the Claude.ai web bug that ignores cross-origin authorization endpoints.przmad_sk_live_...) continue to work directly as Bearer tokens — OAuth is only needed when the client requires it.client_secret field, when used, is your Prizmad API key.client_id for client_credentials is a free-form identifier.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 18,887 | 14,288 | -24% | 1 | 1 | 0% | 3,834 | 4,566 | +19% | 0 | 0 | — |
case-02 | fail→pass | 13,017 | 6,417 | -51% | 1 | 1 | 0% | 2,665 | 2,949 | +11% | 0 | 0 | — |
case-03 | pass→pass | 14,481 | 8,421 | -42% | 1 | 1 | 0% | 2,489 | 3,034 | +22% | 0 | 0 | — |
case-04 | pass→pass | 8,669 | 4,591 | -47% | 1 | 1 | 0% | 1,557 | 2,432 | +56% | 0 | 0 | — |
case-05 | fail→pass | 13,122 | 6,625 | -50% | 1 | 1 | 0% | 2,306 | 2,908 | +26% | 0 | 0 | — |
case-06 | pass→pass | 6,358 | 3,067 | -52% | 1 | 1 | 0% | 1,093 | 2,072 | +90% | 0 | 0 | — |
case-07 | fail→pass | 13,673 | 5,000 | -63% | 1 | 1 | 0% | 1,947 | 2,113 | +9% | 0 | 0 | — |
case-08 | fail→pass | 14,456 | 4,302 | -70% | 1 | 1 | 0% | 2,525 | 2,042 | -19% | 0 | 0 | — |
case-09 | pass→pass | 7,534 | 5,146 | -32% | 1 | 1 | 0% | 1,352 | 2,191 | +62% | 0 | 0 | — |
case-10 | pass→pass | 12,778 | 6,845 | -46% | 1 | 1 | 0% | 2,323 | 2,534 | +9% | 0 | 0 | — |
case-11 | pass→pass | 8,084 | 4,545 | -44% | 1 | 1 | 0% | 1,467 | 2,104 | +43% | 0 | 0 | — |
case-12 | fail→pass | 9,033 | 2,268 | -75% | 1 | 1 | 0% | 1,362 | 1,846 | +36% | 0 | 0 | — |
case-13 | fail→fail | 8,389 | 2,617 | -69% | 1 | 1 | 0% | 1,346 | 1,882 | +40% | 0 | 0 | — |
case-14 | pass→pass | 13,814 | 9,881 | -28% | 1 | 1 | 0% | 2,220 | 3,164 | +43% | 0 | 0 | — |
case-15 | fail→pass | 10,907 | 2,684 | -75% | 1 | 1 | 0% | 1,653 | 2,011 | +22% | 0 | 0 | — |
case-16 | fail→pass | 7,302 | 2,229 | -69% | 1 | 1 | 0% | 1,428 | 1,850 | +30% | 0 | 0 | — |
case-17 | fail→pass | 6,269 | 3,606 | -42% | 1 | 1 | 0% | 1,237 | 2,167 | +75% | 0 | 0 | — |
case-18 | pass→pass | 10,449 | 5,298 | -49% | 1 | 1 | 0% | 2,239 | 2,577 | +15% | 0 | 0 | — |
case-19 | pass→pass | 9,907 | 6,176 | -38% | 1 | 1 | 0% | 2,125 | 2,704 | +27% | 0 | 0 | — |
case-20 | fail→pass | 11,308 | 2,998 | -73% | 1 | 1 | 0% | 1,915 | 2,024 | +6% | 0 | 0 | — |
case-21 | pass→pass | 6,631 | 4,367 | -34% | 1 | 1 | 0% | 1,178 | 2,267 | +92% | 0 | 0 | — |
case-22 | pass→pass | 7,938 | 3,418 | -57% | 1 | 1 | 0% | 1,491 | 2,110 | +42% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +45 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.