Wren MCP
Authentication
Wren uses OAuth 2.0 authorization code with PKCE. Most MCP clients handle this for you; read on if you are writing a client or debugging a sign-in.
What needs a token
Discovery is open: initialize, tools/list and get_drawing_guide work with no token. Every tool that reads or changes a user’s account or notes requires an access token with the matching scope.
A request that needs a token and has none gets the 401 challenge below. A valid token that lacks the scope a tool needs gets a normal tool error result rather than a 401.
The flow
- Call a protected tool with no token. The server answers
HTTP 401with aWWW-Authenticate: Bearerheader that carriesresource_metadata. Clients that follow the MCP authorization spec start sign-in from this response. - Fetch the protected-resource metadata. The URL from
resource_metadatanames the authorization server and the supported scopes. - Fetch the authorization-server metadata. It lists the authorize, token and JWKS endpoints, and the PKCE and grant types the server accepts.
- Identify the client. The server advertises
client_id_metadata_document_supported: trueand no registration endpoint. Use an HTTPSclient_idURL that serves your Client ID Metadata Document; dynamic client registration is not offered. - Send the user to the authorize endpoint. Authorization code flow with
code_challenge_method=S256. The user signs in with their Wren account and approves the requested scopes. - Exchange the code at the token endpoint. Public clients only (
token_endpoint_auth_methods_supported: ["none"]), so there is no client secret. You receive an access token and can renew it with therefresh_tokengrant. - Retry the tool call with the token. Send
authorization: Bearer <access token>on every request.
The 401 challenge
This is the live response to a protected tool call that has no token:
HTTP/2 401
www-authenticate: Bearer resource_metadata="https://mcp.wrenapp.ai/.well-known/oauth-protected-resource/mcp", error="invalid_token", error_description="Link your Wren account", scope="notes.read notes.write profile.read"
content-type: application/json; charset=utf-8
{"jsonrpc":"2.0","error":{"code":-32001,"message":"Link your Wren account to continue."},"id":3}Discovery documents
curl -s https://mcp.wrenapp.ai/.well-known/oauth-protected-resource/mcp
curl -s https://mcp.wrenapp.ai/.well-known/oauth-authorization-serverProtected-resource metadata
{
"resource": "https://mcp.wrenapp.ai/mcp",
"authorization_servers": ["https://mcp.wrenapp.ai"],
"scopes_supported": ["notes.read", "notes.write", "profile.read"],
"bearer_methods_supported": ["header"]
}Authorization-server metadata
{
"issuer": "https://mcp.wrenapp.ai",
"authorization_endpoint": "https://mcp.wrenapp.ai/authorize",
"token_endpoint": "https://mcp.wrenapp.ai/token",
"jwks_uri": "https://mcp.wrenapp.ai/jwks",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["none"],
"scopes_supported": ["notes.read", "notes.write", "profile.read"],
"authorization_response_iss_parameter_supported": true,
"client_id_metadata_document_supported": true
}Scopes
profile.readRead the linked Wren account id and basic profile.
Used by: connect_account, get_profile
notes.readList notes and read a note and its pages.
Used by: list_notes, get_note
notes.writeCreate notes, add pages, edit Wren-written pages, rename notes.
Used by: render_note_preview, create_handwritten_note, add_page, edit_page, update_note
Request only the scopes you need. render_note_preview accepts a call with no token, or a token with notes.write.
Calling a tool with a token
curl -s https://mcp.wrenapp.ai/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-H "authorization: Bearer $WREN_ACCESS_TOKEN" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_notes","arguments":{"limit":5}}}'Next: the tool reference.
