Connect Xero to ChatGPT: Sync Invoices, Payments & Financial Reports
Learn how to connect Xero to ChatGPT using a managed MCP server. Execute financial workflows, sync invoices, and automate payments with AI agents.
If you need to automate financial reporting, invoice generation, or payment reconciliation using natural language, you must connect Xero to ChatGPT. To do this securely and reliably, you need a Model Context Protocol (MCP) server that acts as a translation layer between the LLM's function calls and Xero's underlying REST architecture. If your team uses Claude, check out our guide on connecting Xero to Claude or explore our broader architectural overview on connecting Xero to AI Agents.
Giving a Large Language Model (LLM) read and write access to a core accounting system is inherently risky. Financial APIs are unforgiving. A malformed payload or a hallucinated account code results in bad ledger entries, compliance violations, and angry finance teams. You can either spend weeks building a custom MCP server to manage Xero's complex schema validations, authentication lifecycles, and rate limits, or you can use a managed platform to derive these tools dynamically. This guide breaks down exactly how to use Truto to generate a secure MCP server for Xero, connect it to ChatGPT, and execute complex workflows without writing integration code.
The Engineering Reality of the Xero API
A custom MCP server is a self-hosted integration layer. While Anthropic's open MCP standard provides a predictable protocol for models to discover tools over JSON-RPC 2.0, implementing it against vendor-specific APIs is an exercise in pain.
If you build a custom MCP server for Xero, you own the entire API lifecycle. You are not just dealing with generic CRUD operations. You are dealing with double-entry accounting schemas. Here are the specific integration challenges you face with Xero:
OData Filtering Instead of Standard Query Parameters
Unlike modern APIs that accept standard query strings for filtering (e.g., ?status=AUTHORISED), Xero relies heavily on a custom where parameter that requires strict OData syntax. To filter invoices by status and type, the LLM must construct a query string like where=Status=="AUTHORISED" AND Type=="ACCREC". If your custom MCP server does not provide explicit, detailed documentation inside the tool's JSON Schema, the LLM will hallucinate standard REST query parameters and the Xero API will reject the request.
Deeply Nested Line Items and Account Codes
Creating an invoice or a purchase order in Xero is not a simple flat JSON payload. Every LineItem must specify an exact AccountCode (which maps to the chart of accounts), a TaxType, and a UnitAmount. If an LLM tries to draft an invoice but hallucinates a generic "Sales" account code instead of the specific "200" code your Xero instance requires, the API throws a hard validation error. Your MCP server must first allow the LLM to query the chart of accounts, cache or retain that context, and then inject the correct codes into the creation payload.
The Reality of Rate Limits and HTTP 429s
Xero enforces strict rate limits (typically 60 calls per minute and 5000 per day per tenant). If an AI agent attempts to iterate over thousands of historical bank transactions without pacing itself, Xero will return an HTTP 429 Too Many Requests error.
Factual note on rate limits in Truto: Truto does not retry, throttle, or apply backoff on rate limit errors. When the upstream Xero API returns an HTTP 429, Truto passes that error directly back to the caller. However, Truto normalizes the upstream rate limit information into standardized headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) per the IETF spec. The AI agent or the client framework invoking the tool is entirely responsible for reading these headers and implementing its own retry or backoff logic.
How the Truto Xero MCP Server Works
Instead of hardcoding tool definitions, Truto generates MCP tools dynamically. When you authenticate a Xero account, Truto's MCP Router maps Xero's API endpoints into an array of AI-ready tools.
This is derived from two internal sources: the integration's resource definitions (which define the available endpoints) and the documentation records (which provide the human-readable descriptions and JSON Schema definitions for query and body parameters). A tool only appears in the MCP server if it has a corresponding documentation record. This acts as a strict quality gate, ensuring only well-described, predictable endpoints are exposed to ChatGPT.
When ChatGPT invokes a tool like create_a_xero_invoice, the payload arrives at Truto's /mcp/:token endpoint as a flat JSON object. Truto's router dynamically splits this flat object into query parameters and body parameters using the documented JSON Schemas, maps them to the underlying Xero proxy API, executes the request using the securely managed OAuth token, and returns the serialized result back to the model.
Creating the Xero MCP Server
To expose Xero tools to ChatGPT, you first need to generate an MCP server URL scoped to your specific Xero connection. Each MCP server URL contains a cryptographic token that authenticates the request and routes it to the correct tenant.
You can create this server in two ways.
Method 1: Via the Truto UI
The fastest way to generate an MCP server is directly through the Truto dashboard.
- Navigate to the Integrated Accounts page for your Xero connection.
- Click the MCP Servers tab.
- Click Create MCP Server.
- Select your desired configuration. You can filter by methods (e.g., restrict the server to only "read" operations) or set an expiration date.
- Click Create and copy the generated MCP server URL (e.g.,
https://api.truto.one/mcp/a1b2c3d4...).
Method 2: Via the Truto API
For teams building automated agent provisioning, you can generate the MCP server programmatically via the API. The endpoint validates your configuration, stores the token securely in Cloudflare KV, and returns the URL.
Endpoint: POST /integrated-account/:id/mcp
{
"name": "Xero Finance Agent MCP",
"config": {
"methods": ["read", "write"]
},
"expires_at": "2026-12-31T23:59:59Z"
}Response:
{
"id": "mcp_12345abcde",
"name": "Xero Finance Agent MCP",
"config": { "methods": ["read", "write"] },
"expires_at": "2026-12-31T23:59:59Z",
"url": "https://api.truto.one/mcp/a1b2c3d4e5f67890"
}This URL is fully self-contained. It handles the routing, token lookup, and proxy execution behind the scenes.
Connecting the Xero MCP Server to ChatGPT
Once you have your Truto MCP URL, you must register it with your LLM client. Here are the two primary ways to connect the server.
Method A: Via the ChatGPT UI (Custom Connectors)
If you are using ChatGPT Pro, Team, or Enterprise, you can connect the remote MCP server directly via the interface.
- In ChatGPT, navigate to Settings -> Apps -> Advanced settings.
- Enable Developer mode (MCP support requires this flag).
- Under the MCP servers / Custom connectors section, click to add a new server.
- Enter a name for the connection (e.g., "Xero Production").
- Paste the Truto MCP Server URL into the configuration field.
- Save the configuration. ChatGPT will immediately perform an MCP
initializehandshake and load the available Xero tools.
Method B: Via Manual Config File (SSE Transport)
If you are running a local ChatGPT client wrapper, Claude Desktop, or a custom agent framework (like LangChain or AutoGen) that relies on local configuration files, you can connect to the remote Truto server using a Server-Sent Events (SSE) proxy command.
Add the following to your agent's MCP configuration JSON file:
{
"mcpServers": {
"xero-financials": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sse",
"https://api.truto.one/mcp/a1b2c3d4e5f67890"
]
}
}
}When your agent boots, it executes the npx command, which establishes an SSE connection to the remote Truto endpoint, facilitating the JSON-RPC protocol exchange.
Hero Tools for Financial Automation
Truto exposes the full surface area of the Xero API, but a few high-leverage tools drive the vast majority of AI agent workflows. Here are the most critical tools your agent will use.
list_all_xero_profit_and_loss
This tool retrieves the full Profit and Loss report from Xero. It returns the ReportTitles, ReportDate, and Rows containing the heavily nested financial line-item data. This is the foundation for any AI agent performing financial analysis or answering executive queries about company performance.
"Run the profit and loss report for the current financial period. Summarize our gross profit margin and identify our three highest operational expenses. Compare these expenses to our total revenue."
get_single_xero_invoice_by_id
When a customer asks about a specific bill, or when reconciling a discrepancy, the agent uses this tool to pull the exact invoice record. It returns deeply nested LineItems, TotalTax, AmountDue, AmountPaid, and standard Status fields (like AUTHORISED or PAID).
"Look up invoice INV-1045. Tell me the total amount due, whether it has been paid, and summarize the line items on the bill so I can explain the charges to the client."
create_a_xero_invoice
This tool allows the agent to draft new sales invoices or purchase bills. The agent must construct an array of LineItems containing the exact Description, Quantity, UnitAmount, and crucially, the valid AccountCode. Because the agent handles the construction, it can draft invoices directly from natural language requests.
"Create a draft sales invoice for the contact 'Acme Corp'. Add two line items: 10 hours of 'Consulting Services' at $150 per hour, and 1 'Software License' at $500. Use account code 200 for both lines."
list_all_xero_bank_transactions
This tool pulls spent or received money transactions directly from connected bank accounts in Xero. It returns the Type, Status, SubTotal, and IsReconciled flags. Agents use this to perform automated audits or to match raw bank data against open invoices.
"Fetch all unreconciled bank transactions from the last 7 days. Cross-reference the transaction amounts with our open invoices to see if any client has paid us without explicitly citing their invoice number."
create_a_xero_payment
Closing the loop on accounts receivable requires applying payments to invoices. This tool takes a Payments array containing the InvoiceID, the Account the money landed in, the Date, and the Amount. Executing this tool updates the invoice status in real-time.
"Record a payment of $2,000 against invoice INV-1045. The payment was received today into our primary operating account. Mark the invoice as fully paid."
get_single_xero_contact_by_id
Before drafting quotes, creating invoices, or assigning payments, the agent needs the canonical ID of the customer or supplier. This tool fetches the full profile, including PaymentTerms, Balances, and ContactStatus.
"Pull the full contact record for 'Global Industries'. Check their current outstanding balance and confirm their default payment terms before I draft a new quote for them."
For the complete tool inventory and granular JSON Schema details for Xero (including purchase orders, repeating invoices, and tax rates), review the Xero integration page.
Workflows in Action
Connecting tools to ChatGPT is only useful if the model knows how to chain them together to solve complex problems. Here is how an AI agent executes real-world financial operations.
Workflow 1: End-of-Month Invoice Reconciliation
Reconciliation is highly manual. Finance teams spend hours matching bank deposits to open accounts receivable. An AI agent can automate this investigation process.
"Find all open invoices that are currently past due. Then, check our recent bank transactions for any deposits that perfectly match the total amount due on those invoices. If you find a match, record the payment against the invoice automatically."
Here is how the agent executes this sequence:
list_all_xero_invoices: The agent queries for invoices using a where clause filter (where=Status=="AUTHORISED" AND AmountDue>0) to isolate unpaid bills.list_all_xero_bank_transactions: The agent fetches recent bank activity, looking forType=="RECEIVE"transactions.- Local Computation: The LLM compares the
AmountDuefrom step 1 with theTotalof the received bank transactions in step 2. It identifies a $4,500 deposit that perfectly matches INV-9920. create_a_xero_payment: The agent executes the payment tool, passing theInvoiceID,AccountID, andAmountto reconcile the ledger.
The user receives a confirmation: "I found 4 past-due invoices. I matched a $4,500 bank deposit to INV-9920 and successfully applied the payment in Xero. The invoice is now marked as PAID. The remaining 3 invoices require manual review."
sequenceDiagram
participant User as User
participant ChatGPT as ChatGPT
participant MCP as Truto MCP Server
participant Xero as Xero API
User->>ChatGPT: "Reconcile past-due invoices with bank deposits"
ChatGPT->>MCP: Call tool: list_all_xero_invoices<br>(Status=AUTHORISED)
MCP->>Xero: GET /api.xro/2.0/Invoices
Xero-->>MCP: Return unpaid invoices
MCP-->>ChatGPT: JSON result
ChatGPT->>MCP: Call tool: list_all_xero_bank_transactions
MCP->>Xero: GET /api.xro/2.0/BankTransactions
Xero-->>MCP: Return recent deposits
MCP-->>ChatGPT: JSON result
Note over ChatGPT: Matches $4,500 deposit<br>to INV-9920
ChatGPT->>MCP: Call tool: create_a_xero_payment<br>(InvoiceID, Amount)
MCP->>Xero: PUT /api.xro/2.0/Payments
Xero-->>MCP: 200 OK (Payment recorded)
MCP-->>ChatGPT: Success response
ChatGPT-->>User: "INV-9920 marked as PAID."Workflow 2: Financial Health & Executive Summary
Founders and executives rarely want to log into Xero to generate reports. They just want answers to specific financial questions.
"Analyze our financial performance for the last quarter. Generate a summary of our P&L, highlight the top three expense categories, and calculate our net profit margin."
Here is how the agent handles reporting:
list_all_xero_profit_and_loss: The agent invokes the P&L report tool, specifying the dates for the last quarter.- Local Data Parsing: The LLM ingests the nested
Rowsarray, traversing the hierarchy of the Income and Expense sections. It extracts Total Operating Revenue, calculates the total from the specific expense lines, and derives the net profit margin. - Synthesis: The LLM formats the raw JSON arrays into a human-readable executive summary.
The user gets a concise markdown summary breaking down exact figures directly sourced from the accounting ledger, without ever opening a spreadsheet.
Security and Access Control
Exposing your general ledger to an AI agent requires strict guardrails. Truto's MCP architecture provides multiple layers of security to ensure the LLM cannot cause financial damage.
- Method Filtering: When creating the MCP server, you can restrict operations by HTTP method. Setting
config: { methods: ["read"] }ensures the agent can executegetandlisttools (like running P&L reports) but physically cannot accesscreate,update, ordeletetools. This makes the server completely read-only. - Tag Filtering: You can restrict the MCP server to specific functional domains. If you only want an agent to manage contacts, you can filter tools by specific tags, hiding all banking and payroll endpoints from the LLM.
- Require API Token Auth: By default, possession of the MCP URL is sufficient to call tools. For strict enterprise environments, you can set
require_api_token_auth: true. This forces the client framework to pass a valid Truto API token in the Authorization header, preventing unauthorized access if the MCP URL is accidentally leaked in logs or config files. - Automatic Expiration: If you are provisioning an agent for a temporary audit or a specific short-lived task, you can set an
expires_attimestamp. Cloudflare KV will automatically drop the token and a scheduled Durable Object alarm will purge the database record, ensuring no orphaned access points remain.
The Shift to Agentic Finance
The value of ChatGPT is no longer just in writing emails or generating code; it is in executing complex business logic across enterprise systems. By connecting Xero via a managed MCP server, you transform an LLM from a passive chatbot into an active financial controller.
Building a custom server requires wrestling with Xero's OData syntax, managing OAuth tokens, maintaining massive nested JSON schemas, and building manual rate limit backoff logic. Truto abstracts this entire layer, generating documented, AI-ready tools dynamically from the underlying API. You get secure, rate-limit-aware integration out of the box, allowing your engineering team to focus on building agent capabilities rather than maintaining REST API plumbing.
FAQ
- How do I connect Xero to ChatGPT?
- You can connect Xero to ChatGPT by generating a Model Context Protocol (MCP) server URL via Truto. This URL acts as a secure bridge, allowing ChatGPT to discover and execute Xero API endpoints as native tools.
- Does Truto automatically retry Xero API rate limit errors?
- No. Truto does not retry, throttle, or apply backoff on rate limit errors. When Xero returns an HTTP 429 error, Truto passes that error directly to the caller and normalizes the rate limit info into standardized IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset). The calling AI agent is responsible for implementing retry logic.
- Can I restrict ChatGPT to read-only access for Xero?
- Yes. When creating the MCP server in Truto, you can pass a configuration object with specific method filters (e.g., config: { methods: ["read"] }). This ensures ChatGPT can only list or get data, preventing it from creating or deleting financial records.