UNPKG

xero-mcp

Version:

A Model Context Protocol server allows Clients to interact with Xero

152 lines (151 loc) 7.48 kB
import { XeroClientSession } from "../../XeroApiClient.js"; import { XeroAccountingApiSchema } from "../../Resources/xero_accounting.js"; import { parseArrayValues } from "../../Utils/parseArrayValues.js"; import { convertToCamelCase } from "../../Utils/convertToCamelCase.js"; import { sanitizeObject } from "../../Utils/sanitizeValues.js"; export const GetBankTransactionTool = { requestSchema: { name: "get_bank_transaction", description: "Retrieves a single spent or received money transaction by its Xero bank transaction ID", inputSchema: { type: "object", properties: { bankTransactionID: { type: "string", description: "Xero-generated unique identifier for the bank transaction (UUID)", }, unitdp: { type: "number", description: "Optional. Unit decimal places (e.g. 4) for unit amounts on line items", }, }, required: ["bankTransactionID"], }, }, requestHandler: async (request) => { const bankTransactionID = request.params.arguments ?.bankTransactionID; const unitdp = request.params.arguments?.unitdp; const response = await XeroClientSession.xeroClient.accountingApi.getBankTransaction(XeroClientSession.activeTenantId(), bankTransactionID, unitdp); return { content: [ { type: "text", text: JSON.stringify(response.body.bankTransactions ?? []), }, ], }; }, }; export const ListBankTransactionsTool = { requestSchema: { name: "list_bank_transactions", description: "Retrieves any spent or received money transactions", inputSchema: { type: "object", properties: { where: { type: "string", description: "Filter bank transactions by any element", example: 'Status=="AUTHORISED"', }, order: { type: "string", description: "Order by any element", example: "Type ASC", }, page: { type: "integer", description: "Up to 100 bank transactions will be returned in a single API call with line items details", example: 1, }, }, }, }, requestHandler: async (request) => { const where = request.params.arguments?.where; const order = request.params.arguments?.order; const page = request.params.arguments?.page; const response = await XeroClientSession.xeroClient.accountingApi.getBankTransactions(XeroClientSession.activeTenantId(), undefined, where, order, page); const bankTransactions = response.body.bankTransactions || []; return { content: [ { type: "text", text: JSON.stringify(bankTransactions), }, ], }; }, }; export const CreateBankTransactionsTool = { requestSchema: { name: "create_bank_transactions", description: "Creates one or more spent or received money transaction. Only use this tool when user has directly and explicitly ask you to create transactions.", inputSchema: { type: "object", description: "Transactions with an array of BankTransaction objects to create", properties: XeroAccountingApiSchema.components.schemas.BankTransactions.properties, example: '{ bankTransactions: [{ type: "SPEND", date: "2023-01-01", reference: "INV-001", subTotal: "100", total: "115", totalTax: "15", lineItems: [{ accountCode: "401", description: "taxi fare", lineAmount: "115" }], contact: { contactId: "00000000-0000-0000-0000-000000000000", name: "John Doe" }, "bankAccount": { "accountID": "6f7594f2-f059-4d56-9e67-47ac9733bfe9", "Code": "088", "Name": "Business Wells Fargo" } }]}', }, }, requestHandler: async (request) => { const rawInputData = request.params.arguments; const parsedData = parseArrayValues(rawInputData); const bankTransactions = convertToCamelCase(parsedData); const response = await XeroClientSession.xeroClient.accountingApi.createBankTransactions(XeroClientSession.activeTenantId(), sanitizeObject(bankTransactions)); return { content: [{ type: "text", text: JSON.stringify(response.body) }] }; }, }; export const UpdateBankTransactionTool = { requestSchema: { name: "update_bank_transaction", description: "Updates an existing spent or received money transaction by its Xero bank transaction ID", inputSchema: { type: "object", properties: { bankTransactionID: { type: "string", description: "Xero generated unique identifier for the bank transaction (UUID)", }, bankTransactions: { type: "object", description: "BankTransactions payload containing an array of bank transaction objects", properties: XeroAccountingApiSchema.components.schemas.BankTransactions.properties, example: '{ bankTransactions: [{ type: "SPEND", date: "2026-01-01", reference: "Expense Update", subTotal: 100, total: 115, totalTax: 15, lineItems: [{ accountCode: "401", description: "Taxi fare", lineAmount: 115 }], contact: { contactID: "00000000-0000-0000-0000-000000000000" }, bankAccount: { accountID: "6f7594f2-f059-4d56-9e67-47ac9733bfe9" }, status: "AUTHORISED" }]}', }, unitdp: { type: "number", description: "Optional. Unit decimal places (e.g. 4) for unit amounts on line items", }, idempotencyKey: { type: "string", description: "Optional idempotency key. Allows safe retries without duplicating processing", }, }, required: ["bankTransactionID", "bankTransactions"], }, }, requestHandler: async (request) => { const rawInputData = request.params.arguments; const parsedData = parseArrayValues(rawInputData); const bankTransactionID = parsedData?.bankTransactionID; const unitdp = parsedData?.unitdp; const idempotencyKey = parsedData?.idempotencyKey; const rawBankTransactionsPayload = parsedData?.bankTransactions; const bankTransactionsPayload = sanitizeObject(convertToCamelCase(rawBankTransactionsPayload)); if (!bankTransactionID) { // Should be prevented by request schema, but keep a hard guard. throw new Error("Missing required parameter: bankTransactionID"); } const response = await XeroClientSession.xeroClient.accountingApi.updateBankTransaction(XeroClientSession.activeTenantId(), bankTransactionID, bankTransactionsPayload, unitdp, idempotencyKey); return { content: [ { type: "text", text: JSON.stringify(response.body ?? response.response?.status), }, ], }; }, };