Skip to content

Fixes #1372 - Document the MCP server - #1374

Open
ralf401 wants to merge 3 commits into
pre-releasefrom
rsc/fixes/1372
Open

ralf401 wants to merge 3 commits into
pre-releasefrom
rsc/fixes/1372

Conversation

@ralf401

@ralf401 ralf401 commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

Restructure of system/api.rst to mirror the tabbed settings page of 7.3 (api restructure is part of the same feature branch): H2 Token access with H3 Token Access, H3 Password Access and H3 MCP Server, H2 OAuth. The old H2 Authentication Methods is folded into the intro as a general overview that names the three methods without claiming to mirror the page structure. Claims and their anchors, all from the feature branch
origin/private/dk/issue/6519/mcp-server-agents-work-on-zammad-tickets-from-their-own-ai-client of zammad/zammad (7.3):

  • Setting api_mcp_access, area API::Base, default off: db/seeds/settings.rb (title 'MCP server'), db/migrate/20261103120000_add_mcp_server.rb
  • Request refused while off, whatever the token: mcp_controller.rb (authenticate_with_personal_access_token!, switched-off message before the token check)
  • Personal access tokens are the only authentication, Token Access dependency: mcp_controller.rb delegates to application_controller/authenticates.rb#authentication_check_api_token, which refuses when api_token_access is off
  • The client does what the token and its owner may: Service::AI::Tool::Runtime :Router.offered? narrows by token (lib/user_info.rb#with_token) and all 26 MCP tools carry permission 'ticket.agent'
  • The page shows /mcp and the Claude Code example: app/views/api /access.jst.eco (new file on the feature branch)
  • FQDN, alternative FQDN and loopback hosts, browser origins from other origins refused: app/services/service/mcp_server/addresses.rb
  • Approval with text and recipients shown, form elicitation of MCP revision 2026-07-28, nothing sent without or with an unshown form: app/services/service/mcp_server/confirmation.rb (NOT_CONFIRMED, form capability check), call_tool.rb (elicitation/create, spec suggestion for every result of 2026-07-28), create_article/preparation.rb (confirmation preview and required: outbound || !internal)

Heading name "MCP Server" and no "Tab" in headings per review in zammad-admin-documentation#1372. make gettext ran with the conda env, the committed locale/admin-docs.pot is its output.

The tool table lists what the client gets, with the anchors of every row:

  • The 26 rows are the 26 tool classes in app/services/service/ai/tool/*.rb, each declaring offered_in :mcp and permission 'ticket.agent'; the Router discovers them without a registry (runtime/router.rb) and sorts by tool_name, which is the alphabetical order of the table
  • read/write per row is the tool's effect line in its own class (9 write: add _internal_note, create_article, create_ticket, link_knowledge_base_answer, link_tickets, save_shared_draft, send_shared_draft, set_ticket_tags, update_ticket; 17 read)
  • Each row's description is a summary of that class's own description string (written for the model), reduced to what an admin deciding on the toggle and the token needs
  • The three knowledge base tools appear only with an active knowledge base: get_knowledge_base_answer.rb:32, link_knowledge_base_answer.rb:43 and search_knowledge_base.rb:126 return ::KnowledgeBase.active.exists? (app/models/knowledge_base.rb:90)

Table shape follows manage/roles/permissions.rst (list-table, header row, widths). Cell prose is a paragraph, not a "|" line block, so each description is one msgid instead of one per wrapped line.

@ralf401 ralf401 self-assigned this Nov 5, 2026
@ralf401 ralf401 linked an issue Nov 5, 2026 that may be closed by this pull request
@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Artifacts

Produced during runtime

📦 html-e9172db

@ralf401 ralf401 changed the title Draft: Fixes #1372 - Document the MCP server Fixes #1372 - Document the MCP server Nov 10, 2026
Restructure of system/api.rst to mirror the tabbed settings page of 7.3 (api
restructure is part of the same feature branch): H2 Token access with H3 Token
Access, H3 Password Access and H3 MCP Server, H2 OAuth. The old H2
Authentication Methods is folded into the intro as a general overview that
names the three methods without claiming to mirror the page structure. Claims
and their anchors, all from the feature branch
origin/private/dk/issue/6519/mcp-server-agents-work-on-zammad-tickets-from-their-own-ai-client
of zammad/zammad (7.3):

- Setting api_mcp_access, area API::Base, default off: db/seeds/settings.rb
  (title 'MCP server'), db/migrate/20261103120000_add_mcp_server.rb
- Request refused while off, whatever the token: mcp_controller.rb
  (authenticate_with_personal_access_token!, switched-off message before the
  token check)
- Personal access tokens are the only authentication, Token Access dependency:
  mcp_controller.rb delegates to
  application_controller/authenticates.rb#authentication_check_api_token, which
  refuses when api_token_access is off
- The client does what the token and its owner may: Service::AI::Tool::Runtime
  :Router.offered? narrows by token (lib/user_info.rb#with_token) and all 26
  MCP tools carry permission 'ticket.agent'
- The page shows <fqdn>/mcp and the Claude Code example: app/views/api
  /access.jst.eco (new file on the feature branch)
- FQDN, alternative FQDN and loopback hosts, browser origins from other
  origins refused: app/services/service/mcp_server/addresses.rb
- Approval with text and recipients shown, form elicitation of MCP revision
  2026-07-28, nothing sent without or with an unshown form:
  app/services/service/mcp_server/confirmation.rb (NOT_CONFIRMED, form
  capability check), call_tool.rb (elicitation/create, spec suggestion for
  every result of 2026-07-28), create_article/preparation.rb (confirmation
  preview and required: outbound || !internal)

Heading name "MCP Server" and no "Tab" in headings per review in
zammad-admin-documentation#1372. make gettext ran with the conda env, the
committed locale/admin-docs.pot is its output.

The tool table lists what the client gets, with the anchors of every row:

- The 26 rows are the 26 tool classes in app/services/service/ai/tool/*.rb,
  each declaring offered_in :mcp and permission 'ticket.agent'; the Router
  discovers them without a registry (runtime/router.rb) and sorts by
  tool_name, which is the alphabetical order of the table
- read/write per row is the tool's effect line in its own class (9 write: add
  _internal_note, create_article, create_ticket, link_knowledge_base_answer,
  link_tickets, save_shared_draft, send_shared_draft, set_ticket_tags,
  update_ticket; 17 read)
- Each row's description is a summary of that class's own description string
  (written for the model), reduced to what an admin deciding on the toggle and
  the token needs
- The three knowledge base tools appear only with an active knowledge base:
  get_knowledge_base_answer.rb:32, link_knowledge_base_answer.rb:43 and
  search_knowledge_base.rb:126 return ::KnowledgeBase.active.exists?
  (app/models/knowledge_base.rb:90)

Table shape follows manage/roles/permissions.rst (list-table, header row,
widths). Cell prose is a paragraph, not a "|" line block, so each description
is one msgid instead of one per wrapped line.
…on develop

The page was written against private/dk/issue/6519/... (2026-11-04), the
feature landed on develop as e261524200 with follow-up changes. Claims and
their anchors, all from origin/develop:

- A client that cannot show the confirmation form is not refused: the
  confirmation returns without asking when the client has no form capability,
  and the tool descriptions tell the client to use its own tool approval.
  app/services/service/mcp_server/confirmation.rb (execute, form?),
  app/services/service/ai/tool/create_article.rb (description)
- Zammad asks in the conversation for two changes instead: replacing a shared
  draft that is already there and closing a ticket with an open checklist.
  ai/tool/save_shared_draft.rb:36 (replace_shared_draft_id),
  ai/tool/update_ticket.rb:75 (close_with_open_checklist)
- A declined form still sends nothing and lets the client offer the shared
  draft. ai/tool/create_article/writing.rb:66-71
- The page shows the address of the server and the example with the HTTP type
  and the FQDN of the Base settings.
  app/assets/javascripts/app/views/api/access.jst.eco
- A loopback address includes ::1. mcp_server/addresses.rb:6
- The second address is labelled Alternative fully qualified domain name.
  db/seeds/settings.rb:339
- get_ticket_articles reads chosen messages with their text.
  ai/tool/get_ticket_articles.rb (description)

The tool table itself is unchanged: all 26 tools are offered over MCP, with
the same effect and the ticket.agent permission.
The page repeated the example of the settings screen, which spells out one
vendor's CLI. The server is plain MCP Streamable HTTP at /mcp with a personal
access token, so the docs state what a client needs and leave the client open;
the settings section now only says that the screen shows the address and an
example.

config/routes/mcp.rb (POST /mcp), app/controllers/mcp_controller.rb
(bearer token), app/assets/javascripts/app/views/api/access.jst.eco (the
example on the page).

Copy link
Copy Markdown
Member

Reviewed at 0b621aa7 against Zammad develop 298de2efad. The setup, permission model and 26-tool table match the implementation. I would clarify two points before publishing:

  1. Approval is not guaranteed by the client. In system/api.rst around line 139, explicitly tell users to keep approval enabled for Zammad's write tools. When a client cannot show Zammad's confirmation form, the server proceeds without that extra confirmation; the client's settings may also allow tool calls without a prompt. This instruction is already part of Document the MCP server: enabling it and connecting an AI client #1372.
  2. Make attachment limits visible. In the read_attachment table row, mention that it reads supported text formats up to 10 MB. Unsupported or larger files return a download link for the user. A short note that outgoing attachments are unsupported would also help set expectations.

The client setup example, compatibility wording and channel-specific HTML limits belong in the linked user guide; I am recording those on zammad/zammad-user-documentation#671 and the website MR so the three versions stay consistent.

The documentation build passes. This was a source/content review; rendered layout and a real client connection were not tested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Document the MCP server: enabling it and connecting an AI client

2 participants