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

  1. Call a protected tool with no token. The server answers HTTP 401 with a WWW-Authenticate: Bearer header that carries resource_metadata. Clients that follow the MCP authorization spec start sign-in from this response.
  2. Fetch the protected-resource metadata. The URL from resource_metadata names the authorization server and the supported scopes.
  3. Fetch the authorization-server metadata. It lists the authorize, token and JWKS endpoints, and the PKCE and grant types the server accepts.
  4. Identify the client. The server advertises client_id_metadata_document_supported: true and no registration endpoint. Use an HTTPS client_id URL that serves your Client ID Metadata Document; dynamic client registration is not offered.
  5. 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.
  6. 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 the refresh_token grant.
  7. 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:

Response
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

Terminal
curl -s https://mcp.wrenapp.ai/.well-known/oauth-protected-resource/mcp
curl -s https://mcp.wrenapp.ai/.well-known/oauth-authorization-server

Protected-resource metadata

https://mcp.wrenapp.ai/.well-known/oauth-protected-resource/mcp
{
  "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

https://mcp.wrenapp.ai/.well-known/oauth-authorization-server
{
  "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

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

Terminal
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.