Authentication
PlaceOptimizer has two MCP surfaces with two different trust models. Which one applies depends on which endpoint you call.
| Surface | URL | Auth |
|---|---|---|
| Public endpoint | https://app.placeoptimizer.com/mcp | None for discovery + 3 public tools; OAuth 2.1 Bearer JWT for all 8 tools |
| Console-internal | https://app.placeoptimizer.com/api/v1/mcp | PlaceOptimizer session (active org, member role) |
Public endpoint — OAuth-protected (/mcp)
https://app.placeoptimizer.com/mcp is the dual-auth discovery surface.
Its discovery methods (server/discover, initialize, tools/list, …) and
three read-only tools (ping_console, get_audit_overview,
get_public_endpoints) are served to any caller with no authentication.
A valid OAuth 2.1 Bearer JWT unlocks the five tenant tools
(list_locations, get_location_metrics, list_location_reviews,
list_location_posts, get_org_info) on the same endpoint.
A tenant tool call without a valid token is rejected with 401
Unauthorized and a WWW-Authenticate: Bearer resource_metadata=… challenge
pointing at the RFC 9728 protected-resource metadata — which is how an MCP
client learns where to authenticate. See
Available Tools for what each surface exposes.
Console-internal endpoint — session (/api/v1/mcp)
https://app.placeoptimizer.com/api/v1/mcp is the console-internal path used
by the operator console itself. It sits under /api/v1, so the console's
session guard runs first: the request must carry a valid PlaceOptimizer
session cookie, belong to a user with an active organization, and the
user must hold at least the member role. Third-party connectors do not
use this path — they authenticate to /mcp through the OAuth flow below.
The OAuth 2.1 flow
Third-party clients (Claude, ChatGPT, Cursor, CLI tools) authenticate to
/mcp with a standard OAuth 2.1 / OIDC authorization server run by the
console. The flow is live and fully automatic from the client's perspective:
- Discovery. The client fetches the RFC 9728 protected-resource metadata
at
https://app.placeoptimizer.com/.well-known/oauth-protected-resource, which points it at the authorization-server metadata athttps://app.placeoptimizer.com/.well-known/oauth-authorization-server(issuerhttps://app.placeoptimizer.com/api/v1/auth). - Dynamic client registration (DCR). Public clients register themselves per RFC 7591 at the registration endpoint — no developer portal, no pre-shared secret.
- Authorization + consent. The client opens a browser window to the
PlaceOptimizer sign-in (
/login) and consent (/consent) pages, where you approve the requested scopes. PKCE (RFC 7636) is required. - Token. The client exchanges the authorization code for a short-lived
EdDSA JWT access token with audience
https://app.placeoptimizer.com/mcp(the RFC 8707 resource indicator) plus a refresh token. - Bearer on
/mcp. The client sends the token asAuthorization: Bearer <token>. The resource server verifies the signature against the public JWKS at/api/v1/auth/jwksand enforces the issuer and audience strictly; a verified token unlocks all eight tools.
Scopes
The consent screen and the server's scope allow-list cover five scopes:
| Scope | What it grants |
|---|---|
openid | Verify your PlaceOptimizer account identity |
profile | Read your name and avatar |
email | Read your email address |
offline_access | Stay connected while you are away (refresh token) |
placeoptimizer | Read your locations, metrics, reviews and posts |
Only the scopes you approve are granted, and the access token carries exactly the granted set.
Device flow
CLI-style clients that cannot open a browser use the RFC 8628 device flow. The client asks the authorization server for a device code, shows you a verification URL and code, and polls for its token. On PlaceOptimizer:
- Enter the code at
https://app.placeoptimizer.com/device(/device?user_code=ABCD-1234pre-fills it for one-click flows). - Approve (or deny) the request at the device-approval page
(
/device/approve). - The code expires after 15 minutes; the client polls every 5 seconds.
Refreshing tokens
Because the flow includes offline_access, every grant issues a refresh
token alongside the short-lived access token. The client refreshes
automatically — the access token is renewed without another consent screen.
No action is needed from you until you revoke the grant.
Revoking access
- OAuth grants: open Settings → Connected apps in the console. It lists every app you have granted access to; revoking an app there revokes the grant and invalidates its refresh and access tokens — the app's next tool call returns 401 until it re-authorizes.
- Console session: sign out, or revoke the active session from Settings → Devices.
- Google connection: if you want PlaceOptimizer to stop reading your GBP data, disconnect the Google account from Settings → Google Account.
Next steps
- Troubleshooting — 401s, consent loops, and audience errors
- Setup — connect a client, step by step