create_invoice
Generate a new invoice for a client with optional line items, custom payment terms, taxes, and discounts.
Instructions
Create a new invoice for a client with optional line items and billing details. Supports custom terms, taxes, and payment configurations.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| client_id | Yes | The client ID to invoice (required) | |
| subject | No | Invoice subject line | |
| notes | No | Invoice notes or description | |
| currency | No | 3-letter ISO currency code (e.g., USD, EUR) | |
| issue_date | No | Invoice issue date (YYYY-MM-DD) | |
| due_date | No | Invoice due date (YYYY-MM-DD) | |
| payment_term | No | Payment terms (e.g., "Net 30") | |
| tax | No | Tax percentage (0-100) | |
| tax2 | No | Second tax percentage (0-100) | |
| discount | No | Discount percentage (0-100) | |
| purchase_order | No | Client purchase order number |
Implementation Reference
- src/tools/invoices.ts:58-74 (handler)The CreateInvoiceHandler class implementing ToolHandler. It validates args with CreateInvoiceSchema, calls harvestClient.createInvoice(), and returns the result as JSON text content.
class CreateInvoiceHandler implements ToolHandler { constructor(private readonly config: BaseToolConfig) {} async execute(args: Record<string, any>): Promise<CallToolResult> { try { const validatedArgs = validateInput(CreateInvoiceSchema, args, 'create invoice'); logger.info('Creating invoice via Harvest API'); const invoice = await this.config.harvestClient.createInvoice(validatedArgs); return { content: [{ type: 'text', text: JSON.stringify(invoice, null, 2) }], }; } catch (error) { return handleMCPToolError(error, 'create_invoice'); } } } - src/schemas/invoice.ts:83-95 (schema)Zod schema validating create_invoice input: client_id (required positive int), plus optional fields subject, notes, currency (default USD), issue_date/due_date (YYYY-MM-DD), payment_term, tax/tax2/discount (0-100), purchase_order.
export const CreateInvoiceSchema = z.object({ client_id: z.number().int().positive(), subject: z.string().optional(), notes: z.string().optional(), currency: z.string().length(3).optional().default('USD'), issue_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be in YYYY-MM-DD format').optional(), due_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be in YYYY-MM-DD format').optional(), payment_term: z.string().optional(), tax: z.number().min(0).max(100).optional(), tax2: z.number().min(0).max(100).optional(), discount: z.number().min(0).max(100).optional(), purchase_order: z.string().optional(), }); - src/tools/invoices.ts:152-176 (registration)Registration of the create_invoice tool in registerInvoiceTools(), defining its name, description, input schema (JSON Schema format), and handler instance.
{ tool: { name: 'create_invoice', description: 'Create a new invoice for a client with optional line items and billing details. Supports custom terms, taxes, and payment configurations.', inputSchema: { type: 'object', properties: { client_id: { type: 'number', description: 'The client ID to invoice (required)' }, subject: { type: 'string', description: 'Invoice subject line' }, notes: { type: 'string', description: 'Invoice notes or description' }, currency: { type: 'string', minLength: 3, maxLength: 3, description: '3-letter ISO currency code (e.g., USD, EUR)' }, issue_date: { type: 'string', format: 'date', description: 'Invoice issue date (YYYY-MM-DD)' }, due_date: { type: 'string', format: 'date', description: 'Invoice due date (YYYY-MM-DD)' }, payment_term: { type: 'string', description: 'Payment terms (e.g., "Net 30")' }, tax: { type: 'number', minimum: 0, maximum: 100, description: 'Tax percentage (0-100)' }, tax2: { type: 'number', minimum: 0, maximum: 100, description: 'Second tax percentage (0-100)' }, discount: { type: 'number', minimum: 0, maximum: 100, description: 'Discount percentage (0-100)' }, purchase_order: { type: 'string', description: 'Client purchase order number' }, }, required: ['client_id'], additionalProperties: false, }, }, handler: new CreateInvoiceHandler(config), }, - src/server.ts:138-138 (registration)The create_invoice tool name is listed under the 'invoices' category in the server's category-to-tool-name mappings.
'invoices': ['list_invoices', 'get_invoice', 'create_invoice', 'update_invoice', 'delete_invoice'], - src/client/invoices-client.ts:61-86 (helper)InvoicesClient.createInvoice() - the low-level HTTP client method that validates input using the Zod schema, then POSTs to /invoices endpoint. This is called by harvestClient.createInvoice().
async createInvoice(input: CreateInvoiceInput): Promise<any> { try { const validatedInput = CreateInvoiceSchema.parse(input); this.logger.debug('Creating invoice', { clientId: validatedInput.client_id, subject: validatedInput.subject }); const response: AxiosResponse = await this.client.post('/invoices', validatedInput); this.logger.info('Successfully created invoice', { invoiceId: response.data.id, invoiceNumber: response.data.number, amount: response.data.amount }); return response.data; } catch (error) { if (error instanceof z.ZodError) { this.logger.error('Create invoice validation failed:', error.errors); throw new Error('Invalid invoice input data'); } throw error; } }