update-manual-journal
Modify draft manual journals in Xero by updating narration, line items, dates, or status while preserving unspecified parameters.
Instructions
Update a manual journal in Xero. Only works on draft manual journals. Do not modify line items or parameters that have not been specified by the user.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| narration | Yes | Description of manual journal being posted | |
| manualJournalID | Yes | ID of the manual journal to update | |
| manualJournalLines | Yes | The manualJournalLines element must contain at least two individual manualJournalLine sub-elements | |
| date | No | Optional date in YYYY-MM-DD format | |
| lineAmountTypes | No | Optional line amount types (EXCLUSIVE, INCLUSIVE, NO_TAX), NO_TAX by default | |
| status | No | Optional status of the manual journal (DRAFT, POSTED, DELETED, VOID, ARCHIVED), DRAFT by default | |
| url | No | Optional URL link to a source document | |
| showOnCashBasisReports | No | Optional boolean to show on cash basis reports, default is true |
Implementation Reference
- MCP tool definition for 'update-manual-journal', including schema validation and handler function that invokes the Xero API via updateXeroManualJournal and formats response with deeplink.const UpdateManualJournalTool = CreateXeroTool( "update-manual-journal", "Update a manual journal in Xero. Only works on draft manual journals.\ Do not modify line items or parameters that have not been specified by the user.", { narration: z .string() .describe("Description of manual journal being posted"), manualJournalID: z.string().describe("ID of the manual journal to update"), manualJournalLines: z .array( z.object({ lineAmount: z .number() .describe( "Total for manual journal line. Debits are positive, credits are negative value", ), accountCode: z.string().describe("Account code for the journal line"), description: z .string() .optional() .describe("Optional description for manual journal line"), taxType: z .string() .optional() .describe("Optional tax type for the manual journal line"), // TODO: TODO: tracking can be added here }), ) .describe( "The manualJournalLines element must contain at least two individual manualJournalLine sub-elements", ), date: z.string().optional().describe("Optional date in YYYY-MM-DD format"), lineAmountTypes: z .enum(["EXCLUSIVE", "INCLUSIVE", "NO_TAX"]) .optional() .describe( "Optional line amount types (EXCLUSIVE, INCLUSIVE, NO_TAX), NO_TAX by default", ), status: z .enum(["DRAFT", "POSTED", "DELETED", "VOID", "ARCHIVED"]) .optional() .describe( "Optional status of the manual journal (DRAFT, POSTED, DELETED, VOID, ARCHIVED), DRAFT by default", ), url: z .string() .optional() .describe("Optional URL link to a source document"), showOnCashBasisReports: z .boolean() .optional() .describe( "Optional boolean to show on cash basis reports, default is true", ), }, async (args) => { try { const response = await updateXeroManualJournal( args.narration, args.manualJournalID, args.manualJournalLines, args.date, args.lineAmountTypes as LineAmountTypes | undefined, args.status as ManualJournal.StatusEnum | undefined, args.url, args.showOnCashBasisReports, ); if (response.isError) { return { content: [ { type: "text" as const, text: `Error updating manual journal: ${response.error}`, }, ], }; } const manualJournal = response.result; const deepLink = manualJournal.manualJournalID ? await getDeepLink( DeepLinkType.MANUAL_JOURNAL, manualJournal.manualJournalID, ) : null; return { content: [ { type: "text" as const, text: [ `Manual journal updated: ${manualJournal.narration} (ID: ${manualJournal.manualJournalID})`, deepLink ? `Link to view: ${deepLink}` : null, ] .filter(Boolean) .join("\n"), }, ], }; } catch (error) { const err = ensureError(error); return { content: [ { type: "text" as const, text: `Error updating manual journal: ${err.message}`, }, ], }; } }, );
- Core business logic handler that calls the Xero API to update a manual journal and returns structured response.export async function updateXeroManualJournal( narration: string, manualJournalID: string, manualJournalLines: ManualJournalLine[], date?: string, lineAmountTypes?: LineAmountTypes, status?: ManualJournal.StatusEnum, url?: string, showOnCashBasisReports?: boolean, ): Promise<XeroClientResponse<ManualJournal>> { try { const updatedManualJournal = await updateManualJournal( narration, manualJournalID, manualJournalLines, date, lineAmountTypes, status, url, showOnCashBasisReports, ); if (!updatedManualJournal) { throw new Error("Manual journal update failed."); } return { result: updatedManualJournal, isError: false, error: null, }; } catch (error) { return { result: null, isError: true, error: formatError(error), }; } }
- src/tools/update/index.ts:16-30 (registration)Registers the UpdateManualJournalTool as part of the UpdateTools array, which is used in tool factory for MCP tool registration.export const UpdateTools = [ UpdateContactTool, UpdateCreditNoteTool, UpdateInvoiceTool, UpdateManualJournalTool, UpdateQuoteTool, UpdateItemTool, UpdateBankTransactionTool, ApprovePayrollTimesheetTool, AddTimesheetLineTool, UpdatePayrollTimesheetLineTool, RevertPayrollTimesheetTool, UpdateTrackingCategoryTool, UpdateTrackingOptionsTool ];