Skip to main content
Glama
XeroAPI

Xero MCP Server

Official

update-invoice

Modify details of draft invoices in Xero, including due date, line items, and reference. Ensures accurate updates to financial records.

Instructions

Update an invoice in Xero. Only works on draft invoices.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
dueDateNo
invoiceIdYes
lineItemsNo
referenceNo

Implementation Reference

  • MCP tool handler function for 'update-invoice': calls the core updateXeroInvoice handler, handles results, generates a deep link to the invoice, and formats the response as MCP content.
    { invoiceId, lineItems, reference, dueDate, date, contactId, }: { invoiceId: string; lineItems?: Array<{ description: string; quantity: number; unitAmount: number; accountCode: string; taxType: string; }>; reference?: string; dueDate?: string; date?: string; contactId?: string; }, //_extra: { signal: AbortSignal }, ) => { const result = await updateXeroInvoice( invoiceId, lineItems, reference, dueDate, date, contactId, ); if (result.isError) { return { content: [ { type: "text" as const, text: `Error updating invoice: ${result.error}`, }, ], }; } const invoice = result.result; const deepLink = invoice.invoiceID ? await getDeepLink(DeepLinkType.INVOICE, invoice.invoiceID) : null; return { content: [ { type: "text" as const, text: [ "Invoice updated successfully:", `ID: ${invoice?.invoiceID}`, `Contact: ${invoice?.contact?.name}`, `Type: ${invoice?.type}`, `Total: ${invoice?.total}`, `Status: ${invoice?.status}`, deepLink ? `Link to view: ${deepLink}` : null, ].join("\n"), }, ], }; },
  • Zod input schemas defining parameters for the update-invoice tool, including line items, tracking categories, and top-level fields like invoiceId, reference, dates.
    const trackingSchema = z.object({ name: z.string().describe("The name of the tracking category. Can be obtained from the list-tracking-categories tool"), option: z.string().describe("The name of the tracking option. Can be obtained from the list-tracking-categories tool"), trackingCategoryID: z.string().describe("The ID of the tracking category. \ Can be obtained from the list-tracking-categories tool"), }); const lineItemSchema = z.object({ description: z.string().describe("The description of the line item"), quantity: z.number().describe("The quantity of the line item"), unitAmount: z.number().describe("The price per unit of the line item"), accountCode: z.string().describe("The account code of the line item - can be obtained from the list-accounts tool"), taxType: z.string().describe("The tax type of the line item - can be obtained from the list-tax-rates tool"), itemCode: z.string().describe("The item code of the line item - can be obtained from the list-items tool \ If the item was not populated in the original invoice, \ add without an item code unless the user has told you to add an item code.").optional(), tracking: z.array(trackingSchema).describe("Up to 2 tracking categories and options can be added to the line item. \ Can be obtained from the list-tracking-categories tool. \ Only use if prompted by the user.").optional(), }); const UpdateInvoiceTool = CreateXeroTool( "update-invoice", "Update an invoice in Xero. Only works on draft invoices.\ All line items must be provided. Any line items not provided will be removed. Including existing line items.\ Do not modify line items that have not been specified by the user.\ When an invoice is updated, a deep link to the invoice in Xero is returned. \ This deep link can be used to view the contact in Xero directly. \ This link should be displayed to the user.", { invoiceId: z.string().describe("The ID of the invoice to update."), lineItems: z.array(lineItemSchema).optional().describe( "All line items must be provided. Any line items not provided will be removed. Including existing line items. \ Do not modify line items that have not been specified by the user", ), reference: z.string().optional().describe("A reference number for the invoice."), dueDate: z.string().optional().describe("The due date of the invoice."), date: z.string().optional().describe("The date of the invoice."), contactId: z.string().optional().describe("The ID of the contact to update the invoice for. \ Can be obtained from the list-contacts tool."), },
  • Core handler implementing the business logic for updating a Xero invoice: checks if draft status, fetches existing, updates via Xero API, handles errors.
    export async function updateXeroInvoice( invoiceId: string, lineItems?: InvoiceLineItem[], reference?: string, dueDate?: string, date?: string, contactId?: string, ): Promise<XeroClientResponse<Invoice>> { try { const existingInvoice = await getInvoice(invoiceId); const invoiceStatus = existingInvoice?.status; // Only allow updates to DRAFT invoices if (invoiceStatus !== Invoice.StatusEnum.DRAFT) { return { result: null, isError: true, error: `Cannot update invoice because it is not a draft. Current status: ${invoiceStatus}`, }; } const updatedInvoice = await updateInvoice( invoiceId, lineItems, reference, dueDate, date, contactId, ); if (!updatedInvoice) { throw new Error("Invoice update failed."); } return { result: updatedInvoice, isError: false, error: null, }; } catch (error) { return { result: null, isError: true, error: formatError(error), }; } }
  • Registers the UpdateInvoiceTool as part of the UpdateTools array, likely imported by the server to expose all update tools.
    export const UpdateTools = [ UpdateContactTool, UpdateCreditNoteTool, UpdateInvoiceTool, UpdateManualJournalTool, UpdateQuoteTool, UpdateItemTool, UpdateBankTransactionTool, ApprovePayrollTimesheetTool, AddTimesheetLineTool, UpdatePayrollTimesheetLineTool, RevertPayrollTimesheetTool, UpdateTrackingCategoryTool, UpdateTrackingOptionsTool ];

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/XeroAPI/xero-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server