Add tools to the Storefront MCP server
Edit on GitHubThis document describes how to add a tool to the Storefront MCP server. A tool is an existing Get or GetCollection operation of an API Platform resource. The generator builds the tool and its input class from the operation, so a tool needs no extra PHP code.
Before you start, install the Storefront MCP server.
This is an early-access preview for evaluation and prototyping. The interface, the configuration, and the package versions can change before the general release.
Add a tool
A tool belongs to the feature module that owns the operation. Do not add tools to the GlueStorefrontApiApplication module.
To add a tool, do the following:
-
In the resource schema of the feature module (
resources/api/storefront/*.resource.yml), addmcp:to aGetorGetCollectionoperation:operations: - type: GetCollection uriTemplate: '/example-items' mcp: name: example-items title: 'Example items' description: 'What the tool does and what it returns.' annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }mcp: trueis the short form.mcp: falseremoves the tool, for example in a project schema. -
Generate the resources.
McpValidationRulechecks themcpkey during generation:vendor/bin/glue api:generate storefront -
Send a
tools/listrequest to the server. For the request, see Verify the installation. Make sure the response lists the new tool.
What the generator builds
For each operation with mcp:, the generator builds the following:
- An
McpToolin themcplist of the generated resource. It usesToolProvideras the provider andMcpOperationToolProcessoras the processor. The source operation is kept inextraProperties. - The input class
Generated\Api\Storefront\{Resource}\{ToolName}McpToolInput. It has one required property for each URI variable ofuriTemplate. For aGetoperation withouturiTemplate, the properties come from the properties markedidentifier: true. It also has one property for eachopenapiContext.parametersentry within: query.
The type of a query property comes from schema.type: string, integer, number, boolean, or array. Other types become string. A query parameter name that is not a valid PHP property name becomes a camel case argument name. For example, page[limit] becomes pageLimit, and filter[company-roles][] becomes filterCompanyRoles. McpOperationToolProcessor sends each argument back under its original query parameter name.
Tool results
McpOperationToolProcessor runs the provider of the source operation on a copy of the current request. The arguments of the tool call are the query parameters and the URI variables. The copy keeps the request attributes of the firewall: customer, store, and locale. The REST response attributes of the operation do not reach the MCP response.
The result depends on the operation type:
Get: the normalized item injsonformat. If there is no item, the result hasisError: trueandstatusCode: 404.GetCollection:{"items": [...]}.
When the provider throws an HTTP exception, the result has isError: true with the statusCode and the message of the exception. When a provider answers an error status in the body, it sets RequestAttribute::RESPONSE_STATUS_CODE (_spryker_response_status_code) on the request. From status 400, the result has isError: true.
Tool schema keys
The mcp map supports the following keys:
| KEY | TYPE | DESCRIPTION |
|---|---|---|
name |
string | Tool name. Default: the short name of the resource and the operation key in kebab case, for example stores-get. The name must be unique over all resources. |
title |
string | Human-readable name of the tool. |
description |
string | Description of the tool. Default: the operation description, then the resource description. |
structuredContent |
boolean | Defines if the tool has an outputSchema. Default: false. Set true only when the schema of the resource matches the plain json result. |
annotations |
map | title (string) and the readOnlyHint, destructiveHint, idempotentHint, and openWorldHint booleans. |
McpValidationRule rejects other keys, mcp on an operation type other than Get or GetCollection, and two operations of one resource with the same tool name. The generator stops on a duplicate tool name.
To change a tool that a module provides, declare the same operation again in the project schema of the resource with your own mcp values. Operations are replaced per operation key.
The jsonld format must be in api_platform.formats of the application that loads the resource.
Protect a tool
A tool has the security and securityMessage of its operation. When the operation has none, the tool uses the ones of the resource, together with the anonymous customer header rule of securityAnonymousAuthRequired. As a result, the tool and the REST operation cannot have different permissions.
For a tool with a security expression, the server behaves as follows:
tools/listdoes not show a tool that the expression denies. For this reason, thetools/listcache scope isprivate.tools/callof a denied tool does not reach the processor.McpAccessDeniedSubscriberpasses the denial to the firewall. A caller without a token gets the answer of the firewall entry point. An authenticated caller gets403.- A provider that throws
AccessDeniedException(API Platform or Symfony Security) gets the same answer.
To answer 401 with WWW-Authenticate: Bearer resource_metadata=..., or 403 with error="insufficient_scope", set the entry_point and the access_denied_handler of the firewall that covers /mcp.
SprykerApiPlatformExtension loads these services only when McpBundle is registered. As a result, Glue Backend does not have them.
Thank you!
For submitting the form