reference
mcp tools reference
One MCP server, two profiles. An agent key exposes 5 agent tools; an admin key exposes 12 admin tools. Every tool returns JSON as text content.
connection
| setting | value |
|---|---|
| endpoint | https://mcp.nostro.ag/mcp |
| transport | Streamable HTTP, stateless (no session id), JSON responses |
| auth | Authorization: Bearer <key> |
| headers | content-type: application/json, accept: application/json, text/event-stream |
| server | nostro v0.1.0 |
The tools you see depend on the key: nst_ gives the agent profile, nsa_ the admin profile. A wrong key fails at the HTTP level with 401 and JSON-RPC code -32001. Setup for Claude Code, Claude Desktop and Cursor is in the quickstart.
response shape
Results are MCP text content holding pretty-printed JSON. Business outcomes such as denied or pending_approval are normal results. Failures (not found, frozen agent, invalid input) come back with isError: true:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{\n \"error\": \"Agent gelé par l'entreprise : aucune dépense possible\"\n}"
}
],
"isError": true
}
}get_wallet before any spend, respect every decision, never split amounts to get around the mandate.agent tools
Scoped to the calling agent: its card, its mandate, its activity.
get_wallet
Remaining budget (day, month), caps, card status and the available balance of the company account. Agents are instructed to call it before any spend.
No parameters.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_wallet",
"arguments": {}
}
}{
"agent": {
"id": "agt_3f2b8d10",
"name": "demo-agent",
"status": "active"
},
"card": {
"id": "vcard_5e1d77a0c4b2",
"maskedNumber": "4970 •••• •••• 3182",
"status": "Enabled"
},
"accountAvailable": {
"value": "10000.00",
"currency": "EUR"
},
"budget": {
"currency": "EUR",
"perTxMax": 500,
"approvalAbove": 250,
"dailyRemaining": 2000,
"monthlyRemaining": 5000
},
"transfersEnabled": false
}pay
Pays a merchant with the agent's virtual card. Evaluated against the mandate first: executed, blocked, or held for human approval.
| name | type | description | |
|---|---|---|---|
amount | number | required | Amount in EUR, > 0. Rounded to 2 decimals, e.g. 19.99. |
merchant | string | required | Merchant name. Matched against blockedMerchants. |
mcc | string | optional | Merchant category code, exactly 4 digits, e.g. 5734. Required when the mandate has allowedMccs. |
description | string | optional | What the spend is for. Stored in the audit log. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "pay",
"arguments": {
"amount": 49,
"merchant": "Vercel",
"mcc": "5734",
"description": "Pro plan, November"
}
}
}{
"status": "paid",
"transactionId": "vtx_883b5610e2a1",
"amount": 49,
"merchant": "Vercel"
}{
"status": "pending_approval",
"requestId": "req_ef5c846c",
"reason": "Au-dessus du seuil d'approbation (250 €)",
"message": "Demande transmise à un humain de l'entreprise. Vérifie son statut avec get_request_status."
}{
"status": "denied",
"reason": "Dépasse le plafond par transaction (500 €)"
}{
"status": "declined_by_bank",
"reason": "InsufficientFunds"
}send_transfer
Sends a SEPA transfer from the company account, only if the mandate enables transfers. Usually held for human approval.
| name | type | description | |
|---|---|---|---|
amount | number | required | Amount in EUR, > 0. |
iban | string | required | Beneficiary IBAN. Spaces are stripped; must match ^[A-Z]{2}\d{2}[A-Z0-9]{10,30}$. |
beneficiaryName | string | required | Beneficiary name. |
label | string | optional | Transfer label, max 140 characters. Defaults to "Nostro <agent name>". |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "send_transfer",
"arguments": {
"amount": 1200,
"iban": "FR7630006000011234567890189",
"beneficiaryName": "Acme SAS",
"label": "Invoice 2026-114"
}
}
}{
"status": "pending_approval",
"requestId": "req_51c0aa9e",
"reason": "Virement soumis à approbation humaine",
"message": "Demande transmise à un humain de l'entreprise. Vérifie son statut avec get_request_status."
}{
"status": "initiated",
"paymentId": "vpay_9d21c4e07a11",
"bankStatus": "Initiated"
}{
"status": "denied",
"reason": "Virements désactivés pour cet agent"
}list_my_activity
The agent's own history: every payment, transfer and decision (executed, denied, pending). Newest first.
| name | type | description | |
|---|---|---|---|
limit | integer | optional | 1 to 100, default 20. (REST returns the last 50.) |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_my_activity",
"arguments": {
"limit": 2
}
}
}[
{
"id": 7,
"workspace_id": "ws_7c1e9a42b0d3",
"agent_id": "agt_3f2b8d10",
"type": "card_payment",
"amount": 320,
"counterparty": "AWS",
"decision": "executed",
"reason": null,
"bank_ref": "vtx_acf5376d09be",
"created_at": "2026-11-05T09:20:41.560Z",
"agent_name": "demo-agent"
},
{
"id": 5,
"workspace_id": "ws_7c1e9a42b0d3",
"agent_id": "agt_3f2b8d10",
"type": "card_payment",
"amount": 900,
"counterparty": "Apple",
"decision": "denied",
"reason": "Dépasse le plafond par transaction (500 €)",
"bank_ref": null,
"created_at": "2026-11-05T09:18:02.491Z",
"agent_name": "demo-agent"
}
]get_request_status
Status of a spend held for human approval. Agents can only read their own requests.
| name | type | description | |
|---|---|---|---|
requestId | string | required | The req_... id returned by pay or send_transfer. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_request_status",
"arguments": {
"requestId": "req_ef5c846c"
}
}
}{
"id": "req_ef5c846c",
"kind": "card_payment",
"amount": 320,
"status": "executed",
"reason": "Au-dessus du seuil d'approbation (250 €)",
"result": {
"amount": 320,
"status": "paid",
"merchant": "AWS",
"transactionId": "vtx_acf5376d09be"
},
"createdAt": "2026-11-05T09:19:33.478Z",
"decidedAt": "2026-11-05T09:20:41.561Z"
}admin tools
Scoped to the workspace of the admin key. Give these only to humans, or to a supervised operator agent you trust with the whole budget.
overview
Account, balance, number of active agents, pending approvals and spend this month.
No parameters.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "overview",
"arguments": {}
}
}{
"workspace": {
"id": "ws_7c1e9a42b0d3",
"name": "Acme",
"kind": "sandbox",
"account_id": "vacc_2b9d01e6f3a8",
"created_at": "2026-11-05T09:12:03.870Z"
},
"bankMode": "ledger",
"account": {
"id": "vacc_2b9d01e6f3a8",
"name": "Acme",
"iban": "FR7699999481207365519024618",
"status": "Opened",
"available": {
"value": "9631.00",
"currency": "EUR"
},
"booked": {
"value": "9631.00",
"currency": "EUR"
}
},
"agents": 1,
"pendingApprovals": 0,
"monthSpend": 369,
"swanConfigured": false,
"swanUserId": null
}list_agents
Every non-revoked agent with its card, mandate and current spend.
No parameters.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_agents",
"arguments": {}
}
}[
{
"id": "agt_3f2b8d10",
"name": "demo-agent",
"purpose": "Demo agent (sandbox, fake euros)",
"status": "active",
"keyPrefix": "nst_k3Jd",
"card": {
"id": "vcard_5e1d77a0c4b2",
"status": "Enabled",
"maskedNumber": "4970 •••• •••• 3182",
"consentUrl": null
},
"policy": {
"currency": "EUR",
"perTxMax": 500,
"dailyMax": 2000,
"monthlyMax": 5000,
"approvalAbove": 250,
"allowedMccs": [],
"blockedMerchants": [],
"transfersEnabled": false,
"transferApprovalAbove": 0
},
"spend": {
"today": 49,
"month": 49
},
"createdAt": "2026-11-05T09:12:04.118Z"
}
]create_agent
Creates an agent with its own virtual card in the company's name, its mandate and its API key. The key is returned once and never again.
| name | type | description | |
|---|---|---|---|
name | string | required | Agent name, also printed on the card label. |
purpose | string | optional | Free text, what this agent is for. |
perTxMax | number | optional | Maximum amount of a single card payment, in EUR. Above it the payment is blocked. |
dailyMax | number | optional | Maximum executed spend per calendar day (UTC), card payments and transfers combined. |
monthlyMax | number | optional | Monthly budget. Also set as the spending limit on the card itself (defense in depth). |
approvalAbove | number | optional | Card payments strictly above this amount wait for a human approval instead of executing. |
allowedMccs | string[] | optional | Allowed merchant category codes (4 digits). Empty means every category is allowed. |
blockedMerchants | string[] | optional | Merchant names to block. Case-insensitive substring match on the merchant name. |
transfersEnabled | boolean | optional | Whether the agent may send SEPA transfers at all. |
transferApprovalAbove | number | optional | Transfers strictly above this amount need a human approval. 0 means every transfer is reviewed. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "create_agent",
"arguments": {
"name": "procurement-bot",
"purpose": "Buys SaaS seats",
"perTxMax": 200,
"dailyMax": 600,
"monthlyMax": 3000,
"approvalAbove": 100,
"allowedMccs": [
"5734",
"7372"
]
}
}
}{
"agent": {
"id": "agt_91ad04c2",
"name": "procurement-bot",
"purpose": "Buys SaaS seats",
"status": "active",
"keyPrefix": "nst_Qm7v",
"card": {
"id": "vcard_0c44e1b9a7d0",
"status": "Enabled",
"maskedNumber": "4970 •••• •••• 7745",
"consentUrl": null
},
"policy": {
"currency": "EUR",
"perTxMax": 200,
"dailyMax": 600,
"monthlyMax": 3000,
"approvalAbove": 100,
"allowedMccs": [
"5734",
"7372"
],
"blockedMerchants": [],
"transfersEnabled": false,
"transferApprovalAbove": 0
},
"spend": {
"today": 0,
"month": 0
},
"createdAt": "2026-11-05T09:12:04.118Z"
},
"apiKey": "nst_Qm7v••••••••••••••••••••••••"
}update_agent_policy
Patches an agent's mandate. Only the fields you send change; the rest is kept. Changing monthlyMax also updates the card limit.
| name | type | description | |
|---|---|---|---|
agentId | string | required | The agt_... id. |
perTxMax | number | optional | Maximum amount of a single card payment, in EUR. Above it the payment is blocked. |
dailyMax | number | optional | Maximum executed spend per calendar day (UTC), card payments and transfers combined. |
monthlyMax | number | optional | Monthly budget. Also set as the spending limit on the card itself (defense in depth). |
approvalAbove | number | optional | Card payments strictly above this amount wait for a human approval instead of executing. |
allowedMccs | string[] | optional | Allowed merchant category codes (4 digits). Empty means every category is allowed. |
blockedMerchants | string[] | optional | Merchant names to block. Case-insensitive substring match on the merchant name. |
transfersEnabled | boolean | optional | Whether the agent may send SEPA transfers at all. |
transferApprovalAbove | number | optional | Transfers strictly above this amount need a human approval. 0 means every transfer is reviewed. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "update_agent_policy",
"arguments": {
"agentId": "agt_3f2b8d10",
"approvalAbove": 100,
"blockedMerchants": [
"casino",
"crypto"
]
}
}
}{
"id": "agt_3f2b8d10",
"name": "demo-agent",
"purpose": "Demo agent (sandbox, fake euros)",
"status": "active",
"keyPrefix": "nst_k3Jd",
"card": {
"id": "vcard_5e1d77a0c4b2",
"status": "Enabled",
"maskedNumber": "4970 •••• •••• 3182",
"consentUrl": null
},
"policy": {
"currency": "EUR",
"perTxMax": 500,
"dailyMax": 2000,
"monthlyMax": 5000,
"approvalAbove": 100,
"allowedMccs": [],
"blockedMerchants": [
"casino",
"crypto"
],
"transfersEnabled": false,
"transferApprovalAbove": 0
},
"spend": {
"today": 49,
"month": 49
},
"createdAt": "2026-11-05T09:12:04.118Z"
}freeze_agent
Kill switch: blocks every spend of the agent immediately. Reversible.
| name | type | description | |
|---|---|---|---|
agentId | string | required | The agt_... id. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "freeze_agent",
"arguments": {
"agentId": "agt_3f2b8d10"
}
}
}{
"id": "agt_3f2b8d10",
"name": "demo-agent",
"purpose": "Demo agent (sandbox, fake euros)",
"status": "frozen",
"keyPrefix": "nst_k3Jd",
"card": {
"id": "vcard_5e1d77a0c4b2",
"status": "Enabled",
"maskedNumber": "4970 •••• •••• 3182",
"consentUrl": null
},
"policy": {
"currency": "EUR",
"perTxMax": 500,
"dailyMax": 2000,
"monthlyMax": 5000,
"approvalAbove": 250,
"allowedMccs": [],
"blockedMerchants": [],
"transfersEnabled": false,
"transferApprovalAbove": 0
},
"spend": {
"today": 49,
"month": 49
},
"createdAt": "2026-11-05T09:12:04.118Z"
}unfreeze_agent
Re-activates a frozen agent.
| name | type | description | |
|---|---|---|---|
agentId | string | required | The agt_... id. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "unfreeze_agent",
"arguments": {
"agentId": "agt_3f2b8d10"
}
}
}{
"id": "agt_3f2b8d10",
"name": "demo-agent",
"purpose": "Demo agent (sandbox, fake euros)",
"status": "active",
"keyPrefix": "nst_k3Jd",
"card": {
"id": "vcard_5e1d77a0c4b2",
"status": "Enabled",
"maskedNumber": "4970 •••• •••• 3182",
"consentUrl": null
},
"policy": {
"currency": "EUR",
"perTxMax": 500,
"dailyMax": 2000,
"monthlyMax": 5000,
"approvalAbove": 250,
"allowedMccs": [],
"blockedMerchants": [],
"transfersEnabled": false,
"transferApprovalAbove": 0
},
"spend": {
"today": 49,
"month": 49
},
"createdAt": "2026-11-05T09:12:04.118Z"
}revoke_agent
Revokes the agent's key and cancels its card. Irreversible.
| name | type | description | |
|---|---|---|---|
agentId | string | required | The agt_... id. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "revoke_agent",
"arguments": {
"agentId": "agt_3f2b8d10"
}
}
}{
"ok": true
}list_pending_approvals
Spends held for a human decision, newest first (max 100).
No parameters.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "list_pending_approvals",
"arguments": {}
}
}[
{
"id": "req_ef5c846c",
"agent_id": "agt_3f2b8d10",
"kind": "card_payment",
"amount": 320,
"payload": {
"amount": 320,
"merchant": "AWS",
"mcc": "7372"
},
"reason": "Au-dessus du seuil d'approbation (250 €)",
"status": "pending",
"result": null,
"created_at": "2026-11-05T09:19:33.478Z",
"decided_at": null,
"agent_name": "demo-agent"
}
]approve_request
Approves a pending request and executes it right away. One decision per request, even with concurrent clicks.
| name | type | description | |
|---|---|---|---|
requestId | string | required | The req_... id. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "approve_request",
"arguments": {
"requestId": "req_ef5c846c"
}
}
}{
"id": "req_ef5c846c",
"kind": "card_payment",
"amount": 320,
"status": "executed",
"reason": "Au-dessus du seuil d'approbation (250 €)",
"result": {
"amount": 320,
"status": "paid",
"merchant": "AWS",
"transactionId": "vtx_acf5376d09be"
},
"createdAt": "2026-11-05T09:19:33.478Z",
"decidedAt": "2026-11-05T09:20:41.561Z"
}reject_request
Rejects a pending request. Nothing is charged.
| name | type | description | |
|---|---|---|---|
requestId | string | required | The req_... id. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "reject_request",
"arguments": {
"requestId": "req_51c0aa9e"
}
}
}{
"id": "req_51c0aa9e",
"kind": "transfer",
"amount": 1200,
"status": "rejected",
"reason": "Virement soumis à approbation humaine",
"result": null,
"createdAt": "2026-11-05T09:22:10.002Z",
"decidedAt": "2026-11-05T09:25:47.310Z"
}fund_account
Sandbox only: credits the workspace's virtual ledger (simulated incoming SEPA transfer, fake euros).
| name | type | description | |
|---|---|---|---|
amount | number | required | EUR, > 0 and ≤ 100 000 per call. A sandbox balance is capped at 1 000 000. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "fund_account",
"arguments": {
"amount": 5000
}
}
}{
"transactionId": "vtx_c7b3a7331f0c"
}audit_log
Every decision and operation in the workspace, newest first, optionally for one agent.
| name | type | description | |
|---|---|---|---|
agentId | string | optional | Filter on one agent. |
limit | integer | optional | 1 to 500, default 100. |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "audit_log",
"arguments": {
"agentId": "agt_3f2b8d10",
"limit": 3
}
}
}[
{
"id": 7,
"workspace_id": "ws_7c1e9a42b0d3",
"agent_id": "agt_3f2b8d10",
"type": "card_payment",
"amount": 320,
"counterparty": "AWS",
"decision": "executed",
"reason": null,
"bank_ref": "vtx_acf5376d09be",
"created_at": "2026-11-05T09:20:41.560Z",
"agent_name": "demo-agent"
},
{
"id": 4,
"workspace_id": "ws_7c1e9a42b0d3",
"agent_id": "agt_3f2b8d10",
"type": "card_payment",
"amount": 320,
"counterparty": "AWS",
"decision": "pending_approval",
"reason": "Au-dessus du seuil d'approbation (250 €)",
"bank_ref": "req_ef5c846c",
"created_at": "2026-11-05T09:19:33.480Z",
"agent_name": "demo-agent"
},
{
"id": 2,
"workspace_id": "ws_7c1e9a42b0d3",
"agent_id": "agt_3f2b8d10",
"type": "agent_created",
"amount": null,
"counterparty": null,
"decision": "executed",
"reason": "Carte 4970 •••• •••• 3182 (Enabled)",
"bank_ref": "vcard_5e1d77a0c4b2",
"created_at": "2026-11-05T09:12:04.120Z",
"agent_name": "demo-agent"
}
]