Skip to main content
The Closient MCP server is an OAuth 2.1 resource server, classified per RFC 9728 (Protected Resource Metadata) and the MCP Authorization spec. Most tools are public — no token, no setup, frictionless adoption for AI agents discovering Closient through tools/list. A smaller set of tools is gated behind a scoped OAuth token: generate_qr_url (touches the paid QR-generation pipeline) and the brand-owner product write tools added in C-4038 (create/edit products, images, documents, videos, nutrition, ingredients — see Tool Reference). The pattern is extensible: future protected tools join the same step-up flow.

Two roles, two endpoints

Closient acts as both authorization server and resource server in this stack: The two discovery endpoints conform to RFC 8414 (authorization server metadata) and RFC 9728 (protected resource metadata) respectively. Compliant MCP clients fetch them automatically — you do not need to configure URLs by hand.

Public tools — no token

These tools accept anonymous calls. No header, no setup:
  • ping
  • validate_gtin
  • resolve_gtin
  • lookup_product
  • search_products
  • get_product_detail
  • compare_products
  • check_availability
If you pass a valid token alongside one of these calls, Closient records the authenticated principal in the audit log (see MCP Identity Propagation) but the call behaves identically. This is forward-compat plumbing for future features like “authenticated tier: higher rate limit.”

Protected tools — step-up flow

generate_qr_url requires a bearer token with the qr:generate scope; the product write tools require products:write or dashboard:write depending on which tool (see Scopes below). The step-up flow is what makes the user experience smooth: the client doesn’t have to authenticate up front, only when it actually tries to use a protected tool. The product write tools carry one additional requirement beyond scope: they need an end-user token — one minted via the authorization_code grant, where a real person approved the consent screen. A client_credentials token (an agent acting on its own behalf with no consenting end user) is rejected even with the right scope, because every write is attributed to a specific brand- owner user in the audit trail. generate_qr_url has no such restriction. Step by step:
  1. First call without a token. The MCP client calls the tool anonymously. Closient returns 403 Forbidden with this header:
  2. Client reads resource_metadata and fetches the protected resource metadata document to learn the authorization server URL and supported scopes.
  3. Authorization flow. The client opens the consent screen in the user’s browser (using PKCE per the OAuth 2.1 spec), the user approves, and the client exchanges the authorization code for an access token + refresh token.
  4. Retry with the token. The client retries tools/call generate_qr_url with Authorization: Bearer <token>. Closient validates the token, confirms the qr:generate scope, and dispatches the call.
The whole flow happens transparently in Tier 1 MCP clients (Claude Desktop, Cursor, VS Code) — the user sees a single consent prompt and then the tool just works.

Scopes

MCP-protected tools use three scopes today. products:write and dashboard:write are the same per-app :write scopes REST-API callers use (APP_API_REGISTRY) — no MCP-specific scope machinery was needed to add the C-4038 write tools, only new tool registrations against existing scopes. Future protected tools will register additional scopes following the same domain:action convention. REST-API scopes (accounts:read, products:read, etc.) are independent of MCP in the sense that holding one does not by itself authenticate an MCP call — but products:write and dashboard:write are literally the same scope strings the REST API’s OAuth-authenticated endpoints check, so a token minted for one surface works on the other’s write tools/endpoints for the same permission.

Token lifetimes

When an access token expires, the MCP client uses the refresh token to mint a new one without prompting the user. Expired refresh tokens require the user to consent again.

Client registration

The MCP spec (Nov 2025 revision) supports three registration paths. All work against Closient:
  1. Client ID Metadata Documents (CIMD) — preferred. The client advertises its metadata at a public URL; Closient fetches it on first contact. No upfront registration required.
  2. Dynamic Client Registration (RFC 7591) — the client POSTs to the authorization server’s /register endpoint and receives a client_id + client_secret. Useful for clients that want a stable identity but don’t have a public metadata URL.
  3. Pre-registration — for known clients like Claude Desktop and VS Code, Closient maintains pre-registered application records. No action on your part; the client uses its built-in client_id.
Tier 1 MCP clients pick the right registration path automatically.

Manual token minting

For local development, scripted integrations, or MCP clients that don’t implement the OAuth flow, you can mint a token by hand:
Then call the protected tool with Authorization: Bearer <access_token>.

Verifying scope coverage

A quick way to sanity-check that a token has the right scope before calling a protected tool:
A successful response confirms the token holds qr:generate. A 403 with error="insufficient_scope" means the token is valid but missing the scope — re-run the consent flow and accept the qr:generate request.

Audit & identity

Every tool call (public or protected) emits one structured closient.mcp.audit log line with the agent’s client_id and (for authorization_code tokens) the consenting end user. See MCP Identity Propagation for the full audit schema and the get_current_end_user() accessor for tool authors. For protected tools, @user_action on the underlying service-layer function (e.g. apps.products.services.qr_url.build_digital_link_url) also records a durable database audit row — the answer to “who generated this QR code?” is queryable forever from the audit_events table.

See also