Skip to main content
Status. Two MCP surfaces ship in @opendatalabs/personal-server-ts 1.16.0.
  • The owner’s own client path (OAuth, works with a stock MCP client such as Claude Desktop or Claude Code) runs on both the Node server and the in-browser PS Lite runtime.
  • The third-party app path — an app that holds its own key and signs its own handshake — runs on the Node Personal Server only. PS Lite does not serve POST /mcp/session.
  • Both surfaces are read-only. There are no write tools and no owner-management tools.
A Personal Server exposes an MCP server over streamable HTTP. A tool that serves scope contents resolves to the same read path as the HTTP API, behind the same grant check and the same access log. The grant is the ceiling on what any client can reach, and revoking it fails the client closed immediately. This is the integration path for an app whose consumer is an agent rather than a backend: the model discovers the user’s granted scopes, searches them, and pulls only the blocks it needs, instead of your code hard-coding a scope list.

Which surface you need

The rest of this page covers the third-party path. On the owner’s path the user points their own client at their Personal Server’s /mcp URL and approves scopes in Vana; your app is not part of that flow.

The third-party flow

You sign once to mint a session token, then connect with an unmodified MCP client. The key never leaves your backend — the Personal Server only ever recovers your address, at the handshake.

Prerequisites

Step 1 — Mint a session

The signed payload is the standard Personal Server request envelope — aud, method, uri, bodyHash, iat, exp — and must carry a grantId claim. It is signed EIP-191 by your app key. A bearer credential cannot open a session; the handshake exists to prove control of the key.
The handshake checks that the builder is registered, the grant exists and is not revoked, the grant’s grantee is the handshake signer, and the grant’s grantor is this server’s owner. Per-scope enforcement stays at read time, against the live grant — a grant revoked mid-session fails the next tool call.
Session tokens are held in memory, and the handshake proof is single-use. A Personal Server restart drops every live token; sign a fresh proof and re-handshake. Refresh as expires_in nears rather than waiting for a 401.

Step 2 — Connect a stock MCP client

Point any streamable-HTTP MCP transport at {personalServerUrl}/mcp with Authorization: Bearer <access_token>, then listTools() and callTool() as usual. The endpoint is stateless — there is no retained MCP session, only the auth token on each request.

The tool catalog

Every tool is grant-scoped: a scope your grant does not cover returns scope_not_granted and the list of scopes that are covered. request_scope_access cannot grant anything. It tells you what is missing and what to ask the user for; widening access is always a fresh approval in Vana.

Paying for reads

When the grant is priced, a chargeable read answers with an x402 challenge rather than data:
Sign the challenge’s GenericPayment message with your app key — the same EIP-712 settlement the HTTP read path uses — and call the tool again with the base64 X-PAYMENT payload in its payment argument. read_scope and get_scope_file both take it. Three behaviours to design around:
  • Search does not settle payments. search_personal_context is free discovery and preview. Chargeable scopes come back in paymentRequiredScopes; retrieve each through read_scope with a payment proof.
  • A 402 that will never clear is a different error. A genuine PAYMENT_REQUIRED carries a signable challenge. An empty escrow surfaces as payment_failed with no challenge — resolve the balance rather than signing in a loop.
  • Each cursor page and each retry is its own charge. There is no receipt cache today, so a paginated read of one scope settles once per page. Budget for it, or read with explicit blockIds.
Reads under the owner’s own OAuth connection are never charged: the payment path is built only for a self-signing session.

Limits

  • Read-only. Agent writes over MCP are not built. An app that needs to store a result writes it through the Write API instead, and an agent that should answer a question over data it may not read uses derivative data.
  • Node Personal Server only for the third-party path. The desktop app bundles the full Personal Server; the web app bundles PS Lite, which does not serve /mcp/session. Plan for your users to be on desktop, or check with the Vana team before committing to a launch that assumes otherwise.
  • The Personal Server must be reachable. A browser-hosted server is unreachable while the user’s Vana tab is closed. 503 also covers a server whose bounded-read or compute layer is not wired, so read the error code before deciding whether to retry.
  • Sessions do not survive a restart, and neither does the replay memory for handshake proofs.

Auditability

The properties that make a grant safe apply unchanged to an agent:
  • Consent is on-chain — which app may reach which scopes, until when
  • Each scope-content read is logged in the Personal Server’s access log, attributed to your registered address; the server separately records every MCP tool call in an activity feed the owner can review
  • Each chargeable read settles a fee, leaving an on-chain record per use
  • Revocation is immediate — revoke the grant and the next tool call fails, without touching the session