MCP servers for AI agents (x0 + xerosim)
Two local MCP servers teach agents the x0 OData API and the Xero API simulator before they call your live endpoints. x0 cannot see MCP tool calls on your machine — it only sees the HTTP requests your agent makes afterward. Customers with MCP configured typically make fewer discovery calls (/Tables, /$metadata) and more targeted reads ($select, $filter).
Which MCP do I need?
| MCP | Use when |
|---|---|
x0 (agent_mcp.x0) |
Your agent reads Xero data through x0 OData (api.x0.co.nz) |
xerosim (agent_mcp.xerosim) |
Your agent tests against the Xero API simulator during development |
Most production agents need x0 only. Use xerosim while building integrations before connecting real Xero.
What the MCP gives your agent
Both servers expose tools (and browseable resources) with:
- Every table / resource — name, kind, primary key, OAuth/API scope
- Field-level schema — name, data type, official description, example value
- Linkages — foreign keys (
ContactID→ Contacts),*_Tableline grains, Attachments parent types - Schema diagram — mermaid ER flowchart (
get_schema_diagram) to show users or paste into their docs - Agent rules — auth, cache (
refresh=truesparingly), multi-tenant headers, query options - Xero quirks — journals tier gate, pagination traps, scope consent failures
- Write rules (x0) — Accounts / Contacts / Invoices preflight checks
Your agent should call list_tables / describe_table (or list_resources / describe_resource for sim) once per session, then query x0 with $select — not re-probe /$metadata on every turn.
Install
From your x0 shim checkout (or the copy we ship in docs):
cd shim
python3 -m venv .venv-mcp
.venv-mcp/bin/pip install -r agent_mcp/requirements-mcp.txt
Requirements: Python 3.10+, network only for optional live query_odata / query_sim tools. Schema tools work offline.
Cursor configuration
Project or user mcp.json (paths adjusted to your machine):
{
"mcpServers": {
"x0": {
"command": "/path/to/x0/shim/.venv-mcp/bin/python",
"args": ["-m", "agent_mcp.x0"],
"cwd": "/path/to/x0/shim",
"env": {
"X0_API_BASE_URL": "https://api.x0.co.nz",
"X0_API_KEY": "x0_live_<token_id>.<secret>"
}
},
"xerosim": {
"command": "/path/to/x0/shim/.venv-mcp/bin/python",
"args": ["-m", "agent_mcp.xerosim"],
"cwd": "/path/to/x0/shim",
"env": {
"XEROSIM_BASE_URL": "https://sim.dev.x0.co.nz",
"XEROSIM_BEARER_TOKEN": "<sim-oauth-access-token>"
}
}
}
}
Copy the full example from shim/agent_mcp/mcp-config.example.json.
Security
- Put
X0_API_KEYin the MCP serverenvblock — never in chat or tool arguments. - Issue a key in the portal with minimum scopes your agent needs.
- Optional live tools:
query_odata(x0),query_sim(xerosim). Schema-only workflows need no key.
Claude Desktop / other MCP clients
Same pattern: stdio transport, command = venv python, args = -m agent_mcp.x0 or -m agent_mcp.xerosim, cwd = shim directory.
Recommended agent workflow (x0)
list_tables— see entity sets your key can access (match with portal scopes).describe_tablefor each entity you will use — fields, examples, PK,summary_only_fields.get_linkages— join paths (e.g. Invoices → Contacts).get_schema_diagram— mermaid flowchart for the user (detail=overvieworfull).get_agent_rules— especiallycacheandauthcategories.GET /odata/v1/Accounts?$select=Code,Name(via your HTTP client or optionalquery_odata) — targeted reads.- Use
?_Tableentity sets when you need one row per line item (Invoices_Table, not nestedLineItemsin code).
Avoid on every turn:
GET /odata/v1/$metadataGET /odata/v1/Tables(unless scopes changed)- Full
Invoiceswithout$select refresh=trueon scheduled loops
Cache, gzip, and freshness (agent essentials)
Call get_cache_policy (or get_agent_rules category cache / transport) before assuming live data.
| Topic | Agent behaviour |
|---|---|
| Gzip | Send Accept-Encoding: gzip (Standard+). httpx/curl decompress automatically — you get JSON, not raw bytes. Not used by Excel Power Query. |
| Force refresh | ?refresh=true (or 1 / force) when you posted in Xero. Once per event — not every poll. Watch X-X0-Sync. |
| If-Modified-Since | HTTP header on OData GET → filters cached rows by UpdatedDateUTC. Does not pull from Xero. Use refresh=true first if cache may be stale. |
| TTL | No “query TTL” API. Defaults: reference ~1h, mid ~6h, large ~24h. Use X-X0-Fetched-At + get_cache_policy, or portal Data cache table. |
x0 MCP tools reference
| Tool | Purpose |
|---|---|
list_tables |
OData entity sets, scopes, descriptions |
describe_table |
Full field catalog for one entity |
get_linkages |
FK + line-table relationships |
get_schema_diagram |
Mermaid ER diagram (overview / full) — paste markdown into user docs |
get_agent_rules |
Cache, auth, discovery order |
get_xero_quirks |
Platform traps (journals, scopes) |
get_cache_policy |
TTL classes, refresh=, If-Modified-Since, gzip, freshness headers |
get_write_rules |
Write preflight for Accounts/Contacts/Invoices |
query_odata |
Optional live GET (needs X0_API_KEY; gzip + If-Modified-Since) |
Resources: x0://tables, x0://rules, x0://linkages, x0://schema-diagram
xerosim MCP tools reference
| Tool | Purpose |
|---|---|
list_resources |
Accounting + Bank Feeds collections |
describe_resource |
Fields + pagination, attachments, writable flag |
get_linkages |
Same linkage model as x0 |
get_agent_rules |
OAuth, read-only default, rate limits |
get_xero_quirks |
Shared Xero notes |
query_sim |
Optional live GET (needs bearer token) |
Resources: xerosim://resources, xerosim://rules
How x0 knows MCP is helping
MCP runs locally — we do not receive MCP tool invocations. We infer agent quality from your x0 API traffic:
| Pattern | Meaning |
|---|---|
Many /Tables, /$metadata, /X0 |
Discovery / probing |
Large tables without $select |
Broad pulls — often wasteful |
$select / $filter on entity sets |
Informed reads |
User-Agent: x0-mcp/… |
Live read via MCP query_odata tool |
Your portal Dashboard → Agent API efficiency shows these buckets and a simple score. Staff see aggregates on Mission Control → Performance.
Validate your install
cd shim
./scripts/validate_mcp.sh
Or with pytest: pytest tests/test_mcp_servers.py tests/test_agent_mcp.py -q
Troubleshooting
| Problem | Fix |
|---|---|
| MCP server won't start | Check venv, pip install -r agent_mcp/requirements-mcp.txt, cwd = shim |
query_odata says no key |
Set X0_API_KEY in MCP env, not in chat |
| 403 from x0 | Key missing scope — check portal key scopes vs list_tables |
Agent still hammers /Tables |
Prompt it to call describe_table once; point to this guide |
| Empty field list | Entity may be sim-only (BankStatements) — uses endpoint seed hints |
Related
- AI agents — HTTP discovery order, Bearer auth
- OData —
$filter,$select, scopes - Data schema — dashboard diagram + mermaid
- Data freshness — cache and
refresh=true - Xero API simulator — hosted sim URL and x0 wiring
- Repo:
shim/agent_mcp/README.md(operator notes)