mercury_create_internal_transfer
Move money between two Mercury accounts you own. Use to rebalance cash, sweep idle deposits, or fund sub-accounts. Settles immediately with no approval workflow.
Instructions
Move money between two of your own Mercury accounts (e.g. Checking → Savings). Funds stay inside your organisation.
USE WHEN: rebalancing cash between your own Mercury accounts — sweeping idle deposits to Treasury, funding a sub-account before issuing cards, etc. Both accounts must belong to your workspace.
DO NOT USE: to send money to an external counterparty (use mercury_send_money). To request approval-gated movement, use mercury_request_send_money (different surface, external only).
SIDE EFFECTS: moves real money between two accounts you own. Settles immediately, no approval workflow because no external recipient is involved. Persistent ledger entries on both sides. Idempotent via idempotencyKey — auto-generated if omitted, but pass an explicit one to make retries safe.
RETURNS: { id, amount, status, ... } — the booked transfer.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| sourceAccountId | Yes | Source Mercury account ID | |
| destinationAccountId | Yes | Destination Mercury account ID | |
| amount | Yes | Amount in USD (>= 0.01) | |
| note | No | Optional note attached to the transfer | |
| idempotencyKey | No | Unique key to prevent duplicate transfers. Auto-generated if omitted. |
Implementation Reference
- src/tools/transactions.ts:164-169 (handler)Handler function for mercury_create_internal_transfer. Makes a POST request to `/transfer` with sourceAccountId, destinationAccountId, amount, optional note, and auto-generated idempotencyKey. Returns the booked transfer result via textResult.
async ({ idempotencyKey, ...body }) => { const idem = idempotencyKey ?? randomUUID(); const data = await client.post(`/transfer`, { ...body, idempotencyKey: idem }); return textResult(data); }, ); - src/tools/transactions.ts:154-163 (schema)Input schema (Zod) for mercury_create_internal_transfer. Requires: sourceAccountId (UUID), destinationAccountId (UUID), amount (number >= 0.01). Optional: note (string), idempotencyKey (string).
{ sourceAccountId: z.string().uuid().describe("Source Mercury account ID"), destinationAccountId: z.string().uuid().describe("Destination Mercury account ID"), amount: z.number().min(0.01).describe("Amount in USD (>= 0.01)"), note: z.string().optional().describe("Optional note attached to the transfer"), idempotencyKey: z .string() .optional() .describe("Unique key to prevent duplicate transfers. Auto-generated if omitted."), }, - src/tools/transactions.ts:140-169 (registration)Registration of the 'mercury_create_internal_transfer' tool via defineTool() inside registerTransactionTools(). Includes the full description/usage instructions for the LLM.
defineTool( server, "mercury_create_internal_transfer", [ "Move money between two of your own Mercury accounts (e.g. Checking → Savings). Funds stay inside your organisation.", "", "USE WHEN: rebalancing cash between your own Mercury accounts — sweeping idle deposits to Treasury, funding a sub-account before issuing cards, etc. Both accounts must belong to your workspace.", "", "DO NOT USE: to send money to an external counterparty (use `mercury_send_money`). To request approval-gated movement, use `mercury_request_send_money` (different surface, external only).", "", "SIDE EFFECTS: **moves real money** between two accounts you own. Settles immediately, no approval workflow because no external recipient is involved. Persistent ledger entries on both sides. **Idempotent via `idempotencyKey`** — auto-generated if omitted, but pass an explicit one to make retries safe.", "", "RETURNS: `{ id, amount, status, ... }` — the booked transfer.", ].join("\n"), { sourceAccountId: z.string().uuid().describe("Source Mercury account ID"), destinationAccountId: z.string().uuid().describe("Destination Mercury account ID"), amount: z.number().min(0.01).describe("Amount in USD (>= 0.01)"), note: z.string().optional().describe("Optional note attached to the transfer"), idempotencyKey: z .string() .optional() .describe("Unique key to prevent duplicate transfers. Auto-generated if omitted."), }, async ({ idempotencyKey, ...body }) => { const idem = idempotencyKey ?? randomUUID(); const data = await client.post(`/transfer`, { ...body, idempotencyKey: idem }); return textResult(data); }, ); - src/tools/_shared.ts:29-39 (helper)The defineTool helper wraps the handler with middleware (rate-limiting, dry-run, audit) and registers it on the MCP server via server.registerTool().
export function defineTool<S extends ZodRawShape>( server: McpServer, name: string, description: string, inputSchema: S, handler: (args: z.infer<z.ZodObject<S>>) => Promise<ToolResult>, ): void { const wrapped = wrapToolHandler(name, handler); const strictSchema = z.object(inputSchema).strict(); server.registerTool(name, { description, inputSchema: strictSchema }, wrapped); } - src/tools/index.ts:20-43 (registration)registerAllTools() calls registerTransactionTools(server, client), which is where mercury_create_internal_transfer gets registered on the MCP server.
export function registerAllTools(server: McpServer, client: MercuryClient): void { // Banking registerAccountTools(server, client); registerCardTools(server, client); registerCreditTools(server, client); registerTransactionTools(server, client); registerRecipientTools(server, client); registerStatementTools(server, client); registerTreasuryTools(server, client); registerCategoryTools(server, client); registerOrganizationTools(server, client); // Accounts Receivable (Invoicing) — requires Mercury Plus registerInvoiceTools(server, client); registerCustomerTools(server, client); // Webhooks registerWebhookTools(server, client); }