Shopware hat einen MCP-Server — und er ist abgeschaltet
61 Dateien, 54 Routen, elf Werkzeuge für KI-Agenten stecken im Kern von 6.7. Ab Werk antwortet der Endpunkt mit 404. Wir haben ihn eingeschaltet und benutzt.
Ergebnis
11 Werkzeuge, 8 Ressourcen, ab Werk 404
6.7.13.1 trägt 61 MCP-Dateien und 54 Routen im Kern, 6.6.10.6 keine einzige. Ohne das Feature-Flag MCP_SERVER antwortet /api/_mcp mit 404. Mit Flag meldet der Server Protokollversion 2025-11-25 und elf Werkzeuge — drei davon schreiben, eines löscht.
Wer heute wissen will, wie ein KI-Agent an einen Shopware-Shop kommt, landet schnell bei selbst gebauten Brücken: ein Dienst, der die Admin-API spricht, ein Werkzeugkatalog, eine Authentifizierung. Wir haben nachgesehen, ob Shopware das inzwischen selbst mitbringt. Es bringt es mit — und lässt es aus.
Das Ergebnis
| 6.6.10.6 | 6.7.13.1 | |
|---|---|---|
Dateien unter einem /Mcp/-Pfad im Kern | 0 | 61 |
| davon Werkzeuge | 0 | 13 |
| davon Ressourcen | 0 | 9 |
| davon Prompts | 0 | 1 |
| davon Controller | 0 | 5 |
Routen mit mcp | 0 | 54 |
| davon Admin-API | 0 | 5 |
| davon Store-API | 0 | 1 |
| davon generierte CRUD | 0 | 48 |
Antwort von /api/_mcp ab Werk | — | 404 |
Die 48 generierten CRUD-Routen gehören zu drei neuen Entitäten samt
Übersetzungstabellen: app_mcp_tool, app_mcp_resource und app_mcp_prompt.
Eine App kann also eigene Werkzeuge, Ressourcen und Prompts mitbringen — das
ist der eigentliche Architekturhinweis.
Ab Werk 404, und warum das richtig ist
Der Server hängt am Feature-Flag MCP_SERVER. In der Flag-Definition des Kerns
steht wörtlich Experimental!, der Standardwert ist false, und ohne das Flag
antwortet der Endpunkt mit 404 — nicht mit 401 oder 403. Er existiert für
einen Aufrufer schlicht nicht.
Das ist eine bewusste Entscheidung und eine vernünftige. Wer die Werkzeugliste unten liest, versteht sofort, warum.
Die elf Werkzeuge
Nach dem Einschalten meldet /api/_action/mcp/capabilities genau das hier:
| Werkzeug | Rechte | hängt ab von |
|---|---|---|
shopware-entity-schema | — | — |
shopware-entity-search | lesen | entity-schema |
shopware-entity-read | lesen | entity-schema |
shopware-entity-aggregate | lesen | entity-schema |
shopware-entity-upsert | anlegen, ändern | entity-schema |
shopware-entity-delete | löschen | entity-search |
shopware-media-upload | — | — |
shopware-order-state | — | — |
shopware-system-config-read | — | — |
shopware-system-config-write | — | system-config-read |
shopware-theme-config | — | — |
Dazu acht Ressourcen — Business-Events, Währungen, Entitätenliste,
Erweiterungen, Flow-Aktionen, Sprachen, Verkaufskanäle, State Machines — und
ein Prompt namens shopware-context.
Drei Werkzeuge schreiben, eines löscht, eines ändert die
Systemkonfiguration. Ein MCP-Client mit gültigem Admin-Token kann damit
Produkte anlegen, Bestellstatus setzen, Medien hochladen und Konfiguration
überschreiben. Genau deshalb gibt es im Kern Allowlists — je Integration und je
Benutzer, über eigene Endpunkte pflegbar — und zwei eigene
Ratenbegrenzungsregeln: mcp_admin_api mit 300 Aufrufen je Minute und
mcp_store_api mit 120.
Der Handshake, und die Stelle, an der er scheitert
Der Server spricht Protokollversion 2025-11-25. Der Ablauf ist strikt:
POST /api/_mcp {"method":"initialize", ...}
→ 200, und im Antwortkopf: Mcp-Session-Id: <uuid>
POST /api/_mcp {"method":"notifications/initialized"}
→ ohne diesen Schritt bleibt die Sitzung unbrauchbar
POST /api/_mcp {"method":"tools/call", ...}
→ jetzt erst wird gearbeitet
Wer die Session-ID nicht mitschickt, bekommt:
{"jsonrpc":"2.0","error":{"code":-32600,
"message":"A valid session id is REQUIRED for non-initialize requests."}}
Das ist protokollkonform und trotzdem der Punkt, an dem ein selbst gebauter Client als Erstes hängenbleibt.
Ein Fallstrick, der Zeit kostet
Die Werkzeugparameter sehen nach JSON aus und sind es an einer Stelle nicht.
aggregations und ids werden als Zeichenkette erwartet, die JSON
enthält — nicht als Array. Ein nativ übergebenes Array wird abgewiesen:
Property '/ids': Invalid type. Expected `string`, but received `array`.
Richtig ist also "ids": "[\"<uuid>\"]" und nicht "ids": ["<uuid>"]. Wer
seinen Client generisch aus dem Schema baut, merkt das sofort; wer ihn von Hand
schreibt, sucht eine Weile.
Die Probe aufs Exempel
Zwei Aufrufe, weil eine Werkzeugliste noch nichts darüber sagt, ob die Werkzeuge arbeiten.
Lesend, mit Gegenprobe. shopware-entity-aggregate auf product mit einer
count-Aggregation:
{"success":true,"data":{"aggregations":{"anzahl":{"count":18}}}}
Die Datenbank derselben Installation meldet für SELECT COUNT(*) FROM product
ebenfalls 18. Die Messung prüft sich damit selbst.
Schreibend, im Trockenlauf. shopware-entity-delete auf ein vorhandenes
Produkt. Der Trockenlauf ist der Standard — man muss ihn nicht einschalten,
sondern ausschalten. Zurück kam die vollständige Kaskade:
product 1 Datensatz
product_price 2
product_media 1
product_visibility 1
product_search_keyword …
Und die Zeilenzahl: 18 vorher, 18 nachher. Nichts gelöscht.
Dass ein Löschwerkzeug für KI-Agenten den Trockenlauf als Standard hat und die Folgen vorher ausgibt, ist die durchdachteste Einzelentscheidung in diesem ganzen Paket.
Was das praktisch bedeutet
Für Händler. Nichts ist an, nichts muss abgeschaltet werden. Wer eine 6.7-Installation betreibt, hat keinen offenen KI-Endpunkt — der Server antwortet mit 404, solange das Flag nicht gesetzt ist. Die Frage lautet nicht „Wie mache ich das zu?", sondern „Wann und mit welchen Rechten mache ich das auf?".
Für Integrationen. Wer heute eine eigene Brücke zwischen Agent und Shop baut, sollte wissen, dass der Kern in diese Richtung arbeitet. Ein Eigenbau, der genau die elf Werkzeuge nachbildet, wird mittelfristig doppelte Arbeit. Sinnvoller ist ein Eigenbau für das, was diese elf nicht abdecken.
Für Rechte. Die Allowlists sind der Teil, den man zuerst versteht, nicht
zuletzt. Ein Agent mit shopware-entity-upsert und ohne Einschränkung auf
Entitäten darf alles schreiben, was die DAL kennt — das sind in 6.7 231
Kernentitäten.
Grenzen dieser Messung
Gemessen wurde eine dev-Runtime mit neun installierten Plugins. Zwei der elf
Werkzeuge wurden tatsächlich aufgerufen; über die übrigen neun sagt dieser Text
nur, dass sie registriert sind und welche Rechte sie deklarieren. Der
Store-API-Endpunkt wurde nicht bis zum Werkzeugaufruf durchgespielt.
Und der wichtigste Vorbehalt steht im Kern selbst: Das Flag ist als Experimental gekennzeichnet. Wer heute dagegen baut, baut gegen eine Schnittstelle, die sich in der nächsten Minor-Version ändern darf.
Nach dem Test wurde die Runtime zurückgesetzt und gegengeprüft: .env
byte-identisch zur Sicherung, /api/_mcp wieder 404.
