I spent 2 hours trying to connect Xero to Claude. The reason it failed? My company is registered in Cyprus.
Here's what happened — and the fix that took 5 minutes once I knew what I was looking for.
The Problem
Xero has an official MCP server that connects to Claude Code. Their setup documentation tells you to create a Custom Connection in the Xero developer portal.
I went to the portal. Created an app. Got to the Add Connection step.
Blocked. No useful error. Just couldn't proceed.
After digging through Xero's documentation: Custom Connection is a machine-to-machine OAuth 2.0 feature that Xero only makes available for accounts registered in Australia, New Zealand, United Kingdom, and United States.
Cyprus? No. Most of Europe? No. If your Xero organization is in any other region, the "Add Connection" button in the developer portal simply doesn't work.
Why Custom Connection Is Restricted
Custom Connection uses the OAuth 2.0 client credentials flow — no browser login required, tokens are machine-issued. Xero treats this as a premium feature tied to their enterprise tier in certain markets. It's a business decision, not a technical one.
The restriction applies to the Xero organization, not to your developer account. Even if you create the developer account in a different country, if your connected Xero org is registered in Cyprus, you're blocked.
The Fix: Web App OAuth
In the same Xero developer portal, there's a different app type: Web app. This uses the standard OAuth 2.0 Authorization Code flow — the same flow that every third-party Xero integration uses. It's available for all regions, all Xero plans, with no restrictions.
The tradeoff: you need to do a one-time browser login to authorize access to your Xero organization. After that, the MCP server handles token refresh automatically. You never need to log in again.
Here's the complete setup:
Step 1 — Create a Web App in Xero Developer Portal
- Go to developer.xero.com/app/manage
- Click New app
- Select Web app (not Custom Connection)
- Set Redirect URI to
http://localhost:3000/callback - Save and copy the Client ID and Client Secret
You do not need to touch the "Add Connection" button. That's only for Custom Connections. For Web Apps, the connection to your Xero org happens through the OAuth browser flow.
Step 2 — Configure the MCP Server
Add to your ~/.mcp.json:
{
"mcpServers": {
"xero": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@xeroapi/xero-mcp-server"],
"env": {
"XERO_CLIENT_ID": "your-client-id",
"XERO_CLIENT_SECRET": "your-client-secret"
}
}
}
}
Step 3 — One-Time Browser Authorization
Restart Claude Code. On first use, the server opens a browser window for the Xero OAuth flow. Log in, select your organization, click Allow. Done. The server stores the refresh token and auto-renews it from that point forward.
What Works the Same
The MCP server doesn't care which app type you used to get the credentials. Once authorized, it has the same access either way:
- Invoices, contacts, accounts, payments
- Reports (P&L, balance sheet, aged receivables)
- Bank transactions and reconciliation status
- Create and update operations (with the right scopes)
The only difference from Custom Connection: that initial browser login, and the fact that Web App tokens are tied to a specific user's authorization rather than a machine identity. For a solo user or small team, this is irrelevant.
If You Hit This Wall
The symptom is specific: you can create a Xero developer app, you get a Client ID and Client Secret, but the "Add Connection" step in the portal fails silently or is greyed out. That's the Custom Connection restriction.
The moment you switch to Web App as the app type, the "Add Connection" step disappears from the flow entirely — because Web Apps don't use it. The connection happens at authorization time in the browser.
For the full Xero MCP setup guide including scopes, troubleshooting, and what Claude can query, see the complete tutorial here.