Provider REST API
FinanceConnect Claude to Ramp
Read card transactions, cards, people, departments, locations, reimbursements, bills, and spend limits. Toolspoke puts 12 of its actions behind one MCP endpoint that Claude, Cursor, and Codex all speak.
- Connection
- Provider REST API
- Authentication
- Ramp API client credentials
- Actions exposed
- 12
- Cost per call (typical)
- 1 credit
- Adapter
- Maintained by Toolspoke
Connected in three steps
- 1
Install Ramp
Open the marketplace in your workspace, add Ramp to the project your agents work in, and it appears on the gateway immediately.
- 2
Connect the credential
Authenticate with ramp api client credentials. Where to get one, and what it has to be able to reach, is the next section.
- 3
Point your agent at the gateway
Give your client one address, https://toolspoke.com/mcp. Claude Code takes it as a command, Claude and Claude Desktop add it as a custom connector, and Cursor, Codex and VS Code each read it from a config file of their own.
.mcp.json{
"mcpServers": {
"toolspoke": {
"type": "http",
"url": "https://toolspoke.com/mcp"
}
}
}One block covers every tool you have installed. Ramp shows up in the client as soon as your policy allows it, and so does everything else you install later.
Where the address goes, per client
- Claude Code
Run it in your project, then /mcp to sign in
claude mcp add --transport http toolspoke https://toolspoke.com/mcp- Claude and Claude Desktop
Settings, then Connectors, then Add custom connector
https://toolspoke.com/mcp- Cursor
~/.cursor/mcp.json, or .cursor/mcp.json for one project
{ "mcpServers": { "toolspoke": { "url": "https://toolspoke.com/mcp" } } }- Codex
~/.codex/config.toml
[mcp_servers.toolspoke] url = "https://toolspoke.com/mcp"- VS Code
.vscode/mcp.json, or the MCP: Add Server command
{ "servers": { "toolspoke": { "type": "http", "url": "https://toolspoke.com/mcp" } } }
What Ramp asks for
Ramp API client credentials. You provide it once, when you install the connector. Toolspoke encrypts it at rest and decrypts it only for the length of a single call, and the gateway attaches it to the outbound request itself, so it is never part of the arguments an agent sends.
- Client IDRequired
- Ramp → Settings → Developer API → create an app with the Client credentials grant type. The id is shown on the app's page.
- ramp_id_…
- Client secretRequired
- Shown once when the app is created. Ramp exchanges this for a one-hour access token before every call; the secret itself never reaches an API endpoint.
- Paste the secret
- ScopesOptional
- Space-separated, and every one of them must already be ticked on the Ramp app - Ramp rejects the whole sign-in if the app was not granted a scope this asks for. Leave blank for the full read set every operation here needs: transactions:read cards:read users:read departments:read locations:read reimbursements:read bills:read funds:read. Narrow it to enable fewer operations.
- transactions:read cards:read users:read
What Claude can do in Ramp
12 actions, each one declared and named by the connector rather than discovered at runtime. A workspace policy grants a person all of them, a hand-picked selection, everything on the read side, everything on the write side, or none.
- Reads
- 12Reads
- Writes
- 0Writes
- Destructive
- 0Destructive
Reads
12Fetches data and changes nothing.
list_transactionsList card transactions, newest first by default. This is the main spend feed: each row carries the merchant, the amount and currency, the card and cardholder, the accounting categorisation and the approval and sync state. Narrow it with from_date and to_date before anything else - a busy account has thousands of rows a month, and `page_size` caps one response rather than the query. `state` is the transaction's lifecycle (PENDING is authorised but not settled, CLEARED has settled, DECLINED never went through), which is not the same question as `sync_status`, the accounting export state. Ids returned here are what get_transaction takes.
get_transactionFetch one transaction by id, with its full accounting categorisation, line items, receipts, policy violations and approval chain - more than the listing returns for each row. Ids come from list_transactions. Set include_merchant_data to add what Ramp knows about the merchant itself.
list_virtual_cardsList virtual cards with each one's display name, cardholder, spending restrictions, state and last four digits. Ramp splits cards into two resources rather than one, so this is half the card estate and list_physical_cards is the other half. Full card numbers are never returned by this route and this connector exposes no operation that returns them. Creating, editing, suspending and terminating cards are all deliberately absent.
list_physical_cardsList physical cards - the plastic people carry - with cardholder, display name, activation state and last four digits. The other half of the card estate; list_virtual_cards covers the rest. Full card numbers are never returned here.
get_virtual_cardFetch one virtual card by id, with its spending restrictions, the spend limit it draws on, its cardholder and its state. Ids come from list_virtual_cards, or from the card_id on a transaction. The full card number lives behind Ramp's separate vault route, which this connector does not expose.
list_usersList the people on the Ramp account with their name, email, role, department, location and status. Use it to turn a name into the user_id that list_transactions, list_virtual_cards and list_reimbursements filter on. This returns a staff directory, so it is not the health check.
get_userFetch one person by id, with their role, manager, department, location and status. Ids come from list_users or from the user_id on a transaction or a card.
list_departmentsList the departments configured on the account, with their ids and names. This is org structure rather than anybody's data, which is why it is the health check: it is the cheapest call that proves the client credentials, the scopes and the account all line up, and it returns no personal information while doing it. The ids are what list_users and list_transactions filter on.
list_locationsList the locations configured on the account, with their ids and names. Org structure, like list_departments, and the source of the location_id that list_users and list_transactions filter on.
list_reimbursementsList out-of-pocket expense reimbursements with the person who claimed, the amount, the merchant, the memo and the approval and payment state. Narrow with from_date and to_date. `direction` separates money owed to a person (BUSINESS_TO_USER) from money a person owes back (USER_TO_BUSINESS). Nothing here approves, pays or rejects a claim - those routes exist in Ramp's API and are deliberately not exposed.
list_billsList accounts-payable bills with the vendor, the invoice number, the amount, the due date and the payment and approval state. Narrow by due date with from_due_date and to_due_date, or by issue date with from_issued_date and to_issued_date. `payment_status` is OPEN or PAID; `approval_status` is the separate question of whether anyone has signed it off. Paying, holding and releasing a bill are all routes Ramp offers and this connector does not.
get_spend_limitFetch one spend limit by id: its name, the cards drawing on it, its members, its restrictions and its cleared, pending and total balance. Ramp now calls these funds and the route is /funds/{fund_id}, which is why an id from Ramp's own interface still works here. Reading a limit does not change it - creating, editing, suspending and terminating one all move real spending authority and are not exposed by this connector at all.
What it will not do
Enforced by the gateway rather than left to convention, which is why each of these can be stated flatly.
- It cannot call anything else
- The 12 actions above are the whole of it. A call to any other name is refused before it reaches Ramp rather than forwarded on, and connecting your account does not add to the list: it is fixed by the connector, not discovered at run time.
- It only reads
- Every action here reads. Nothing this connector can do changes anything in Ramp.
- It reaches no further than your credential
- Toolspoke holds no access to Ramp of its own. Every call carries the credential you stored and nothing besides, so whatever that credential cannot reach, this connector cannot reach either.
- It never hears from Ramp
- Nothing is pushed to it. There is no webhook, no subscription and no polling, so this connector cannot notice by itself that something changed in Ramp. An agent has to ask.
- It does not smooth over provider limits
- Toolspoke does not retry, queue or back off around Ramp's own rate limits. A call that Ramp refuses comes back to the agent as a failed call.
Before you connect it
What can Claude do in Ramp?
12 named actions: 12 that only read. They include list_transactions, get_transaction and list_virtual_cards. Nothing outside that list is reachable: the connector declares each operation by name rather than proxying whatever an agent asks for.
What credentials does the Ramp connector need?
Ramp API client credentials. The connector asks for client id and client secret, and optionally scopes. Values are encrypted at rest and attached to the outbound request by the gateway, so they are never part of the arguments an agent sends and never reach the audit log.
Does the Ramp connector work with Cursor and Codex, or only Claude?
Any client that speaks MCP, and every one of them gets the same 12 actions. There is a single address, https://toolspoke.com/mcp. Claude Code adds it with claude mcp add --transport http, Claude and Claude Desktop take it as a custom connector in settings, Cursor reads it from .cursor/mcp.json, Codex from ~/.codex/config.toml, and VS Code from .vscode/mcp.json. Each of them signs in to the gateway itself, so there is no key to paste.
What does the Ramp connector not do?
The 12 actions above are the whole of it. A call to any other name is refused before it reaches Ramp rather than forwarded on, and connecting your account does not add to the list: it is fixed by the connector, not discovered at run time. Every action here reads. Nothing this connector can do changes anything in Ramp. Toolspoke holds no access to Ramp of its own. Every call carries the credential you stored and nothing besides, so whatever that credential cannot reach, this connector cannot reach either. Nothing is pushed to it. There is no webhook, no subscription and no polling, so this connector cannot notice by itself that something changed in Ramp. An agent has to ask. Toolspoke does not retry, queue or back off around Ramp's own rate limits. A call that Ramp refuses comes back to the agent as a failed call.
Can I limit which actions an agent can call?
Yes, in two places. The project switches Ramp's actions on and off one at a time, for everyone in the project at once, and the screen groups them by read, write and destructive so turning off everything that deletes is one click. An individual agent key can then be narrowed further, to particular toolkits in a project and to particular actions in a toolkit. Whatever it was granted, a key never reaches a project its owner cannot.
What gets recorded when an agent calls Ramp?
Every attempt, with the agent that made it and the person that agent belongs to, the full request payload, the response payload, the status, the duration, and the credits spent. Values whose key names a secret are masked out before the record is shown to anyone. An operation the connector marks as not retained never has its response body written at all, so the gateway keeps no second copy of what was read.