Skip to main content
Glama
invoice-update.ts4.76 kB
/** * invoice_update Tool * * Update an existing invoice in FreshBooks. */ import { z } from 'zod'; import { InvoiceUpdateInputSchema, InvoiceSingleOutputSchema } from './schemas.js'; import { FreshBooksClientWrapper } from '../../client/index.js'; import { ErrorHandler } from '../../errors/error-handler.js'; import { ToolContext } from '../../errors/types.js'; import { logger } from '../../utils/logger.js'; /** * Tool definition for invoice_update */ export const invoiceUpdateTool = { name: 'invoice_update', description: `Update an existing invoice in FreshBooks. WHEN TO USE: - User wants to modify invoice details - User says "update invoice", "change invoice", "edit invoice" - Correcting invoice amounts or line items - Changing invoice status (mark as sent, etc.) - Updating due date or payment terms REQUIRED: - accountId: FreshBooks account ID (get from auth_status if not specified) - invoiceId: Invoice ID to update - At least one field to update UPDATABLE FIELDS: - customerId: Change the client - createDate: Invoice date (YYYY-MM-DD) - dueDate: Payment due date (YYYY-MM-DD) - currencyCode: Currency code - lines: Replace line items (replaces ALL existing lines) - notes: Invoice notes - terms: Payment terms - status: Invoice status (draft, sent, etc.) - discount: Discount amount PARTIAL UPDATES: Only include fields you want to change. Omitted fields remain unchanged. Note: Setting lines will REPLACE all existing line items. RETURNS: Updated invoice record with all current information. EXAMPLES: - "Update invoice 123's due date to next month" - "Change invoice 456 status to sent" - "Add a discount to invoice 789"`, inputSchema: InvoiceUpdateInputSchema, outputSchema: InvoiceSingleOutputSchema, /** * Execute the tool */ async execute( input: z.infer<typeof InvoiceUpdateInputSchema>, client: FreshBooksClientWrapper ): Promise<z.infer<typeof InvoiceSingleOutputSchema>> { const handler = ErrorHandler.wrapHandler( 'invoice_update', async ( input: z.infer<typeof InvoiceUpdateInputSchema>, _context: ToolContext ) => { const { accountId, invoiceId, lines, ...invoiceData } = input; logger.debug('Updating invoice', { accountId, invoiceId, fields: Object.keys(invoiceData), }); // Build update payload const updates: Record<string, unknown> = {}; if (invoiceData.customerId !== undefined) { updates.customerid = invoiceData.customerId; } if (invoiceData.createDate !== undefined) { updates.create_date = invoiceData.createDate; } if (invoiceData.dueDate !== undefined) { updates.due_date = invoiceData.dueDate; } if (invoiceData.currencyCode !== undefined) { updates.currency_code = invoiceData.currencyCode; } if (invoiceData.notes !== undefined) { updates.notes = invoiceData.notes; } if (invoiceData.terms !== undefined) { updates.terms = invoiceData.terms; } if (invoiceData.status !== undefined) { updates.status = invoiceData.status; } if (invoiceData.discount !== undefined) { updates.discount_value = { amount: invoiceData.discount.amount, code: invoiceData.discount.code || invoiceData.currencyCode || 'USD', }; } if (lines && lines.length > 0) { updates.lines = lines.map((line) => ({ name: line.name, description: line.description || '', qty: line.qty || 1, unit_cost: { amount: line.unitCost.amount, code: line.unitCost.code || invoiceData.currencyCode || 'USD', }, taxName1: line.taxName1 || null, taxAmount1: line.taxAmount1 || null, taxName2: line.taxName2 || null, taxAmount2: line.taxAmount2 || null, })); } const result = await client.executeWithRetry( 'invoice_update', async (fbClient) => { const response = await fbClient.invoices.update(accountId, String(invoiceId), updates); if (!response.ok) { throw response.error; } return response.data; } ); // FreshBooks returns: { invoice: { ... } } const updatedInvoice = (result as { invoice?: unknown }).invoice ?? result; logger.info('Invoice updated successfully', { invoiceId, }); return updatedInvoice as z.infer<typeof InvoiceSingleOutputSchema>; } ); return handler(input, { accountId: input.accountId }); }, };

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/Good-Samaritan-Software-LLC/freshbooks-mcp'

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