Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

A read-only MCP server that connects AI assistants to Freshservice Service Desk for ticket triage, asset analysis, and support history summarization.

README.md

FS_MCP_thin 🚀

![MCP](https://modelcontextprotocol.io/) ![Freshservice](https://api.freshservice.com/v2/)

A powerful, read-only Model Context Protocol (MCP) server that bridges the gap between your AI assistant (like Claude) and your Freshservice Service Desk. Empower your AI with deep context to triage incidents, analyze asset distribution, and summarize support history.

---

✨ Features

  • 🎫 Ticket Intelligence – Deep dive into tickets, conversations, private notes, and service request items.
  • 📚 Knowledge Integration – Search and retrieve the full content of your solution articles.
  • 🔧 Problem Analysis – Inspect root-cause investigation records.
  • 📦 Inventory Visibility – Browse and drill down into Assets (Hardware) and Software inventory.
  • 👤 Identity Context – Lookup Requesters and Agents, and view their specific ticket/asset history.
  • ⏱️ Governance Context – Access SLA policies, business hours, and org structure as standing context.
  • 💬 Canned Success – Use your curated response templates to draft high-quality replies.
  • 🪶 Token-Efficient – Responses are shaped (field-projected, HTML-stripped, compacted) before they reach the model, cutting context bloat 5-10x on list/detail calls. See Response Shaping.

---

🛠 Prerequisites

  • Node.js: Version 18.x or higher.
  • Freshservice: An active account with API access enabled.
  • API Key: Found in your Profile Settings → API Key.

---

🚀 Quick Start

1. Installation

# Clone or download the repository
cd FS_MCP_thin

# Install dependencies
npm install

# Setup environment variables
cp .env.example .env

2. Configuration

The server needs exactly two environment variables. Both are required — if either is missing the server exits immediately on startup with an error.

| Variable | What it is | Where to get it | |----------|-----------|-----------------| | FRESHSERVICE_DOMAIN | Your Freshservice URL | The host in your browser, e.g. acme.freshservice.com. | | FRESHSERVICE_API_KEY | Your personal API key | Freshservice → avatar → Profile SettingsAPI Key (right sidebar). |

Domain format: supply just the host (acme.freshservice.com). A full URL (https://acme.freshservice.com) also works — the client adds https:// only if no protocol is present. Do not include a trailing slash or path.

How auth works: Freshservice uses HTTP Basic auth with the API key as the username and a dummy password. The server handles this for you — you only ever supply the raw key.

Edit the .env file with your details:

FRESHSERVICE_DOMAIN=acme.freshservice.com
FRESHSERVICE_API_KEY=your_api_key_here

.env is git-ignored. Your credentials never leave your machine — see Security & Privacy.

3. Integration with Claude Desktop

Add this snippet to your claude_desktop_config.json. The env block here is an alternative to a .env file — when Claude Desktop launches the server it injects these, so you don't need both. (If both exist, the values in env take precedence.)

{
  "mcpServers": {
    "freshservice": {
      "command": "node",
      "args": ["C:\\path\\to\\FS_MCP_thin\\src\\index.js"],
      "env": {
        "FRESHSERVICE_DOMAIN": "acme.freshservice.com",
        "FRESHSERVICE_API_KEY": "your_api_key_here"
      }
    }
  }
}

Use the absolute path to src/index.js. On Windows, escape backslashes (\\) as shown.

Troubleshooting credentials

| Symptom | Likely cause | |---------|--------------| | Server exits with FRESHSERVICE_DOMAIN and FRESHSERVICE_API_KEY ... are required | One or both env vars are unset (typo, wrong key name, or .env not loaded). | | 401 Unauthorized on every call | API key is wrong, revoked, or copied with surrounding whitespace. | | 403 Forbidden on specific tools (assets, problems, catalog) | Your account's role or plan tier doesn't grant access to that resource — not a config bug. | | 404 Not Found | Wrong domain, or the record ID doesn't exist. | | 429 Too Many Requests | Rate limit hit. Limits are per-plan; the server surfaces the error but does not auto-retry. |

---

📁 Project Structure

FS_MCP_thin/
├── src/
│   ├── index.js              # MCP server entry point — registers all tools,
│   │                         #   resources, and prompts; wires responses through shape.js
│   ├── freshservice.js       # FreshserviceClient — thin axios wrapper over the
│   │                         #   Freshservice v2 REST API (auth, requests, error mapping)
│   ├── shape.js              # Token-economy engine — projects/strips/compacts responses
│   ├── shape.config.js       # Declarative per-domain field/shaping rules (edit this to tune output)
│   ├── index.test.js         # Tests for tool registration & handler behavior
│   ├── freshservice.test.js  # Tests for the API client
│   └── shape.test.js         # Tests for the shaping engine + config
├── eslint.config.js          # ESLint flat config (Node + Jest, recommended rules)
├── tsconfig.json             # TypeScript config for `checkJs` type-checking
├── .env.example              # Template for required environment variables
├── .gitignore                # Ignores node_modules/ and .env (credentials)
├── package.json              # Dependencies, scripts, bin entry
└── README.md

Data flow: index.js (MCP request) → freshservice.js (API call) → shape.js + shape.config.js (trim response) → back to the AI assistant.

Where to make changes:

  • Add/modify a tool, resource, or promptsrc/index.js
  • Add/modify a Freshservice API callsrc/freshservice.js
  • Change what fields the model seessrc/shape.config.js (no code changes needed)

---

🧰 Available Tools

🎫 Tickets & Conversations

| Tool | Purpose | |------|---------| | search_tickets | Flexible search using status, priority, or subject. | | list_open_tickets | List open tickets (status:2) with pagination. | | get_ticket | Curated detail view of a ticket (key fields + HTML-stripped body). | | get_ticket_conversations | Complete thread of public and private messages. | | get_ticket_notes | Isolates private internal notes for audit/context. | | get_service_request_items| Views quantity and custom fields for SR items. |

📚 Knowledge Base & Problems

| Tool | Purpose | |------|---------| | search_kb | Find articles by keywords. | | get_kb_article | Retrieve the full article body (Markdown/HTML). | | list_problems | Get a list of recent Problem records. | | get_problem | Detailed view of a root cause investigation. |

📦 Assets & Software

| Tool | Purpose | |------|---------| | list_assets | Browse the CI (Configuration Item) inventory. | | get_asset | Deep dive into a specific piece of hardware. | | list_software | See software installations and licenses. |

?? Service Catalog & Responses

| Tool | Purpose | |------|---------| | list_service_catalog_items | List items available in the service catalog. | | get_service_catalog_item | Retrieve details of a specific service catalog item. | | list_canned_responses | List canned response templates. |

👤 Identity & History

| Tool | Purpose | |------|---------| | search_requesters | Find users by name or email. | | get_requester | Detailed profile of a user. | | get_requester_tickets | Historical view of all tickets for a specific user. | | get_requester_assets | List of hardware currently assigned to a user. | | search_agents | Find support staff members. | | get_agent / get_agent_group| Inspect specific agents or support teams. |

---

📖 Available Resources (Standing Context)

Resources can be attached to a conversation to provide the AI with constant reference data without needing a tool call.

| URI | Content | |-----|---------| | freshservice://departments | Your organizational hierarchy. | | freshservice://ticket-fields | The schema for custom ticket fields and their values. | | freshservice://agent-groups | Valid routing destinations (support teams). | | freshservice://sla-policies | Your response and resolution time targets. | | freshservice://business-hours | Operation schedules for various teams. |

---

🪄 Available Prompts (Workflows)

| Prompt | Scenario | |--------|----------| | triage_ticket | Input: Ticket ID. Output: A comprehensive assessment including history, SR items, and suggested KB articles. | | summarize_ticket | Input: Ticket ID. Output: A concise executive summary perfect for handoffs or manager reviews. | | draft_reply | Input: Ticket ID. Output: A professional draft reply incorporating KB solutions and empathy. | | sla_check | Input: Ticket ID. Output: An analysis of breach risk based on business hours and policies. |

---

🔍 Search Syntax Reference

The search_tickets tool supports the Freshservice Filter API syntax:

  • Status Codes: 2: Open, 3: Pending, 4: Resolved, 5: Closed.
  • Priority Codes: 1: Low, 2: Medium, 3: High, 4: Urgent.

Examples for AI:

  • "status:2 AND priority:4" → Show me urgent open tickets.
  • "created_at:>'2024-01-01'" → Show me tickets from this year.
  • "type:'Incident'" → Filter for incidents only.

---

🪶 Response Shaping (Token Economy)

Freshservice API responses are verbose — a single ticket carries 40-60 fields (many null), HTML bodies, and internal metadata the model never needs. To avoid bloating the AI's context window, tool and resource responses pass through a shaping layer before they're returned. Most are field-projected and HTML-stripped; a few (e.g. service-request items, whose custom_fields hold the request's actual answers) are compacted but deliberately kept whole.

What it does:

  • Compact JSON – no pretty-print whitespace (~15-30% saving on every call).
  • Field projection – list/search tools return lean summary rows (e.g. a ticket → id, subject, status, priority, requester_id, group_id, timestamps); detail tools (get_ticket, get_asset, …) return a curated, richer set.
  • HTML stripping – descriptions, conversation bodies, and articles are converted from HTML to plain text (descriptiondescription_text), then truncated if very long.
  • Noise removalnull/empty fields and empty custom-field entries are dropped; attachments are reduced to filenames.
  • Defensive fallback – if a response doesn't match the expected shape, it passes through compacted but otherwise untouched (never mangled).

Summary-then-drill-down: list tools intentionally return summaries. When the model needs everything about one record, it calls the matching get_* tool. This keeps broad queries cheap.

Tuning what the model sees

All shaping rules are declarative and live in one file — src/shape.config.js. The engine (src/shape.js) contains no per-domain logic, so adjusting output requires no code changes.

Each domain defines a list (summary) and/or detail profile:

tickets: {
  container: 'tickets',   // array key for list responses
  item: 'ticket',         // object key for single-record responses
  list:   { fields: ['id', 'subject', 'status', 'priority', /* … */] },
  detail: {
    fields:  ['id', 'subject', 'status', /* …more… */],
    text:    [{ from: ['description_text', 'description'], to: 'description_text', max: 2000 }],
    objects: ['custom_fields'],   // kept, but null/empty entries dropped
  },
}

| Profile key | Effect | |-------------|--------| | fields | Whitelist of keys to keep (present + non-empty only). | | text | Take the first available from field, strip HTML, truncate to max, store under to. | | objects | Custom-field-style objects to keep but compact (drop null/empty). | | names | Reduce an array of { name, … } objects to an array of names (e.g. attachments). |

To add a field to a tool's output, append it to that domain's fields array. To expose more/less body text, change max. That's the whole workflow.

Note: the field names in shape.config.js are mapped to the Freshservice v2 API. If your instance relies on a field that isn't surfaced, add it to the relevant fields array — it's a one-line change.

---

⚡ Performance & Reliability

The Freshservice client (src/freshservice.js) includes several measures to stay fast and resilient under real-world conditions:

  • Request timeout – every request times out after 10s rather than hanging indefinitely on a stalled connection.
  • Automatic retry with backoff – transient failures (429 rate limits, 5xx, network/timeout errors) are retried up to 3 times with exponential backoff. A 429's Retry-After header is honored when present. Non-transient errors (401, 403, 404) are not retried.
  • Caching of static data – near-static reference endpoints (departments, ticket/requester fields, SLA policies, business hours, agent groups) are cached in memory for 10 minutes, so the AI's repeated context-gathering doesn't re-hit the API. Failed lookups are never cached.
  • Concurrent pagination – tools that aggregate every page (list_canned_responses, list_service_catalog_items) fetch page 1, then pull the remaining pages in bounded-concurrency batches (per_page=100, 5 pages at a time) instead of one slow page at a time — turning ~10 sequential round-trips into 2-3 parallel batches.

These are tuned by constants at the top of src/freshservice.js (STATIC_TTL_MS, REQUEST_TIMEOUT_MS, MAX_RETRIES).

---

🧪 Development

| Command | What it does | |---------|--------------| | npm start | Run the MCP server on stdio. | | npm test | Run the Jest test suite. | | npm run lint | Lint with ESLint (flat config, eslint:recommended + Node/Jest globals). | | npm run lint:fix | Lint and auto-fix where possible. | | npm run typecheck | Type-check the JS via TypeScript in checkJs mode (no emit). | | npm run check | Run lint + typecheck + tests together (use before committing). |

Type-checking uses TypeScript's checkJs against the application code (tsconfig.json). It catches real errors — e.g. wrong API shapes or SDK misuse — without requiring the code to be migrated to TypeScript. Test files are excluded from tsc (their Jest mocks are validated by the test runner, not the type-checker). Implicit-any is allowed, so the checker surfaces genuine type errors rather than annotation noise.

---

🔒 Security & Privacy

  1. Read-Only: This server has NO capability to create, edit, or delete data. It is inherently safe.
  2. Local Only: Credentials NEVER leave your machine.
  3. Auditability: All API requests are standard HTTPS and appear in your Freshservice API logs.

📄 License

ISC License. Build with freedom.

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use AI & ML servers.