servicetitan-mcp

servicetitan-mcp

A read-only MCP server over the ServiceTitan API providing six task-shaped tools to find customers, view their jobs, billing details, and resolve external IDs.

Category
Visit Server

README

tests

servicetitan-mcp

A read-only MCP server over the ServiceTitan API: six task-shaped tools (find a customer, look at their jobs, their money, resolve an external id) instead of a thin wrapper over ServiceTitan's own endpoints. ReadOnlyClient defines only get and get_page — no write path exists. See docs/DESIGN.md for the reasoning behind these choices.

The credentials rule

The MCP client config carries exactly one setting: ST_ENV_FILE, a path — never a secret directly. Everything else (client id, secret, app key, tenant id) lives in the file it points at, chmod 600, outside the repo and outside any MCP config: MCP configs get pasted into chats, and some (.mcp.json) are designed to be committed. permission_warning checks the file's mode at startup and warns — doesn't refuse to start — if it's looser than 600. Full reasoning in docs/DESIGN.md.

{
  "mcpServers": {
    "servicetitan": {
      "command": "/absolute/path/to/servicetitan-mcp/.venv/bin/servicetitan-mcp",
      "env": { "ST_ENV_FILE": "/home/you/.config/servicetitan-mcp/env" }
    }
  }
}

command must be an absolute path into this project's .venv — an MCP client launches from an arbitrary directory, so a bare python may resolve to an interpreter without mcp/httpx/st_mcp installed.

The six tools

Tool Answers Reach for it when
find_customer Who is this, by name/phone/external id? You have a human identifier, not a ServiceTitan id. One match returns the full card; several return a short list to disambiguate.
customer_overview Full card for one customer: contacts, locations, 5 recent jobs, external ids. You already have the numeric customer id — from find_customer or a prior call.
find_jobs Which jobs match these filters, and when's the next visit? You want a list of jobs by customer, date range, or status. Not for finding a customer — that's find_customer.
job_detail Everything about one job: appointments, technicians. You have a job id and need its full appointment history.
customer_money Balance, estimates, invoices, payments — for one customer, one call. Any "what do they owe" or billing-history question.
find_by_external_id Which ServiceTitan customer has this id in another system? You're crossing over from a CRM synced into ServiceTitan via externalData (requires ST_APP_GUID).

Job types, business units, and payment types are also exposed as MCP resources (cached client-side) rather than tools, and back the id→name substitution above.

Token savings, measured against a live tenant

chars / 4, on the same four ServiceTitan reads:

tokens
customer_overview, raw JSON pretty-printed 1516
customer_overview, raw JSON minified 1001
customer_overview, this server's output 69
customer_money 43
find_jobs, one customer 28
find_jobs, 20 jobs with next-visit dates 318

22x against pretty-printed JSON, 15x against minified, per call — and customer_overview is one model round trip for four ServiceTitan reads, where an endpoint-shaped tool surface would spend four.

ServiceTitan findings

  • totalCount is null unless the request sends includeTotal=true.
  • jpm/appointments has no batch filter — jobIds, jobId=<csv>, repeated jobId are all ignored or wrong; only jobId=<single> works.
  • sales/estimates ignores customerId; reachable only via jobId or locationId.
  • A 404 on an appointment's assigned-technicians means "nobody assigned yet", not "not found" — the API's own "could not" that actually means "none".

Setup

Requires Python 3.11+.

python -m venv .venv
.venv/bin/pip install -e ".[dev]"

Create the env file ST_ENV_FILE will point at (e.g. ~/.config/servicetitan-mcp/env), chmod 600 it, and fill in:

ST_CLIENT_ID=...
ST_CLIENT_SECRET=...
ST_APP_KEY=...
ST_TENANT_ID=...
# Optional:
ST_AUTH_HOST=auth.servicetitan.io
ST_API_HOST=api.servicetitan.io
ST_APP_GUID=...            # required only for find_by_external_id
ST_EXTERNAL_ID_KEY=...     # the externalData key find_customer treats as an id

ST_AUTH_HOST/ST_API_HOST default to production; ServiceTitan's sandbox uses different hosts (*-integration.*) and both must match the credentials' environment, or the token request 400s with invalid_client.

Registering it with a client

Both routes need an absolute path to the servicetitan-mcp console script in this project's .venv, and ST_ENV_FILE. Neither carries a secret.

Claude Code:

claude mcp add servicetitan -s user \
  -e ST_ENV_FILE=/home/you/.config/servicetitan-mcp/env \
  -- /home/you/servicetitan-mcp/.venv/bin/servicetitan-mcp

-s user registers it for every project on the machine — prefer it over -s project, which writes a committable .mcp.json. Verify with claude mcp list (✔ Connected).

Claude Desktop: copy claude_desktop_config_example.json, fix the two paths, and merge it into the client's own config.

Run the tests with .venv/bin/pytest. Nothing in the suite makes a live ServiceTitan call — every test uses the fake clients in tests/conftest.py.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured