Files
freshservice-claude/mcp-server
spencerm e38841918d Fix status-cache poisoning, add HTTP timeouts, coerce custom status names
- _status_choices no longer caches failures: a transient /ticket_form_fields
  error used to cache [] forever, silently degrading unresolved=True to an
  unfiltered listing (including Resolved/Closed) until container restart.
  unresolved=True and list_ticket_statuses now return an explicit error when
  the status list can't be fetched instead of degrading silently.
- All API calls (server and skill helper) now use a 30s timeout with a clean
  error, so a hung connection can't block a tool call indefinitely.
- _coerce_status falls back to the instance's live status list, so custom
  names like "Working" coerce to their id instead of 400ing at the API.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 10:38:56 -06:00
..

Freshservice MCP server (for Cowork / Claude Desktop)

Cowork runs the agent inside an isolated VM, so a locally-installed skill can't see your credentials or reach your Freshservice host. This MCP server runs as a container on the LAN box (192.168.101.12) — outside the VM — and Claude Desktop connects to it through mcp-remote, exactly like the existing sharepoint-lists server. Credentials and network both live on the LAN box.

(The skill in the parent directory remains the right tool for the Claude Code CLI, which is not sandboxed.)

Deploy on 192.168.101.12

# on the LAN box, in this directory
cp .env.example .env
# edit .env: FRESHSERVICE_DOMAIN, FRESHSERVICE_API_KEY, MCP_AUTH_TOKEN
#   token:  openssl rand -hex 32
docker compose up -d --build
docker compose logs -f          # confirm it started on :3838 inside the container

The container listens on container port 3838, published to host port 3839 (3838 is used by sharepoint-lists). Adjust in docker-compose.yml if needed.

Verify

# from the LAN box or any host that can reach it:
curl -s -o /dev/null -w "%{http_code}\n" -X POST \
  http://192.168.101.12:3839/mcp \
  -H "Authorization: Bearer <MCP_AUTH_TOKEN>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"t","version":"0"}}}'
# expect 200 (401 means bad/missing token)

Connect Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json under mcpServers (alongside sharepoint-lists):

"freshservice": {
  "command": "/opt/homebrew/bin/npx",
  "args": [
    "-y", "mcp-remote",
    "http://192.168.101.12:3839/mcp",
    "--allow-http",
    "--header", "Authorization:${MCP_AUTH_HEADER}"
  ],
  "env": { "MCP_AUTH_HEADER": "Bearer <MCP_AUTH_TOKEN>" }
}

Restart Claude Desktop. The Freshservice tools then appear in chat and Cowork.

Tools

Tickets (list_tickets, get_ticket, create_ticket, update_ticket, reply_ticket, add_note, list_ticket_conversations), assets (search_assets, get_asset, update_asset), people (find_requester, list_agents, list_groups, list_departments), change/problem/release (list_changes, get_change, create_change, list_problems, get_problem, list_releases, get_release), and freshservice_request for any other v2 endpoint.