MCP Access Model
The MCP gateway in AuthProxy lets AI assistants drive the platform. Because MCP sessions are programmatic and long-lived, they need a stricter access model than ordinary browser sessions.
This page describes — from an integrator's point of view — what each MCP login type is allowed to do, how delegation to a third-party app works, and how the sessionless capability mode fits in.
For the request/response shape, headers and JSON-RPC examples see the MCP Protocol reference.
Login types at a glance
| Login type | How the session is created | Proof of possession | Default access |
|---|---|---|---|
McpBasic | POST /auth/v1/mcp_login with X-PublicKey only | No (public key only) | Read-only on a curated subset of platform tools |
McpVerified | POST /auth/v1/mcp_login with X-PublicKey + signed X-Timestamp | Yes (Ed25519 signature) | Full personal access for the user behind the key |
McpApp | POST /auth/v1/mcp_login with X-PublicKey + X-App-Id | Yes, indirectly (key bound to an approved user_app) | Only the tools explicitly allowed for delegated apps, scoped to the app's own data |
| Capability mode | No mcp_login. POST /mcp?code=<capability_code> | Possession of the public code | Only tools published for that code family (chat invite or payment order) |
All three login types require:
- A
user_keyrow in the database for the public key. - The
McpAccessflag set on that key. - The user not being blocked.
McpApp additionally requires:
- The
user_appto exist and have theMcpEnabledflag set. - The signing key to belong to the app owner or to be the explicit
pubkeyregistered against thatuser_app.
Two layers of authorisation
Every tools/call (and resources/read) is checked twice before the underlying REST endpoint runs:
- Login-type policy.
The platform classifies each tool by which login types may call it:
- tools with proof of possession only (deny
McpBasic), - tools allowed for delegated apps (
McpApp-eligible), - capability-only tools (only callable from a capability code, never from a session).
- tools with proof of possession only (deny
- App scope (for
McpApponly). When the calling tool targets app-bound data (a payment order, app payments, app info), AuthProxy injects the session'sapp_idinto the request and rejects the call if the client tried to address a differentapp_id.
Both checks must pass. A McpVerified user cannot reach a capability-only tool by adding session headers; an McpApp session cannot bypass the curated read-only baseline by switching login type. Capability codes never see session-only tools.
What McpBasic can do
McpBasic is a low-friction bootstrap mode. It is meant for read-only AI helpers that surface the user's own data ("show my balance", "what did I send today?") without ever putting state at risk.
Allowed (typical):
- Read wallet info, balances, transaction history, transaction details, deposit addresses.
- Read chat threads, messages, friends, pinned messages, file metadata.
- Read public market data — rates, swap pairs, candles, asset metadata.
- Read public payment-order info via
payorder_info/payorder_terminals.
Denied:
- All write/state-changing tools (
*_create_*,*_internal_transfer,wallet_create_withdraw,market_create_swap,chat_send_message, etc.). - Security-sensitive read tools that expose authentication state:
sessions,login_log,user_keys,get_usr_apps,list_app_access. - Merchant payment history (
payorder_payments,payorder_payment,payorder_create).
This is intentional. McpBasic does not prove possession of the private key, so a leaked public key must not be enough to drain a wallet, send messages or enumerate authentication metadata.
If you need to perform any of the denied actions from an AI agent, upgrade the login flow to McpVerified.
What McpVerified can do
McpVerified is the standard mode for personal AI automation. The Ed25519 signature over a fresh timestamp proves that the agent currently holds the private key, so the gateway treats the session as fully equivalent to the user signing in interactively (with the small set of exceptions below).
It can call:
- Everything
McpBasiccan. - All write tools the user is normally entitled to: wallet transfers and withdrawals, market swaps and orders, chat sending and editing, room creation, app management, etc.
- Security-sensitive read tools (
sessions,login_log,user_keys, …).
It still cannot call:
- Capability-only tools — those are only reachable through capability mode.
- Tools that a module or a custom Core integration explicitly restricted to non-MCP login types.
Multi-step tools that require an OTP confirmation (for example wallet_internal_transfer, wallet_create_withdraw, market_create_swap) work the same way as in the PWA: the first call returns a confirmation pending state, the second call passes confirmationCode/confirmationTimetick to complete the operation.
What McpApp can do
McpApp is for third-party applications acting on behalf of a user — typically merchant integrations or external agents that the user delegated access to. The gateway treats it as a strict subset of the user's own permissions, narrowed even further to data that belongs to the calling app.
By default, McpApp sessions cannot call any platform tool — every tool is opt-in. The platform-level allow list is small and intentional:
| Allowed tool | Purpose |
|---|---|
get_app_info | Read the app's own registration record |
payorder_info | Read public payment-order info |
payorder_terminals | List payment methods for an order |
payorder_payments | List payments received by the app |
payorder_payment | Read a specific payment for the app |
payorder_create | Create a payment order on behalf of the app |
market_get_rates | Read market rates |
market_swap_info | Read swap pairs |
market_get_trade_info | Read order book |
get_candles | Read OHLC data |
assets | Read currency catalogue |
tokens_networks | Read networks for a currency |
Custom Core tools can also opt into McpApp by declaring "appScope": true in appsettings.json. New tools that do not declare it are automatically denied for McpApp — the safe default is "no access".
For tools whose endpoints take an app_id (or appId) argument, AuthProxy enforces that the value matches the session's app:
- If you omit it, AuthProxy fills in the session's own
app_idautomatically. - If you supply it explicitly, it must match the session's
app_id. Any other value is rejected with a forbidden error.
This guarantees one app cannot read or mutate another app's data, even with a shared user account.
Capability mode (sessionless access)
Capability mode lets AI assistants act on public, code-based flows that have no logged-in user — for example an anonymous customer landing on a payment page or a guest joining an invite-only chat.
There is no mcp_login and no session. Instead, every /mcp request carries a capability code:
- Query string:
?code=<capability_code>, headerX-MCP-Code, or argumentcodeinsideparams.arguments. - For chat-family codes, also a stable
device_guid(headerX-Device-Guid, querydevice_guidor argumentdevice_guid).
The gateway resolves the code to a module family:
| Code family | Tools/resources visible | Module identity propagated |
|---|---|---|
chat (anonymous invite) | chat_anon_* family — read messages, send messages, mark read, resolve attachments | X-Device-Guid |
wallet (payment order) | payment_* family — read public order info, pay by card / P2P / crypto, confirm crypto, cancel | None — scope is bound to the order code itself |
Capability mode never sees session-scoped tools. Equally, an MCP session never sees capability-only tools — the two are isolated.
What modules see (HTTP headers injected by AuthProxy)
When AuthProxy forwards an MCP call to the underlying module it injects the following headers, so module code can apply additional policy if needed without re-implementing auth:
| Header | When | Meaning |
|---|---|---|
X-Project | Always | Project numeric identifier |
X-Crm | Session mode | Authenticated CRM user id |
X-Scopes | Session mode | User scopes for the current login |
X-KeyType | Session mode | Numeric LoginMethod (so modules can branch on Mcp*) |
X-MCP-App-Id | McpApp only | App id for delegated calls |
X-Device-Guid | Capability chat | Device guid for anonymous identity |
Modules may decline operations on Mcp* login types — typically AML-relevant flows that require an interactive confirmation flow only available to browser sessions. This is by design.
MCP is not a browser session
A common integration mistake is reusing an MCP session for "any platform call". That breaks for several reasons:
mcp_logindoes not set the standardsidcookie used by the PWA — browsers cannot authenticate against the PWA with an MCP session.- Some module endpoints intentionally refuse to perform side-effecting browser-only operations on
Mcp*sessions (for example device-bound flows). - CORS and federation allowlists are evaluated against the calling app's
user_app, not against the MCP session.
When you need to test the PWA or reproduce a user-reported bug, use the challenge-response browser flow instead:
GET /auth/v1/login_options(with the standarddevice_guid,resolution,lang,tzoneheaders).- Sign the returned challenge with the user's Ed25519 key.
POST /auth/v1/loginwith the public key and signature; the response sets a browser-compatiblesidcookie.
For pure server-to-server testing of an inter-module API, prefer hitting the module directly with X-API-Key (private endpoints) or an X-Crm header in Local / Test environments. Both paths are documented per module.
Operator workflow
Operators manage MCP access from the AuthProxy admin panel:
| Page | Action |
|---|---|
/ProxyAdmin/UserKeys | Add or remove the McpAccess flag on a user key. Without it, mcp_login rejects the key. |
/ProxyAdmin/UserApps | Add or remove the McpEnabled flag on a registered app, and toggle the app's Approved flag. Disabling either immediately blocks new McpApp sessions for that app. |
/ProxyAdmin/McpMonitor | Inspect per-tool call counters and the most recent accepted / rejected MCP calls so drift between an integration's expected and actual behaviour is visible. |
/ProxyAdmin/Sessions | Close active MCP sessions on demand (Close session). |
Quotas (McpApiRPSLimit) are configured in the platform settings and apply per public key. A 429 response carries X-RateLimit and Retry-After headers — see MCP Protocol → Rate limits.
Choosing the right mode
| You are building… | Use |
|---|---|
| A personal AI assistant for a single end user | McpVerified |
| A read-only AI dashboard / "show me my data" agent | McpBasic is fine; switch to McpVerified the moment you need writes |
| A merchant or third-party AI integration that should not see foreign data | McpApp, with the operator approving the user_app |
| A public, code-driven page (anon chat, payment landing) | Capability mode (no mcp_login) |
Related
- MCP Protocol — request shape, JSON-RPC examples, custom tool configuration.
- Session Management — session lifecycle shared across browser and MCP clients.
- Authentication API — challenge-response browser login.