helpdesk-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@helpdesk-mcpTriage the urgent open tickets and add internal notes"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
helpdesk-mcp
A customer support helpdesk exposed over the Model Context Protocol (MCP), plus an AI agent that triages tickets through it.
Plug the server into Claude Desktop (or any MCP client) and the model can search tickets, read customer history, look up knowledge base articles and leave notes. Or run the included agent, which connects to the server over MCP, discovers its tools at runtime, and asks a person before it changes anything.
It runs with no API key: an offline demo model drives the agent, so you can clone it and see it work in a minute.
$ helpdesk-agent --yes "Triage the urgent open tickets"
model: demo-offline server: helpdesk-mcp over stdio
model I'll find the urgent open tickets first.
call search_tickets({"status": ["open"], "priority": ["urgent"], "limit": 3})
result {"result": [{"id": 2, "subject": "Charged twice for October", "priority": "urgent", ...
model Reading 3 ticket(s).
call get_ticket({"ticket_id": 2})
call get_ticket({"ticket_id": 1})
call get_ticket({"ticket_id": 3})
model Checking the knowledge base for each one.
call search_kb({"query": "Teachers locked out after SSO change"})
result {"result": [{"slug": "sso-setup", "title": "Setting up single sign-on (SSO)", ...
call add_comment({"ticket_id": 3, "body": "Triage: urgent account ticket from an enterprise customer. Relevant article: sso-setup ...
model Triage summary:
- #2 Charged twice for October (urgent, billing): article `refund-policy`.
- #1 Invoices export is empty since the update (urgent, bug): article `export-data`.
- #3 Teachers locked out after SSO change (urgent, account): article `sso-setup`.
I left an internal note on each ticket. Nothing was sent to customers.
5 model turns, 5,048 tokens, 0.1sWhat the server exposes
Kind | Name | What it does |
Tool (read) |
| Text search plus filters for status, priority, category and unassigned. Most urgent first. |
Tool (read) |
| Full ticket with customer and comments. |
Tool (read) |
| Company and plan. Email addresses are masked. |
Tool (read) |
| BM25 search over knowledge base articles. |
Tool (read) |
| Counts by status and priority, unassigned work, oldest open ticket. |
Tool (write) |
| Internal note by default, or a customer-facing reply. |
Tool (write) |
| Status, priority and assignee, following the ticket workflow. |
Tool (write) |
| Open a ticket for a customer. |
Resource |
| A ticket as JSON. |
Resource |
| Knowledge base index and articles as Markdown. |
Resource |
| The latest writes, with who made them. |
Prompt |
| Reusable instructions for common jobs. |
Related MCP server: TicketDesk MCP
Safety by design
An MCP server hands real capabilities to a model, so the limits live in code, not in the prompt:
Typed, bounded inputs. Every tool argument has a type and limits (ids at least 1, text length caps, enums for status and priority). The SDK rejects bad input before any of my code runs.
Business rules the model can't skip. Status changes follow a fixed workflow, and closed tickets are final. A refused change comes back as a clear error the model can act on.
Read-only mode.
--read-onlydoesn't register the write tools at all, which is a good default for a first connection.Tool annotations. Each tool declares
readOnlyHint,destructiveHintandidempotentHint, so clients can decide what needs confirmation.Human approval in the agent. The agent asks before running any tool the server marks as not read-only. A declined action is reported back to the model, which is told not to retry it.
Least personal data. Customer emails are masked before they reach the model.
Audit log. Every write is recorded with the actor, the action and what changed.
Errors that help, crashes that don't leak. Expected failures raise
ToolErrorwith a useful message; anything unexpected reaches the model only as a generic error, and the details stay in the server log.
Architecture
flowchart LR
subgraph Clients
CD[Claude Desktop]
AG[helpdesk-agent<br/>agent loop + approval]
end
subgraph Server["helpdesk-mcp (MCP server)"]
T[Tools<br/>typed + annotated]
R[Resources]
P[Prompts]
S[(SQLite store<br/>+ audit log)]
end
M{{Model<br/>Claude or offline demo}}
CD -- stdio --> T
AG -- "stdio or HTTP" --> T
AG <--> M
T --> S
R --> SThe agent never imports the server's code. It sees only what any MCP client sees, so it works the same against this server or any other.
Getting started
Requires Python 3.11+ and uv.
git clone https://github.com/s-talha/helpdesk-mcp.git
cd helpdesk-mcp
uv sync --group dev
uv run helpdesk-agent "Triage the urgent open tickets" # asks before each write
uv run helpdesk-agent --yes "Triage ticket 4" # approve writes automatically
uv run helpdesk-agent --read-only "Triage ticket 4" # server has no write toolsThe demo database (10 customers, 16 tickets, 10 articles) is created at ~/.helpdesk-mcp/helpdesk.db on first run. Pass --db to use another file.
To run the agent on Claude instead of the demo model:
uv sync --extra anthropic
export ANTHROPIC_API_KEY=...
uv run helpdesk-agent "Which unassigned tickets are at risk, and why?"Use it from Claude Desktop
Add this to claude_desktop_config.json, then restart Claude Desktop:
{
"mcpServers": {
"helpdesk": {
"command": "uv",
"args": ["--directory", "/path/to/helpdesk-mcp", "run", "helpdesk-mcp", "--read-only"]
}
}
}Remove --read-only once you're happy for Claude to add notes and update tickets.
Run over HTTP
uv run helpdesk-mcp --http --port 8000 # Streamable HTTP at http://127.0.0.1:8000/mcp
docker build -t helpdesk-mcp . && docker run -p 8000:8000 helpdesk-mcpTests
uv run pytest40 tests cover the store (search ranking, workflow rules, masking, audit), the server through a real MCP client (schemas, annotations, read-only mode, invalid input, resources, prompts), and the agent (an end-to-end triage, declined approvals, read-only runs, step limits, and errors fed back to the model). Two tests start the server as a subprocess and talk to it over stdio, exactly as Claude Desktop does.
All tests use the offline demo model, so CI needs no secrets.
Project layout
src/helpdesk_mcp/
models.py domain models and the status workflow
store.py SQLite store: queries, search, audit log
seed.py deterministic demo data
server.py the MCP server: tools, resources, prompts
__main__.py helpdesk-mcp command (stdio or HTTP)
agent/
loop.py agent loop over an MCP client, with approval and step limits
providers.py Claude provider and the offline demo model
cli.py helpdesk-agent command
tests/License
MIT
Available Tools
8 toolsadd_commentA
Add a comment. Internal notes (the default) are only visible to support staff.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | ||
| internal | No | ||
| ticket_id | Yes | Ticket id, for example 3. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| body | Yes | |
| author | Yes | |
| internal | Yes | Internal notes are visible to agents only, never to the customer. |
| created_at | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false and openWorldHint=false, so the write/non-destructive profile is covered. The description does add one genuinely useful trait beyond them — internal notes are visible only to support staff — but says nothing about permissions required, whether a public comment notifies the customer, or any rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with zero filler, and the visibility constraint for the default mode is front-loaded where an agent will see it before deciding on parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity, 3-parameter write tool with annotations covering safety and an output schema covering return values, the description addresses the main failure mode (posting a support-only note thinking it is public). It could still mention the public/internal routing more explicitly, but nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 33% (ticket_id is the one documented parameter), so the description must carry weight — and it does, explaining that 'internal' defaults to a support-staff-only note, which the schema does not convey at all. The body parameter remains unexplained, which keeps it from a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Add a comment'), so the action is unambiguous, but it never says the comment attaches to a ticket — the reader must infer that from the ticket_id parameter and the sibling set (search_tickets, get_ticket, update_ticket). No sibling differentiation is offered, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to use this tool versus update_ticket or the other siblings, and no prerequisites are given. The note about internal notes implies a choice between internal and customer-visible comments, but that choice is never framed as guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_ticketC
Open a new ticket for a customer.
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | ||
| subject | Yes | ||
| category | No | how_to | |
| priority | No | normal | |
| customer_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| body | Yes | |
| status | Yes | |
| subject | Yes | |
| assignee | Yes | |
| category | Yes | |
| comments | Yes | |
| customer | Yes | |
| priority | Yes | |
| created_at | Yes | |
| updated_at | Yes | |
| customer_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false and openWorldHint=false, so the safety profile is covered. The description adds nothing beyond that: it does not say whether the ticket is auto-assigned, whether notifications are sent, or what status a new ticket starts in.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single short sentence is front-loaded and free of waste, so it is not verbose. However, at this level of triviality it is under-specification rather than true conciseness for a 5-parameter mutation tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, and annotations cover the safety profile. Still, for a creation tool with 5 parameters, defaults, and validation bounds, the description omits required inputs, default behavior, and side effects, leaving real gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All 5 parameters have 0% schema description coverage and the description documents none of them. Notably absent are the category and priority enums with their defaults ('how_to' and 'normal') and the length limits on subject and body, leaving the agent with no semantic guidance whatsoever.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Open a new ticket'), and the word 'new' implicitly separates it from update_ticket and add_comment. It does not explicitly name or differentiate from any sibling, but an agent can tell this is a creation tool without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no prerequisites (e.g. customer must exist), and no mention of alternatives such as updating an existing ticket or adding a comment to one. The agent must infer all routing from the tool name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_customerBRead-only
Get a customer's company and plan. The email address is masked.
| Name | Required | Description | Default |
|---|---|---|---|
| customer_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| plan | Yes | |
| Yes | Masked: the local part is hidden to keep personal data out of model context. | |
| company | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description contributes one genuinely non-obvious behavioral fact — the email address is masked — but says nothing about lookup failures, missing customers, or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the purpose, and the masking note is relevant rather than filler. No wasted words, though the second sentence could have been folded into the first.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained in prose. For a trivial single-parameter lookup the description is close to adequate, but the total absence of usage context and parameter meaning leaves a real gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description says nothing about customer_id — not its origin, format, or whether it is an internal ID versus a public identifier. The single integer parameter is simple, but the description makes no attempt to compensate for the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get a customer') plus the fields returned (company, plan). It is clear, but the sibling list is entirely ticket-oriented, so there is no peer tool it needs to be disambiguated from, and it does not articulate its scope relative to any of them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No when-to-use guidance, no prerequisites, and no alternatives mentioned. It never says whether this is the right tool for looking up a customer referenced by a ticket, or what to do when the ID is unknown.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ticketARead-only
Get one ticket with its full text, the customer and all comments.
| Name | Required | Description | Default |
|---|---|---|---|
| ticket_id | Yes | Ticket id, for example 3. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| body | Yes | |
| status | Yes | |
| subject | Yes | |
| assignee | Yes | |
| category | Yes | |
| comments | Yes | |
| customer | Yes | |
| priority | Yes | |
| created_at | Yes | |
| updated_at | Yes | |
| customer_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds the useful fact that comments and customer data are expanded into the response, but says nothing about behavior for a missing/invalid id or any size limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence, front-loaded with the verb and resource, with zero filler. Everything stated (full text, customer, comments) is load-bearing information about the payload.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with an output schema that documents the return shape, the description is close to sufficient. Only the absent error/not-found behavior keeps it from being fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter and schema description coverage is 100%, so the schema ('Ticket id, for example 3.') already carries full meaning. The description adds no additional format or sourcing guidance for the id, making 3 the correct baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clear verb ('Get') plus resource ('one ticket') with an explicit payload scope: full text, the customer, and all comments. It is distinguishable from the plural sibling search_tickets by the singular, single-record framing, though it never names that sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the required ticket_id: retrieve one known ticket by id. There is no statement of when to prefer this over search_tickets when the id is unknown, nor any exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_kbBRead-only
Search knowledge base articles. Read the full article with the helpdesk://kb/{slug} resource.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| category | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description usefully adds that results are abbreviated and full content lives behind a resource URI, but says nothing about result limits, ranking, or empty-match behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, with the core action front-loaded and the follow-up instruction second. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the resource pointer covers post-search behavior. The gap is the undocumented 'category' filtering dimension, which an agent would not discover without inspecting the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the burden — and it does not. The 'category' filter (with its billing/bug/account/how_to enum) is never mentioned, and no meaning is added for 'query' beyond the obvious. The agent must open the schema to learn a filterable dimension exists.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Search knowledge base articles'), which is inherently distinct from the ticket/customer siblings. However, it never explicitly contrasts itself with siblings like search_tickets, so the differentiation must be inferred from the resource noun.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives next-step guidance ('Read the full article with the helpdesk://kb/{slug} resource'), which implies search returns partial results and full content requires a follow-up. It offers no when-to-use vs when-not-to-use framing and no mention of alternatives, so usage is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_ticketsBRead-only
Find tickets by text and filters. Results are sorted most urgent first, then oldest first.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | No | Words to search for. Leave empty to match everything. | |
| status | No | ||
| category | No | ||
| priority | No | ||
| unassigned_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds genuinely non-obvious behavior — the ordering rule (most urgent first, then oldest first) — but says nothing about pagination beyond the schema's limit, result truncation, or what matching means (substring vs token).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, the operational purpose first and the ordering guarantee second. Nothing is padded and the most decision-relevant behavior is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the safety profile is in annotations. However, for a six-parameter search tool the filter-combination semantics remain undocumented, which is the main thing that could cause a malformed or over-narrow query.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 17%: only 'query' has a description. The description's phrase 'text and filters' does not explain the key ambiguity for the three array filters — whether multiple values are OR-ed within a field and AND-ed across fields — nor what unassigned_only overrides. With low coverage, the description needed to compensate and does not.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Find') and resource ('tickets') plus the two mechanisms of retrieval: text and filters. It is distinguishable from get_ticket (single fetch) by implication, but it never explicitly contrasts with its siblings such as search_kb or ticket_stats.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use guidance, no exclusions, and no reference to any of the seven sibling tools. The agent must infer that this is the discovery tool before reaching for get_ticket or ticket_stats, and nothing tells it whether search should precede direct retrieval.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
ticket_statsBRead-only
Counts by status and priority, unassigned work, and the age of the oldest open ticket.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| by_status | Yes | |
| unassigned_open | Yes | |
| by_priority_open | Yes | Open and pending tickets by priority. |
| oldest_open_hours | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds behavioral value by disclosing which aggregates are returned, but says nothing about the scope of the aggregation (all tickets vs. a subset), whether the counts are cached, or any rate/refresh behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single short sentence with no wasted words, and the most distinctive metrics are listed first. It is grammatically a fragment with no stated verb, which slightly reduces clarity but not length efficiency.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not explain return values, and with zero parameters there are no inputs to document; annotations cover the safety profile. The only residual gap is that the aggregation scope (which tickets are counted) is unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4 and there is no parameter semantics for the description to clarify. Nothing here misleads about inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description enumerates exactly what is computed — counts by status and priority, unassigned work, and oldest open ticket age — which is far more specific than a generic 'ticket statistics' phrasing. It is a noun-phrase fragment with no explicit verb, so the agent must infer 'returns aggregate statistics', but the metric list distinguishes it clearly from siblings like search_tickets and get_ticket.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no statement of what this tool is for in a workflow, and no mention of alternatives (e.g., use search_tickets when you need individual records rather than aggregates). The agent must infer the routing from the metric list alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_ticketAIdempotent
Change status, priority or assignee. Status changes follow the workflow: open <-> pending, open/pending -> resolved, resolved -> open or closed. Closed is final.
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | ||
| assignee | No | ||
| priority | No | ||
| unassign | No | ||
| ticket_id | Yes | Ticket id, for example 3. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| body | Yes | |
| status | Yes | |
| subject | Yes | |
| assignee | Yes | |
| category | Yes | |
| comments | Yes | |
| customer | Yes | |
| priority | Yes | |
| created_at | Yes | |
| updated_at | Yes | |
| customer_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this as a non-read-only, idempotent, non-destructive mutation, so safety is covered. The description adds genuinely new behavioral context beyond them: the state machine for status transitions and the terminal nature of 'closed', which an agent cannot derive from the enum alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with the core action front-loaded and the constraint detail following; every clause carries information and nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no explanation, and annotations cover the safety profile. However, for a 5-parameter mutation tool with 20% schema coverage, the undisclosed 'unassign' parameter and the ambiguous relationship between assignee and unassign leave a real functional gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 20% (only ticket_id is documented), so the description must compensate. It does explain the meaning and legal transitions of the status parameter, which the enum does not, but it never mentions the 'unassign' boolean or the assignee semantics, leaving two parameters effectively undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (change) and names the exact mutable fields (status, priority, assignee), which cleanly separates it from read-only siblings like get_ticket and search_tickets. It does not explicitly name or contrast with any sibling, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The transition rules implicitly say when a status change is legal, which is useful usage context, but there is no guidance on when to choose update_ticket over add_comment or create_ticket, and no prerequisites or exclusions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
8 tool updates
v0.1.0- First observed
add_comment - First observed
create_ticket - First observed
get_customer - First observed
get_ticket - First observed
search_kb - First observed
search_tickets - First observed
ticket_stats - First observed
update_ticket
TDQS
Scored across 8 tools
Each tool targets a distinct resource and action: search_tickets vs get_ticket (query vs single-fetch), ticket_stats (aggregates) vs search_tickets (filtered lists), get_customer vs get_ticket, and search_kb vs all ticket tools. add_comment and update_ticket also have clearly separate mutation scopes. No tool pair is likely to be confused.
Seven tools follow a clean verb_noun pattern (search_tickets, get_ticket, get_customer, search_kb, add_comment, update_ticket, create_ticket). The lone outlier is ticket_stats, which is a noun-only name, a minor deviation from an otherwise predictable convention.
Eight tools is well within the ideal range and each earns its place by covering a distinct capability (search, fetch, create, update, comment, stats, KB, customer). No redundant or filler tools are present.
Core helpdesk lifecycle is covered: create/read/search/update tickets, comment, stats, KB search, and customer lookup. Minor gaps exist (no customer listing/search, no comment editing or deletion), but the closed-is-final status workflow makes ticket deletion reasonably unnecessary.
Maintenance
Related MCP Connectors
Hosted support inbox over MCP: answer web chat, WhatsApp, email and SMS, manage knowledge.
Remote MCP server for managing Muninx tickets, messages, ticket search, and support analytics.
Help desk for agents. Search questions and answers first. Read-only MCP.
Native MCP access to CRM contacts, organizations, deals and tasks with user permissions.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI-driven customer support operations including conversation management, knowledge base, contacts, metrics, and settings via MCP.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to search and retrieve support tickets, add notes, close tickets, and access SLA policies through MCP tools, resources, and prompts over Streamable HTTP.MIT
- FlicenseNot gradedqualityCmaintenanceEnables AI clients to access and manage an internal support ticket queue through MCP tools, resources, and prompts, including searching and viewing tickets, adding comments, closing tickets with confirmation, reading knowledge base articles, and viewing queue summaries over OAuth-secured Streamable HTTP.-
- AlicenseAqualityCmaintenanceProvides customer lookup, transaction history, knowledge-base search, and ticket management tools to any MCP client.5MIT