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.
README
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
totalCountisnullunless the request sendsincludeTotal=true.jpm/appointmentshas no batch filter —jobIds,jobId=<csv>, repeatedjobIdare all ignored or wrong; onlyjobId=<single>works.sales/estimatesignorescustomerId; reachable only viajobIdorlocationId.- 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.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。