What it is
The LootRush MCP server lets an AI assistant — Claude, Cursor, or any Model Context Protocol client — read your own LootRush data: your account balance, cards, card transactions, card balance (collateral) and its ledger, cashback, spending-limit auto-refills, and your account history. So you can ask your assistant “how much USDC do I have on Base right now?” or “list my card transactions at Amazon last month” without leaving the chat. If your key also carries themcp:write scope, the assistant can create
cards and change them (status, nickname, spending limit and interval).
Nothing else is writable — the server moves no funds and changes no account
settings.
Every tool reads only your own account. The server works out who you are from
your API key, and there is no parameter for pointing a tool at anyone else.
At a glance
Connecting
You need two things: the endpoint above and your LootRush API key — the same per-user key that authenticates the Withdraw and History APIs. Send it as a Bearer credential on every request.Claude Code
Claude Desktop / Cursor / other JSON-configured clients
Add LootRush to your client’s MCP server list:Some MCP clients can’t attach custom headers to a remote server. For those, the
server also accepts the key as a query parameter:
https://mcp.lootrush.com/mcp?token=YOUR_API_KEY. Prefer the Authorization
header where you can — a key in a URL is easier to leak.Authentication
Generate your API key at Settings → API Key. The same key works across the Withdraw, History, and MCP APIs. The server looks for it in this order:Authorization: Bearer <api-key>header — preferred.?token=<api-key>query parameter — fallback for clients that can’t set headers.
Available tools
Tool names are called exactly as written (camelCase).getAccountBalance
Your total account value in USD — crypto holdings, staked balances, tokenized
assets, and available wallet stablecoins, exactly like the portfolio Summary.
Also reports your card balance (collateral) as a separate bucket.
getUserCards
Your cards across all issuers, with aggregated balances and a normalized card
balance summary. Optionally reveals a single card’s number and CVV —
end-to-end encrypted, decrypted only on your client.
getUserCardTransactions
Card transactions across all cards, or a single card.
getCashbackSummary
Your LootRush Rewards cashback — what’s redeemable now, what’s still
maturing, and this month’s rate.
getUserCardSummary
A point-in-time snapshot of your cards — per-card balance, status, and limits
as of any instant.
getUserCardBalanceMovements
Your card balance (collateral) ledger — each entry’s running balance and
previous balance, the statement-style running total transactions don’t carry.
getUserCardBalanceAutomation
Your card spending-limit auto-refill history — each automatic balance top-up
(amount, status, retries, on-chain tx hash, when it ran).
getAccountHistory
Your account history — deposits, withdrawals, converts, sends, and card
operations — by date window, or one transaction by hash/id.
aggregate
Totals, counts, averages, min, max and medians over your card transactions
or account history — computed over the whole filtered set, without paging
every row.
createUserCards
Write (
mcp:write). Creates one card, or queues a batch of up to 30 and
returns a batchId you poll with the same tool.updateUserCard
Write (
mcp:write). Changes one card — status (block, unblock, cancel),
nickname, spending limit and interval.getAccountBalance
Returns the total USD value of your account — everything shown in your portfolio Summary: crypto holdings, staked balances, tokenized assets (stocks/ETFs) plus their profit/loss, and your available wallet stablecoins — with a per token/network breakdown so the balance can be charted, not just totalled. Your card balance (collateral) is reported as a separate bucket and is not included intotalUsdValue. Takes no parameters. All values are human-readable
strings.
If your balance snapshot is more than 5 minutes old, the tool refreshes it
on-chain before responding. (The refresh runs at most once every 5 minutes per
account; if it can’t complete, you get the last snapshot.) lastFetchedAt tells
you when the returned data was captured.
getUserCards
Returns your cards across all issuers plus aggregated balances. Each card carries itscardId and cardIssuerUserId — pass those to getUserCardTransactions to
scope to a single card, or back into this tool (with includeCardSecrets) to
reveal that card’s number and CVV.
The response also carries cardBalance — your card collateral, shared across all
your cards, normalized to { total, pendingDeposit, pendingWithdraw } (the same
shape getAccountBalance returns; null if the balances read failed). The raw
balances field sits alongside it if you need the full licensed/nonLicensed
regulatory split.
cashback comes back too — the same summary
getCashbackSummary returns, minus monthProgress. If
cashback can’t be read you still get your cards, with a cashbackError in place
of that section.
Revealing card number & CVV
The server returns only the issuer’s ciphertext — the number and CVV are decrypted on your client, with a key that never leaves it. That makes this an advanced flow: your MCP client has to run a small encryption handshake, which a plain chat client can’t do. Wrap the tool in your own client (Node/Python/Bash) that implements the two steps below. Beyond the basemcp scope, revealing secrets needs the mcp_card_reveal
scope on your key, read permission on the card-details feature, and a card
you own.
The handshake
- Fetch the reveal public key with
getCardRevealPublicKey. Generate a random AES-128 key locally and RSA-OAEP–wrap it with that key (SHA-1 hash). The base64 of the wrapped key is yoursessionId. - Call
getUserCardswithincludeCardSecrets: true, the targetcardId/cardIssuerUserId, and yoursessionId. The response carriescardSecrets.encryptedPanandcardSecrets.encryptedCvc, each{ data, iv }(both base64) — AES-GCM ciphertext, wheredatais the ciphertext with the 16-byte auth tag appended andivis the nonce. - Decrypt each locally with the AES key you kept in step 1.
Don’t hardcode the public key:
getCardRevealPublicKey always serves the
current one, so LootRush can rotate it without any change on your side. It also
returns the wrapping algorithm (RSA-OAEP, SHA-1).getCardRevealPublicKey (reveal helper)
The helper tool behind step 1. Takes no parameters; fetch it once and cache the result — it changes only when LootRush rotates the key.
Node example
getUserCardTransactions
Fetches your card transactions across all issuers, or a single card’s whencardId is given.
Card transactions carry no running balance. For the statement-style running
total, use
getUserCardBalanceMovements.getCashbackSummary
Your LootRush Rewards cashback across every enrolled card-issuer account. Takes no card ids — enrollment is resolved from your identity server-side.The four cashback balances
Cashback isn’t a single balance with a pending amount — it has four states, and only one of them is money you can use today:
Also returned:
currency, expiring (soonest slice about to lapse, or null),
accruingByMonth (a release calendar: month, amount, releaseDate),
accounts (how many accounts were folded in), and monthProgress — this month’s
spend buckets with their band ladder. A meaning object restates each field in
one line, so your assistant doesn’t have to guess which bucket is which.
If your accounts disagree about currency, the headline amounts stay zero and a
byCurrency array carries the real split — amounts in different currencies
are never added together.partial: true means at least one account did not answer, so the amounts cover
only the ones that did.getUserCardSummary
A point-in-time snapshot of your cards across all issuers — each card’s balance, status, and limits as ofasOf (defaults to now). Handy for “what did
my cards look like at the end of last month?”.
Returns
cardsSnapshot (the per-card rows) plus pagination.
The snapshot covers cards of every status, canceled ones included — read
each row’s
status if you only want the ones still spendable.getUserCardBalanceMovements
Your card balance (collateral) ledger. Unlike card transactions, each movement carries arunningBalance and previousBalance — the classic statement
running total. The upstream feed is per-issuer, so results are grouped by
issuer to keep each running-balance series coherent.
Returns
balanceMovements: an array of { cardIssuerUserId, movements, pagination }
groups, where each movement carries runningBalance and previousBalance.
getUserCardBalanceAutomation
Your card balance-automation history: spending-limit auto-refills. Each entry is one automatic top-up of your card’s spending limit — its amount, status, retry count, on-chain transaction hash, and when it executed.
Returns
autoRefillHistories (the per-top-up rows) plus pagination.
getAccountHistory
Your account history as report transactions — deposits, withdrawals, converts, sends, and card operations, joined with their source records (amounts human-readable). Newest first. PassfilterByHash or filterByOrderId to fetch a
single transaction (this replaces the date window); otherwise you get the window
bounded by startDate/endDate, capped by limit.
aggregate
Computes a total over your data without paging every row.getUserCardTransactions and getAccountHistory return rows; this returns the
number those rows add up to, across the whole filtered set rather than the
page you happened to fetch. You describe the slice — column, grouping, filters —
and get back the figure.
The response carries
byGroup (one entry per group, with its value and row
count), plus rowsCovered, totalCount and complete.
Amounts in different currencies come back as separate entries and are never
added together. Card money columns are also split by
status unless you pin
one: a declined transaction is an attempt, not spend, and only settled (and
on_hold, still authorising) is money that actually left the account.Filtering and grouping by merchant
Card networks don’t send a clean merchant name. What arrives is a settlement descriptor — a brand fragment, an acquirer prefix and a per-transaction reference, truncated at 25 characters:aggregate canonicalises
them. groupBy: "merchantName" returns one group per merchant, and each group
carries a few of the raw descriptors behind it under samples so you can check
the grouping.
For the same reason, where/whereNot on merchantName take the brand as a
person would say it — "facebook", "tiktok" — and match loosely enough to
reach the abbreviations the networks send. Don’t pass a descriptor copied off a
row: that filters down to the single transaction it came from.
whereNot works on cardTransactions
only — accountHistory rejects it rather than silently ignoring it.
Grouping by card nickname
cardNickname is groupable too, and matched the same loose way. It’s the name
you gave the card, not cardName — that one carries the embossed legal name,
which is identical on every card of a business account.
So if you name cards per campaign or per person (DAVID LORRAN 15), one call
totals them:
Reading matched
Every response that used a loose match carries matched — the canonical names
each term actually selected, keyed by column and then term:
What each source can aggregate
accountHistory has no fiat column to aggregate — that column is stored in
different scales depending on the transaction type, so a total over it would add
incompatible units. Use the token columns, or aggregate cardTransactions for
spend in your account currency.The datasetId handle
Listing responses carry a datasetId alongside their rows, plus the columns you
can aggregate and group by:
filterableText names the keys that take free text in where/whereNot, and
aggregateFilterHint says how to phrase them. ops lists the operations that
source can answer, and appears only where a source supports fewer than all six —
treat its absence as “all of them”.
The handle stores that call’s filters, never its rows, and expires after 15
minutes. Passing it to aggregate re-runs the same filters with the aggregation
applied, so the total covers the same slice you were shown rather than just the
page you fetched.
A listing sometimes returns no datasetId — one pinned to a single cardId,
for example, which the aggregate can’t reproduce. Pass source and filters
yourself in that case.
Writing — creating and changing cards
The two tools below are the only ones that change anything, and both need a key carrying themcp:write scope. Without it the tool returns
This API key is not authorized to make changes (missing the mcp:write scope).
and nothing is created or changed.
You usually don’t pass cardIssuerUserId. Most accounts have a single
card-issuer account and it’s filled in for you, so you can leave the parameter
out. If your account holds more than one, the tool asks for it and lists the ids
you can use. An account with no approved card-issuer account can’t create or
change cards yet, and the tool says so.
Write limits
Like every operation, each write tool gets one call per second on its own budget — see Rate limits.createUserCards and updateUserCard
don’t compete with each other, or with any read.
Card creation carries one more limit that counts cards, not calls: 300
cards per hour. A request that would cross the ceiling is refused whole — no
partial batch — and the message tells you how many you’ve used and how many are
left.
Because it counts cards, a single call for 30 spends 30. A refused request spends
nothing, so asking for 30 when only 5 fit doesn’t burn those 5 — ask for 5 and
they go through. The refusal is an error tool result rather than an HTTP status,
and nothing is created, so it’s safe to retry once the window rolls over.
createUserCards
Creates a single card, or queues a batch of up to 30.batchId decides which
mode you’re in:
batchIdomitted — creates.quantity: 1(the default) returns the card itself; a higherquantityqueues the batch and returns abatchId.batchIdgiven — a pure status read of that batch. Nothing is created, and an id that isn’t a valid batch id is an error rather than a fall-through to creating cards.
A batch never blocks. Thirty cards take longer to issue than the request may
stay open, so the tool hands back a handle instead of waiting:
batchId returns the batch’s progress — status,
totalCards, cardsCreated, cardsFailed, and cardIds for the cards issued so
far.
Retrying a batch does not double it. If a batch is still running with the
same recipe and the same size, that batch is returned (with
alreadyRunning: true) instead of a second one being queued — so retrying on a
dropped connection is safe without an idempotency key.updateUserCard
Changes one card per call. PasscardId plus at least one of status,
nickname, spendingLimit, spendingInterval.
The response carries
updated: true and the card’s state after the change,
read back for you:
If the change lands but the read-back fails, the response still says
updated: true and adds a note telling you not to retry — the write already
happened, and repeating it would apply it twice.Access & scoping
- Your account, always. It’s resolved from your API key when you connect, and every tool is scoped to it.
- Business roles are honored. If you’re a member of a business, a tool that reads a resource runs only when your role grants read permission for that feature, and a tool that changes one only when your role grants write — you are authorized as yourself, not as the account’s owner. Individual accounts and business owners are unrestricted over their own data.
- Writes are limited to cards. The only changes are creating a card and changing a card. The server moves no funds, opens no withdrawals, and changes no account settings.
Rate limits
One call per second, per operation. Every tool has its own budget, sogetUserCards running at its ceiling leaves getAccountHistory and
createUserCards untouched. tools/list and the connection handshake have their
own budgets too. In practice you can run different tools back to back without
throttling, and only repeated calls to the same tool wait a second.
createUserCards with a batchId reads a batch back rather than creating
anything, but it’s the same operation and draws on the same row — so poll a batch
at most once per second.
Beyond the limit, the server returns a 429 with JSON-RPC error code -32005,
naming the operation you exceeded:
429 is
always safe to retry after waiting.
Tips for staying under it
- Ask for a batch, not a loop.
createUserCardstakes aquantityup to 30 in one call. Thirty separate calls take thirty seconds and hit the limit twenty-nine times; one call takes one. - Page with
pageSize, not with parallel calls. The listing tools accept up to 100 rows per page. - Total instead of paging.
aggregatecomputes a sum, count or average over the whole filtered set in a single call — it exists precisely so you don’t page thousands of rows to add them up. - Reading a batch back doesn’t count as a write.
createUserCardswith abatchIdspends the read budget for that tool, so following a batch you just queued never blocks the next creation.
Errors
Errors come back as a standard JSON-RPC 2.0 error envelope.
Request bodies are capped at 256 KB.
A missing
mcp:write is not an HTTP error. The key is valid for the server,
so the request succeeds and the refusal comes back as a normal tool result
marked as an error — “This API key is not authorized to make changes”. Check the
tool result, not the status code. The same goes for every other rejection a
write tool reports: an unknown batchId, a card-issuer account you don’t own,
or bulk creation not being enabled.Support
Happy to help if you get stuck:- Email: [email protected]
- Dashboard: LootRush Dashboard