Gravv MCP server

Connect an AI assistant to Gravv with the @gravv-infra/mcp server: install it, pick toolsets, and know the confirm, live-money and sandbox-only gates.

The Gravv MCP server connects an AI assistant to the Gravv API through the Model Context Protocol. The assistant can search these docs, then onboard customers, run KYC, open accounts, add payees, move money, issue cards and exchange currency with your own API key. It runs on your machine as a stdio process, so it works with Claude, Cursor, VS Code and any other MCP client.

This page describes version 0.4.0 of the npm package @gravv-infra/mcp. Gravv published earlier releases as @gravvfi/mcp. Install @gravv-infra/mcp.

Example. You ask your assistant to "pay our US supplier 1,250 USD by ACH". It searches the docs and learns that a new payee must reach active before a transfer can succeed. It adds the payee with createExternalAccount, reads it with getExternalAccount until it is active, and calls createTransfer. That first call does not run. It returns a preview: "Transfer 1250.00 USD from … to external_account … Once submitted this cannot be reversed from the API." The transfer runs only when you agree and the assistant calls again with confirm: true.

Before you start

  • Node.js 20 or later (node --version).
  • A sandbox API key that starts with grvSec_sandbox_. See Authentication. The key decides the environment, because sandbox and live share one host, https://api.gravv.xyz.
  • Keep the key out of files you commit. Where your client can read it from an environment variable or ask for it, use that instead of pasting it into a config file.

Without a key, the server still starts in docs-only mode.

To run the same calls yourself from a terminal, use the Gravv CLI. It uses the same error fixes and the same list of calls that move money as this server.

Install

Every client runs the same command: npx -y @gravv-infra/mcp, with GRAVV_API_KEY in its environment. Replace <SANDBOX_API_KEY> with your key.

Claude Code

claude mcp add gravv --env GRAVV_API_KEY=<SANDBOX_API_KEY> -- npx -y @gravv-infra/mcp

VS Code and GitHub Copilot

VS Code uses servers, not mcpServers, and needs type. Put this in .vscode/mcp.json to share it with your team, or run MCP: Open User Configuration for your own:

{
  "servers": {
    "gravv": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@gravv-infra/mcp"],
      "env": { "GRAVV_API_KEY": "<SANDBOX_API_KEY>" }
    }
  }
}

Codex CLI

codex mcp add gravv --env GRAVV_API_KEY=<SANDBOX_API_KEY> -- npx -y @gravv-infra/mcp

Or in ~/.codex/config.toml:

[mcp_servers.gravv]
command = "npx"
args = ["-y", "@gravv-infra/mcp"]

[mcp_servers.gravv.env]
GRAVV_API_KEY = "<SANDBOX_API_KEY>"

Claude Desktop, Cursor, Windsurf, Cline and Zed

These use the mcpServers shape:

{
  "mcpServers": {
    "gravv": {
      "command": "npx",
      "args": ["-y", "@gravv-infra/mcp"],
      "env": { "GRAVV_API_KEY": "<SANDBOX_API_KEY>" }
    }
  }
}
Client Where the configuration goes
Claude Desktop claude_desktop_config.json (open Settings, then Developer, then Edit Config)
Cursor ~/.cursor/mcp.json, or .cursor/mcp.json in a project
Windsurf ~/.codeium/windsurf/mcp_config.json
Cline The MCP Servers panel, or cline_mcp_settings.json
Zed settings.json, under context_servers

Any other client

Point it at a stdio process:

command: npx
args:    ["-y", "@gravv-infra/mcp"]
env:     GRAVV_API_KEY=<SANDBOX_API_KEY>

The server negotiates MCP protocol version 2025-06-18 and still serves clients that speak only 2024-11-05.

Check it works

Ask your assistant "What Gravv accounts do I have?". It should call listAccountsV2 and answer with your sandbox data. If you have no accounts yet, ask it to search the Gravv docs for how to open one. The server also writes one line to stderr when it starts, with the number of tools and prompts and the environment.

How to use it

Ask in plain words, as you would ask a teammate. The assistant picks the tools, reads the docs it needs and shows you what it did.

You ask What the assistant does
"How do I pay a Kenyan mobile money wallet?" Searches these docs with searchGravvDocs and answers with the steps and links
"Onboard a test customer called Ada Lovelace" Calls createCustomer, then startCustomerKyc, and gives you the KYC link
"Which accounts can a Nigerian business open?" Calls getAccountCapabilities with NG and business
"Send 50 USD to payee ext_123" Checks the payee is active, then shows a preview from createTransfer. It sends only after you agree
"Why is transfer trx_123 stuck?" Reads the transaction and its webhooks, then tells you the next step
"Write a Python function that creates a payee" Reads the payee docs and writes the code with the right fields

For a whole task, pick one of the prompts instead. A prompt tells the assistant what to ask you first and which tools to call in order.

To keep an assistant from changing anything, start the server with --read-only. It can then only read.

Configuration

Variable Default What it does
GRAVV_API_KEY none Your secret key. Its prefix selects the environment. Leave it out for docs-only mode
GRAVV_ALLOW_LIVE_WRITES not set true lets money-moving tools run on a live key. See A live key needs a second signal
GRAVV_TOOLSETS the default set A comma-separated list of toolsets, or all. Same as --toolsets
GRAVV_RATE_PER_MINUTE 60 The server's own request rate, with bursts of 15. The API allows 600 a minute per business (Rate limits)
GRAVV_BASE_URL https://api.gravv.xyz The API host. Another host, or plain http, starts the server with a warning, because the server sends your key there. Same as --base-url
GRAVV_DOCS_ORIGIN https://gravv-docs.syntext.dev Where the documentation tools read these docs. Same as --docs-origin
GRAVV_DOWNLOAD_DIR gravv-mcp-downloads in the system temp folder Where the server saves downloaded files. Same as --download-dir

The command-line options are --toolsets=<list>, --read-only, --base-url=<url>, --docs-origin=<url>, --download-dir=<dir> and --help. --read-only has no variable.

  • A toolset name that does not exist stops the server with the list of names.
  • Version 0.3.2 removed approvals and payment-links, and version 0.4.0 removed account-applications. The server ignores these names and gives a warning.
  • Version 0.4.0 merged features into cards. For features, the server loads cards instead and gives a warning.
  • A --docs-origin that is not an http or https address, or that carries a query, a fragment or credentials, stops the server with the reason.
  • The server reads the key from the environment and sends it only to the API host. The server never writes it to disk, logs it or puts it in a result.

Toolsets

There are 83 API tools in 12 toolsets. Every toolset loads by default. That is 83 tools, or 82 on a live key, because a live key hides the sandbox tool. The two documentation tools are always loaded.

npx -y @gravv-infra/mcp --toolsets=customers,accounts,cards
npx -y @gravv-infra/mcp --toolsets=all
Toolset Default Tools
customers Yes createCustomer, getCustomer, listCustomers, updateCustomer
kyc Yes startCustomerKyc, startCustomerKycS2S, uploadCustomerKycDocument, getCustomerKycDocuments, downloadCustomerKycDocument, getCustomerKycStatus
accounts Yes getAccountCapabilities, getAccountRequirements, createAccountV2, getAccountV2, listAccountsV2, getAccountApplicationV2, listAccountApplicationsV2, updateAccountApplicationV2, and createAccount, getAccount, listAccounts for your business's one card account only
external-accounts Yes createExternalAccount, getExternalAccount, listExternalAccounts, updateExternalAccount, verifyExternalAccount, listExternalAccountInstitutions
transfers Yes createTransfer, uploadTransferDocument, resumeTransfer, getCustomerLimits, getRemitterLimits, getTransferRates, listTransferSupportedCurrencies, listTransferSupportedCountries, listTransferSupportedCountriesForAddress
transactions Yes listTransactions, getTransaction, getTransactionsVolume, exportTransactions
cards Yes createCard, getCard, listCards, getCardBalance, updateCardStatus, withdrawFromCard, createCardApplication, getCardApplication, listCardApplications, startCardholderKyc, startCardholderKycS2S, uploadCardholderKycDocument, listFeatures, checkFeatureEligibility, activateFeature
wallets Yes createWallet, getWallet, listWallets
fx Yes getFxQuote, listFxRates, listFxCurrencyPairs, createFxOrder, getFxOrder, listFxOrders, cancelFxOrder, listFxPendingApprovals, listSettlementInstructions, createSettlementInstruction, getSettlementInstruction, updateSettlementInstruction, deleteSettlementInstruction
collections Yes createCardPaymentIntent, chargeSavedCard, listSavedCards, getSavedCard, deleteSavedCard, createCollection, getCollection
webhooks Yes getWebhookHistory, getWebhookEventDetail, getWebhookCallHistory, retryWebhookEvent
sandbox Yes, sandbox keys only simulateDeposit
  • Card KYC (startCardholderKyc and its pair) verifies a cardholder for card issuing. It is separate from a customer's own KYC in kyc. After card KYC, activateFeature with feature_id virtual_cards issues a card at once in sandbox. In live it submits a card application, and you issue the card with createCard once Gravv approves it. See Cards. If the assistant calls an old name, startRiskKyc, startRiskKycS2S or uploadRiskDocument, the server tells it the new name to use.
  • createCollection takes bank transfers only. A card payment goes through createCardPaymentIntent, which returns the hosted payment link, the intent id and the card token that later charges need.
  • Each tool's description lists its prerequisites, such as "the customer's KYC must be completed", and the assistant reads them before it calls.

Safety gates

Sandbox and live share one host, so nothing in a request shows which environment it reaches. The server uses the gates below to keep the two apart.

Money-moving tools take two calls

createTransfer, resumeTransfer, withdrawFromCard, createFxOrder, cancelFxOrder, createCollection, createCardPaymentIntent and chargeSavedCard return a preview on the first call. The preview has status confirmation_required, says what the call will do, and shows the request it will send. Nothing reaches the API. The call runs only when the assistant calls again with the same arguments plus confirm: true, after you agree.

  • resumeTransfer is gated because resuming a paused transfer releases the payout.
  • cancelFxOrder is gated because you cannot undo a cancel, and Gravv does not return money it already debited.
  • createCardPaymentIntent is gated because, with a saved card_token, it charges the card at once. It asks even when it only makes a link.

A live key needs a second signal

On a grvSec_live_ key, the server refuses money-moving tools, even with confirm: true, unless you started it with GRAVV_ALLOW_LIVE_WRITES=true. The server treats a key with any other prefix as live. Reads and other writes work on a live key without it. On a live key the preview also carries a warning that confirming moves real money.

Tools that cannot be undone take two calls too

deleteSavedCard, deleteSettlementInstruction and activateFeature return a preview first and run only with confirm: true. activateFeature can issue a card, and you cannot switch off a feature it activates. These tools move no money, so they do not need GRAVV_ALLOW_LIVE_WRITES.

The deposit simulator works only in sandbox

simulateDeposit (POST /v2/accounts/simulate/deposit) appears only with a key that starts grvSec_sandbox_. On any other key, the server hides it and refuses a call to it by name before it sends any request. The server does not offer the card and collection simulators.

Read-only mode

--read-only turns off every tool that is not a GET, for reporting. For live, a safe setup is one read-only server entry on the live key, and all writes on a sandbox key.

Files stay out of the conversation

Upload tools take a local file_path. The server reads the file, checks its type from its first bytes (JPEG, PNG or PDF) and its size, and sends it, so the file never passes through the assistant. The server refuses a file over the tool's limit before it sends anything. The limits are:

Tool Largest file
uploadCustomerKycDocument 10 MB
uploadCardholderKycDocument 5 MB
uploadTransferDocument 700 KB
createAccountV2, updateAccountApplicationV2 2 MB each

In sandbox, keep the files of one call under 500 KB in total. See Upload sizes. downloadCustomerKycDocument saves the image to a file readable only by you, in a folder only you can open. It returns the file's path, type and size, not the image.

Cardholder data is never returned

The card number, CVV and PIN routes are not tools under any setting, and the server redacts any field named like card data from results. Show card details with the client-side decryption flow.

Prompts

A prompt is a complete task that you pick in your client, often from / or a prompt menu. Each prompt does these things:

  • It says what the assistant must ask you before any call.
  • It gives the tool order for each path, with its confirm steps and how to recover.
  • It names the docs page to read.
  • It ends with the rules every task shares. Never invent a value, confirm before money moves, and know when to resend with the same idempotency_key.

An optional argument narrows a prompt to one path.

Prompt For Optional argument
open-account A bank account or your business's card account; an application the bank is waiting on; deposit details path: v2, card-account, manage
onboard-customer Create and verify a person or a business; resubmit; read KYC documents path: person-hosted, person-s2s, business, resubmit, documents
send-payout ACH, wire, RTP, SWIFT, SEPA, Faster Payments, or between own accounts rail: ach, wire, rtp, swift, sepa, fps, book
send-remittance A bank account or mobile wallet abroad country: NG, GH, KE, RW, ZM, UG, CG, CI, BJ, MX, BR, CO, IN, HK, or xof
send-crypto USDC or USDT to a wallet; USDT to USDC between own wallets path: same-network, cross-network, convert
convert-currency Quote and place an FX order; settlement instructions; follow or cancel path: quote-and-order, settlement-instruction, manage
issue-card Verify a cardholder and issue a card; fund, limit, freeze, close path: hosted-kyc, own-kyc, fund, limit, freeze-or-block, close, another-card
collect-payment Stablecoin deposits, bank deposits, bank transfers, card checkout, saved cards method: stablecoin, bank-deposit, bank-transfer, card, saved-card
reconcile Transactions against your books, one transfer's webhooks, fees, missed events path: transactions, trace, fees, webhooks
fix-stuck-transfer A transfer that is pending, paused, under review or failed transaction_id

Prompts use the same route labels as these docs (Available, Not yet available, Not supported). A prompt says when it needs a tool the session has not loaded, such as simulateDeposit on a live key, and when there is no API key.

Documentation tools and docs-only mode

Two tools search and read every page of these docs:

  • searchGravvDocs takes a query, an optional limit (default 6) and an optional docs section.
  • getGravvDocPage takes a page slug or its full URL.

Both tools read the site's /llms.txt and /llms-full.txt and refresh them every hour. When they cannot reach the site, they keep answering from the last copy and add a note. Search matches words, not meaning. If it finds nothing, use the words these docs use, such as "transfer" or "payee".

Without GRAVV_API_KEY, the server runs in docs-only mode. The two documentation tools and the ten prompts work, and an API tool replies that it needs a key. You can use this mode to learn the API before you have credentials.

Results and errors

  • Every result carries environment, which is sandbox, live or unknown. unknown means the server does not recognize the key prefix, and the server treats that key as live. A write also carries the idempotency_key that the server sent.
  • A result that is HTTP 200 but not done, such as a paused transfer, a declined card payment or a refused card KYC file, carries next_step ahead of data.
  • An error carries status, the API's code when there is one, and a hint that says what to do instead.
  • After a timeout, a network error or a 5xx, the result says outcome_unknown: true, which means the call may have run. First check whether it ran, with the tool the hint names. If nothing happened, call again with the same arguments plus that idempotency_key. After any other 4xx, call again without it, because the API keeps a 4xx response for 24 hours under its key. See Idempotent requests.
  • ignored_arguments names the arguments the tool does not take. The server did not send them, so a misspelled filter shows up here.
  • The server cuts a result over 100,000 characters. A list keeps fewer items and says to ask for a smaller page.

Going live

  1. Run the whole flow in sandbox first. Sandbox and live hold separate data, so an id from one does not exist in the other.
  2. Replace GRAVV_API_KEY with your live key. The host does not change.
  3. Reads and other writes work at once. Money movement stays blocked until you also set GRAVV_ALLOW_LIVE_WRITES=true:
{
  "mcpServers": {
    "gravv": {
      "command": "npx",
      "args": ["-y", "@gravv-infra/mcp"],
      "env": {
        "GRAVV_API_KEY": "<LIVE_API_KEY>",
        "GRAVV_ALLOW_LIVE_WRITES": "true"
      }
    }
  }
}

What it cannot do

Asked for Answer Instead
Card number, CVV or PIN Not available over MCP, under any setting The client-side decryption flow
Approving or rejecting a transfer, payee or FX order Not available. Those routes are Dashboard-only The Gravv Dashboard. FX orders placed with an API key need no approval
Card or collection simulators Not offered yet simulateDeposit funds a sandbox account
Payment links Retired createCardPaymentIntent for a hosted card payment
Freezing, unfreezing or closing an account Not available Contact support

Troubleshooting

What you see Why Fix
Only two tools load GRAVV_API_KEY is not set, so the server is in docs-only mode Set the key and restart
401 on every call The API refused the key Copy the whole current key
404 for an id you know The id is from the other environment Check environment in the result
"exists but its toolset is not loaded" The tool's toolset is off Restart with --toolsets=all, or name the toolset
confirmation_required instead of a result The tool moves money or cannot be undone Review the preview, then call again with confirm: true
"moves money and this is a LIVE key" GRAVV_ALLOW_LIVE_WRITES is not set Set it only if you mean live payments
"is a sandbox-only test tool" You called simulateDeposit with a key that is not a sandbox key Use a grvSec_sandbox_ key
A warning about a grvPub_ key Publishable keys cannot call the API Use a secret key
422 You reused an idempotency_key with other arguments, or the API refused a transfer for a limit, a block or missing details Read code and the hint
Repeated 429 Another process uses the same Gravv account Wait, then try again
413 on an upload The file is over the tool's limit, or over 500 KB in sandbox Send a smaller file
Was this page helpful?