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:pingvalidate_gtinresolve_gtinlookup_productsearch_productsget_product_detailcompare_productscheck_availability
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:
-
First call without a token. The MCP client calls the tool
anonymously. Closient returns
403 Forbiddenwith this header: -
Client reads
resource_metadataand fetches the protected resource metadata document to learn the authorization server URL and supported scopes. - 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.
-
Retry with the token. The client retries
tools/call generate_qr_urlwithAuthorization: Bearer <token>. Closient validates the token, confirms theqr:generatescope, and dispatches the call.
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:- 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.
- Dynamic Client Registration (RFC 7591) — the client
POSTs to the authorization server’s/registerendpoint and receives aclient_id+client_secret. Useful for clients that want a stable identity but don’t have a public metadata URL. - 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.
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: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: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 structuredclosient.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
- Install the MCP Server
- Tool Reference
- MCP Error Contract
- MCP Identity Propagation
- Authentication (REST API) — API-key auth for the REST API, independent of MCP OAuth.
- RFC 9728 — OAuth 2.0 Protected Resource Metadata
- MCP Authorization spec (draft)