Freshservice MCP Server
# Freshservice MCP Server
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that connects Claude, Codex, and other MCP clients to your Freshservice ITSM instance.
## Supported modules
| Module | Operations |
|--------|-----------|
| **Tickets** | Create, view, list, update, delete, filter, get field definitions |
| **Conversations** | List, reply to ticket, add notes (public/private), delete notes |
| **Changes** | Create, view, list, update, close, delete, filter, tasks, notes |
| **Assets** | Create, view, list, update, delete, search, filter, get types |
| **Problems** | Create, view, list |
| **Agents** | List, view, filter |
| **Requesters** | Create, list, view, filter |
| **Agent Groups** | List, view |
| **Requester Groups** | List, view |
| **Products** | List, view |
| **Workspaces** | List |
| **Canned Responses** | List folders, list responses, view |
| **Solution Categories** | Create, list, view |
| **Solution Folders** | Create, list, view |
| **Solution Articles** | Create, list, view, search |
| **Departments** | List, view |
| **Locations** | List |
| **Software** | List, view |
| **Vendors** | List |
| **Service Catalog** | List items, view item |
| **Announcements** | List |
| **Contracts** | List, view |
| **Purchase Orders** | List |
## Prerequisites
- **Python 3.10+**
- **uv** — fast Python package manager
- **Claude Desktop**, **Claude Code**, or **Codex app/CLI/IDE** (see [Setup](#setup) below)
- A **Freshservice account** with an API key
### Install uv
```bash
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
# Or with Homebrew
brew install uv
```
### Get your Freshservice API key
1. Log in to your Freshservice portal
2. Click your **profile picture** → **Profile Settings**
3. Your API key is shown on the right side under **Change Password**
## Setup
### 1. Clone the repository
```bash
git clone https://github.com/matthewlboyd/freshservice-mcp.git
cd freshservice-mcp
```
### 2a. Configure Claude Desktop
**Option A — macOS install script (recommended):**
```bash
./install.sh
```
This handles everything automatically: prompts for your repo path, API key, and domain, writes the config, tests the connection, and restarts Claude Desktop.
**Option B — Manual setup (all platforms):**
Open the Claude Desktop config file in any text editor:
| OS | Path |
|---|---|
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
| Linux | `~/.config/Claude/claude_desktop_config.json` |
Paste the following into the file, replacing the placeholder values. If the file doesn't exist yet, create it with just this content:
```json
{
"mcpServers": {
"freshservice": {
"command": "uv",
"args": [
"run",
"--directory",
"/full/path/to/freshservice-mcp",
"freshservice-mcp"
],
"env": {
"FRESHSERVICE_APIKEY": "your_api_key_here",
"FRESHSERVICE_DOMAIN": "yourcompany.freshservice.com"
}
}
}
}
```
`FRESHSERVICE_DOMAIN` should be just the hostname — no `https://` prefix.
If you're behind a corporate proxy with SSL inspection, add `SSL_CERT_FILE` to the `env` block pointing at your CA bundle:
```json
"env": {
"FRESHSERVICE_APIKEY": "your_api_key_here",
"FRESHSERVICE_DOMAIN": "yourcompany.freshservice.com",
"SSL_CERT_FILE": "/path/to/your/ca-bundle.crt"
}
```
> Already have other MCP servers? Add just the `"freshservice": { ... }` block inside your existing `"mcpServers"` object instead of replacing the whole file.
**Restart Claude Desktop** — quit and reopen it. The first launch will automatically install dependencies (takes ~30 seconds). You should see a hammer icon (🔨) in the chat input, indicating MCP tools are available.
### 2b. Configure Claude Code
**Recommended: project-local scope**
```bash
claude mcp add freshservice \
--scope local \
--env FRESHSERVICE_APIKEY=your_api_key_here \
--env FRESHSERVICE_DOMAIN=yourcompany.freshservice.com \
-- uv run --directory /full/path/to/freshservice-mcp freshservice-mcp
```
`--scope local` stores the config in `.claude/settings.local.json`, which is **gitignored by default** — your API key will not be committed to version control.
**Alternative: user scope (available in all your projects)**
```bash
claude mcp add freshservice \
--scope user \
--env FRESHSERVICE_APIKEY=your_api_key_here \
--env FRESHSERVICE_DOMAIN=yourcompany.freshservice.com \
-- uv run --directory /full/path/to/freshservice-mcp freshservice-mcp
```
> **Security note:** Never use `--scope project` with credentials hardcoded in the command — the `project` scope writes to `.mcp.json`, which is typically committed to version control. Use `local` or `user` scope, or pass credentials via environment variables already set in your shell.
If you're behind a corporate proxy with SSL inspection, add `--env SSL_CERT_FILE=/path/to/your/ca-bundle.crt` to the command above.
**Verify the server is registered:**
```bash
claude mcp list
```
You should see `freshservice` in the output. No restart is needed — Claude Code picks up MCP servers at the start of each session.
### 2c. Configure Codex app, CLI, or IDE
Codex app, Codex CLI, and the Codex IDE extension share MCP configuration through `config.toml`. The server uses Codex-supported stdio transport and can run through the Codex-specific entrypoint alias `freshservice-mcp-codex`.
**Option A — install script:**
```bash
./install-codex.sh
```
This prompts for your repo path, Freshservice API key, domain, and optional CA bundle, then writes a `[mcp_servers.freshservice]` block to `~/.codex/config.toml` (or `$CODEX_HOME/config.toml` if `CODEX_HOME` is set).
**Option B — Codex CLI:**
```bash
codex mcp add freshservice \
--env FRESHSERVICE_APIKEY=your_api_key_here \
--env FRESHSERVICE_DOMAIN=yourcompany.freshservice.com \
-- uv run --directory /full/path/to/freshservice-mcp freshservice-mcp-codex
```
If you're behind a corporate proxy with SSL inspection, add `--env SSL_CERT_FILE=/path/to/ca-bundle.crt`.
**Option C — manual `config.toml`:**
Open Codex **Settings** → **Integrations & MCP** → **Open config.toml**, or edit `~/.codex/config.toml` directly. Add this block, replacing the placeholders:
```toml
[mcp_servers.freshservice]
enabled = true
command = "uv"
args = [
"run",
"--directory",
"/full/path/to/freshservice-mcp",
"freshservice-mcp-codex",
]
startup_timeout_sec = 30
tool_timeout_sec = 120
[mcp_servers.freshservice.env]
FRESHSERVICE_APIKEY = "your_api_key_here"
FRESHSERVICE_DOMAIN = "yourcompany.freshservice.com"
```
`FRESHSERVICE_DOMAIN` should be just the hostname — no `https://` prefix.
If you're behind a corporate proxy with SSL inspection, add this to the env block:
```toml
SSL_CERT_FILE = "/path/to/your/ca-bundle.crt"
```
> **Security note:** Values under `[mcp_servers.freshservice.env]` are stored in plaintext in `config.toml`. If you already provide these variables to the Codex process another way, you can use `env_vars = ["FRESHSERVICE_APIKEY", "FRESHSERVICE_DOMAIN"]` instead of the env table.
Restart the Codex app, or start a new Codex CLI/IDE session. In Codex, use `/mcp` to confirm the `freshservice` server is loaded.
## Example prompts
### Tickets
- "Show me all open urgent tickets"
- "Create a ticket for a VPN connectivity issue — assign to the Network team, high priority"
- "Update ticket #4521 to resolved"
- "Find all tickets created this week by john@example.com"
### Changes
- "Create a change request for server maintenance this Saturday, 10pm–2am"
- "Show all changes awaiting approval"
- "Close change #89 — migration completed successfully"
### Assets
- "List all laptops in the asset inventory"
- "Search for assets tagged 'datacenter'"
- "Show all unassigned hardware assets"
### Knowledge Base
- "Search the knowledge base for VPN setup instructions"
- "Create a new solution article on how to reset your password"
- "List all articles in the Onboarding folder"
### General
- "How many open tickets are assigned to the Help Desk group?"
- "List all active agents and their departments"
- "Show me all software registered in the system"
## Running the tests
The test suite covers all 62 tools and the API client (117 tests total). No Freshservice credentials are needed — all tests use mocked HTTP calls.
**Install dev dependencies:**
```bash
uv pip install -e ".[dev]"
```
**Run all tests:**
```bash
uv run pytest tests/ -v
```
**Run a specific module's tests:**
```bash
uv run pytest tests/test_tickets.py -v
```
**Test files:**
| File | What it covers |
|------|---------------|
| `test_client.py` | HTTP client — auth, domain normalisation, error handling |
| `test_tickets.py` | Ticket tools |
| `test_conversations.py` | Reply, notes, delete note |
| `test_changes.py` | Change request tools |
| `test_assets.py` | Asset tools |
| `test_people.py` | Agents, requesters, groups |
| `test_knowledge_base.py` | Solution categories, folders, articles |
| `test_misc.py` | Problems, products, workspaces, canned responses, departments, locations, software, vendors, service catalog, announcements, contracts, purchase orders |
## Troubleshooting
**Tools don't appear in Claude Desktop**
Make sure the path in `--directory` is the absolute path to the repo and that you've fully quit and restarted Claude (not just closed the window).
**Tools don't appear in Claude Code**
Run `claude mcp list` to confirm the server is registered. If it is, start a new `claude` session — MCP servers are loaded at session start. If it's missing, re-run the `claude mcp add` command.
**Tools don't appear in Codex**
Check `~/.codex/config.toml` (or `$CODEX_HOME/config.toml`) for the `[mcp_servers.freshservice]` block, then restart the Codex app or start a new Codex CLI/IDE session. In Codex, run `/mcp` to inspect loaded MCP servers. If first launch times out while `uv` installs dependencies, keep `startup_timeout_sec = 30` or increase it.
**Authentication error (401)**
Your API key is incorrect. Double-check it in Freshservice → Profile Settings. Copy it using the copy icon rather than selecting the text manually.
**403 Forbidden**
The API key doesn't have permission for that operation, or the domain is wrong. Confirm `FRESHSERVICE_DOMAIN` is just the hostname (e.g. `yourcompany.freshservice.com`), with no `https://` prefix.
**SSL certificate errors**
If you're behind a corporate proxy with SSL inspection, requests will fail with a certificate verification error. Set the `SSL_CERT_FILE` environment variable to the path of your organisation's CA bundle. In Claude Desktop, add it to the `"env"` block in `claude_desktop_config.json`. In Claude Code, pass `--env SSL_CERT_FILE=/path/to/ca-bundle.crt` when running `claude mcp add`. In Codex, add `SSL_CERT_FILE = "/path/to/ca-bundle.crt"` under `[mcp_servers.freshservice.env]`.
**Rate limiting (429)**
Freshservice enforces per-minute API rate limits based on your plan. Wait a moment and try again.
**Filter queries returning errors**
Filter strings must use double-quoted field values. Example: `"status:2 AND priority:4"` not `status:2 AND priority:4`.
**Checking logs**
If something isn't working, check the MCP server logs:
- **macOS:** `~/Library/Logs/Claude/mcp-server-freshservice.log`
- **Windows:** `%APPDATA%\Claude\logs\mcp-server-freshservice.log`
## License
MIT
TDQS
Scored across 70 tools
Most tools are clearly separated by entity type, but there is notable overlap between list, filter, and search tools for the same entities (e.g., get_assets vs search_assets vs filter_assets, get_changes vs filter_changes). An agent may struggle to choose the right variant.
All tools use a consistent snake_case verb_noun pattern (get_, create_, update_, delete_, filter_, search_). Even variations like get_ticket_by_id or get_agent_group_by_id are predictable and follow the same convention.
With 70 tools, this is far beyond the 50+ threshold for 'extreme mismatch'. The server tries to cover every Freshservice module, resulting in an overwhelming surface that is unlikely to be navigated efficiently by agents.
Tickets, changes, and assets have solid CRUD coverage, but many other entities (agents, groups, products, contracts, etc.) are read-only with no create/update/delete operations. This creates significant gaps where agents can retrieve data but cannot complete lifecycle workflows.