MCP
Connect agents to Tollbridge over stdio or Streamable HTTP — the tool catalog with x402 + prepaid-credit payment semantics.
Tollbridge ships an MCP server (apps/mcp over the transport-independent packages/mcp catalog)
whose twenty-seven tools are thin 1:1 proxies of the API surfaces — same data assembly, same
PRICING objects (zero price literals), zod-validated structured outputs only.
The tool catalog
| Tool | Proxied surface | Price key | Free/paid |
|---|---|---|---|
tollbridge_market_state | GET /v1/market/{asset} | — | FREE (open-data carve-out) |
tollbridge_liquidation_risk | GET /v1/market/{asset}/risk | signals.evaluate | PAID |
tollbridge_funding_opportunities | GET /v1/funding/opportunities | signals.evaluate | PAID |
tollbridge_wallet_intelligence | GET /v1/wallet/{chain}/{address} | wallet.profile | PAID |
tollbridge_transaction_risk | POST /v1/risk/transaction | risk.assess | PAID |
tollbridge_token_risk | POST /v1/risk/token | risk.assess | PAID |
tollbridge_decision | POST /v1/decisions | decision.deep | PAID |
tollbridge_pricing | GET /v1/pricing | — | FREE |
tollbridge_scout | POST /v1/billing/scout | — | FREE (first 3 entry-tier questions per payer address) |
tollbridge_get_decision | GET /v1/decisions/{decision_id} | — | FREE |
tollbridge_get_resolution | GET /v1/resolutions/{decision_id} | — | FREE |
tollbridge_lineage | GET /v1/lineage/{decision_id} | — | FREE |
tollbridge_calibration | GET /v1/calibration | — | FREE |
tollbridge_sheet | GET /v1/sheet | — | FREE |
tollbridge_blotter | GET /v1/blotter | — | FREE |
tollbridge_feed | GET /v1/feed | — | FREE |
tollbridge_open_clocks | GET /v1/clocks/open | — | FREE |
tollbridge_universe | GET /v1/universe | — | FREE |
tollbridge_wallet_state | GET /v1/wallet/{chain}/{address}/state | wallet.state | PAID |
tollbridge_call | POST /v1/calls | — | FREE (a calibration game — no wagering, no payout) |
tollbridge_calls | GET /v1/calls/scoreboard | — | FREE |
tollbridge_stand | POST /v1/standings | — | FREE registration (each run bills its question at settle time) |
tollbridge_stands | GET /v1/standings | — | FREE |
tollbridge_hook | POST /v1/hook-endpoints | billing.addon.hook | PAID add-on |
tollbridge_export | POST /v1/exports | billing.export.asset_period | PAID add-on |
tollbridge_get_intelligence | GET /v1/intelligence | — | FREE (the measured record) |
tollbridge_list_releases | GET /v1/intelligence/releases | — | FREE (the release feed — deltas and rejections) |
question_id for the deep decision takes any catalog signal (S01..S11) — see
Decisions. Its asset argument is any symbol tollbridge_universe lists
(not only BTC/ETH/SOL); an unknown or delisted symbol is a typed 404.
Agent first-run (step 0: Scout)
Before an agent can ask anything it needs a payer. tollbridge_scout grants the free
allowance — the first 3 entry-tier questions per payer address (1,000 credits each) — to a
Base address and returns the readable balance; no x402 facilitator required:
{
"jsonrpc": "2.0",
"id": 0,
"method": "tools/call",
"params": { "name": "tollbridge_scout", "arguments": { "payer": "0x957B4b908Fce18e44ECcB08331fcaf2BE7728510" } }
}It is idempotent: an address that already holds its free allowance answers granted: false with
the balance, never a second grant. The same allowance is served over HTTP at POST /v1/billing/scout.
Connect — Streamable HTTP (stateless)
/mcp is a stateless Streamable HTTP endpoint: each POST builds a fresh server, JSON responses
(no SSE stream), no session state. Discover it at GET /.well-known/mcp.json.
{
"mcpServers": {
"tollbridge": {
"type": "http",
"url": "https://api.tollbridge.app/mcp"
}
}
}The POST accept header must offer application/json, text/event-stream; malformed JSON
bodies are refused with a typed 400 (JSON-RPC -32700) before the transport sees them.
Connect — stdio
The same server runs over stdio for local agents:
{
"mcpServers": {
"tollbridge": {
"type": "stdio",
"command": "tollbridge-mcp",
"args": []
}
}
}All logs go to stderr (protocol cleanliness); --self-check runs the full server on fixture
seams with no env and no network. The production wiring uses the real provider stack and the
payments ledger, exactly like the HTTP server.
Payment semantics
- Unpaid call to a PAID tool → a
payment_requiredresult — a normal result, NOT an error: x402 v2 requirements built from PRICING (scheme/network/asset/amount-atomic/payTo) plus ahow_to_payblock. The challenge class structurally cannot carry data — a fabricated paid result is impossible. - Paid call → sign EIP-3009 (
transferWithAuthorization, USDC on Base) and embed the payload at_meta["tollbridge.dev/x402-payment"](or the base64PAYMENT-SIGNATUREHTTP header), then retry the SAME call. - Success →
okresult with the §I honesty meta and the settlement receipt atmeta.settlement. The payment is recorded before the handler runs; a failed handler never settles (authorization flow — the client is uncharged). - Failures →
PAYMENT_INVALID(bad signature/requirements mismatch),PAYMENT_REPLAYED(spent nonce), honestPROVIDER_DOWN/STALE_DATArefusals with typed envelopes.
Prepaid credits — agents on the same ledger as the site
A paid tool also settles on Scout credits — the exact ledger the web app uses. Pass payer
(your Base address) as a tool argument, or send x-tollbridge-payer: 0x<address> on the MCP HTTP
request. The call debits the balance at the PRICING-derived rate; a refusal reverses the debit
and returns the typed refusal — a refusal is the immune system, never a product, so it never
keeps the charge. An empty balance returns the payment_required challenge with
payment.reason: INSUFFICIENT_BALANCE, and you can always fall back to x402. There is no live
x402 facilitator registered on this deployment, so the credit rail is the working payer path.
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "tollbridge_decision",
"arguments": { "asset": "BTC", "chain": "base", "question_id": "S06_funding_anomaly" },
"_meta": {
"tollbridge.dev/x402-payment": "<base64 PaymentPayload>"
}
}
}Agent recipe (the honest loop)
The honest loop for a live question — scout first, never ask while a horizon is open:
-
Scout (FREE, first run) —
tools/call tollbridge_scout { "payer": "0x<base-address>" }(orPOST /v1/billing/scout) grants the one-time 200-credit Scout lot and returns the balance (idempotent). Read the full credit journal atGET /v1/billing/draws?payer=. -
Latest (FREE) —
GET /v1/decisions/latest?question_id=<question_id>&asset=<asset>: the current tile on that pair, or an explicit empty answer when none is on record. -
Resolution (FREE) —
GET /v1/resolutions/<decision_id>: either a terminal outcome (realized/obtains/not/unresolvable+ the predicted/realized sentence) or{ "status": "pending", "horizon_end": "…" }. -
Ask — only when the latest resolution is terminal and the question is available. The available set is DERIVED (the resolution-evaluator registry ∧ the emit gates), never a hand list — read
tollbridge_sheet(orGET /v1/signals) for the authoritative set:{ "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "tollbridge_decision", "arguments": { "question_id": "S06_funding_anomaly", "asset": "BTC", "payer": "0x<your-base-address>" } } }The same ask over HTTP is
POST /v1/decisionswith the same body and thex-tollbridge-payerheader. The call debits your prepaid Scout credits; a refusal reverses the debit and returns the typed refusal (out_of_scope/stale_input/insufficient_sample). -
Else wait — do NOT ask while the horizon is open. Sleep until
horizon_end, re-read step 2, and ask only once it is terminal. The blocked questions (S02/S03/S04 — no market-wide liquidation tape on record yet) refuse + refund by design and are off the default rail. Readtollbridge_sheetfor the derived available/blocked sets rather than trusting any static list.
The same object is served on HTTP and MCP: a resolution, a ledger tile and a tool result never disagree.
Honesty laws (carried over from the API)
tollbridge_market_stateis free — it never consults the payment gate.- Every
okresult carries the EXPLICIT §I meta:request_id,timestamp,state,probabilities,confidence(null on raw data),freshness,horizon(null on raw data),data_sources,methodology_version,pricing(null on free),settlement(null until settled). - The funding-opportunities assumptions ship verbatim with
economics_modeled: "none"; the response states "This response is not a profit claim or execution advice". - Refusals (
stale_input/insufficient_confidence/suppress) are honest decisions, never made-up numbers.