MCP server
MCP server
Open HelpDesk ships a Model Context Protocol server. Point Claude, or any MCP client, at a workspace and it can search tickets, read a whole conversation, look up what you have already published in the help centre, and — when you ask it to — answer.
It speaks to the public REST API, never to the database. So it inherits the API key's scopes, its rate limit and its workspace isolation, and it cannot reach round the rules engine. The same server works against the hosted product and against a self-hosted instance.
Setting it up
Two environment variables, and nothing else:
| Variable | Value |
|---|---|
OHD_BASE_URL | https://acme.open-helpdesk.com |
OHD_API_KEY | a key from Settings → API & webhooks |
Claude Desktop / Claude Code
Code
Run from a clone for now — the package is not published to npm yet, and this
page will show the one-line npx form when it is, not before.
Give it a read-only key unless you actually want the assistant writing to
your helpdesk. Scope is chosen when you mint the key — read, read/write, or
create-tickets-only — and a read key turns every mistake into a 403.
The tools
Nine, chosen for what someone does with a helpdesk rather than one per endpoint — a faithful mirror of thirty-two routes is thirty-two choices an assistant makes badly.
Reading
| Tool | What it does |
|---|---|
search_tickets | Find tickets by status, priority, assignee, organization, tag, or what changed since a given time. |
get_ticket | One ticket and its whole thread, internal notes included. |
search_knowledge_base | Published articles matching some words. |
get_article | One article in full. |
find_contact | Look someone up by email. |
list_workspace | Agents, teams, organizations or tags — for assigning and filing. |
Writing
| Tool | What it does |
|---|---|
create_ticket | Opens a ticket. Reaches a real customer: rules, SLA policies and acknowledgement emails run as they would for an inbound email. |
reply_to_ticket | Adds a message. Defaults to an internal note; internal: false sends it to the customer. |
update_ticket | Status, priority, assignee, tags, type, organization. Sends nothing itself — but the workspace's rules may. |
The writing tools are annotated as such, so a client that asks for confirmation
knows which ones to ask about. reply_to_ticket defaults to an internal note on
purpose: drafting is the common case, and sending to a customer should be the
sentence you typed, not the default you forgot.
What it will not do
- It cannot configure the workspace. Rules, SLA policies, macros and views are readable so an assistant can reason about them, and are changed by a human who can see the consequences.
- It cannot delete anything. No tool maps to
DELETE. - It cannot see another workspace. The key carries one, and only one.
Using it well
The pattern that works:
Read ticket 4821, check the knowledge base for what we have already published on that, and draft a reply as an internal note.
The assistant reads the thread, finds the article, drafts — and you send it, or you do not. Asking it to reply publicly straight away skips the one step where a mistake is still cheap.
Running it from source
Code
The server is packages/mcp, AGPL-3.0 like the rest of the core. It logs to
stderr only — stdout is the protocol.