Skip to content
navoka

Give your agent a bank.

One MCP endpoint. A dedicated account with an IBAN, cards, payments, payouts and a ledger, under a policy the agent can't change.

The endpoint
https://mcp.navoka.com
transport: MCP over HTTP (streamable)
auth:      OAuth 2.1 + PKCE
scopes:    ledger:read policy:read cards:issue
           payments:write payouts:write
https://mcp.navoka.com
The agent gets tools. The holder keeps the policy. Every call becomes a ledger row the holder can read.

The endpoint.

Endpoint, transport, auth, scopes
https://mcp.navoka.com
transport: MCP over HTTP (streamable)
auth:      OAuth 2.1 + PKCE (holder authorizes once; agent session receives a scoped token)
scopes:    ledger:read policy:read cards:issue payments:write payouts:write
https://mcp.navoka.com
  • Claude Code

    claude mcp add --transport http navoka https://mcp.navoka.com

  • Any MCP client

    add the URL; on first call the holder is sent to authorize.

  • ChatGPT / Claude / Grok

    consumer paths on Connect.

The holder authorizes. The agent works inside what the holder allowed. There is no API key that grants more than the policy.Isolation

The tools.

The tools
CapabilityDoesAmountsHeld when
get_balanceBalance and available budget by currency—never
get_policyRead the holder's policy (limits, allowlist, mode)—never
issue_cardIssue a debit card to the agent (or read its existing one); returns a token reference, never a PAN. Every authorization on it is checked against the policy—never (the policy is enforced at authorization)
pay_invoiceParse or accept an invoice and pay by ACH / SEPA / Faster Payments{value, currency}new payee · above threshold · over ceiling
sendTransfer to a person or business; rail chosen or auto (ach, sepa_instant, fps, swift, usdc, eurc, push_to_card){value, currency}new payee · above threshold · country not allowed
payoutBatch payment from a list or sheet; one approval for the batchper-linenew payees · batch above threshold · monthly cap
get_ledgerRows with what, rule, approver, reason, line_id, timestamps—never
get_lineStatus of one line_id: held · approved · declined · settled—never
set_policyHolder-only. Refused from an agent session; attempt is logged.—always, for agents
  • Every write tool takes reason (string, required).

    It's stored on the ledger row verbatim and is what the holder reads at approval and in a dispute.

  • Every write tool returns a line_id and a status.

    held is a normal outcome, not an error. Poll get_line or subscribe to the webhook.

The policy.

The mandate as JSON. Written by the holder, readable by the agent, enforced at the account — not in your prompt.

policy.json
{
  "policy_id": "pol_7f3a",
  "currency": "EUR",
  "monthly_budget": { "value": 500.00, "currency": "EUR" },
  "approve_above": { "value": 250.00, "currency": "EUR" },
  "per_transaction_ceiling": { "value": 600.00, "currency": "EUR" },
  "velocity": { "count_per_day": 10, "value_per_day": { "value": 800.00, "currency": "EUR" } },
  "allowlist": {
    "merchants": ["amazon.es", "booking.com", "farfetch.com", "spotify.com", "netflix.com"],
    "payees": ["pay_iberdrola", "pay_anna_reid", "pay_studio_marr"]
  },
  "countries": ["ES", "GB", "US", "AE"],
  "mcc": { "allow": ["5411", "4722", "5734", "4900"], "deny": ["7995", "6011"] },
  "mode": "run_inside_limit",
  "card": { "id": "card_4412", "status": "active" },
  "kill_switch": false
}

Anything the agent requests is evaluated against this at the account. A request outside it returns status: held with reason_code (new_payee, above_threshold, merchant_not_allowed, country_not_allowed, mcc_denied, velocity, budget_exceeded) — never a silent failure.Limits and approvals

The same call, two views.

What the agent sends
{
  "tool": "pay_invoice",
  "payee": "Studio Marr",
  "iban": "ES91••••4402",
  "amount": { "value": 1250.00, "currency": "EUR" },
  "reference": "INV-2041",
  "reason": "Invoice INV-2041, due 15 Oct",
  "policy_id": "pol_7f3a"
}
→ returns
{ "line_id": "ln_01J9K2…", "status": "held", "reason_code": ["new_payee", "above_threshold"] }
After approval
{ "line_id": "ln_01J9K2…", "status": "approved", "approver": "holder", "approved_at": "2026-10-01T09:41:12Z", "rail": "sepa_instant" }
What the holder seesTelegram, web, or their assistant
Studio Marr · €1,250.00 · Held · new payee · above €250
Approved by you · 09:41 · sent by SEPA instant.

No PAN, no full IBAN in either view. The token and the vault handle that.Security

Held, approved, declined.

requestedheld|approvedsettled·heldapproved|declined·anyfrozenon kill switch
  • held

    evaluated, outside policy, waiting for the holder. Your agent should tell the user why (the reason_code is human-readable) and stop. Don't retry; don't split the amount to get under the threshold — velocity and budget catch it, and it's logged.

  • approved

    the holder tapped. Execution follows; settled when the rail confirms.

  • declined

    nothing left the account; no authorization was made.

  • frozen

    kill switch. All write tools return frozen until the holder unpauses.

Webhook: line.held, line.approved, line.declined, line.settled, policy.updated, account.frozen.Sandbox

Sandbox.

Sandbox endpoint
https://mcp.sandbox.navoka.com

# same tools, synthetic rails, instant settlement
# test holder auto-approves after 5 s
#   or never, with:  X-Navoka-Test-Hold: always
# test cards decline on merchant:  decline.test
https://mcp.sandbox.navoka.com

https://mcp.sandbox.navoka.com — same tools, synthetic rails, instant settlement, a test holder who auto-approves after 5 seconds (or never, with X-Navoka-Test-Hold: always). Test cards decline on merchant decline.test. No KYC, no real money.

Isolation.

  • One agent, one VM.

    Each agent runs in its own isolated virtual machine with its own encrypted storage.

  • Token, never PAN.

    The agent's debit card is provisioned as a network token; issue_card returns a token reference, never card data. The policy is applied at every authorization on it.

  • Policy at the account.

    Enforcement doesn't depend on your prompt or your client. A jailbroken agent still gets held.

Full pageSecurity

Fees.

Sandbox is free. Rail fees are returned on every write call before execution (quote field) so your agent can show them to the holder.

Questions.

How do I give my agent a bank account via MCP?
Point your MCP client at the Navoka endpoint and have the account holder sign in once — the account is created on that first sign-in — and your agent receives tools for balance, cards, invoice payment, transfers, payouts and the ledger. The account has a real IBAN and a real card. What the agent can do is set by the holder's policy, which it can read but not write.
Is this an API or an MCP server?
An MCP server first: one endpoint, tools with JSON schemas, works with Claude, Claude Code, ChatGPT, Grok and any MCP client. A REST surface for the same operations is available at api.navoka.com/v1. Either way the policy is enforced at the account, so the client you use doesn't change what's allowed.
What happens when my agent asks for something outside the policy?
It gets status: held with a readable reason_code — new payee, above threshold, merchant not allowed, country not allowed, category denied, velocity, budget exceeded. Nothing has moved. The holder sees the same line with Approve and Decline. Your agent should explain and wait, not retry or split the amount; both are caught and logged.
Can my agent change the policy if the user asks it to?
No. set_policy is holder-only and is refused from an agent session; the attempt is logged. The user changes limits on the limits screen or in the chat with an explicit confirmation bound to their identity. This is deliberate: a policy the agent could edit is a policy a prompt injection could edit.
Does my agent ever see a card number or a full IBAN?
No. issue_card returns a token reference and the card's status; the PAN is provisioned to the network token from the issuer's vault and never enters your process. IBANs are masked in every response. Receipts and ledger rows carry the payee name, amount, rule, approver and reason — enough to reconcile, nothing to leak.
Is there a sandbox and what does it cost?
Yes. Synthetic rails, instant settlement, a test holder you can set to auto-approve or always-hold, and test cards that decline on demand. It's free and needs no KYC. Rail fees come back on every write call as a quote before execution, so your agent can show them to the holder.

Get an endpoint.

Sandbox in minutes. Production when the holder says so.