Templatetypescriptexpressadvancedโœ“ Production ReadyFreeโœ… Code Verified

Production Xero MCP Server Starter Template (TypeScript)

A production-ready Xero MCP Server built with TypeScript and Express, featuring OAuth 2.0 Authorization Code flow with token refresh, structured Pino logging, rate limiting, health monitoring, Docker support, and GitHub Actions CI/CD. Includes realistic Xero API tools for invoices, contacts, and accounts with full type safety.

๐Ÿ“– 18 min readโš™๏ธ Setup: 45 minutesutilities
xeroxero mcp servermcptypescriptstarter templateproductiondockeroauthclaudecursor

Files(15)

# โ”€โ”€โ”€ Server โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# Port the Express server will listen on
PORT=3000

# Runtime environment: development | production | test
NODE_ENV=development

# Pino log level: trace | debug | info | warn | error | fatal
LOG_LEVEL=info

# Public base URL used in log messages and OAuth redirects (no trailing slash)
SERVER_BASE_URL=http://localhost:3000

# โ”€โ”€โ”€ MCP Authentication โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# Shared secret that clients must supply in the X-API-Key request header.
# Generate a strong random value: openssl rand -hex 32
MCP_API_KEY=change-me-to-a-strong-random-secret

# โ”€โ”€โ”€ Xero OAuth 2.0 โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# Client ID from https://developer.xero.com/app/manage
XERO_CLIENT_ID=your-xero-client-id

# Client Secret from https://developer.xero.com/app/manage
XERO_CLIENT_SECRET=your-xero-client-secret

# Must exactly match one of the redirect URIs registered in your Xero app
XERO_REDIRECT_URI=http://localhost:3000/auth/xero/callback

# Space-separated list of Xero OAuth scopes to request
XERO_SCOPES=openid profile email accounting.transactions accounting.contacts accounting.settings offline_access

# โ”€โ”€โ”€ Rate Limiting โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
# Time window for rate limiting in milliseconds (default: 15 minutes)
RATE_LIMIT_WINDOW_MS=900000

# Maximum number of requests per IP per window
RATE_LIMIT_MAX=100

Interactive tester

Test Your Server

Enter a deployed HTTP MCP server URL and API key to run live browser checks.

No signup

Use the public MCP endpoint, not a dashboard URL or local stdio command.

The key stays in this browser check and is sent to the endpoint you enter.

For local servers, use the local testing guide or MCP Inspector. This online tester works best with deployed HTTP MCP servers.

Production Xero MCP Server Template (TypeScript)

Overview

This template provides a complete, production-ready Model Context Protocol (MCP) server that integrates with the Xero accounting platform. Built with TypeScript and Express, it implements the full OAuth 2.0 Authorization Code flow with automatic token refresh, enabling Claude and other MCP clients to securely interact with Xero data on behalf of authenticated users.

The server exposes realistic Xero accounting tools โ€” creating and listing invoices, managing contacts, retrieving account balances, and tracking payments โ€” giving your AI assistant genuine financial superpowers. Every component follows production engineering standards: structured JSON logging with Pino, per-request correlation IDs, configurable rate limiting, a dependency-aware health endpoint, and a multi-stage Docker build that produces a lean production image.

This template targets TypeScript developers building internal finance tools, accounting automation platforms, or AI-powered bookkeeping assistants. It is designed to be cloned, configured with your Xero app credentials, and deployed to Railway, Fly.io, or any Docker-capable host within minutes.

๐Ÿš€ Production Repository

Want the complete production-ready starter template?

โญ GitHub Repository:

https://github.com/kamolc4/xero-mcp-server

Includes:

  • Complete TypeScript source code
  • OAuth 2.0 implementation
  • MCP tools
  • Jest tests
  • GitHub Actions CI
  • MIT License
  • Ready for Claude Desktop, Cursor and Windsurf

What You'll Learn

  • How to implement the full OAuth 2.0 Authorization Code flow (PKCE-ready) with Xero, including token storage and automatic refresh
  • Registering typed MCP tools using the official @modelcontextprotocol/sdk with Zod input validation
  • Structuring a production Express + MCP HTTP server with middleware layering
  • Generating and propagating per-request correlation IDs for distributed tracing
  • Configuring Pino for structured JSON logging with child loggers and log-level control via environment variables
  • Implementing a /health endpoint that reports on OAuth token validity and external API reachability
  • Applying express-rate-limit to protect your MCP endpoint from abuse
  • Writing HTTP-level integration tests with Jest and Supertest covering auth, tools, and health
  • Building a multi-stage Dockerfile that separates build and runtime layers for minimal image size
  • Automating lint, type-check, test, and Docker build steps in a GitHub Actions CI pipeline
  • Managing all configuration through environment variables with runtime validation
  • Handling Xero API errors gracefully and surfacing them as structured MCP error responses

Architecture

Claude Desktop / Cursor
        โ”‚
        โ”‚  HTTP POST /mcp  (MCP JSON-RPC)
        โ–ผ
  Express Server
        โ”‚
        โ”œโ”€โ”€ Correlation ID Middleware
        โ”œโ”€โ”€ Pino Request Logger
        โ”œโ”€โ”€ Rate Limiter (express-rate-limit)
        โ”œโ”€โ”€ Authentication Middleware (X-API-Key header)
        โ”‚
        โ–ผ
   MCP SDK Handler
        โ”‚
        โ”œโ”€โ”€ Tool: xero_list_invoices    โ”€โ”€โ–บ Xero Token Store โ”€โ”€โ–บ Xero API
        โ”œโ”€โ”€ Tool: xero_create_invoice   โ”€โ”€โ–บ Xero Token Store โ”€โ”€โ–บ Xero API
        โ”œโ”€โ”€ Tool: xero_list_contacts    โ”€โ”€โ–บ Xero Token Store โ”€โ”€โ–บ Xero API
        โ”œโ”€โ”€ Tool: xero_get_account      โ”€โ”€โ–บ Xero Token Store โ”€โ”€โ–บ Xero API
        โ””โ”€โ”€ Tool: xero_create_payment   โ”€โ”€โ–บ Xero Token Store โ”€โ”€โ–บ Xero API

  OAuth Flow (separate routes)
        GET /auth/xero          โ†’ redirect to Xero
        GET /auth/xero/callback โ†’ exchange code, store tokens
        GET /auth/status        โ†’ token validity check

  GET /health  โ†’  { status, xero, uptime, version }

Project Structure

xero-mcp-server/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ __tests__/
โ”‚   โ”‚   โ”œโ”€โ”€ setup.ts
โ”‚   โ”‚   โ””โ”€โ”€ config.test.ts
โ”‚   โ”œโ”€โ”€ auth.ts
โ”‚   โ”œโ”€โ”€ config.ts
โ”‚   โ”œโ”€โ”€ health.ts
โ”‚   โ”œโ”€โ”€ logger.ts
โ”‚   โ”œโ”€โ”€ server.ts
โ”‚   โ””โ”€โ”€ xeroClient.ts
โ”œโ”€โ”€ .dockerignore
โ”œโ”€โ”€ .env.example
โ”œโ”€โ”€ .gitignore
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ docker-compose.yml
โ”œโ”€โ”€ eslint.config.js
โ”œโ”€โ”€ jest.config.ts
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ package-lock.json
โ””โ”€โ”€ tsconfig.json

Source Code

This article explains every part of the implementation.

If you want to skip the manual setup and start immediately, clone the complete repository:

https://github.com/kamolc4/xero-mcp-server

The repository includes:

  • Production-ready project structure
  • OAuth implementation
  • Xero client
  • MCP tools
  • CI pipeline
  • Tests
  • Documentation
  • MIT license

You can fork the repository or download it as a ZIP.

Prerequisites

  • Node.js 20+
  • npm 10+
  • A Xero Developer App with OAuth 2.0 credentials
  • Docker & Docker Compose (for containerised development)
  • A Xero sandbox or real organisation connected to your developer app

Quick Start

# 1. Clone the template
git clone https://github.com/your-org/xero-mcp-server.git
cd xero-mcp-server

# 2. Install dependencies
npm install

# 3. Configure environment
cp .env.example .env
# Edit .env with your Xero Client ID, Client Secret, and a strong MCP_API_KEY

# 4. Start in development mode
npm run dev

# 5. Authorise with Xero (opens browser flow)
curl http://localhost:3000/auth/xero
# Follow the redirect, complete OAuth, tokens are stored automatically

# 6. Check health
curl http://localhost:3000/health

# 7. Test a tool call
curl -X POST http://localhost:3000/mcp \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: your-mcp-api-key' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"xero_list_invoices","arguments":{"status":"DRAFT","page":1}}}'

# 8. Run tests
npm test

Features

  • Full Xero OAuth 2.0 flow โ€” Authorization Code + PKCE-ready flow, automatic token refresh, in-memory token store (swap for Redis/DB in production)
  • Five realistic Xero tools โ€” list invoices, create invoice, list contacts, get account details, create payment
  • Zod input validation โ€” every tool validates its arguments at the MCP layer before hitting the API
  • Pino structured logging โ€” JSON output, configurable log level, per-request correlation IDs propagated through child loggers
  • Rate limiting โ€” 100 requests/15 min window on the MCP endpoint, configurable via env vars
  • Health endpoint โ€” /health returns uptime, version, and live Xero token/API status
  • MCP endpoint authentication โ€” simple API key guard on the /mcp route
  • Multi-stage Docker build โ€” builder stage compiles TypeScript, runtime stage contains only compiled JS
  • docker-compose.yml โ€” single command local dev with automatic .env loading
  • Jest + Supertest tests โ€” covers health 200, auth 401, and tool execution
  • GitHub Actions CI โ€” lint, type-check, test, and Docker build on every push and PR

Works With

  • Claude Desktop โ€” add server URL and API key to claude_desktop_config.json
  • Claude Code โ€” use --mcp-server flag pointing at your deployed URL
  • Cursor โ€” configure under Settings โ†’ MCP Servers
  • Windsurf โ€” add to MCP server list in workspace settings
  • Continue โ€” add as an MCP provider in config.json

Claude Desktop Configuration Example

{
  "mcpServers": {
    "xero": {
      "url": "http://localhost:3000/mcp",
      "headers": {
        "X-API-Key": "your-mcp-api-key"
      }
    }
  }
}

Configuration

VariableDescriptionRequired
PORTHTTP port the server listens onOptional (default: 3000)
NODE_ENVRuntime environment (development/production)Optional (default: development)
LOG_LEVELPino log level (trace/debug/info/warn/error)Optional (default: info)
MCP_API_KEYShared secret required in X-API-Key header for /mcpRequired
XERO_CLIENT_IDOAuth 2.0 Client ID from Xero Developer portalRequired
XERO_CLIENT_SECRETOAuth 2.0 Client Secret from Xero Developer portalRequired
XERO_REDIRECT_URICallback URL registered in your Xero app (must match exactly)Required
XERO_SCOPESSpace-separated Xero OAuth scopesOptional (default: openid profile email accounting.transactions accounting.contacts accounting.settings offline_access)
RATE_LIMIT_WINDOW_MSRate limit window in millisecondsOptional (default: 900000)
RATE_LIMIT_MAXMax requests per window per IPOptional (default: 100)
SERVER_BASE_URLPublic base URL of this server (used to build redirect URIs in logs)Optional

Deployment

Docker (local)

docker compose up --build

Docker (production build)

docker build -t xero-mcp-server:latest .
docker run -d \
  --name xero-mcp \
  -p 3000:3000 \
  --env-file .env \
  xero-mcp-server:latest

Railway

npm install -g @railway/cli
railway login
railway init
railway variables set XERO_CLIENT_ID=xxx XERO_CLIENT_SECRET=xxx MCP_API_KEY=xxx XERO_REDIRECT_URI=https://your-app.railway.app/auth/xero/callback
railway up

Fly.io

flyctl launch --name xero-mcp-server
flyctl secrets set XERO_CLIENT_ID=xxx XERO_CLIENT_SECRET=xxx MCP_API_KEY=xxx XERO_REDIRECT_URI=https://xero-mcp-server.fly.dev/auth/xero/callback
flyctl deploy

Production Checklist

  • MCP_API_KEY is at least 32 random characters and stored in a secrets manager
  • XERO_CLIENT_SECRET is never committed to source control
  • NODE_ENV=production is set in the deployment environment
  • XERO_REDIRECT_URI exactly matches the URI registered in the Xero Developer portal
  • Token storage is backed by a persistent store (Redis or database) rather than in-memory
  • Rate limiting values are tuned to your expected load
  • LOG_LEVEL=info or warn in production (avoid debug/trace)
  • HTTPS termination is handled by a reverse proxy (Railway/Fly.io do this automatically)
  • /health endpoint is wired up to your load balancer or uptime monitor
  • Docker image is scanned for vulnerabilities (e.g. docker scout cves)
  • GitHub Actions secrets DOCKER_USERNAME and DOCKER_PASSWORD are configured for image push
  • Xero app scopes are minimal โ€” only request scopes your tools actually use
  • Token refresh errors trigger an alert so re-authorisation can happen before expiry
  • Request correlation IDs are forwarded to any downstream services for tracing
  • Dependency audit passes: npm audit --audit-level=high

Testing

Automated tests

npm test              # run all tests
npm run test:watch    # watch mode
npm run test:coverage # coverage report

The test suite covers:

  • GET /health returns HTTP 200 with structured JSON
  • POST /mcp without a valid API key returns HTTP 401
  • POST /mcp with valid API key and tools/list returns the registered tools
  • POST /mcp calling xero_list_invoices while unauthorised returns a structured MCP error

Manual testing with curl

# List available tools
curl -s -X POST http://localhost:3000/mcp \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: your-mcp-api-key' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | jq

# Call xero_list_contacts
curl -s -X POST http://localhost:3000/mcp \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: your-mcp-api-key' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"xero_list_contacts","arguments":{"page":1}}}' | jq

โญ GitHub Repository

The complete production-ready implementation is maintained on GitHub.

Repository:

https://github.com/kamolc4/xero-mcp-server

If this template saved you time, consider:

โญ Star the repository

๐Ÿด Fork it

๐Ÿ› Open an Issue

๐Ÿš€ Submit improvements

Keeping everything on GitHub makes it easier to receive updates, bug fixes, and new MCP features. express typescript utilities xero xero mcp server mcp typescript starter template production docker oauth claude cursor

โœ… Template ready. What's next?

  1. 1.Copy or download the template above
  2. 2.Deploy your MCP server (Railway, Vercel)
  3. 3.Test your deployment
  4. 4.Verify production readiness