MCP tool reference
All 73 tools the Helmdesk MCP server exposes. You will rarely name one yourself — you describe what you want and the agent picks. This page is for the other moments: deciding which scopes a key needs, working out why a tool was refused, or checking what a prompt is about to do before you run it.
This page is generated
The table is built from the server's own tool catalog at release time, so it cannot drift from the tools that actually exist. If a tool is listed here, it is registered.
What the markers mean
Every tool carries machine-readable annotations, which is how a client like Claude Code decides what to auto-approve and what to stop and ask about. Without them list_tickets and delete_ticket look identical to a permission layer.
| Marker | Count | What it means |
|---|---|---|
| read | 28 | Looks at data and never changes it. Safe to call speculatively. |
| write | 24 | Changes data inside your account. Nothing leaves Helmdesk. |
| destructive | 10 | Deletes data. There is no trash to recover it from. |
| outbound | 10 | Reaches a real person. An email goes out and cannot be unsent. |
| external | 1 | Calls your own endpoint, never a customer. Nothing to undo. |
The two lists worth knowing by heart
10 tools reach a real customer: update_ticket, reply_to_ticket, bulk_update_tickets, send_email, send_email_batch, send_custom_email, resend_email, reply_to_feedback, request_feedback, approve_agent_item. Note update_ticket is on that list — resolving a ticket emails the customer a satisfaction survey.
10 tools delete with no undo: delete_ticket, delete_email_template, delete_article, delete_log_issue, delete_log_events, delete_feedback_request, delete_customer, delete_webhook, revoke_api_key, reset_sandbox.
Both lists behave differently in sandbox: no mail is ever delivered, and Safety & approvals covers how to keep a key away from them entirely.
Tickets (10 tools)
| Tool | Scope | What it does | |
|---|---|---|---|
| list_tickets | tickets:read | read | List support tickets, newest first, with optional filters |
| get_ticket | tickets:read | read | Get one ticket in full: the complete message thread (customer and staff messages, internal notes), tags, assignee, category and customer info |
| create_ticket | tickets:write | write | Open a support ticket on a customer's behalf — for example from a conversation you had with them elsewhere |
| update_ticket | tickets:write | outbound | Change a ticket's status, priority, category or assignee |
| reply_to_ticket | tickets:write | outbound | Post a staff reply on a ticket. This reaches the customer: the message is recorded on the thread as staff and emailed to them immediately with a link back to the conversation, and a ticket in statu… |
| add_ticket_note | tickets:write | write | Add an internal note to a ticket — staff-only text that is never emailed to the customer, never shown on their portal, and never changes the ticket's status |
| bulk_update_tickets | tickets:write | outbound | Apply one change — status, priority, and/or assignee — to up to 100 tickets at once, for sweeps like "close every ticket tagged spam" or "assign all unassigned billing tickets to Ann" |
| add_ticket_tag | tickets:write | write | Add a tag (label) to a ticket for triage or categorisation, e.g. "vip", "needs-engineering", "refund" |
| remove_ticket_tag | tickets:write | write | Remove a tag from a ticket. Removing a tag it does not have is a no-op |
| delete_ticket | tickets:write | destructive | Permanently delete a ticket with its whole thread — messages, tags, and attachments (storage objects removed) |
Team (1 tool)
| Tool | Scope | What it does | |
|---|---|---|---|
| list_team_members | tickets:read | read | List the active members of the account (user id, name, email, role) — the valid assignedTo values for update_ticket |
Email (16 tools)
| Tool | Scope | What it does | |
|---|---|---|---|
| list_email_templates | emails:send | read | List the email templates this project can send: its own templates (with subject and the variables each body references) and the account's shared templates (keys already @account/-prefixed) |
| import_email_template | emails:manage | write | Create or update an email template from Handlebars source |
| send_email | emails:send | outbound | Send a transactional email from a template to one recipient |
| send_email_batch | emails:send | outbound | Send templated emails to up to 100 recipients in one request, each with its own template, recipient and variables |
| preview_email | emails:send | read | Render a template with the given variables — same layout, partials and project branding as a real send — without sending or storing anything |
| send_custom_email | emails:send | outbound | Send a ONE-OFF email written on the spot: a subject and a Markdown body, no template |
| preview_custom_email | emails:send | read | Render a custom (template-less) email — subject + Markdown body, wrapped in its layout with the project branding — without sending or storing anything |
| get_template_schema | emails:manage | read | Get the names of the variables a template's body references, plus its key, display name and unresolved subject line |
| list_email_sends | emails:read | read | List the project's email log, newest first — the "did the customer get it?" tool |
| get_email_send | emails:read | read | Get one email send with its full event timeline — queued, sent, delivered, opened, bounced, complained — plus the block reason, provider message id and the variables it was rendered with |
| resend_email | emails:send | outbound | Send an existing email AGAIN to its original recipient — the customer receives it a second time, so confirm before calling |
| cancel_scheduled_email | emails:send | write | Cancel an email that is still waiting in status "scheduled" (one sent with sendAt) so it never goes out |
| list_suppressions | emails:read | read | List the addresses this project will NOT email — the suppression list |
| add_suppression | emails:manage | write | Add an address to the suppression list so the project stops emailing it |
| remove_suppression | emails:manage | write | Remove an address from the suppression list so mail flows to it again |
| delete_email_template | emails:manage | destructive | Permanently delete a project email template by key, in the chosen environment, with all its versions |
Knowledge base (8 tools)
| Tool | Scope | What it does | |
|---|---|---|---|
| search_articles | articles:read | read | Search the project's published knowledge base for articles matching a query |
| list_articles | articles:read | read | List the project's knowledge-base articles in the chosen environment, newest-updated first — DRAFTS INCLUDED, unlike search_articles, which only sees published articles |
| create_article | articles:write | write | Create a knowledge-base article in Markdown. Use it to capture a resolution or a recurring answer so future replies can cite it |
| get_article | articles:read | read | Get one knowledge-base article by id, including its full Markdown body, status and category |
| update_article | articles:write | write | Revise an article's title, body or category, or change its status |
| delete_article | articles:write | destructive | Permanently delete a knowledge-base article. It disappears from the public help centre, from search_articles, and from the widget's AI answers at once, and images it referenced are removed from sto… |
| list_article_categories | articles:read | read | List the project's article categories with their ids — the valid categoryId values for create_article and update_article |
| create_article_category | articles:write | write | Create an article category for organising the knowledge base |
Logs (6 tools)
| Tool | Scope | What it does | |
|---|---|---|---|
| write_log | logs:write | write | Ship one or more log events to this project. Events are fingerprinted server-side and grouped into log issues that the Log Watch agent monitors |
| query_logs | logs:read | read | Query raw application log events your own code shipped to this project, newest first |
| list_log_issues | logs:read | read | List grouped error issues (one per error fingerprint) for this project, most recently seen first |
| set_log_issue_status | logs:write | write | Acknowledge, resolve, or reopen a grouped log issue from list_log_issues. "acknowledged" means "I have seen it" — it stays in the list but stops looking new; "resolved" means "fixed" — a resolved i… |
| delete_log_issue | logs:delete | destructive | Delete a grouped log issue AND the raw log events behind it |
| delete_log_events | logs:delete | destructive | Delete up to 200 raw log events by id. IRREVERSIBLE. Ids outside the project or environment of the current key match nothing rather than erroring, so compare `deleted` against `requested` to see wh… |
Feedback (7 tools)
| Tool | Scope | What it does | |
|---|---|---|---|
| list_feedback_conversations | feedback:read | read | List feedback conversations (customer feedback threads) with optional filters, newest first |
| get_feedback_conversation | feedback:read | read | Get a feedback conversation's full detail including the complete message thread (customer + staff messages, with any attachments), rating, and status |
| reply_to_feedback | feedback:write | outbound | Post a staff reply to a feedback conversation. The reply is recorded on the thread and the customer is emailed the message with a link back to the conversation — so only send text you intend the cu… |
| close_feedback_conversation | feedback:write | write | Close a feedback conversation once it has been handled |
| list_feedback_requests | feedback:read | read | List outgoing feedback requests ("tickles") with their funnel status, newest first |
| request_feedback | feedback:write | outbound | Ask a customer for feedback. With the default channel "email" this creates a feedback request AND immediately emails the customer a branded message with your prompt and a respond link (with a sandb… |
| delete_feedback_request | feedback:write | destructive | Permanently delete a feedback request ("tickle") by id |
Customers (8 tools)
| Tool | Scope | What it does | |
|---|---|---|---|
| list_customers | customers:read | read | List the project's customers, most recently seen first |
| get_customer | customers:read | read | Get a customer including their full interaction history — their tickets and feedback conversations, joined by email, recent-first, capped at 50 each |
| create_customer | customers:write | write | Create a customer explicitly. Customers are also created automatically when someone opens a ticket or gives feedback — use this to pre-load or enrich the directory, e.g. syncing your own user base… |
| update_customer | customers:write | write | Update a customer's profile. Email is immutable — it is the join key back to tickets and feedback. internalNote is a staff-only, CRM-style note the customer never sees: use it to record context lik… |
| delete_customer | customers:write | destructive | Delete a customer from the directory. Their tickets and feedback conversations are untouched — linkage is by email, not foreign key — and any new interaction from the same email simply re-creates t… |
| tag_customer | customers:write | write | Add a tag to a customer. Tags are the directory's segmentation primitive: use a plain tag for a property ("vip", "beta-tester", "churn-risk") or a namespace:value tag for a state that has exactly o… |
| untag_customer | customers:write | write | Remove a tag from a customer. Returns the customer's remaining tags |
| set_customer_tags | customers:write | write | Replace a customer's tags in one call. This is the tool to use when syncing state from another system |
Webhooks (6 tools)
| Tool | Scope | What it does | |
|---|---|---|---|
| list_webhooks | webhooks:manage | read | List the project's webhook endpoints for this environment: URL, subscribed events and active state |
| create_webhook | webhooks:manage | write | Register a webhook endpoint that will receive signed event payloads (whsec_ secret) for the chosen events, in the environment of the current key |
| update_webhook | webhooks:manage | write | Change a webhook endpoint's URL, subscribed events, active flag, or Slack formatting |
| delete_webhook | webhooks:manage | destructive | Delete a webhook endpoint by id. Deliveries stop immediately and there is no undo — recreating it issues a new secret |
| test_webhook | webhooks:manage | external | Send a synthetic ticket.created payload (ticket number 0, all-zero id, data.test=true) to ONE webhook endpoint and report what it answered: success, HTTP status, response body (up to 1 KB), and dur… |
| list_webhook_deliveries | webhooks:manage | read | List a webhook endpoint's recent deliveries, newest first — every attempt with its event, success flag, HTTP status, response body, and time |
Projects, keys & sandbox (8 tools)
| Tool | Scope | What it does | |
|---|---|---|---|
| list_projects | projects:read | read | List the projects this API key can reach, and which one is the default (null when the key reaches several and no HELMDESK_PROJECT is set) |
| get_project | projects:read | read | The setup view of one project, by slug or id: branding (name, logo, colour), the public support and knowledge-base URLs to link from the app, whether email sending is configured (from address, mode… |
| get_project_overview | projects:read | read | One snapshot of how an app is doing right now, for its project and environment: the ticket queue by status plus how many await a reply and how many of those are stale (5+ days), tickets resolved th… |
| get_usage | projects:read | read | The account's plan tier and every quota meter next to its limit: tickets this month against the allowance (and whether it is in overage), email sends, log events and retention days, storage bytes… |
| create_project | projects:manage | write | Create a new Helmdesk project for an app — one project per app |
| create_api_key | api_keys:manage | write | Mint an API key for an app you are building, so the app can call Helmdesk from its own code (SDK emails, logs, tickets) |
| revoke_api_key | api_keys:manage | destructive | Revoke an API key by id, permanently. The key stops authenticating on its very next request, so every app or CI job still using it breaks immediately — confirm with the user which app holds it befo… |
| reset_sandbox | projects:manage | destructive | Clear a project's SANDBOX plane in one call — the thing to run between test runs or when a seeded sandbox has gone stale |
Agent review queue (3 tools)
| Tool | Scope | What it does | |
|---|---|---|---|
| list_agent_activity | agents:review | read | The "anything waiting for me?" tool: list what this project's agents did that needs a human, newest first |
| approve_agent_item | agents:review | outbound | Keep what an agent did and mark the item approved. Read the item with list_agent_activity FIRST — what this does depends on details.kind |
| revert_agent_item | agents:review | write | Undo what an agent did and mark the item reverted. Nothing is emailed |
Resources
Alongside the tools, the server publishes three read-only snapshots an agent can pull in as context without deciding to call anything. They always use the server's default project and environment.
| URI | Contents |
|---|---|
| helmdesk://tickets/open | Up to 50 new and 50 open tickets, newest first |
| helmdesk://tickets/pending | Up to 50 tickets waiting on the customer or a third party |
| helmdesk://articles | Up to 100 published knowledge base articles |
Every tool takes two extra arguments
Every project-scoped tool above accepts project (a slug or id) and environment (live or sandbox) on top of its own arguments. The one exception is reset_sandbox, which takes only project — it is always the sandbox plane, so there is nothing to choose. You almost never type either: the project comes from HELMDESK_PROJECTor from a key that reaches exactly one project, and the environment comes from the key. They exist so an agent can say "do this one against Ledgerly, in sandbox" without you reconfiguring anything.
A live key may ask for sandbox on a single call. A sandbox key asking for live is a 403. The downgrade only runs one way — see Sandbox.
Where to go next
- Prompt cookbook — what to actually say, and which of these tools it calls.
- Safety & approvals — scoping a key so the outbound and destructive tools are out of reach.
- REST API — the same surface for code rather than an agent.