Skip to main content
Glama
LogeshR15

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