Sylius Admin: Technical Details
Technical details of Sylius Admin: plugin layout, two servers from one codebase, startup via run.py, request flow with JWT and scope allowlist, error translation, dependencies and directory structure.
Sylius Admin: Technical Details
This documentation always describes the latest published version.
Plugin layout
| File or folder | Purpose |
|---|---|
.claude-plugin/plugin.json |
Plugin manifest (syliusadmin), points to skills/ and .mcp.json |
.claude-plugin/marketplace.json |
Marketplace entry claude-plugin-syliusadmin with the plugin syliusadmin |
.mcp.json |
Registers two stdio servers: syliusadmin-stage-mcp and syliusadmin-prod-mcp |
bin/run-server, bin/run-server.cmd |
Launchers for POSIX and Windows, call the venv interpreter with run.py |
servers/syliusadmin-server/run.py |
Entry point: selects and loads the .env, builds client and server, starts stdio |
servers/syliusadmin-server/src/syliusadmin/ |
Server code |
skills/setup/, skills/sylius-produkt-wizard/ |
The two skills |
Overview
graph TD
A["Claude Code"] --> B["syliusadmin-stage-mcp"]
A --> C["syliusadmin-prod-mcp"]
B --> D["run.py with SYLIUS_ENV_NAME=stage"]
C --> E["run.py with SYLIUS_ENV_NAME=prod"]
D --> F["stage/.env"]
E --> G["prod/.env"]
D --> H["Sylius stage Admin API"]
E --> I["Sylius prod Admin API"]
Both servers run from the same codebase. They differ only by the variable SYLIUS_ENV_NAME, which run.py translates into the path of the respective .env. The server introduces itself to Claude as sylius-admin-<environment> and names the environment in its instructions.
Flow of a tool call
sequenceDiagram
participant C as "Claude"
participant T as "Tool"
participant K as "SyliusClient"
participant S as "Sylius Admin API"
C->>T: Tool call with parameters
T->>T: Validate parameters
T->>K: get, post, put, patch or delete
K->>K: Check scope allowlist
alt Path not allowed
K-->>T: SyliusScopeError
T-->>C: Error message
else Path allowed
K->>S: Login if no valid token
S-->>K: JWT
K->>S: Request with bearer token
S-->>K: Response
K-->>T: JSON
T-->>C: Result
end
Flow in detail
- Validate parameters: Every tool validates its inputs before a request is built (codes, lengths, value ranges, required combinations).
- Check scope:
SyliusClientmatches method and path against the allowlist. It also rejects form fields starting with_method. - Authenticate: The JWT comes from
POST /api/v2/admin/administrators/token, is kept in memory and fetched again 30 seconds before expiry. - Send the request: With
Authorization: Bearer ...,Accept: application/jsonand, if configured,X-Stage-Api-Key. The HTTP timeout is 30 seconds. - Evaluate the response: Status codes of 400 and above become
SyliusApiError(with status, method, path, environment and at most 500 characters of detail). An empty body or 204 becomesnull. - Translate errors: All of the client's own error classes are converted centrally into
ToolError, so Claude sees the original message instead of a generic tool error.
Special behavior
| Topic | Behavior |
|---|---|
| Update method | Updates run as PUT, not PATCH, because Sylius registers no merge patch for these resources. |
| Translations | When changing existing translations, the server reads the existing locales and sends them with their @id (JSON-LD) so Sylius updates them in place instead of creating new entries. |
| Prices | update_variant_channel_pricing reads the existing channel prices and sends the complete collection so other channels are not lost. |
| Collection responses | The server accepts the bare list as well as the member and hydra:member envelopes. |
| Archiving | archive_shipping_method and restore_shipping_method are PATCH calls without a body. |
| Image upload | Multipart form with a file; a CDN image is sent as a multipart form without a file. |
| Loading configuration | load_dotenv(..., override=True): the file wins over SYLIUS_* variables already set. |
| Caching, rate limiting | Apart from the token in memory there is neither a cache nor rate limiting of its own. |
Admin API resources used
All paths are under /api/v2/admin/.
| Resource | Access |
|---|---|
administrators/token |
Login |
products (including images and translations) |
Read and write |
product-variants |
Read and write (including channel prices) |
taxons (including images and translations) |
Read and write |
product-attributes, product-options |
Read and create |
zones, countries |
Read, create, change |
shipping-methods (including archive and restore), shipping-categories, tax-categories |
Read, create, change |
product-marketplace-links |
Read, create, change, delete |
channels, product-custom-input-fields |
Read-only |
Server directory structure
servers/syliusadmin-server/
βββ run.py # entry point, .env selection
βββ src/syliusadmin/
βββ server.py # create_server() factory, tool registration
βββ config.py # SyliusConfig from the environment
βββ sylius_client.py # HTTP client, JWT, scope allowlist
βββ tools/
βββ _errors.py # SyliusError becomes ToolError
βββ _codes.py # code validation
βββ _translations.py # merging translations, SEO fields
βββ products.py
βββ variants.py
βββ taxons.py
βββ attributes.py
βββ options.py
βββ product_images.py
βββ channels.py
βββ countries.py
βββ zones.py
βββ shipping_categories.py
βββ shipping_methods.py
βββ tax_categories.py
βββ marketplace_links.py
βββ custom_input_fields.py
Protocol and dependencies
| Property | Value |
|---|---|
| Transport | stdio |
| MCP SDK | mcp from 2.0.0, below 3.0.0 |
| HTTP client | httpx 0.28.x |
| Configuration | python-dotenv from 1.2.0, below 2.0.0 |
| Concurrency | anyio from 4.9, below 5.0.0 |
| Python | 3.12 or newer |
Read-only tools are marked with the MCP hint read_only. Writing tools carry the corresponding hints; replacements and the deletion of marketplace links are marked destructive.