Passport MCP — for builders
A read-only Model Context Protocol server your agent reads inside a run — the user's identity, wallet balance and the current conversation's history. No sign-in to build: the session token arrives in the webhook.
#What's a Passport?
Every ONBF user carries an ONBF Passport — their identity, wallet and chat history (with memory, connected tools & files coming next), all in one place. It's how an agent can act *on a user's behalf* ("ONBF" reads aloud as *on behalf*) without you ever building sign-in, accounts or connectors yourself.
When a user opens your agent they already arrive *known*: a verified identity, a prepaid wallet to pay you, and — with their consent — the context your agent needs to be useful from the first message. The Passport MCP is your read-only window into the parts of that Passport a user has granted you.
Are you an end-user?: This page is the agent-/builder-facing reference. If you want to connect *your own* Passport to an external agent or MCP client, see Passport for users.
#Overview
The Passport MCP is a standard MCP server at https://onbf.ai/api/mcp speaking the Streamable HTTP transport (protocol revision 2025-03-26). You authenticate with a bearer token; the server advertises only the tools your token is entitled to.
| Field | Value |
|---|---|
| Endpoint | https://onbf.ai/api/mcp |
| Transport | Streamable HTTP (JSON responses) |
| Protocol | 2025-03-26 |
| Auth | Authorization: Bearer <token> |
| Methods | POST for JSON-RPC · GET for unauthenticated discovery |
| Rate limit | 120 requests / 60s per token |
#The session token
As a builder you almost never deal with tokens by hand. Every run ONBF dispatches to your webhook carries a session token (onbf_sess_…) in its mcp block — that's your key to the Passport for the duration of that run.
- Per-run & time-limited — it's minted for a single run and bound to one
{user, conversation, project}. It stays valid only for that run's reply window (reply.expiresInSeconds), then expires. - Zero setup — nothing for you or the user to configure; it's delivered to you in the
agent.run.createdpayload. - Conversation-aware — unlike a user's personal token, it can read the *current* conversation's history (the
conversation:readscope) so your agent answers in context.
Personal access tokens: Your end-users can also mint a long-lived personal token to connect their Passport to *any* agent or MCP client themselves. That flow lives on the Passport for users page — as a builder you don't issue or handle those.
#Scopes
Tools declare the scopes they need; a connection sees a tool only when its token holds every required scope (so it's never advertised, not just denied at call time). The in-run session token holds all three:
| Scope | Session token | User's personal token |
|---|---|---|
identity:read | ✓ | ✓ |
balance:read | ✓ | ✓ |
conversation:read | ✓ | — |
#Tools
| Tool | Returns | Requires |
|---|---|---|
get_identity | Display name, handle, bio, member-since date. | Any token |
get_balance | The user's current prepaid wallet balance. | Any token |
get_conversation_history | The transcript of the current conversation, so the agent can ground its reply. | Session token only |
Discovery & health check: There's no separate /healthz — an unauthenticated GET https://onbf.ai/api/mcp is your health/discovery endpoint. It returns server identity, the protocol revision and the public tool catalog (session-only tools are not advertised there).
#Reading conversation history inside a run
When ONBF dispatches a run to your webhook, the payload includes an mcp block with the session token. Use it to read the current conversation so your reply stays in context — no PAT, no user setup required:
// When a run arrives, the payload includes an `mcp` block with a
// per-run session token (time-limited to the run's reply window). Use it to
// also read the CURRENT conversation's history — so your agent answers in
// context. No PAT, no user setup: it's delivered to you in the webhook.
if (event.mcp) {
const res = await fetch(event.mcp.url, {
method: "POST",
headers: {
"content-type": "application/json",
"accept": "application/json, text/event-stream",
"authorization": `Bearer ${event.mcp.token}`,
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: { name: "get_conversation_history", arguments: {} },
}),
});
const history = await res.json();
}Where the mcp block comes from: It rides on the agent.run.created webhook alongside your reply token — see the inbound payload on the Your Webhook page.