Skip to content

Zammad MCP Server — 206 tools

contains code

The Zammad DADL turns Zammad's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 206 tools — ticket, checklist, user, organization, calendar, email, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process.

Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by Zammad feature area, required credential scopes.

Source: Zammad REST API

Credits: Dunkel Cloud GmbH -- maintainerUpdated: 2026-05-22

Which Zammad endpoints are covered?

93% (205 of ~220 endpoints)

Focus: tickets (CRUD + search + history + merge + summarize + tags + links + mentions + shared_draft + time_accounting), ticket_articles (CRUD + attachments inline base64), ticket_states/priorities (CRUD), global search (across all models + per-model + tag autocomplete), users (CRUD + me + search + password + preferences + devices + access_tokens + avatar + email_verify), organizations (CRUD + search), groups (CRUD), roles (CRUD), online_notifications (list + mark_seen + mark_all_read), object_manager_attributes (CRUD + execute_migrations), calendars (CRUD), slas (CRUD), knowledge_bases (init + categories + answers + publish/archive + permissions + reorder + attachments), checklists (CRUD + items + templates), macros, triggers, overviews, jobs (schedulers), reports, signatures, text_modules, templates, email_addresses, postmaster_filters, translations, settings, tag_list admin + tag_search, data_privacy_tasks, activity_stream, karma, monitoring (health/status/amount_check)

Missing: external_credentials (OAuth setup for Twitter/Facebook/Google/Microsoft), form_submit (public embed form), upload_caches (form_id-based -- Web-UI internal), getting_started wizard, sessions long-polling (/message_send + /message_receive), email channel probe/verify sub-actions, channels generic CRUD, two-factor admin

Last reviewed: 2026-05-22

How do you configure the Zammad DADL?

  1. Log in to your Zammad instance as the user who will own the token
  2. Click your avatar (bottom-left of the sidebar) -> Profile -> Token Access
  3. If 'Token Access' is hidden, an admin must grant the role permission 'user_preferences.access_token' (Admin -> Roles)
  4. Click 'Create', fill in a label (e.g. 'ToolMesh Integration')
  5. Tick the required permissions: ticket.agent (or ticket.customer), admin.user, admin.organization, knowledge_base.editor, etc. -- the token cannot exceed the user's own permissions
  6. Optionally set an expiry date (YYYY-MM-DD)
  7. Click 'Create' -- the token is shown ONCE, copy it immediately (cannot be recovered, only revoked)
  8. Provide only the raw token value in your credential store -- ToolMesh prepends 'Token token=' automatically

Environment variable: CREDENTIAL_ZAMMAD_TOKEN

Authentication docs ↗

The url MUST include the /api/v1 suffix, e.g. "https://helpdesk.example.com/api/v1". Zammad is self-hosted, no central endpoint. Impersonation modes (X-On-Behalf-Of): - Off -- no header sent, action recorded as token owner. - Pass-through -- the calling agent supplies X-On-Behalf-Of per call (e.g. forwards the end-user's email). - Fixed user -- operator pins a value in backends.yaml under headers.X-On-Behalf-Of. Tool-level header still wins when supplied. The token cannot exceed the creating user's permissions. For full admin access, create the token as an admin account; for pure customer self-service flows, create it as a customer.

How do you install the Zammad MCP server with ToolMesh?

Add to your backends.yaml:

- name: zammad
  transport: rest
  dadl: zammad.dadl
  url: "https://helpdesk.example.com/api/v1"
  # Optional fixed-user impersonation: pin every outbound request
  # to act on behalf of a specific Zammad user. Comment out for
  # default (token owner) behaviour or pass-through mode.
  # headers:
  #   X-On-Behalf-Of: "[email protected]"

Set the credential:

CREDENTIAL_ZAMMAD_TOKEN=your-token-here

What 206 tools does the Zammad DADL expose?

GETlist_ticketsList all tickets visible to the authenticated user. Paginated. Use search_tickets for filtered queries -- this endpoint has no filter parameters beyond pagination.
GETget_ticketRetrieve a single ticket by ID. Set all_articles=true to include the full article list under .articles.
POSTcreate_ticketCreate a new ticket with an initial article. Required: title, group (group name or group_id), customer (email or customer_id), and an article object {subject, body, type, internal}. Returns the created ticket with its first article. Use X-On-Behalf-Of header to record the ticket as created by another user.
PUTupdate_ticketUpdate an existing ticket. Any field can be partially updated. Pass an 'article' object alongside other fields to append a new article in the same call (common pattern for replying with a state change).
DELETEdelete_ticketPermanently delete a ticket. Requires admin permission. Irreversible -- consider closing/merging instead.
GETsearch_ticketsFull-text ticket search using Elasticsearch query syntax when ES is enabled, or limited SQL otherwise. Examples: 'state.name:open', 'priority.name:"2 normal" AND tags:feedback', 'customer.email:*@example.com AND created_at:[2026-01-01 TO 2026-12-31]'.
GETget_ticket_historyGet the full audit history for a ticket -- all changes, article additions, state transitions, with timestamps and acting users.
POSTmerge_ticketsMerge slave ticket into master ticket. All articles from slave move to master; slave is closed with state 'merged'. IRREVERSIBLE.
POSTsummarize_ticketGet an AI-generated summary of the ticket. Returns the existing summary or triggers async generation -- retry after ~30 seconds if generation is in progress.
GETglobal_searchSearch across ALL searchable models (Ticket, User, Organization, KnowledgeBase::Answer::Translation, Chat::Session). Returns a mixed array of result objects each tagged with .type. Use search_in_model if you only need one type -- it's much cheaper.
GETsearch_in_modelSearch within a single model. Cheaper and more focused than global_search. {model} must be lowercased model name: 'ticket', 'user', 'organization', 'knowledge_base/answer/translation', 'chat/session'. THIS is the canonical way to find a ticket by free text (e.g. 'find ticket about offline printer').
GETtag_search_autocompleteTag-name autocomplete -- returns up to ~25 tag names matching the prefix. Used by UI search boxes.
GETlist_articles_by_ticketList all articles belonging to a ticket. Returns chronological array.
GETget_articleRetrieve a single ticket article by ID.
PUTupdate_articleUpdate an existing ticket article. The most common use is toggling the `internal` flag (publish an internal note, or hide a previously public article). Other editable fields (subject, body) depend on Zammad's "ui_ticket_zoom_article_*_edit" settings -- by default, body editing is allowed for a limited time after creation by the author and by agents with the relevant permission.
POSTcreate_articleAppend a new article to an existing ticket. Common pattern: reply via email (type=email, sender=Agent), internal note (type=note, internal=true), or customer-side message (type=web, sender=Customer with X-On-Behalf-Of=<customer email>).
GETdownload_attachmentDownload an attachment file. Returns the raw binary content.
GETlist_tags_for_objectGet all tags attached to a specific object (ticket, user, organization, KB answer).
POSTadd_tagAttach a tag to an object. Creates the tag if it does not exist (unless tag administration restricts this).
DELETEremove_tagRemove a tag from an object. Does not delete the tag definition itself.
GETlist_ticket_linksList all links between tickets. Pass link_object_value as the ticket NUMBER (not ID).
POSTadd_ticket_linkCreate a link between two tickets. link_type controls direction: 'normal' (peer), 'parent' (source is parent), 'child' (source is child).
DELETEremove_ticket_linkRemove a link between two tickets.
GETlist_my_mentionsList all mentions targeting the authenticated user (or impersonated user).
POSTcreate_mentionAdd a mention -- subscribes the current user to updates on a mentionable object (typically a ticket).
DELETEdelete_mentionRemove a mention -- unsubscribes from updates.
GETlist_time_accountingList all time-accounting entries for a ticket.
GETget_time_accountingGet a single time-accounting entry.
POSTcreate_time_accountingRecord time spent on a ticket. time_unit is in minutes (decimals allowed).
PUTupdate_time_accountingUpdate an existing time entry. Admin permission required.
DELETEdelete_time_accountingDelete a time-accounting entry. Admin permission required.
GETget_shared_draftGet the shared draft for a ticket (collaborative reply being composed).
PUTcreate_shared_draftCreate the shared draft for a ticket.
PATCHupdate_shared_draftUpdate the shared draft for a ticket.
DELETEdelete_shared_draftDelete the shared draft for a ticket.
GETlist_ticket_prioritiesList all ticket priorities (e.g. '1 low', '2 normal', '3 high').
GETget_ticket_priorityGet a single ticket priority.
POSTcreate_ticket_priorityCreate a new ticket priority. Admin permission required.
PUTupdate_ticket_priorityUpdate a ticket priority.
DELETEdelete_ticket_priorityDelete a ticket priority. Fails if the priority is in use.
GETlist_ticket_statesList all ticket states (e.g. new, open, pending reminder, pending close, closed, merged, removed).
GETget_ticket_stateGet a single ticket state.
POSTcreate_ticket_stateCreate a new ticket state. state_type_id references a state type (new/open/closed/pending action/pending reminder/merged/removed).
PUTupdate_ticket_stateUpdate a ticket state.
DELETEdelete_ticket_stateDelete a ticket state. Fails if the state is in use.
GETget_meGet the currently authenticated user. With X-On-Behalf-Of header, returns the impersonated user.
GETlist_usersList users. Use search_users for filtered queries.
GETget_userGet a single user by ID.
GETsearch_usersSearch users by firstname/lastname/login/email (Elasticsearch syntax when enabled). Returns matching users.
POSTcreate_userCreate a new user. Email or login is required as a primary identifier.
PUTupdate_userUpdate a user. All fields are optional -- only supplied fields are changed.
DELETEdelete_userPermanently delete a user. NOT recommended -- prefer marking inactive or using a GDPR data_privacy_task.
POSTchange_my_passwordChange the authenticated user's password. Requires the current password.
POSTrequest_password_resetInitiate a password reset for a user (sends a reset email).
POSTverify_password_resetComplete a password reset using the token from the reset email.
POSTsend_email_verificationSend a verification email to the supplied address. Used for self-signup flows.
POSTverify_email_tokenComplete an email verification by submitting the token from the verification email.
POSTupload_my_avatarUpload an avatar image for the authenticated user. Both fields are data-URLs (e.g. 'data:image/png;base64,iVBOR...'). avatar_full is the original; avatar_resize is the cropped version (typically square).
GETget_user_avatarDownload a user avatar by its hash (returned in user objects under image).
POSTunlock_userUnlock a user account that was locked due to failed login attempts.
GETget_my_preferencesGet the authenticated user's preferences (notification settings, locale, etc.).
PUTupdate_my_preferencesUpdate the authenticated user's preferences. Body shape mirrors the user.preferences field.
GETlist_my_devicesList devices that have authenticated as the current user (browsers, mobile apps).
DELETErevoke_deviceRevoke a device session for the current user.
GETlist_my_access_tokensList API tokens owned by the authenticated user, plus the catalog of permissions available to assign.
POSTcreate_my_access_tokenCreate a new personal access token. Token value is returned ONCE in the response under .token -- store immediately. Permissions cannot exceed the user's own.
DELETEdelete_my_access_tokenRevoke a personal access token by ID.
GETlist_data_privacy_tasksList pending and completed GDPR deletion tasks.
GETget_data_privacy_taskGet a single data-privacy task.
POSTcreate_data_privacy_taskSchedule the deletion of a user (GDPR right to be forgotten). Currently only User is deletable.
DELETEcancel_data_privacy_taskCancel a pending data-privacy task.
GETlist_organizationsList organizations.
GETget_organizationGet a single organization.
GETsearch_organizationsSearch organizations (Elasticsearch syntax when enabled).
POSTcreate_organizationCreate a new organization.
PUTupdate_organizationUpdate an organization.
DELETEdelete_organizationDelete an organization. Fails if the organization has users or tickets.
GETlist_groupsList all groups (ticket inboxes / queues).
GETget_groupGet a single group.
POSTcreate_groupCreate a new group. Nested groups use '::' as separator (e.g. 'Sales::Europe').
PUTupdate_groupUpdate a group.
DELETEdelete_groupDelete a group. Fails if the group contains tickets or users.
GETlist_rolesList all roles (permission bundles).
GETget_roleGet a single role.
POSTcreate_roleCreate a new role with the given permissions.
PUTupdate_roleUpdate a role.
GETlist_online_notificationsList the authenticated user's in-app notifications. Use expand=true for human-friendly object labels.
GETget_online_notificationGet a single online notification.
PUTupdate_online_notificationUpdate notification status (typically mark as seen).
DELETEdelete_online_notificationDismiss / delete a single notification.
POSTmark_all_notifications_readMark all of the current user's notifications as seen.
GETlist_object_attributesList all object-manager attributes (built-in + custom fields) across Ticket, User, Organization, Group.
GETget_object_attributeGet a single object-manager attribute definition.
POSTcreate_object_attributeCreate a custom field. NOTE: changes do not take effect until execute_object_manager_migrations is called.
PUTupdate_object_attributeUpdate a custom field. Requires execute_object_manager_migrations to apply.
DELETEdelete_object_attributeDelete a custom field. Requires execute_object_manager_migrations to apply.
POSTexecute_object_manager_migrationsApply pending object-manager schema migrations. MUST be called after create/update/delete of any custom field.
GETlist_calendarsList business-hour calendars (used for SLA escalation timing).
GETget_calendarGet a single calendar.
POSTcreate_calendarCreate a business-hour calendar.
PUTupdate_calendarUpdate a calendar.
DELETEdelete_calendarDelete a calendar. Fails if used by an SLA.
GETlist_slasList Service Level Agreements.
GETget_slaGet a single SLA.
POSTcreate_slaCreate an SLA. Time values are in minutes.
PUTupdate_slaUpdate an SLA.
DELETEdelete_slaDelete an SLA.
POSTinit_knowledge_baseInitial KB overview -- returns the list of KBs, categories, and answer summaries.
GETget_knowledge_baseGet a single Knowledge Base by ID.
PATCHupdate_knowledge_baseUpdate KB settings (visibility, custom address, etc.).
GETget_kb_permissionsGet role-based permissions for a KB. Returns an array of {role_id, access} where access is admin|editor|reader|none.
PUTset_kb_permissionsSet role-based permissions for a KB. Pass full permissions array (replaces existing).
PATCHreorder_kb_root_categoriesSet the display order of top-level KB categories. Pass the full ordered list of category IDs.
GETget_kb_categoryGet a single KB category.
POSTcreate_kb_categoryCreate a KB category. translations_attributes is an array of {title, locale}.
PATCHupdate_kb_categoryUpdate a KB category.
DELETEdelete_kb_categoryDelete a KB category. Fails if it has child categories or answers.
GETget_kb_category_permissionsGet role permissions for a specific KB category (override category-level access).
PUTset_kb_category_permissionsSet role permissions for a KB category (overrides KB-wide permissions for this subtree).
PATCHreorder_kb_subcategoriesSet the display order of subcategories within a category.
PATCHreorder_kb_answersSet the display order of answers within a category.
GETget_kb_answerGet a KB answer. Use include_contents=<translation_id> to inline the body content.
POSTcreate_kb_answerCreate a KB answer. translations_attributes must contain at least one {title, content (HTML), locale}.
PATCHupdate_kb_answerUpdate a KB answer.
DELETEdelete_kb_answerDelete a KB answer.
POSTpublish_kb_answerPublish a KB answer publicly.
POSTinternal_kb_answerPublish a KB answer to internal audience only.
POSTarchive_kb_answerArchive a KB answer (soft-hide without delete).
POSTunarchive_kb_answerRestore an archived KB answer.
POSTupload_kb_answer_attachmentAttach a file to a KB answer. Multipart upload -- file_url is fetched by ToolMesh and forwarded as multipart/form-data.
DELETEdelete_kb_answer_attachmentRemove an attachment from a KB answer.
GETget_checklistGet a single ticket checklist.
POSTcreate_checklistCreate a checklist on a ticket, optionally from a template.
PATCHupdate_checklistUpdate checklist (rename, reorder items).
DELETEdelete_checklistDelete a checklist (and all its items).
GETget_checklist_itemGet a single checklist item.
POSTcreate_checklist_itemAdd an item to a checklist.
PATCHupdate_checklist_itemUpdate a checklist item (text and/or checked state).
DELETEdelete_checklist_itemDelete a checklist item.
GETlist_checklist_templatesList checklist templates.
GETget_checklist_templateGet a single checklist template.
POSTcreate_checklist_templateCreate a reusable checklist template.
PATCHupdate_checklist_templateUpdate a checklist template.
DELETEdelete_checklist_templateDelete a checklist template.
GETlist_macrosList macros (named action-bundles applied to tickets).
GETget_macroGet a single macro.
POSTcreate_macroCreate a macro. perform is a map of attribute -> {value, ...}.
PUTupdate_macroUpdate a macro.
DELETEdelete_macroDelete a macro.
GETlist_triggersList automation triggers.
GETget_triggerGet a single trigger.
POSTcreate_triggerCreate an event trigger. condition selects matching tickets; perform applies actions.
PUTupdate_triggerUpdate a trigger.
DELETEdelete_triggerDelete a trigger.
GETlist_overviewsList saved ticket overviews (custom queues / views).
GETget_overviewGet a single overview.
POSTcreate_overviewCreate an overview (named ticket query) shared with selected roles.
PUTupdate_overviewUpdate an overview.
DELETEdelete_overviewDelete an overview.
GETlist_jobsList scheduler jobs (recurring tasks executed on a timer).
GETget_jobGet a single scheduler job.
POSTcreate_jobCreate a recurring scheduler job.
PUTupdate_jobUpdate a scheduler job.
DELETEdelete_jobDelete a scheduler job.
POSTgenerate_reportGenerate a report dataset (counts/aggregates) for a given metric over a date range.
GETlist_report_setsList available report sets (configured profiles and backends).
GETlist_signaturesList email signatures.
GETget_signatureGet a single signature.
POSTcreate_signatureCreate an email signature. body supports Zammad variable placeholders.
PUTupdate_signatureUpdate a signature.
DELETEdelete_signatureDelete a signature.
GETlist_text_modulesList text modules (canned replies / snippets).
GETget_text_moduleGet a single text module.
POSTcreate_text_moduleCreate a text module. keywords trigger autocomplete in the compose box.
PUTupdate_text_moduleUpdate a text module.
DELETEdelete_text_moduleDelete a text module.
GETlist_templatesList ticket-creation templates.
GETget_templateGet a single template.
POSTcreate_templateCreate a ticket template. options is a map of attribute -> value used to pre-fill the create form.
PUTupdate_templateUpdate a template.
DELETEdelete_templateDelete a template.
GETlist_email_addressesList configured email-sender addresses.
GETget_email_addressGet a single email address.
POSTcreate_email_addressAdd a sender email address linked to an outbound channel.
PUTupdate_email_addressUpdate an email address.
DELETEdelete_email_addressDelete an email address.
GETlist_postmaster_filtersList postmaster filters (email pre-processing rules: match headers, set ticket properties).
GETget_postmaster_filterGet a single postmaster filter.
POSTcreate_postmaster_filterCreate a postmaster filter. match selects emails by header; perform assigns ticket fields.
PUTupdate_postmaster_filterUpdate a postmaster filter.
DELETEdelete_postmaster_filterDelete a postmaster filter.
GETlist_all_tagsList all defined tags with usage counts.
POSTcreate_tag_definitionCreate a tag in the catalog (without attaching it to an object yet).
PUTrename_tagRename a tag everywhere it is used.
DELETEdelete_tag_definitionDelete a tag from the catalog and detach it from all objects.
GETlist_translationsList UI string translations.
GETlist_admin_translationsGet all translations for a locale, including admin-overridable strings.
GETlist_settingsList system settings. Returns full setting objects -- use jq to filter by area or name.
GETget_settingGet a single setting by ID.
PUTupdate_settingUpdate a system setting. Only state_current can typically be changed; structure depends on the setting.
GETget_activity_streamGet the activity stream for the authenticated user (recent changes across visible objects).
GETget_recent_viewedGet the list of recently viewed objects for the authenticated user.
GETlist_karma_usersGet the Karma gamification leaderboard. Returns an array of {user_id, score, level} entries (level e.g. 'Beginner', 'Master'). Karma awards points for actions like first-response-within-SLA, ticket-closed, KB-answer-published. Often disabled by admins -- 404 means the feature is not enabled.
GETmonitoring_health_checkHealth check endpoint. NOTE: requires a separate monitoring token passed as ?token=... query parameter (configured in Admin -> System -> Monitoring), NOT the user access token.
GETmonitoring_statusSystem status / counts. Requires monitoring token (see monitoring_health_check).
GETmonitoring_amount_checkVolume check (e.g. tickets created in last period).

What composite workflows does the Zammad DADL provide? ⚠ contains code

FNreply_and_closeAppend an outbound email reply to a ticket and close it in one atomic call. Common agent workflow.
FNcreate_ticket_with_articlesCreate a ticket and append additional follow-up articles in sequence. Useful for migrating existing conversations.
FNfind_or_create_customerLook up a customer by email; create them if they do not exist. Returns the user object.