Model Context Protocol (MCP) server exposing the Service Fusion REST API to AI agents — job lookup, customer management, dispatch, and more
mcp-servicefusion
A Model Context Protocol (MCP) server exposing the Service Fusion REST API to AI agents. Enables AI-assisted field service management: job lookup, customer management, dispatch, invoicing, equipment tracking, and more.
Disclaimer: This is an unofficial, community-built integration. Not affiliated with or endorsed by Service Fusion.
Features
Read tools:
get_todays_jobs— today's scheduled jobs with assigned techssearch_jobs— flexible search with filters (status, customer, date range, etc.)get_job_details— full job record with expanded relationsget_customer_jobs— all jobs for a given customersearch_customers— by name, phone, email, or addressget_equipment— customer equipment with custom fieldsget_open_invoices— outstanding invoicesget_techs— technician listget_job_statuses,get_job_categories,get_sources— reference dataget_me— current authenticated user
Create tools:
create_job,create_customer,create_estimate
API documentation:
get_api_docs— look up the Service Fusion API reference directly from the MCP connection. Sections:index,jobs,customers,estimates,invoices,techs,data-types,authentication,known-issues,full
Prerequisites
- Node.js ≥ 18
- Service Fusion API credentials (My Office → Developer Settings → API Credentials)
Setup (local / stdio transport)
git clone https://github.com/commair-tools/mcp-servicefusion-public.git mcp-servicefusion
cd mcp-servicefusion
npm install
npm run build
cp .env.example .env
# Edit .env and add SF_CLIENT_ID and SF_CLIENT_SECRET
Claude Desktop
Add to your claude_desktop_config.json (see claude_desktop_config.example.json):
{
"mcpServers": {
"service-fusion": {
"command": "node",
"args": ["/absolute/path/to/mcp-servicefusion/build/index.js"],
"env": {
"SF_CLIENT_ID": "your_client_id_here",
"SF_CLIENT_SECRET": "your_client_secret_here"
}
}
}
}
Claude Code CLI
claude mcp add service-fusion node /absolute/path/to/mcp-servicefusion/build/index.js \
-e SF_CLIENT_ID=your_client_id -e SF_CLIENT_SECRET=your_client_secret
Setup (remote / HTTP transport)
The server also supports Streamable HTTP transport for hosted deployments (Railway, Fly.io, Cloud Run, etc.) with OAuth 2.1 authentication.
Environment variables
| Variable | Required | Description |
|---|---|---|
| SF_CLIENT_ID | Yes | Service Fusion OAuth client ID |
| SF_CLIENT_SECRET | Yes | Service Fusion OAuth client secret |
| TRANSPORT | Yes (for HTTP) | Set to http to enable HTTP transport |
| PORT | No | HTTP port (default: 3000) |
| BASE_URL | Yes (for HTTP) | Public URL of your server, e.g. https://mcp.example.com — required for OAuth discovery |
| MCP_OAUTH_PIN | Recommended | PIN for browser-based OAuth approval (required by Claude.ai web) |
| MCP_AUTH_TOKEN | Optional | Static Bearer token for non-OAuth clients (e.g., Claude Code CLI) |
| SF_API_BASE_URL | No | Defaults to https://api.servicefusion.com/v1 |
| SF_TOKEN_URL | No | Defaults to https://api.servicefusion.com/oauth/access_token |
Deploying to Railway
- Fork or import this repo on Railway
- Set the environment variables listed above
- Railway auto-builds via
railway.tomland exposes a public URL - Use that URL as your
BASE_URL
Authentication
Claude.ai web (OAuth flow): add the server URL (without trailing slash, e.g., https://mcp.example.com/mcp) as a remote MCP connector in Settings. Leave OAuth client ID/secret fields blank — the server advertises discovery metadata so Claude.ai handles the full OAuth handshake automatically. On first connect, you'll be redirected to a browser page to enter your MCP_OAUTH_PIN. After that, tokens auto-refresh for 30 days.
Claude Code / CLI clients: use the static token via the Authorization: Bearer <MCP_AUTH_TOKEN> header.
No authentication: if neither MCP_OAUTH_PIN nor MCP_AUTH_TOKEN is set, the server runs unauthenticated (not recommended for public-facing deployments).
API Reference
The repo includes a complete Service Fusion API reference in service-fusion-api-reference.md, auto-generated from the official RAML spec at docs.servicefusion.com. Agents can access it through the get_api_docs tool at runtime.
To regenerate it after Service Fusion updates their spec:
node scripts/update-api-docs.mjs
Known Issues
/jobs endpoint hangs without sort parameter
As of 2026-04-09, Service Fusion's /jobs list endpoint hangs indefinitely when queried without a sort parameter. This server works around it by defaulting all /jobs list queries to sort=-start_date in src/client.ts. If you see hangs on other endpoints in the future, check whether they require a sort param too.
Equipment is a nested resource
There is no top-level /equipment endpoint. Equipment must be fetched via GET /customers/{customer-id}/equipment. The get_equipment tool handles this by resolving customer_name to customer_id internally.
API Limitations
Confirmed by Service Fusion support:
- No PUT, PATCH, or DELETE on any endpoint (read and create only)
- No native webhook/callback support
- No sandbox/test environment
- Rate limit: 60 requests/minute (server enforces backoff automatically)
Tech Stack
- TypeScript + Node.js
@modelcontextprotocol/sdkfor MCP protocol- Express for HTTP transport
- OAuth 2.1 with PKCE, Dynamic Client Registration, and resource indicators
License
Business Source License 1.1 — see LICENSE
TL;DR: Free to use, modify, and redistribute (including internally at HVAC businesses to manage your own operations). You may not resell it or offer it as a paid hosted service to third parties. On April 10, 2036 it automatically converts to the Apache License 2.0 (fully permissive).