Zoho FSM MCP Server
by LogeshR15
README.md
# Zoho FSM MCP Server
A production-ready [Model Context Protocol](https://modelcontextprotocol.io) server that exposes the [Zoho FSM](https://www.zoho.com/fsm/) (Field Service Management) REST API as AI-friendly **tools**, **resources**, and **prompts**.
It is modular and extensible: thin API-wrapper tools, higher-level "intelligent" workflow tools, cached read-only resources, and a dedicated extension point for tools auto-generated from an OpenAPI spec.
---
## Features
- π **OAuth** with automatic access-token refresh (refresh-token grant), multi-region.
- π **Single API client** (`FSMClient`) with retries, backoff, timeouts, 401 recovery, and typed responses.
- π§° **Tools** for Requests, Work Orders, Appointments, Contacts, Companies, Estimates, Invoices, Assets, and Users.
- π€ **Intelligent workflow tools** that orchestrate multiple API calls (`create_service_request`, `assign_best_technician`, `complete_job`).
- π **Resources** (`fsm://modules`, `fsm://statuses`, `fsm://territories`, `fsm://users`, `fsm://services`, `fsm://parts`, `fsm://metadata`) with TTL caching.
- π¬ **Prompt templates** (`dispatch-summary`, `job-summary`, `invoice-summary`, `technician-brief`, `customer-history`).
- πͺ΅ **Structured logging** to stderr (never logs secrets) and **centralized error handling**.
- π§© **Extensible**: `src/tools/generated/` is reserved for OpenAPI-generated tools.
---
## Project structure
```
zoho-fsm-mcp/
βββ src/
β βββ auth/oauth.ts # OAuth token manager (refresh + caching)
β βββ client/
β β βββ fsmClient.ts # The only place HTTP happens
β β βββ types.ts # Shared FSM/response types
β βββ tools/
β β βββ requests.ts workOrders.ts appointments.ts contacts.ts
β β βββ companies.ts invoices.ts estimates.ts assets.ts users.ts
β β βββ intelligent.ts # Multi-step workflow tools
β β βββ generated/ # Reserved for OpenAPI-generated tools
β β βββ shared.ts # Shared Zod shapes + context type
β β βββ index.ts # registerAllTools()
β βββ resources/ # modules, statuses, metadata (+ live)
β βββ prompts/ # Reusable prompt templates
β βββ utils/ # config, logger, errors, cache, mcp helpers
β βββ server.ts # Wires everything together
β βββ index.ts # stdio entry point
βββ .env.example
βββ package.json tsconfig.json eslint.config.js .prettierrc
βββ README.md
```
---
## Installation
```bash
git clone <this-repo>
cd zoho-fsm-mcp
npm install
npm run build
```
Requires Node.js β₯ 18.
---
## OAuth setup
1. Go to the [Zoho API Console](https://api-console.zoho.com/) and create a **Self Client** (or Server-based Application).
2. Note the **Client ID** and **Client Secret**.
3. Generate a **grant token** with the FSM scopes, e.g.:
```
ZohoFSM.modules.ALL,ZohoFSM.settings.ALL,ZohoFSM.users.READ
```
4. Exchange the grant token for a **refresh token** (one-time), using the accounts endpoint for your region:
```bash
curl -X POST "https://accounts.zoho.com/oauth/v2/token" \
-d "grant_type=authorization_code" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "code=YOUR_GRANT_TOKEN"
```
Save the `refresh_token` from the response.
5. Copy `.env.example` to `.env` and fill in:
```
ZOHO_CLIENT_ID=...
ZOHO_CLIENT_SECRET=...
ZOHO_REFRESH_TOKEN=...
ZOHO_REGION=com # com | eu | in | au | jp
```
The server refreshes access tokens automatically and picks the correct base URL from `ZOHO_REGION`:
| Region | Accounts endpoint | FSM API base |
|--------|-------------------|--------------|
| `com` | `accounts.zoho.com` | `fsm.zoho.com/fsm/v1` |
| `eu` | `accounts.zoho.eu` | `fsm.zoho.eu/fsm/v1` |
| `in` | `accounts.zoho.in` | `fsm.zoho.in/fsm/v1` |
| `au` | `accounts.zoho.com.au` | `fsm.zoho.com.au/fsm/v1` |
| `jp` | `accounts.zoho.jp` | `fsm.zoho.jp/fsm/v1` |
---
## Running locally
```bash
# Development (auto-reload)
npm run dev
# Type-check / lint / format
npm run typecheck
npm run lint
npm run format
# Production
npm run build
npm start
```
Inspect the tools interactively with the MCP Inspector:
```bash
npm run inspect
```
---
## Configuring Claude Desktop
Edit `claude_desktop_config.json`:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"zoho-fsm": {
"command": "node",
"args": ["/absolute/path/to/zoho-fsm-mcp/dist/index.js"],
"env": {
"ZOHO_CLIENT_ID": "...",
"ZOHO_CLIENT_SECRET": "...",
"ZOHO_REFRESH_TOKEN": "...",
"ZOHO_REGION": "com"
}
}
}
}
```
Restart Claude Desktop. The `zoho-fsm` tools appear in the tools menu.
---
## Configuring ChatGPT / other MCP clients
Any MCP-compatible client that supports stdio servers can launch it the same way:
```bash
node /absolute/path/to/zoho-fsm-mcp/dist/index.js
```
For ChatGPT's MCP support, register a connector pointing at this command (or wrap it behind an HTTP/SSE bridge if your client requires a URL). Environment variables are supplied the same way as above.
---
## Available tools
| Category | Tools |
|----------|-------|
| Requests | `create_request`, `get_request`, `search_requests`, `update_request` |
| Work Orders | `create_work_order`, `update_work_order`, `search_work_orders` |
| Appointments | `create_appointment`, `update_appointment`, `schedule_appointment` |
| Contacts | `create_contact`, `search_contacts` |
| Companies | `create_company`, `search_companies` |
| Estimates | `create_estimate` |
| Invoices | `create_invoice`, `mark_invoice_paid` |
| Assets | `create_asset`, `update_asset` |
| Users | `list_users`, `get_user` |
| Workflows | `create_service_request`, `assign_best_technician`, `complete_job` |
Every tool validates input with Zod, calls `FSMClient`, and returns a structured MCP response. Errors are converted into a consistent payload with `status`, `code`, `retryable`, `message`, and `details`.
---
## Adding a new tool
1. Create (or extend) a file in `src/tools/`, e.g. `parts.ts`.
2. Export a `registerXTools(ctx: ServerContext)` function.
3. Inside it, call `server.registerTool(name, { title, description, inputSchema }, handler)`.
- Define `inputSchema` as a Zod raw shape.
- Wrap the handler with `withToolLogging(name, ...)` for logging + error handling.
- Build the API payload with `buildRecord(...)` and call a `FSMClient` method.
- Return via `ok(data, summary)`.
4. Register your function in `src/tools/index.ts`.
Example skeleton:
```ts
export function registerPartTools({ server, client }: ServerContext): void {
server.registerTool(
'create_part',
{ title: 'Create Part', description: '...', inputSchema: { name: z.string() } },
withToolLogging('create_part', async (args) => {
const created = await client.create('Parts', buildRecord({ Name: args.name }));
return ok(created, `Created part "${args.name}".`);
}),
);
}
```
New REST calls should go through `FSMClient` (add a method there) β never call `axios` directly from a tool.
---
## Future: OpenAPI-generated tools
`src/tools/generated/` is reserved for tools generated from the Zoho FSM OpenAPI spec. A codegen step will emit `*.generated.ts` files there, each exporting a `registerβ¦GeneratedTools(ctx)` function called from `generated/index.ts`. Generated code stays separate from the hand-written intelligent tools and is safe to regenerate wholesale.
---
## License
MIT
TDQS
B3.4/5.0
Scored across 24 tools
Disambiguation4/5
Most tools have distinct purposes, but there is potential confusion between create_appointment and schedule_appointment, as well as between create_request and create_service_request, though descriptions clarify.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern in snake_case, making them predictable and easy to understand.
Tool Count4/5
24 tools cover a broad but appropriate scope for an FSM server, though slightly on the high side; each tool serves a clear purpose.
Completeness4/5
The tool set covers the core lifecycle from request to invoicing, but lacks delete operations and some advanced FSM features like inventory or territory management.
Maintenance
ActivityStale
ResponsivenessNo issues