Skip to main content

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 typeHow the session is createdProof of possessionDefault access
McpBasicPOST /auth/v1/mcp_login with X-PublicKey onlyNo (public key only)Read-only on a curated subset of platform tools
McpVerifiedPOST /auth/v1/mcp_login with X-PublicKey + signed X-TimestampYes (Ed25519 signature)Full personal access for the user behind the key
McpAppPOST /auth/v1/mcp_login with X-PublicKey + X-App-IdYes, indirectly (key bound to an approved user_app)Only the tools explicitly allowed for delegated apps, scoped to the app's own data
Capability modeNo mcp_login. POST /mcp?code=<capability_code>Possession of the public codeOnly tools published for that code family (chat invite or payment order)

All three login types require:

  • A user_key row in the database for the public key.
  • The McpAccess flag set on that key.
  • The user not being blocked.

McpApp additionally requires:

  • The user_app to exist and have the McpEnabled flag set.
  • The signing key to belong to the app owner or to be the explicit pubkey registered against that user_app.

Two layers of authorisation

Every tools/call (and resources/read) is checked twice before the underlying REST endpoint runs:

  1. 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).
  2. App scope (for McpApp only). When the calling tool targets app-bound data (a payment order, app payments, app info), AuthProxy injects the session's app_id into the request and rejects the call if the client tried to address a different app_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 McpBasic can.
  • 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 toolPurpose
get_app_infoRead the app's own registration record
payorder_infoRead public payment-order info
payorder_terminalsList payment methods for an order
payorder_paymentsList payments received by the app
payorder_paymentRead a specific payment for the app
payorder_createCreate a payment order on behalf of the app
market_get_ratesRead market rates
market_swap_infoRead swap pairs
market_get_trade_infoRead order book
get_candlesRead OHLC data
assetsRead currency catalogue
tokens_networksRead 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_id automatically.
  • 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>, header X-MCP-Code, or argument code inside params.arguments.
  • For chat-family codes, also a stable device_guid (header X-Device-Guid, query device_guid or argument device_guid).

The gateway resolves the code to a module family:

Code familyTools/resources visibleModule identity propagated
chat (anonymous invite)chat_anon_* family — read messages, send messages, mark read, resolve attachmentsX-Device-Guid
wallet (payment order)payment_* family — read public order info, pay by card / P2P / crypto, confirm crypto, cancelNone — 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:

HeaderWhenMeaning
X-ProjectAlwaysProject numeric identifier
X-CrmSession modeAuthenticated CRM user id
X-ScopesSession modeUser scopes for the current login
X-KeyTypeSession modeNumeric LoginMethod (so modules can branch on Mcp*)
X-MCP-App-IdMcpApp onlyApp id for delegated calls
X-Device-GuidCapability chatDevice 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_login does not set the standard sid cookie 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:

  1. GET /auth/v1/login_options (with the standard device_guid, resolution, lang, tzone headers).
  2. Sign the returned challenge with the user's Ed25519 key.
  3. POST /auth/v1/login with the public key and signature; the response sets a browser-compatible sid cookie.

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:

PageAction
/ProxyAdmin/UserKeysAdd or remove the McpAccess flag on a user key. Without it, mcp_login rejects the key.
/ProxyAdmin/UserAppsAdd 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/McpMonitorInspect 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/SessionsClose 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 userMcpVerified
A read-only AI dashboard / "show me my data" agentMcpBasic is fine; switch to McpVerified the moment you need writes
A merchant or third-party AI integration that should not see foreign dataMcpApp, with the operator approving the user_app
A public, code-driven page (anon chat, payment landing)Capability mode (no mcp_login)