Cloudflare Workers Model Context Protocol server bridging Claude to Xero accounting — invoices, contacts, bank transactions, payments, P&L, balance sheet. Proxied OAuth 2.0. Built on @bashco/mcp-toolkit.
Xero-mcp demonstrates solid fundamentals: all 19 tools have clear verb-noun naming (get_, list_, create_, update_), descriptions present for all tools and parameters, and explicit Zod schemas with type validation. However, output schemas are not documented, responses are JSON stringified without field-level documentation, forcing LLMs to infer structure. Parameter descriptions are functional but generic (e.g., 'Contact UUID' lacks context on when to use contact_id vs contact_name). Address objects lack nested field documentation. Error handling is present but minimal, no recovery guidance or actionable next steps. Pagination is implemented but not consistently documented across all list tools.
Create a new bank transaction in Xero with contact, line items, bank account, and dates
Create a new contact in Xero with name, email, phone, addresses, and tax information
Create a new invoice in Xero with contact, line items, dates, and optional reference
Create a new payment in Xero for an invoice with amount, date, and account
Retrieve Xero balance sheet report for a specified date
Retrieve detailed information for a specific Xero bank transaction by ID
Output schemas not documented. Tools return JSON.stringify() of sanitized objects without field-level documentation. LLMs cannot plan downstream calls or extract specific fields reliably.
Mutually exclusive parameters (contact_id vs contact_name, account_id vs account_code, bank_account_id vs bank_account_code) lack explicit documentation of the mutual exclusivity constraint. LLMs may pass both, causing ambiguous behavior.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 58 | 2026-07-28+ | v2 |
Retrieve detailed information for a specific Xero contact by ID
Retrieve detailed information for a specific Xero invoice by ID
Retrieve the current Xero organisation details
Retrieve detailed information for a specific Xero payment by ID
Retrieve Xero profit and loss report for a specified date range
List Xero accounts with optional filtering by type and pagination
List Xero bank transactions with optional filtering by type, status, contact, and pagination
List Xero contacts with optional name filtering and pagination
List Xero invoices with optional filtering by type, status, contact, and pagination
List Xero payments with optional filtering by invoice, status, and pagination
Update an existing Xero bank transaction by ID with new contact, line items, bank account, and dates
Update an existing Xero contact by ID with new name, email, phone, addresses, and tax information
Update an existing Xero invoice by ID with new contact, line items, dates, and reference
Nested object parameters (street_address, billing_address, line_items) lack field-level descriptions. LLMs cannot determine which nested fields are required vs optional or what format they expect.
Error handling returns raw ToolError without recovery guidance. Errors like 'Contact not found' do not suggest next steps (e.g., 'Try list_contacts() to find the correct ID').
Pagination documented inconsistently. list_contacts, list_invoices, list_bank_transactions, list_payments, and list_accounts all support pagination but descriptions do not state result limits or total count availability.