Set up an MCP server¶
JWT¶
MCP servers use JWT for authentication.
TODO: Enable authorization header in config/packages/lexik_jwt_authentication.yaml.
In config/packages/security.yaml, uncomment the ibexa_jwt_mcp firewall.
TODO: Config to get a JWT token in the first place. Through REST, GraphQL or something else?
MCP Server configuration¶
MCP servers are configured per repository then enabled per SiteAccess scope.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
TODO: ddev php bin/console debug:router --siteaccess=<within_scope_siteaccess> should list some ibexa.mcp.<server_identifier> GET|POST|DELETE|OPTIONS <server_route_path>
TODO: Maybe explain that routes are built automatically from MCP server path configs thank to config/routes/ibexa_mcp.yaml and \Ibexa\Bundle\Mcp\Routing\McpRouteLoader
MCP server options¶
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | Yes | MCP server endpoint path | |
enabled |
boolean | No | false |
Whether the server is enabled |
version |
string | No | 1.0.0 |
MCP server version |
description |
string | No | null |
Human-readable server description |
instructions |
string | No | null |
Instructions dedicated for LLM interaction |
discovery_cache |
string | Yes | PSR-6 ou PSR-16 cache pool service identifier | |
session |
object | Yes | Session storage configuration |
Notice that a server is disabled by default, it needs to be explicitly enabled.
MCP server discovery cache¶
TODO
MCP server session storage¶
Options¶
| Option | Type | Default | Description |
|---|---|---|---|
type |
enum | memory |
Session store type: psr16, file, or memory |
service |
string | null |
PSR-16 cache service ID for psr16 session store |
prefix |
string | mcp_ |
Key prefix for psr16 session store |
directory |
string | null |
Directory path for file session store |
ttl |
integer | 3600 |
Session TTL in seconds |
PSR-16¶
Sessions are stored using a PSR-16 compatible cache implementation. Requires service option pointing to a valid cache service ID.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
File¶
Sessions are persisted to the filesystem. Requires directory option to be set.
1 2 3 | |
Memory¶
Sessions are stored in memory. Suitable for development and STDIO transport.
TODO: Might not work with DDEV or Docker
1 2 | |
MCP server capabilities¶
TODO: Ibexa\Contracts\Mcp\McpCapabilityInterface
TODO: Ibexa\Contracts\Mcp\Attribute namespace
Example¶
This example introduce an example MCP server with a single greet tool.
It's enabled on all SiteAccesses.
It's accessible with the path /mcp/example (for example, on http://localhost/mcp/example and http://localhost/admin/mcp/example).
It uses files for both discovery cache and session storage.
In a new config/packages/mcp.yaml file, the configuration of the MCP server:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Then, a McpCapabilityInterfacecontaining a greet function with a McpTool attribute associating with the example server:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
To check the server configuration, a short command using the MCP server configuration registry (injected through McpServerConfigurationRegistryInterface and autowiring):
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 | |
To test the example MCP server, a sequence of curl commands is used to simulate an AI to MCP server communication.
- Ask for a JWT token through REST
- Initialize a connection to the MCP server
- Validate the MCP Session ID
- List the available tools
- Call a tool
jq, grep, and sed are also used to parse or display outputs.
The initialization:
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 33 34 35 36 | |
1 2 3 4 | |
The list of tools:
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
The greet tool usage:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
TODO: Connect an AI client to the MCP server. Copilot CLI MCP server addition is strangely asking for some OAuth ID even with a proper JWT/Bearer header.