Integrate with Whimful's MCP server.
Whimful exposes its accounts, sites, and analytics as a Model Context Protocol server at https://mcp.whimful.com. This guide shows how to register
as a client and mint OAuth access tokens on behalf of your users.
Already using an MCP client? Just plug it in.
If you're building on top of an MCP-aware host (Claude, Cursor, custom agents using the MCP SDK), there's nothing to register manually. Point the client at our server URL — it handles discovery, registration, consent, and token exchange for you.
Server URL
https://mcp.whimful.com The first time a user connects, the client performs RFC 7591 dynamic registration, opens the Whimful consent page in their browser, and stores the resulting access token. Read on if you need to drive the OAuth flow yourself.
Approval required before tokens issue
Anyone can register a client at /oauth/register — that part is open. But Whimful gates which redirect URIs are allowed to mint access tokens. Until your callback URL is on Whimful's allowlist, the consent screen will refuse the request and the token endpoint will return invalid_grant.
Email developers@whimful.com with your client name and the exact redirect URI(s) you need approved. We typically turn these around within a business day.
Drive the OAuth flow yourself.
Whimful implements OAuth 2.1 with the authorization-code + PKCE flow for public clients. The full integration is four steps.
Discover server metadata
All endpoints are advertised at the standard well-known URLs (RFC 8414, RFC 9728). Hard-coding them is fine for now, but discovery is the future-proof path.
curl https://mcp.whimful.com/.well-known/oauth-authorization-server Response
{
"issuer": "https://mcp.whimful.com",
"authorization_endpoint": "https://whimful.com/oauth/authorize",
"token_endpoint": "https://mcp.whimful.com/oauth/token",
"registration_endpoint": "https://mcp.whimful.com/oauth/register",
"scopes_supported": ["sites:read", "sites:write", "reports:read"],
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["none"]
}Register your client
POST to the registration endpoint with the redirect URIs you'll use. We issue a client_id immediately. We don't issue client secrets — every client must be public and use PKCE.
curl -X POST https://mcp.whimful.com/oauth/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "Acme Agent",
"redirect_uris": ["https://app.acme.com/oauth/callback"]
}' Response (201)
{
"client_id": "client_abc123…",
"client_name": "Acme Agent",
"redirect_uris": ["https://app.acme.com/oauth/callback"],
"grant_types": ["authorization_code"],
"response_types": ["code"],
"token_endpoint_auth_method": "none",
"client_id_issued_at": 1769990400
} http://localhost / http://127.0.0.1 for local development. Matching is exact —
register every URI you intend to use. The client_name shows up on
the Whimful consent screen, so make it recognisable to your users.Send the user to consent
Generate a PKCE pair, then redirect the user's browser to the authorization endpoint. After they sign in to Whimful and approve, we redirect back to your callback with a one-shot code.
PKCE (RFC 7636)
// 1. Random verifier (43–128 chars, URL-safe)
const code_verifier = base64url(crypto.randomBytes(32));
// 2. SHA-256 hash, base64url-encoded
const code_challenge = base64url(sha256(code_verifier)); Authorization URL
https://whimful.com/oauth/authorize
?client_id=client_abc123…
&redirect_uri=https://app.acme.com/oauth/callback
&response_type=code
&code_challenge=<BASE64URL(SHA256(verifier))>
&code_challenge_method=S256
&scope=sites:read+reports:read
&state=<random_state> Callback
GET https://app.acme.com/oauth/callback?code=…&state=… state matches what you sent before exchanging the code. Codes are
single-use and expire after 10 minutes.Exchange the code for a token
POST to the token endpoint with the code, the original redirect URI, your client ID, and the original PKCE verifier. The body is application/x-www-form-urlencoded.
curl -X POST https://mcp.whimful.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "code=${CODE}" \
--data-urlencode "redirect_uri=https://app.acme.com/oauth/callback" \
--data-urlencode "client_id=client_abc123…" \
--data-urlencode "code_verifier=${VERIFIER}" Response (200)
{
"access_token": "wmcp_…",
"token_type": "Bearer",
"expires_in": 31536000,
"scope": "sites:read reports:read"
} Call MCP tools with the access token.
Once you have an access token, talk to the MCP server like any other Streamable HTTP MCP endpoint. Send the token as a Bearer credential.
Example: list the user's accounts
curl -X POST https://mcp.whimful.com \
-H "Authorization: Bearer wmcp_…" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": { "name": "list_accounts", "arguments": {} }
}' If you're using the official MCP SDK, point a StreamableHTTPClientTransport at https://mcp.whimful.com with an Authorization header. The server is stateless per request, so no session bookkeeping is needed.
Three scopes.
Request the narrowest set of scopes your integration needs. The user sees each scope on the consent screen and can deny the whole request, but not individual scopes.
sites:read List sites and read metadata across the user's accounts.
sites:write Create sites and run domain verification on behalf of the user.
reports:read Run pre-defined BigQuery analytics reports against the user's data.
Handling expiry & errors.
Errors follow the OAuth 2.1 conventions and arrive as JSON with an `error` and `error_description`.
The bearer token is missing, malformed, expired, or revoked. Drop it and run the consent flow again.
The token is valid but the requested tool needs a scope the user didn't grant. Re-run the
consent flow with the additional scope in the scope parameter.
The most common causes are: code already redeemed (single-use), code older than 10 minutes, redirect_uri doesn't match the original /authorize call, PKCE code_verifier doesn't hash to the original challenge,
or your redirect URI hasn't been approved yet (see "Approval required" above).
Need a hand integrating?
Email developers@whimful.com with what you're building. We'll help you get the OAuth flow wired up and your first MCP call green.
Get in touch