Markus Michalski FAQ

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.

Deutsche Version

Back to overview

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

  1. Validate parameters: Every tool validates its inputs before a request is built (codes, lengths, value ranges, required combinations).
  2. Check scope: SyliusClient matches method and path against the allowlist. It also rejects form fields starting with _method.
  3. Authenticate: The JWT comes from POST /api/v2/admin/administrators/token, is kept in memory and fetched again 30 seconds before expiry.
  4. Send the request: With Authorization: Bearer ..., Accept: application/json and, if configured, X-Stage-Api-Key. The HTTP timeout is 30 seconds.
  5. 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 becomes null.
  6. 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.