Files
freshservice-claude/mcp-server
spencerm e0bf450e08 Pin mcp SDK below 2.0
A fresh image build pulled mcp 2.0.0, which removed mcp.server.fastmcp and
crash-looped the container (ModuleNotFoundError). Pin to the 1.x line the
server is written against; the 2.x migration is a deliberate change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 12:32:20 -06:00
..
2026-08-24 12:32:20 -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.

Multiple users

The server can act as each caller's own Freshservice identity instead of a single shared one. Each client sends its own credentials as headers on every request; the server uses them per-call (they take precedence over the env vars). Actions are then attributed to each person, with their own permissions and rate limits.

To run the server multi-user:

  1. Omit FRESHSERVICE_DOMAIN / FRESHSERVICE_API_KEY from .env (keep only MCP_AUTH_TOKEN). With no env fallback, a client that forgets its headers gets a clean "Missing credentials" error rather than silently acting as whoever owns the env key.

  2. Each user adds the extra headers to their own claude_desktop_config.json, with their own Freshservice API key (Profile settings → API key):

    "freshservice": {
      "command": "/opt/homebrew/bin/npx",
      "args": [
        "-y", "mcp-remote",
        "http://192.168.101.12:3839/mcp",
        "--allow-http",
        "--header", "Authorization:${MCP_AUTH_HEADER}",
        "--header", "X-Freshservice-Domain:${FS_DOMAIN}",
        "--header", "X-Freshservice-Key:${FS_KEY}"
      ],
      "env": {
        "MCP_AUTH_HEADER": "Bearer <shared MCP_AUTH_TOKEN>",
        "FS_DOMAIN": "pesco.freshservice.com",
        "FS_KEY": "<that user's own Freshservice API key>"
      }
    }
    

    MCP_AUTH_TOKEN is the same shared value for everyone (it only gates reaching the server); FS_KEY is each person's own identity. The key stays on the user's machine and travels per-request — the server never stores it.

Note: the LAN transport is plain HTTP, so these headers travel unencrypted. Fine on a trusted network; put a TLS-terminating reverse proxy in front if this ever leaves it.

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.