Idempotency
The create and update tools accept an idempotency_key argument. It is sent to the endpoint as the X-Idempotency-Key header the REST API already honours — see Idempotency in the API.
{ "name": "finance_payables_create",
"arguments": {
"company_id": "…",
"description": "November rent",
"amount": 4500,
"due_date": "2026-11-10T00:00:00Z",
"person": { "name": "Downtown Realty" },
"idempotency_key": "7c4a8d09-ca37-4f21-b1f0-3d2f2b8c9a11"
} }
| Format | Opaque string, 1 to 255 characters. A UUID is the usual choice. |
| Repeat with the same body | Returns the original response, without running the operation again. |
| Repeat with a different body | Conflict (IDEMPOTENCY_KEY_REUSED). |
Delete tools do not take the argument: the route does not read it, and deleting twice already gives the same result.
Why an agent needs this more than your backend
An MCP client that times out and retries, or a model that decides "I'm not sure that worked, let me do it again", is exactly the pattern that creates the second title and the second transaction. Your backend has a retry loop you wrote; the agent has judgement.
Send a key whenever the operation creates something. A new key is a new attempt; to retry safely, repeat the same one.
The ones that move money: the key is required
On these four the key is not optional — the tool refuses the call without it, like the route:
| Tool | What it does |
|---|---|
finance_payables_send_to_bank | Sends the payment to the bank through Kobana |
finance_payables_cancel_dispatch | Cancels the bank dispatch |
finance_receivables_charge | Issues a bank slip or Pix to the customer |
finance_receivables_charge_cancel | Cancels the charge |
A duplicated dispatch is a duplicated payment, and a duplicated charge is a duplicated debt — no _delete undoes that. They are also destructive tools: the server only runs them after confirming with the person — see Confirming destructive tools.