MCP Server
Give AI assistants native access to your help desk using the Model Context Protocol.
Open Help Desk includes a built-in Model Context Protocol (MCP) server mounted at /mcp/. MCP allows AI assistants — Claude, Cursor, VS Code with Continue, and others — to call help desk operations as structured tools, rather than trying to interact with the web UI.
With the MCP server connected, an AI assistant can:
- List open tickets and summarize them
- Look up the details and history of a specific ticket
- Create a ticket on behalf of a user
- Add a reply or internal note
- Change a ticket's status or assignee
The MCP server sits on top of the REST API — every operation goes through the same permission checks. An AI assistant using a Staff user's API key cannot do anything a Staff user couldn't do manually.
Available tools
list_tickets
List open tickets with optional filters
any role
Returns a list of tickets the authenticated user has permission to view. Scope rules apply — a Staff user only sees tickets within their group scope.
Parameters
| Name | Type | Description |
|---|---|---|
status | string (optional) | Filter by status name, e.g. "New" or "In Progress". |
priority | string (optional) | "Critical", "High", "Medium", or "Low". |
assignee_id | string (optional) | Filter to a specific assignee's tickets. |
category | string (optional) | Filter by category name (case-insensitive). |
q | string (optional) | Text search across subject and description. |
limit | int (optional) | Maximum results to return (default: 20, max: 100). |
Example
list_tickets(status="New", priority="High", limit=10)
get_ticket
Retrieve a ticket with its full reply thread
any role
Returns the complete ticket including all replies (public and, for Staff/Admin, internal notes), linked tickets, and metadata.
| Name | Type | Description |
|---|---|---|
ticket_id | string (required) | The ticket ULID. |
create_ticket
Submit a new support ticket
any role
Creates a ticket on behalf of the authenticated user. The ticket is attributed to the API key's owner as the submitter.
| Name | Type | Description |
|---|---|---|
subject | string (required) | Short summary, max 255 characters. |
description | string (required) | Full detail of the request. Markdown supported. |
category_id | string (required) | Category ULID. Use list_categories to get available IDs. |
type_id | string (optional) | Type ULID. |
item_id | string (optional) | Item ULID. |
priority | string (optional) | Default: "Medium". |
reply_to_ticket
Add a public reply or internal note
any role
Adds a reply to a ticket's thread. Internal notes (is_internal: true) require Staff or Admin role — attempting to post an internal note as a User returns an error.
If the ticket is Resolved and within the reopen window, submitting a reply as a User automatically reopens the ticket.
| Name | Type | Description |
|---|---|---|
ticket_id | string (required) | The ticket ULID to reply to. |
body | string (required) | Reply content. Markdown supported. |
is_internal | bool (optional) | Default: false. If true, posts as an internal note visible only to Staff and Admins. |
update_ticket_status
Change a ticket's status
staff / admin
Transitions the ticket to a new status. Use list_statuses to get available status IDs.
| Name | Type | Description |
|---|---|---|
ticket_id | string (required) | The ticket ULID. |
status_id | string (required) | The target status ULID. |
assign_ticket
Assign a ticket to a staff member or group
staff / admin
Assigns a ticket. Provide either assignee_id (a staff user) or group_id (a group), not both. Pass null to both to unassign.
| Name | Type | Description |
|---|---|---|
ticket_id | string (required) | The ticket ULID. |
assignee_id | string (optional) | Staff user ULID to assign to. |
group_id | string (optional) | Group ULID to assign to. |
list_categories
List available ticket categories
any role
Returns all categories. Useful for getting category IDs before calling create_ticket.
list_statuses
List all ticket statuses
any role
Returns all statuses with their IDs and names. Useful for getting status IDs before calling update_ticket_status.
Connecting clients
Claude (claude.ai / Claude Code)
Add a server entry to your MCP configuration. In Claude Code, this lives in .claude/mcp.json (project-level) or ~/.claude/mcp.json (global).
{
"mcpServers": {
"helpdesk": {
"type": "http",
"url": "https://helpdesk.example.com/mcp/",
"headers": {
"Authorization": "Bearer ohd_sk_xxxxxxxxxxxxxxxxxxx"
}
}
}
}
After saving, Claude will have access to the help desk tools in any conversation where MCP is active.
VS Code with Continue
// .continue/config.json
{
"experimental": {
"modelContextProtocolServers": [
{
"transport": {
"type": "http",
"url": "https://helpdesk.example.com/mcp/",
"requestOptions": {
"headers": {
"Authorization": "Bearer ohd_sk_xxxxxxxxxxxxxxxxxxx"
}
}
}
}
]
}
}
Cursor
// cursor/mcp.json (in project root or ~/.cursor/mcp.json)
{
"mcpServers": {
"helpdesk": {
"url": "https://helpdesk.example.com/mcp/",
"headers": {
"Authorization": "Bearer ohd_sk_xxxxxxxxxxxxxxxxxxx"
}
}
}
}
Any HTTP MCP client
The MCP server implements the standard Streamable HTTP transport. Point any compliant client at:
https://<BASE_URL>/mcp/
Include an Authorization header with either an API key or a JWT from the OAuth2 token endpoint.
Authentication
The MCP server uses the same authentication mechanisms as the REST API:
- API key (recommended for long-lived client configs) —
Authorization: Bearer ohd_sk_... - OAuth2 JWT (recommended for server-to-server) — obtain a token from
POST /api/auth/token, include asAuthorization: Bearer <jwt>. Tokens expire after 1 hour; your client must handle token refresh.
Session cookies are not accepted by the MCP server — they require a browser context.
One API key per integration — create a dedicated API key for each AI assistant or integration that connects to the MCP server. This lets you revoke a single client's access without affecting others, and gives you a named audit trail in logs.
Permissions
Every MCP tool call is subject to the same permission system as the REST API. The permissions granted depend on the role of the account whose credentials are used.
| Tool | Minimum role | Scope applied? |
|---|---|---|
list_tickets | Any | Yes — Users see only their own tickets; Staff see their group scope. |
get_ticket | Any | Yes — Users can only get their own tickets. |
create_ticket | Any | N/A — ticket is attributed to the key owner. |
reply_to_ticket (public) | Any | Yes — Users can only reply to their own tickets. |
reply_to_ticket (internal) | Staff / Admin | Yes |
update_ticket_status | Staff / Admin | Yes |
assign_ticket | Staff / Admin | No — any Staff member can assign to any user or group. |
list_categories | Any | N/A |
list_statuses | Any | N/A |
If a tool call fails a permission check, the MCP server returns a structured error response and does not execute the operation. The AI assistant receives a description of the error and can inform the user.