An MCP host hands your agent tools that can charge real money. A per-transaction cap does not help much: twelve $399 tool calls under a $500 cap still clear $4,788, because each approval has no memory of the last — and a cleared charge is not proof the work happened.
Paybond ships a tenant-bound MCP server that closes that gap. It binds delegated spend to a signed intent, releases or refunds against submitted completion evidence, and returns a receipt finance can replay — while preserving the same tenant boundary as the SDKs and APIs. Use it for internal agent runtimes and orchestration systems that prefer MCP over custom HTTP wrappers.
First-class adapter surface. MCP hosts are a supported framework integration path alongside in-process adapters — see Agent middleware, Coding-agent setup, and the Kit support matrix.
For coding-agent setup, including Codex and generic stdio MCP snippets using npx -y -p @paybond/kit paybond-mcp-server, start with Coding-agent setup.
For a first guardrail integration outside MCP, start with the sandbox scaffold:
npx -p @paybond/kit paybond-init \ --preset paid-tool-guard \ --framework provider-agnostic \ --out paybond-paid-tool-guard.ts paybond-kit-init \ --preset paid-tool-guard \ --framework provider-agnostic \ --out paybond_paid_tool_guard.py
For MCP-native hosts, the matching sandbox tools are paybond_bootstrap_sandbox_guardrail and paybond_submit_sandbox_guardrail_evidence.
The server is stdio-first by default — most desktop hosts launch it as a local child process. Hosts that need a network URL instead can use the hosted Streamable HTTP endpoint or self-host the same HTTP transport; see Remote HTTP (Streamable HTTP) below.
Paybond does not assume a specific model provider or agent framework. The only assumption is that your host can speak MCP tool calls, either over stdio or Streamable HTTP.
Install
Install
npm install @paybond/mcpImport from @paybond/mcp
import { createPaybondMcpToolSurface } from "@paybond/mcp";- Equivalent subpath on the core package: `@paybond/kit/mcp` — use `@paybond/kit` when you need multiple adapters in one app.
- For stdio MCP hosts, launch npx -y -p @paybond/kit paybond-mcp-server — see Coding-agent setup in the docs.
- Python: `paybond agent demo mcp smoke` requires the optional `mcp` extra. Use `pip install "paybond-kit[mcp]"`, `pipx install 'paybond-kit[mcp]'`, or `pipx inject paybond-kit mcp` (when base paybond-kit is already installed).
- Smoke: `paybond agent demo mcp smoke --operation paid-tool --requested-spend-cents 100 --evidence-preset cost_and_completion --format json` (in-process MCP).
Required environment
Always required. For sandbox setup, use one of the login CLIs first:
npx -p @paybond/kit paybond login paybond-kit-login
The CLIs write PAYBOND_API_KEY to .env.local; the packaged MCP servers load .env.local by default when PAYBOND_API_KEY is not already present. Set PAYBOND_ENV_FILE for a different local secrets file, or pass PAYBOND_API_KEY in the MCP host launch environment. Production keys are created in Console and stored in deployment secret managers.
Restricted MCP keys (recommended for hosts)
For Cursor, Claude Desktop, Codex, and other MCP hosts, prefer a restricted key (paybond_rk_*) over a standard service-account key (paybond_sk_*). Restricted keys carry an explicit MCP scope grant; tools/list and tools/call expose only the tools those scopes unlock, and the gateway enforces the same scopes on the underlying routes. Standard keys keep role-based RBAC and optional PAYBOND_MCP_TOOL_POLICY for local dev.
Create one from Console (Machine access → API keys → Restricted MCP key) or the CLI:
paybond keys create \ --name cursor-discovery \ --role analyst \ --kind restricted \ --preset mcp-readonly \ --label cursor-discovery
Presets (settlement / live-money write is never included — add --scope mcp.settlement:write only when you intentionally need fund/confirm):
| Preset | Scopes |
|---|---|
mcp-readonly | discovery, signal, compliance, receipts (read) |
mcp-spend-operator | readonly + spend + evidence (write) |
mcp-sandbox-agent | discovery + sandbox + spend (write) |
List the catalog (offline):
paybond mcp scopes list paybond mcp scopes list --format json
When mcp install detects a restricted key in the env file, it omits PAYBOND_MCP_TOOL_POLICY from the generated host config — scopes come from the key. Pairing --tool-policy / --tool-allowlist with a restricted key is rejected.
Optional:
export PAYBOND_PRINCIPAL_PATH="/v1/auth/principal" export PAYBOND_MCP_MAX_RETRIES="3" export PAYBOND_MCP_EVIDENCE_POLICY="strict" export PAYBOND_ENV_FILE=".env.local"
PAYBOND_MCP_EVIDENCE_POLICY defaults to strict. In strict mode, evidence submit tools refuse calls until paybond_validate_completion_evidence succeeds for the same preset and payload. Set off only for local debugging. Harbor predicate and schema validation remain authoritative at submit time.
Optional policy hot-reload for long-lived MCP processes:
export PAYBOND_POLICY_FILE="./paybond.policy.yaml" export PAYBOND_POLICY_RELOAD="watch" # watch | poll | off (default off) export PAYBOND_POLICY_RELOAD_ALLOW_LOOSEN="0"
When PAYBOND_POLICY_FILE is set, paybond_authorize_agent_spend and paybond_verify_capability enforce the policy registry before Harbor verification. Spend caps resolve from the policy file when requested_spend_cents is omitted. Reload waits for in-flight MCP tool calls to finish before swapping the registry; failed reloads keep the previous snapshot. Use poll with tenant overlay policies to refresh effective policy from the Gateway.
Run
Python
paybond-mcp-server
TypeScript
npx paybond-mcp-server
Remote HTTP (Streamable HTTP)
Stdio remains the default for desktop hosts (Cursor, Claude Desktop, Codex CLI). For hosts that need a network URL instead of a local subprocess — remote agent runtimes, MCP Inspector's HTTP mode, or any orchestrator that cannot launch child processes — Paybond also runs the same tool surface over Streamable HTTP, MCP's current remote transport (a single POST /mcp with a JSON response; no legacy HTTP+SSE).
Hosted endpoint: https://mcp.paybond.ai/mcp
curl https://mcp.paybond.ai/mcp \ -X POST \ -H "content-type: application/json" \ -H "authorization: Bearer $PAYBOND_API_KEY" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Every request supplies its own service-account or restricted MCP key as Authorization: Bearer paybond_sk_... or Bearer paybond_rk_... — the hosted endpoint is multi-tenant and stateless: tenant scope comes from the key alone (never from a client-supplied tenant_id), and each request is handled independently with nothing cached or shared across callers. Restricted keys filter the tool surface per request from principal.mcp_scopes. Because there is no per-connection session, always pass capability_token explicitly to paybond_authorize_agent_spend / paybond_verify_capability rather than relying on the token being remembered from an earlier call in the same process (that convenience only applies to a single long-lived stdio session).
Example MCP client config for an HTTP-capable host (prefer a restricted key in production):
{ "url": "https://mcp.paybond.ai/mcp", "headers": { "Authorization": "Bearer paybond_rk_sandbox_..." } }
Self-hosting the same contract: both Kit CLIs can run the identical Bearer/Origin//healthz contract locally instead of depending on the hosted endpoint:
# TypeScript npx paybond-kit mcp serve --transport http # Python (requires the optional `mcp` extra: pip install "paybond-kit[mcp]") paybond-kit mcp serve --transport http
The Python CLI binds to one tenant for the life of the process: set PAYBOND_API_KEY in the process environment and every incoming Bearer token is checked against that single key (a shared-secret gate on network access, not a way to serve multiple tenants from one process). The TypeScript CLI is multi-tenant like the hosted endpoint — it derives tenant scope per request from whatever key the caller presents. Both accept the same PAYBOND_MCP_HTTP_* environment variables:
export PAYBOND_MCP_HTTP_ADDR="0.0.0.0:8080" # default export PAYBOND_MCP_HTTP_ALLOWED_ORIGINS="https://example.com" # comma-separated; only enforced when a client sends an Origin header export PAYBOND_MCP_HTTP_MAX_BODY_BYTES="1048576" # 1 MiB default export PAYBOND_MCP_HTTP_RATE_LIMIT_PER_MINUTE="120" # per authenticated API key export PAYBOND_MCP_HTTP_RATE_LIMIT_UNAUTH_PER_MINUTE="30" # per source IP, slows credential scanning
GET /healthz returns 200 without auth for load-balancer and container health checks. PAYBOND_POLICY_RELOAD=watch|poll (policy hot reload) is rejected at HTTP startup — it depends on one long-lived process instance and is only supported for stdio; use PAYBOND_POLICY_RELOAD=off (the default) or omit it entirely when running HTTP.
Tool categories
Read-only discovery and compliance (allowed under --tool-policy readonly):
paybond_get_principalpaybond_list_intentspaybond_get_intentpaybond_list_audit_exportspaybond_get_audit_exportpaybond_get_reputation_receiptpaybond_get_portfolio_summarypaybond_get_signed_portfolio_artifactpaybond_get_fraud_assessmentpaybond_get_fraud_metricspaybond_get_a2a_agent_cardpaybond_list_a2a_task_contractspaybond_get_a2a_task_contractpaybond_verify_agent_mandate_v1paybond_verify_agent_recognition_proof_v1paybond_get_settlement_receipt_v1paybond_verify_protocol_receipt_v1paybond_get_agent_receipt_v1paybond_verify_agent_receipt_v1paybond_validate_completion_evidencepaybond_get_budget_remainingpaybond_explain_policy
Spend and mutation tools (default --tool-policy spend-write; live-money tools such as paybond_fund_intent and paybond_confirm_settlement stay blocked unless explicitly allowlisted):
paybond_verify_capabilitypaybond_authorize_agent_spendpaybond_bootstrap_sandbox_guardrailpaybond_submit_sandbox_guardrail_evidencepaybond_import_agent_mandate_v1paybond_create_intentpaybond_create_spend_intentpaybond_fund_intentpaybond_submit_evidencepaybond_submit_spend_evidencepaybond_confirm_settlement
For production hosts, mint a restricted key (see Restricted MCP keys) so the credential itself limits the tool surface. For local standard-key installs, a readonly env policy still works:
# Preferred (scopes on the key) paybond keys create --name cursor --role analyst --kind restricted --preset mcp-readonly paybond mcp install --host generic --scope project # Local standard-key override (dev only) paybond mcp install --host generic --scope project --tool-policy readonly
Local audit bundle verification (paybond audit exports verify <path> or paybond.audit.exports.verify(...)) is SDK/CLI only. MCP hosts cannot verify downloaded ZIP paths on disk. Compliance bundles that include agent_receipts may also contain PEF companion files (*.pef.json) alongside each signed receipt.
The spend-named tools are aliases over the same tenant-bound Harbor and Gateway routes. They exist so agent hosts can match user requests like "control agent spend", "add tool-call spend limits", or "authorize paid vendor actions" without guessing from lower-level capability names.
paybond_get_budget_remaining and paybond_explain_policy call the side-effect-free gateway route POST /v1/spend/preflight. They evaluate the same spend-control policy as authorize without creating decisions, reservations, or approval requests. Use them before paybond_authorize_agent_spend when an agent needs remaining budget or a human-readable allow / approval_required / deny explanation. Matching CLI commands: paybond spend budget-remaining and paybond spend explain-policy.
paybond_verify_protocol_receipt_v1 is a read-only offline verify of a signed protocol-v2 authorization or settlement receipt (POST /protocol/v2/receipts/verify). Pass the full receipt object (not a receipt_id). Use paybond_verify_agent_mandate_v1 for mandate envelopes and paybond_verify_capability / paybond_authorize_agent_spend for Harbor capability gates. Fetch a settlement receipt first with paybond_get_settlement_receipt_v1 when you only have an intent UUID.
paybond_get_agent_receipt_v1 fetches a signed paybond.agent_receipt_v1 by receipt_id (tenant-bound GET /protocol/v2/agent-receipts/{receipt_id}). paybond_verify_agent_receipt_v1 runs the same offline operational-tier signature check as resources/read on paybond://receipt/{receipt_id}; pass optional validity_tier=primary|attested when you need a stronger bar. Continuity-chain, inclusion proofs, owner disclosure, and ACTA/PEF/SCITT adapters remain Kit TypeScript/Python and CLI/Gateway auditor surfaces—not MCP’s full job.
paybond_get_principal returns the tenant-bound service-account principal for the configured PAYBOND_API_KEY (tenant_id, subject, roles) via a read-only gateway GET. Use it when you need to confirm auth identity; call early as a prerequisite before intent lifecycle calls, Signal reads, or other tenant-scoped tools when tenant identity is unknown. Not required before every later call once tenant_id is already known. Do not use it when you need intent detail—use paybond_get_intent instead when you have an intent_id. Do not use it for A2A discovery—use paybond_get_a2a_agent_card instead.
paybond_get_portfolio_summary returns a tenant-scoped Signal aggregate (counts, average score, volume, operators under review). Omit score_version to use the gateway default (1.0). Prefer paybond_get_signed_portfolio_artifact when you need a portable signed operator list for partner or verifier sharing, and paybond_get_reputation_receipt for one operator.
paybond_get_signed_portfolio_artifact returns a tenant-scoped signed Signal portfolio snapshot (operator list plus Ed25519 signing material) for offline verifier checks or partner sharing. Omit score_version to use the gateway default (1.0). Prefer paybond_get_portfolio_summary for unsigned aggregates, paybond_get_reputation_receipt for one operator, and paybond_get_fraud_assessment for fraud review posture.
paybond_get_fraud_metrics returns tenant-wide fraud backtesting metrics for a rolling window (24h default, or 7d / 30d). Unsupported windows fail with HTTP 400. Use paybond_get_fraud_assessment when you need one operator's fraud posture instead of tenant aggregates.
paybond_get_reputation_receipt fetches the signed Signal reputation receipt for one operator DID (GET /reputation/{operator_did}). Omit score_version to use the gateway default (1.0). Returns null when no receipt exists. Prefer paybond_get_portfolio_summary for tenant aggregates, paybond_get_signed_portfolio_artifact for a portable signed operator list, and paybond_get_fraud_assessment for fraud review posture.
The sandbox guardrail tools are separate developer-only helpers. They call /v1/sandbox/guardrails/..., derive tenant scope from the configured service-account API key, and do not replace the production Harbor create/fund/evidence tools.
Typical spend flow
- Call
paybond_create_spend_intentto create the signed spend intent. - If the intent is not funded immediately, call
paybond_fund_intent. - Optionally call
paybond_get_budget_remainingorpaybond_explain_policyfor a read-only preflight of remaining budget and policy outcome. - Use the returned
intent_idandcapability_tokenwithpaybond_authorize_agent_spendbefore any paid API call, vendor action, settlement step, or other side-effecting tool. - Call
paybond_validate_completion_evidencewith the completion preset and payload you plan to submit. - After the guarded work completes, call
paybond_submit_spend_evidencewith the same preset and payload.
If you are writing SDK code instead of exposing MCP tools, use paybond.spendGuard(intentId, capabilityToken) in TypeScript or paybond.spend_guard(intent_id, capability_token) in Python. PaybondCapabilityBinding is only needed for Python framework adapters that require a run-context object.
Sandbox guardrail smoke flow
- Call
paybond_bootstrap_sandbox_guardrailwith an operation and sandbox spend amount. - Use the returned
intent_idandcapability_tokenwithpaybond_authorize_agent_spendbefore the sample paid tool executes. - Call
paybond_validate_completion_evidencewhen using a completion preset (for exampleapi_response_ok). - Call
paybond_submit_sandbox_guardrail_evidencewith the sandboxintent_id,completion_preset_id, and evidence payload.
Bundled smoke command
Validate the MCP authorize and evidence path without launching a stdio subprocess or an LLM:
paybond agent demo mcp smoke \ --operation paid-tool \ --requested-spend-cents 100 \ --evidence-preset cost_and_completion \ --format json
The smoke uses in-process PaybondMCPServer.callTool() (TypeScript) or build_mcp_server().call_tool() (Python): sandbox bind, paybond_authorize_agent_spend, mock side-effect completion, and paybond_submit_sandbox_guardrail_evidence. Python requires the optional mcp extra (pip install "paybond-kit[mcp]").
Security model
- The server is bound to one tenant derived from the configured service-account API key.
- Do not pass tenant IDs manually through tool arguments for normal flows.
- Gateway-backed state-changing tools require the right proof material and fail closed when proofs are missing, stale, replayed, or mismatched.
- Signed Harbor request bodies remain the caller's responsibility. The MCP server does not manage long-lived signing keys on behalf of the model.
- The hosted HTTP endpoint (
https://mcp.paybond.ai/mcp) accepts:- Restricted keys (
paybond_rk_*) — preferred for agents and automation; scopes on the key are the permission model. - Standard keys (
paybond_sk_*) — full role entitlements; use only when you intentionally want an unrestricted machine credential. - MCP OAuth access tokens (
paybond_oat_*) — user-scoped grants from the Console consent flow for interactive hosts (Cursor, Claude, VS Code). Short-lived; refresh withpaybond_ort_*viaPOST /v1/oauth/token.
- Restricted keys (
- Prefer a sandbox restricted key for testing; for production hosts mint a restricted key with the minimum MCP scopes in Console, or use OAuth consent for interactive hosts.
Check which credential a host config will actually use:
paybond doctor --mcp --host claude
--mcp fails when the config resolves to an unrestricted paybond_sk_* key (the gateway cannot cap its MCP surface) and again when that key is not even narrowed by PAYBOND_MCP_TOOL_POLICY. Pass --config <path> to grade an on-disk host config instead of the one paybond mcp install would generate.
MCP OAuth (interactive hosts)
Interactive MCP hosts can obtain a scoped bearer without embedding a long-lived API key:
- Host redirects the browser to
GET /v1/oauth/authorize(PKCE S256,response_type=code). - Console opens
/console/authorize/mcp?request=…for a humantenant_admin. - Admin reviews requested scopes / visible tools, optionally narrows the grant, and approves (live
mcp.settlement:writerequires MFA step-up). - Host redeems the code at
POST /v1/oauth/tokenand callshttps://mcp.paybond.ai/mcpwithAuthorization: Bearer paybond_oat_….
Tenant admins manage the per-environment MCP kill switch, active OAuth sessions, and custom redirect URIs under Console → Machine access → MCP access. Disabling MCP blocks new grants and rejects existing paybond_oat_* bearers for that environment.
Example MCP client config
Example local stdio entry using the default .env.local written by paybond login:
{ "command": "npx", "args": ["-y", "-p", "@paybond/kit", "paybond-mcp-server"], "env": { "PAYBOND_ENV_FILE": ".env.local" } }
Advanced direct-key entry for hosts that cannot read env files:
{ "command": "npx", "args": ["-y", "-p", "@paybond/kit", "paybond-mcp-server"], "env": { "PAYBOND_API_KEY": "paybond_sk_sandbox_..." } }
Agent receipt resources (MCP)
MCP’s ARS role is agent-to-agent receipt handoff via the resource URI paybond://receipt/{receipt_id}—hosts pass the URI between agents without embedding full JSON in prompts.
| Item | Value |
|---|---|
| URI template | paybond://receipt/{receipt_id} |
| MIME type | application/json |
| Source | Tenant-bound GET /protocol/v2/agent-receipts/{receipt_id} |
| Verify on read | Operational-tier signature check (schema, digest, Gateway Ed25519) |
TypeScript and Python stdio servers:
resources/templates/list— publishes thepaybond://receipt/{receipt_id}templateresources/read— fetches the signedpaybond.agent_receipt_v1JSON and verifies at the operational tier before returning; verification failure returns a clear error (contents are not handed off unsigned)
Readonly tools (same surface as settlement-receipt tools):
paybond_get_agent_receipt_v1— fetch byreceipt_idpaybond_verify_agent_receipt_v1— offline verify of a receipt object; optionalvalidity_tier(operationaldefault, orprimary/attested)
Validity tiers beyond a quick handoff check, continuity-chain audits, Merkle inclusion / tree-head proofs, confidential owner disclosure, and ACTA / PEF / SCITT export adapters are Kit TypeScript/Python, CLI, and Gateway auditor surfaces—not MCP’s full job. Use Kit client libraries for those flows.
Compliance audit exports that include agent receipts may also ship PEF companions (*.pef.json) beside each signed receipt JSON.