Skip to content
For AI agents: the complete documentation index is available at llms.txt; this page is also available as Markdown at index.md.

Install and configure MCP Servers

With Ibexa DXP's MCP Servers LTS Update package, you can expose MCP servers to external AI agents.

Installation

Run the following command to install the package:

1
composer require ibexa/mcp

MCP Servers feature comes with built-in tools but doesn't come with a default configuration. You have to create your own MCP servers by providing their configuration and enable JWT authentication for them.

Configure authentication

JWT MCP firewall

AI agents use JWT authentication against Ibexa DXP's MCP servers.

In config/packages/lexik_jwt_authentication.yaml, enable the authorization_header token extractor to allow the use of JWT token bearer in Authorization header.

In config/packages/security.yaml, make the following changes:

  • Uncomment the ibexa_jwt_rest firewall to enable requesting JWT tokens through REST or GraphQL API.
  • Add the ibexa_jwt_mcp firewall to allow the use of JWT authentication against MCP servers.
1
2
3
4
5
6
7
8
9
security:
    firewalls:
        # …
        ibexa_jwt_mcp:
            request_matcher: Ibexa\Mcp\Security\McpRequestMatcher
            user_checker: Ibexa\Core\MVC\Symfony\Security\UserChecker
            provider: ibexa
            stateless: true
            jwt: ~

Authentication for the APIs

You don't need to activate JWT authentication for the REST or GraphQL API.

For sample JWT token requests, see REST JWT authentication, GraphQL JWT authentication and cURL test of MCP server.

Repository user

The AI agents authenticate against the MCP server with a JWT token generated for a specific repository user account.

This repository user can be:

  • an individual user account (for example, of an editor or administrator)
  • a dedicated account created specifically for AI integrations

The repository user can generate a JWT token with their own account, or a secondary dedicated account, and pass the token to the MCP client. A gateway could use a dedicated shared repository user to generate a JWT token and establish the connection.

MCP server configuration

You define MCP servers within a repository configuration and then assign those servers to specific SiteAccess scopes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
ibexa:
    repositories:
        <repository_identifier>:
            mcp:
                <server_identifier>:
                    path: <server_route_path>
                    enabled: true
                    # Server options…
                    discovery_cache: <cache_pool_service>
                    session:
                        type: <psr16|file>
                        # Session options…
                    allowed_hosts:
                        - '<domain_name>'
    system:
        <siteaccess_scope>:
            mcp:
                servers:
                    - <server_identifier>

Servers are automatically registered as services with an ID following the pattern ibexa.mcp.server.<repository_identifier>.<server_identifier>. You can list all defined servers by running the following command:

1
php bin/console debug:container ibexa.mcp.server

Routes are built automatically from MCP server path configs. Those routes are identified as ibexa.mcp.<server_identifier>. You can list them by running the following command:

1
php bin/console debug:router --siteaccess=<siteaccess> ibexa.mcp

MCP server options

Option Type Required Default Description
path string Yes MCP server endpoint path (appended to SiteAccess-aware base URL)
enabled boolean No false Server state: decides whether it is enabled or disabled
version string No 1.0.0 MCP server version
description string No null Server implementation description
instructions string No null Prompt-like instructions provided to the AI agent
tools array No [] List of tool classes
discovery_cache string Yes PSR-6 or PSR-16 cache pool service identifier
session object No { type: psr16,
service: ibexa.cache_pool }
Session storage configuration
allowed_hosts array No [
'localhost',
'127.0.0.1',
'[::1]'
]
Accepted Host headers

New servers are disabled by default

After you define a server, it remains disabled until you explicitly enable it.

Tool configuration

The main capabilities of an MCP server are called tools. They are the actions that an AI agent can invoke on the system.

MCP server design best practices

Avoid creating MCP servers with large tool sets. Too many tools make it more difficult for the AI agent to select the appropriate action. Instead, create multiple MCP servers with specific sets of tools dedicated to specific contexts or use cases. When designing MCP servers, focus on the needs and tasks of the human user who actually interacts with the AI agent rather than exploring every technical capability.

There are two ways to associate tools with a server:

  • By listing PHP classes (FQCNs) in the server's configuration tools. All tools marked with the McpTool attribute in those classes are automatically associated with the server (for example, for built-in or third party tools).
  • By using the servers argument in McpTool attribute to explicitly associate a specific tool with MCP servers.

Built-in tools

MCP Servers LTS Update comes with the following experimental built-in tools:

  • Ibexa\Mcp\Tool\Content\ContentTools
    • get_content_info - gets version-independent metadata of a content item
    • get_content_version_info - gets metadata of a specific version of a content item (current by default)
    • get_content - gets a content item with its metadata, a version and the field values of that version
    • create_content - creates an unpublished draft
    • create_content_draft - creates a new draft from the published or archived version
    • update_content - sets field values on a draft, in the draft's initial language (unless initialLanguageCode is given)
    • publish_version - publishes a draft
  • Ibexa\Mcp\Tool\ContentType\ContentTypeGroupTools
    • get_content_type_groups - gets all content type groups
  • Ibexa\Mcp\Tool\ContentType\ContentTypeTools
    • get_content_type - gets a content type by its ID or identifier
    • get_content_type_list - gets content types by their IDs
    • create_content_type - creates a draft for a new content type
    • create_content_type_draft - creates a draft for an existing content type
    • get_content_type_draft - gets a content type draft by content type ID
    • publish_content_type_draft - publishes a content type draft by content type ID
  • Ibexa\Mcp\Tool\ContentType\FieldDefinitionTools
    • add_field_definition - adds a field definition to a content type draft
    • update_field_definition - updates a field definition in a content type draft
    • remove_field_definition - removes a field definition from a content type draft
    • get_field_type_list - lists all available field types with identifiers, empty value structure, settings, and validator configuration
  • Ibexa\Mcp\Tool\Language\LanguageTools
    • get_language - gets a language by its language code, together with information whether it is enabled
    • get_default_language_code - gets the first configured language of the current SiteAccess
  • Ibexa\Mcp\Tool\Location\LocationTools
    • list_locations - lists direct children of a parent location, and/or locations that match a pattern, paginated
    • get_root_location - gets the root location of the content tree of a SiteAccess (current if no SiteAccess name is given)
  • Ibexa\Mcp\Tool\RichText\RichTextTools
    • convert_to_richtext_xml - converts plain text, HTML fragments or complete DocBook / XHTML5 edit documents into the DocBook XML stored in RichText fields
  • Ibexa\Mcp\Tool\SeoTools
    • get_non_seo_content_ids - returns IDs of content items that are missing SEO optimization (no meta title tag). You can use it to identify content that needs SEO attention
  • Ibexa\Mcp\Tool\TranslationTools
    • list_languages - lists all languages in the current SiteAccess
    • list_content_languages - lists languages which have translations for a given content item
    • list_non_translated_content_ids - lists IDs of content which have missing translations for a given language code

The following tools are included with their respective packages, Taxonomy and Workflow:

  • Ibexa\Taxonomy\Mcp\Tool\TaxonomyTools
    • list_taxonomies - lists the taxonomies
    • list_taxonomy_entries - lists entries of a taxonomy, paginated and ordered by entry ID
    • assign_to_taxonomy_entry - assigns up to 100 content items to a taxonomy entry
    • list_taxonomy_entry_content - lists the content items assigned to a taxonomy entry
    • unassign_from_taxonomy_entry - removes the assignment of content items to a taxonomy entry
  • Ibexa\Workflow\Mcp\Tool\WorkflowTools
    • list_workflows - lists the editorial workflows
    • get_content_workflow_status - gets the workflow status of a content version
    • apply_workflow_transition - applies a workflow transition to a content version
1
2
3
4
5
6
7
8
9
            mcp:
                <server_identifier>:
                    path: <server_route_path>
                    enabled: true
                    tools:
                        - Ibexa\Mcp\Tool\TranslationTools
                        - Ibexa\Mcp\Tool\SeoTools
                        - Ibexa\Workflow\Mcp\Tool\WorkflowTools
                    # …

Experimental tools

The built-in tools are experimental and may change in future releases. They are provided as examples of how to implement tools and how to configure them in an MCP server. As-is, they may not cover all your needs or may not be practical to all AI agents. If you use them, be prepared to update your MCP server configuration and tool usage when upgrading to a new version of Ibexa DXP.

See how to build your own tools in Work with MCP servers.

List available tools

To see which MCP tools are available and which MCP servers expose them, use the ibexa:debug:mcp-tools command. It lists the tools provided by the installed packages, together with the MCP servers that expose them, in every repository and SiteAccess. You can also use it to discover whether a tool is exposed through the server's tools configuration or the servers argument of its McpTool attribute.

Ignoring discovery cache

Until the server's cache pool is cleared, it may serve a cached tool list. Therefore, to avoid errors, the command reads tools directly from the code, and ignores the discovery cache.

To list tools exposed on all MCP servers, use:

1
php bin/console ibexa:debug:mcp-tools

Pass a tool name as an argument to get the details of this specific tool, including input and output schemas.

You can modify the command's behavior with the following options:

Options
Description
--all Lists all tools, including those that aren't exposed on any MCP server or shadowed by other tool of the same name on that server
--package=<package_name> Lists tools provided by a specific package. Repeatable
--repository Shows only tools exposed on MCP servers of the given repository
--siteacces=<siteaccess> Shows only tools exposed by MCP servers that a specific SiteAccess serves. If you don't use argument, the command covers every SiteAccess and repository
--server=<server name> Lists tools exposed by a specific MCP server, in any repository. Repeatable
--show-handler In text format, shows the class and method that handle each tool
--format=<format> Returns output as text (txt) or JSON (json). The default format is text

By default, the command lists only tools that are actually served by an MCP server. Here is an example of a JSON response:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
    "tools": [
        {
            "name": "get_content_type",
            "title": "Get content type",
            "description": "Gets a content type by its ID (integer) or identifier (string).",
            "handler": {
                "class": "Ibexa\\Mcp\\Tool\\ContentType\\ContentTypeTools",
                "method": "getContentType"
            },
            "package": "ibexa/mcp",
            "annotations": {
                "readOnlyHint": true,
                "destructiveHint": false,
                "idempotentHint": true,
                "openWorldHint": false
            },
            "attributeServers": [],
            "exposures": [
                {
                    "repository": "default",
                    "server": "admin",
                    "enabled": true,
                    "via": ["config"],
                    "siteAccesses": ["admin"],
                    "shadowedBy": null,
                    "shadows": []
                }
            ]
        }
    ]
}

Shadowed tools

An MCP server can only serve one tool per name. If two tool definitions share the same name on the server, only one is served, the others are shadowed, and a warning is returned that lists the shadowed tools.

Discovery cache

Discovery is cached to avoid scanning for capabilities on every request. You must provide a PSR-6 or PSR-16 cache pool for this caching.

For example, you could set up a dedicated Redis/Valkey:

1
                    discovery_cache: cache.redis.mcp

For a production cluster, it's recommended to use a Redis/Valkey cache pool so the cache can be shared by all nodes.

Clear the cache pool after making changes:

1
php bin/console cache:pool:clear cache.redis.mcp

Tip

Use ibexa.cache_pool as service identifier to have the default cache service.

It can be set to null to disable caching to ease development, which isn't recommended for production environment.

See another example of configuration in Work with MCP servers.

Session storage

MCP servers store session data in their own way.

Options

Option Type Default Description
type enum psr16 Session store type: psr16 or file
service string ibexa.cache_pool PSR-16 or PSR-6 cache service ID for the psr16 session store
prefix string mcp_ Key prefix for the psr16 session store
directory string null Directory path for the file session store
ttl integer 3600 Session TTL in seconds

In production, it’s recommended to use psr16 with Redis/Valkey, like with regular sessions.

PSR-16

Sessions are stored with a PSR-16 or PSR-6 compatible cache implementation. It requires that a service option points to a valid cache service ID. Optionally, you could use a more specific prefix option than the default mcp_ to avoid key collisions with other cache usages. Such setup is suitable for production environments.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
                    session:
                        type: psr16
                        service: cache.redis.mcp
                        prefix: 'mcp_<server_identifier>_'
services:
    cache.redis.mcp:
        public: true
        class: Symfony\Component\Cache\Adapter\RedisTagAwareAdapter
        parent: cache.adapter.redis
        tags:
            -   name: cache.pool
                clearer: cache.app_clearer
                provider: 'redis://mcp.redis:6379'
                namespace: 'mcp'

File

Sessions are stored on the filesystem. This requires that you configure a directory. Such setup is suitable for development environments.

In this example, sessions are stored in the var/cache/<environment>/mcp/sessions/ directory (for example, var/cache/dev/mcp/session/ for the dev environment, and var/cache/prod/mcp/sessions/ for the prod environment):

1
2
3
                    session:
                        type: file
                        directory: '%kernel.cache_dir%/mcp/sessions'

Allowed hosts

This parameter lists the domains, the Host headers, accepted by the MCP server. The port is not part of the matching. There is no wildcard character, all cases must be listed. As item, you can use a hostname, an IP, or an IPv6. IPv6 addresses must be bracketed, for example [::1].

In this example, only requests from admin.example.com domain, my-ddev-project.ddev.site domain, or from 127.0.0.1 IP are accepted:

1
2
3
4
                    allowed_hosts:
                        - 'www.example.com'
                        - 'my-ddev-project.ddev.site'
                        - '127.0.0.1'