Skip to content

MCP Tools

Every expert of this bundle is also available as an MCP tool, so AI clients (Claude, ChatGPT, your own agent) can use the same capabilities editors use in the admin — without going through the admin UI.

The tools only provide the AI capabilities. Reading and writing Sulu content is the job of the Sulu MCP Bundle, which exposes pages, articles, snippets, media and taxonomies as sulu_* tools. Install both bundles together and a client can, for example, read a page, ask sulu_ai_seo_generate for SEO data, and write the result back.

Setup

The tools ship with this bundle and only load when sulu/mcp-bundle is installed and registered:

composer require sulu/mcp-bundle

It requires Sulu 3, registers #[RequiresPermission]-gated tools on the "sulu" MCP server, and pulls in symfony/mcp-bundle itself to expose the transport. Follow its own setup to configure the transport and secure the endpoint with OAuth2 — every tool of this bundle checks the Sulu permission of the currently authenticated user, so the endpoint has to run behind an authenticated firewall.

Experts have to be synchronized before the tools can be used, because a tool call always addresses an expert variant:

php bin/console sulu:ai:synchronize-experts

Available Tools

Tool Expert Permission Writes content
sulu_ai_seo_generate SEO Generator sulu.ai.seo_generator no
sulu_ai_excerpt_generate Excerpt Generator sulu.ai.excerpt_generator no
sulu_ai_media_metadata_generate Media Metadata Generator sulu.ai.media_metadata_generator no
sulu_ai_translate Translator sulu.ai.translate no
sulu_ai_writing_assistant_optimize Writing Assistant sulu.ai.writing_assistant no
sulu_ai_content_translate_full Translator sulu.ai.translate yes — disabled by default

A user without the VIEW permission of the listed security context gets an error instead of a result, exactly like in the admin UI. See Experts → Permissions.

Every tool carries the MCP tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) in tools/list. The generating tools are read-only and idempotent, they return text and store nothing, so an agent client may run them without asking the user; sulu_ai_writing_assistant_optimize is read-only but not idempotent because every call adds a turn to its chat. sulu_ai_content_translate_full is marked destructive because it overwrites the stored translation, so a client should ask before calling it. All tools are open-world: they call the sulu.ai platform.

sulu_ai_seo_generate

Generates SEO title, description and keywords for a page, article or snippet. The expert loads the stored content itself, so only identifiers are needed. The result is returned, not persisted.

Argument Type Required Description
uuid string yes UUID of the document
locale string yes Locale of the content to analyze
resourceKey string no pages (default), articles or snippets
currentSeoData object no Current SEO data — pass it to optimize instead of generating from scratch
webspace string no Resolved automatically when omitted
expertUuid string no Expert variant, see Expert variants

Returns { "uuid": "…", "data": { "title": "…", "description": "…", "keywords": "…" } }. The uuid identifies this generation on the sulu.ai platform.

sulu_ai_excerpt_generate

Same arguments as sulu_ai_seo_generate, except that the current data argument is called currentExcerptData. Returns { "uuid": "…", "data": { "title": "…", "description": "…", "more": "…" } }.

sulu_ai_media_metadata_generate

Generates a title (alt text) and a description (caption) for an image in the media library. Only image media types are supported.

Argument Type Required Description
id integer yes Numeric id of the media item (not a UUID)
locale string yes Locale the metadata is generated in
currentMetadata object no Current {title, description} — pass it to optimize instead of generating from scratch
expertUuid string no Expert variant, see Expert variants

The platform fetches the image over HTTP, so the tool needs to know the public base URL. It uses the current request when there is one and falls back to the router request context (router.request_context.host / router.request_context.scheme) otherwise.

sulu_ai_translate

Translates a list of strings with the project glossary and tone of voice. It does not read or write Sulu content.

Argument Type Required Description
texts array of strings yes Translated in the given order
targetLanguage string yes For example en, de or en-gb
sourceLanguage string no Detected automatically when omitted
html boolean no false by default — set it when the texts contain markup
webspace string no Webspace whose glossary and tone of voice are applied

sulu_ai_writing_assistant_optimize

Asks the writing assistant to revise a piece of text in the context of a document. Unlike the generators this is conversational: one call is one turn, and the returned chatId continues the conversation on the next call.

Argument Type Required Description
text string yes The text to work on
message string yes The instruction, e.g. "shorten this to two sentences"
resourceKey string yes Resource key of the content the text belongs to: pages, articles or snippets
uuid string yes UUID of the document the text belongs to
locale string yes Locale the revised text is written in
chatId string no Continues a previous conversation
expertUuid string no Variant to use — the platform default is used when omitted
webspace string no Webspace whose glossary and tone of voice are applied

The conversation history is stored in the Symfony session, the same way the admin UI does it, so continuing a conversation across calls only works for a client that sends the session cookie back — the admin UI itself, or an MCP client configured to keep cookies. A transport with no request at all (stdio) gets a clear error instead of silently losing history. A bearer-token client with no cookie — including the OAuth setup this doc recommends — gets a new, empty session on every call: the tool call still succeeds, but chatId has no effect and the history is lost without any error.

sulu_ai_content_translate_full

Translates every translatable field of a page, article or snippet — including blocks, SEO and excerpt data — and saves the result. This is the tool behind the translate option of Sulu's "copy locale" action.

Argument Type Required Description
uuid string yes UUID of the document
locale string yes Locale that is translated in place
resourceKey string no pages (default), articles or snippets
sourceLanguage string no Language the current content is written in
webspace string no Resolved automatically when omitted

The tool translates the content that is currently stored in locale and writes the translation back into that same locale. To translate a document into a locale that is still empty, first copy the source locale into it — with Sulu's "copy locale" action in the admin UI, or by writing the source content with the content tools of the Sulu MCP bundle — and translate afterwards. The resource locator is regenerated from the translated title, except for the homepage.

Unlike the other tools, this one checks two permissions: the sulu.ai.translate context from the table above, and — because it writes to a specific document — the EDIT permission on the target page, article or snippet in locale, exactly like the admin UI checks before a write. A user holding only sulu.ai.translate is refused for a document they cannot edit. The check always uses the document's own webspace; the webspace argument cannot be used to bypass it.

Because it overwrites many fields at once, the tool is disabled by default by sulu/mcp-bundle's dangerous-tool gate:

sulu_mcp:
    dangerous_tools:
        sulu_ai_full_content_translation: true

While disabled the tool is neither registered as a service nor discovered, so it does not show up in the tool list of a client at all.

Expert Variants

Every expert can have several variants. The admin UI lets editors pick one; a tool call takes the optional expertUuid argument instead.

  • omitted — the first variant returned for the expert is used
  • given — the variant is validated against the synchronized variants, an unknown UUID is reported as an error listing the available ones

When no variant exists at all, the tool asks for sulu:ai:synchronize-experts to be run.

sulu_ai_writing_assistant_optimize is the exception: it forwards the argument as-is, so omitting it uses the expert configuration of the platform without selecting a variant.

Errors

Tool errors are reported as MCP tool call errors with a message the client can display:

Situation Message
Missing permission Names the required permission and security context
Unknown expert variant Lists the available variant UUIDs
No expert variant at all Asks for sulu:ai:synchronize-experts
Failed or invalid AI response The message key of the underlying error, for example sulu_ai.ai_response_invalid