mercury_create_invoice
Create a new invoice for an existing Mercury customer. Optionally email it immediately with a payment link.
Instructions
Create a new invoice (one-shot or to be sent recurrently). Requires AR write scope.
USE WHEN: billing a customer that already exists in Mercury (customerId from mercury_create_customer or mercury_list_customers). Set sendEmailOption: "SendNow" to email the invoice immediately to the customer's contact email.
DO NOT USE: when the customer does not exist yet (call mercury_create_customer first). To attach a file to the invoice, use the Mercury web app at creation time — the API attachment-upload endpoint is not exposed by this MCP currently.
SIDE EFFECTS: writes a new invoice to Mercury. Persistent. With sendEmailOption: "SendNow" (the default), Mercury also sends a real email with a payment link to the customer — confirm the customer's email and the line items before calling. Mercury Plus tier required for the AR write scope.
RETURNS: { id, status, amount, paymentUrl, ... } — paymentUrl is the Mercury-hosted page where the customer pays.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| customerId | Yes | Customer ID (created via mercury_create_customer) | |
| destinationAccountId | Yes | Mercury account ID where invoice payments will be deposited | |
| invoiceDate | Yes | Invoice date (YYYY-MM-DD) | |
| dueDate | Yes | Due date (YYYY-MM-DD) | |
| lineItems | Yes | Invoice line items | |
| achDebitEnabled | No | Allow ACH debit payments. Default: true | |
| creditCardEnabled | No | Allow credit card payments. Default: true | |
| useRealAccountNumber | No | Show real (vs virtual) account number on the invoice. Default: false | |
| ccEmails | No | CC emails for notifications | |
| sendEmailOption | No | Whether to email the invoice immediately. Default: SendNow | |
| invoiceNumber | No | Customer-facing invoice number (≤255 chars; Mercury rejects 300+ characters on the edit endpoint) | |
| poNumber | No | Purchase order number | |
| payerMemo | No | Memo shown to payer | |
| internalNote | No | Note visible only to your org | |
| servicePeriodStartDate | No | Service period start (YYYY-MM-DD) | |
| servicePeriodEndDate | No | Service period end (YYYY-MM-DD) |
Implementation Reference
- src/tools/invoices.ts:79-140 (handler)The handler function for mercury_create_invoice. Defined via defineTool on line 79-140. It accepts customerId, destinationAccountId, invoiceDate, dueDate, lineItems, and optional fields, then POSTs to /ar/invoices with the provided body.
defineTool( server, "mercury_create_invoice", [ "Create a new invoice (one-shot or to be sent recurrently). Requires AR write scope.", "", 'USE WHEN: billing a customer that already exists in Mercury (`customerId` from `mercury_create_customer` or `mercury_list_customers`). Set `sendEmailOption: "SendNow"` to email the invoice immediately to the customer\'s contact email.', "", "DO NOT USE: when the customer does not exist yet (call `mercury_create_customer` first). To attach a file to the invoice, use the Mercury web app at creation time — the API attachment-upload endpoint is not exposed by this MCP currently.", "", 'SIDE EFFECTS: writes a new invoice to Mercury. Persistent. With `sendEmailOption: "SendNow"` (the default), Mercury also sends a real email with a payment link to the customer — confirm the customer\'s email and the line items before calling. Mercury Plus tier required for the AR write scope.', "", "RETURNS: `{ id, status, amount, paymentUrl, ... }` — `paymentUrl` is the Mercury-hosted page where the customer pays.", ].join("\n"), { customerId: z.uuid().describe("Customer ID (created via mercury_create_customer)"), destinationAccountId: z .uuid() .describe("Mercury account ID where invoice payments will be deposited"), invoiceDate: z.iso.date().describe("Invoice date (YYYY-MM-DD)"), dueDate: z.iso.date().describe("Due date (YYYY-MM-DD)"), lineItems: z.array(lineItemSchema).min(1).describe("Invoice line items"), achDebitEnabled: z.boolean().optional().describe("Allow ACH debit payments. Default: true"), creditCardEnabled: z .boolean() .optional() .describe("Allow credit card payments. Default: true"), useRealAccountNumber: z .boolean() .optional() .describe("Show real (vs virtual) account number on the invoice. Default: false"), ccEmails: z.array(z.email()).optional().describe("CC emails for notifications"), sendEmailOption: z .enum(["DontSend", "SendNow"]) .optional() .describe("Whether to email the invoice immediately. Default: SendNow"), invoiceNumber: z .string() .max(255) .optional() .describe( "Customer-facing invoice number (≤255 chars; Mercury rejects 300+ characters on the edit endpoint)", ), poNumber: z.string().optional().describe("Purchase order number"), payerMemo: z.string().optional().describe("Memo shown to payer"), internalNote: z.string().optional().describe("Note visible only to your org"), servicePeriodStartDate: z.iso.date().optional().describe("Service period start (YYYY-MM-DD)"), servicePeriodEndDate: z.iso.date().optional().describe("Service period end (YYYY-MM-DD)"), }, async (args) => { const body = { ...args, achDebitEnabled: args.achDebitEnabled ?? true, creditCardEnabled: args.creditCardEnabled ?? true, useRealAccountNumber: args.useRealAccountNumber ?? false, ccEmails: args.ccEmails ?? [], }; const data = await client.post("/ar/invoices", body); return textResult(data); }, { title: "Create Invoice", destructiveHint: false, openWorldHint: true }, ); - src/tools/invoices.ts:93-127 (schema)Zod input schema for mercury_create_invoice. Defines all input parameters: customerId, destinationAccountId, invoiceDate, dueDate, lineItems (array of lineItemSchema), plus optional fields like sendEmailOption, ccEmails, etc.
{ customerId: z.uuid().describe("Customer ID (created via mercury_create_customer)"), destinationAccountId: z .uuid() .describe("Mercury account ID where invoice payments will be deposited"), invoiceDate: z.iso.date().describe("Invoice date (YYYY-MM-DD)"), dueDate: z.iso.date().describe("Due date (YYYY-MM-DD)"), lineItems: z.array(lineItemSchema).min(1).describe("Invoice line items"), achDebitEnabled: z.boolean().optional().describe("Allow ACH debit payments. Default: true"), creditCardEnabled: z .boolean() .optional() .describe("Allow credit card payments. Default: true"), useRealAccountNumber: z .boolean() .optional() .describe("Show real (vs virtual) account number on the invoice. Default: false"), ccEmails: z.array(z.email()).optional().describe("CC emails for notifications"), sendEmailOption: z .enum(["DontSend", "SendNow"]) .optional() .describe("Whether to email the invoice immediately. Default: SendNow"), invoiceNumber: z .string() .max(255) .optional() .describe( "Customer-facing invoice number (≤255 chars; Mercury rejects 300+ characters on the edit endpoint)", ), poNumber: z.string().optional().describe("Purchase order number"), payerMemo: z.string().optional().describe("Memo shown to payer"), internalNote: z.string().optional().describe("Note visible only to your org"), servicePeriodStartDate: z.iso.date().optional().describe("Service period start (YYYY-MM-DD)"), servicePeriodEndDate: z.iso.date().optional().describe("Service period end (YYYY-MM-DD)"), }, - src/tools/invoices.ts:6-17 (schema)Zod schema for invoice line items (lineItemSchema). Defines name (required, ≤200 chars), description (optional), quantity (positive number), and unitPrice (nonnegative number).
const lineItemSchema = z.object({ name: z .string() .min(1) .max(200) .describe( "Line item name (required, ≤200 characters — Mercury rejects longer values on the edit endpoint with 'Item name: Must be 200 characters or fewer', leaving the invoice unmodifiable). Put long descriptions in the optional `description` field or in the attached invoice PDF.", ), description: z.string().optional().describe("Optional longer description"), quantity: z.number().positive().describe("Quantity"), unitPrice: z.number().nonnegative().describe("Price per unit in USD"), }); - src/tools/_shared.ts:28-54 (registration)The defineTool helper that registers the tool on the McpServer via server.registerTool. Called by the invoices.ts handler definition.
export function defineTool<S extends ZodRawShape>( server: McpServer, name: string, description: string, inputSchema: S, handler: (args: z.infer<z.ZodObject<S>>) => Promise<ToolResult>, annotations: ToolAnnotations, ): void { const wrapped = wrapToolHandler(name, handler); const strictSchema = z.object(inputSchema).strict(); // MCP behavioral annotations (readOnlyHint / destructiveHint / // idempotentHint / openWorldHint) — declared machine-readable so // hosts and rubrics (TDQS / Glama Behavior dimension) can detect // tool semantics without scraping the prose description. Required // (not optional) so every new tool ships with explicit semantics — // forgetting the annotation now fails typecheck instead of // silently shipping a tool with no hint set. // The MCP SDK overloads `registerTool` with shape narrowing the runtime // strict-schema and the wrapped callback can't satisfy through generics. // Both casts are runtime-safe — the signatures only diverge at the type // level. Asserted by the existing tool-registration tests. (server.registerTool as unknown as (...a: unknown[]) => unknown)( name, { description, inputSchema: strictSchema, annotations }, wrapped, ); } - src/middleware.ts:53-53 (helper)Middleware registration mapping mercury_create_invoice to the 'invoices_write' bucket for rate limiting (daily: 10, monthly: 200).
mercury_create_invoice: "invoices_write", - src/tools/index.ts:33-33 (registration)Top-level registration: calls registerInvoiceTools(server, client) to register all invoice tools including mercury_create_invoice.
registerInvoiceTools(server, client);