MCP für PrestaShop, ohne einem Agenten die Schlüssel zu geben

Ein MCP-Server in PHP, der die Webservice-API von PrestaShop mit vier schreibgeschützten Werkzeugen umschließt, geschrieben und getestet an einem Shop mit Version 9.1.4, dann an Codex angebunden und in Claude Code deklariert.

MCP für PrestaShop, ohne einem Agenten die Schlüssel zu geben
Schnelle Antwort

PrestaShop bringt seit April 2026 ein offizielles MCP-Modul heraus, proprietär und an sein OAuth gebunden. Um die Kontrolle zu behalten, schreibe einen MCP-Server in PHP, der die Webservice-API mit einem auf GET beschränkten Schlüssel umschließt, plus ein paar Werkzeuge, die eine Frage beantworten, statt die API weiterzureichen. Rechne mit rund 650 Zeilen PHP und drei unabhängigen Ablehnungsschichten.

Einen Code-Agenten an einen PrestaShop-Shop anzubinden ist verlockend: Er würde den Katalog lesen, unvollständige Produktseiten und Lagerengpässe an deiner Stelle aufspüren. Das Risiko kommt nicht von seiner Unvorsichtigkeit, sondern von der Angriffsfläche, die du ihm öffnest. Dieses Tutorial baut einen MCP-Server in PHP, der nur vier Lesevorgänge freigibt, und durch den keine Schreibaktion hindurchkommt.

Gibt es bereits einen MCP-Server für PrestaShop?

Ja, seit dem Frühjahr 2026. PrestaShop bringt sein eigenes Modul heraus, PrestaShop MCP Server, dessen öffentliche Dokumentation ausdrücklich erklärt, dass der Hersteller „holds all associated intellectual property rights“ und eine persönliche, nicht exklusive und nicht übertragbare Lizenz gewährt. Die Einführungsseite, die ich am 7. September 2026 geöffnet habe, zeigt eine letzte Aktualisierung vom 30. April 2026. Zwei Einschränkungen zählen für eine Entwicklerin: Das Modul ist nicht Open Source, und seine Authentifizierung „works exclusively with PrestaShop OAuth“.

Datierter und unabhängiger Beleg für seine Existenz: das Paket prestashop/ps-mcp-server-stubs, veröffentlicht auf Packagist in Version 1.0.3 am 9. Juli 2026, Lizenz proprietary, beschrieben als „IDE stubs for ps_mcp_server MCP attributes and exceptions“. Drittmodule können darüber übrigens eigene Werkzeuge einklinken, über die PHP-Attribute PsMcpTool, PsMcpSchema und PsMcpToolAnnotations.

Auf der Community-Seite zeichnet die GitHub-API ein weniger einladendes Bild. Die vier am 7. September 2026 gefundenen Repositorys haben nach ihrer Erstellungswoche keinen einzigen weiteren Commit mehr erhalten.

Repository Sprache Lizenz Erstellt Letzter Push Sterne
latinogino/prestashop-mcp Python MIT 30.06.2025 30.06.2025 8
promokit/prestashop-mcp TypeScript keine 12.07.2025 16.07.2025 2
florinel-chis/prestashop-mcp Python MIT 24.11.2025 24.11.2025 9
100peck/prestashop-mcp-server TypeScript MIT 01.03.2026 02.03.2026 0

Keines davon wurde hier ausgeführt, und das ist Absicht: Die Entscheidung, die zählt, fällt zwischen beherrschter und erlittener Angriffsfläche, nicht zwischen offiziell und Community. Ein Server, den du selbst schreibst, passt in drei PHP-Dateien, und du weißt, Zeile für Zeile, was er kann.

Warum das Webservice, und nicht die Datenbank?

PrestaShop stellt seit Langem eine REST-API bereit, das Webservice, „a CRUD API“ laut der Entwicklerdokumentation von Version 9. Sein Interesse liegt hier mehr in der Zugriffskontrolle als im Reichtum des Modells, denn ein zweiunddreißig Zeichen langer Schlüssel erhält Rechte pro Ressource und pro HTTP-Methode. Die Dokumentation sagt es unverblümt: „you might want a user to have read and write access on some resources, but only read access on others“.

Die Ablehnung steht also nicht in deinem PHP-Code, wo ein Programmierfehler sie löschen könnte. Sie wird vom Shop selbst durchgesetzt, noch bevor dein Server überhaupt existiert. Das ist dieselbe Logik der Tiefenverteidigung wie im Artikel über Sandboxes und Berechtigungen von Code-Agenten.

Der Schlüssel wird im Backoffice erstellt (Erweiterte Einstellungen > Webservice) oder per Code, mit der Klasse WebserviceKey und ihrer Methode setPermissionForAccount(). Für das Labor habe ich ihn per SQL erstellt, da kein Browser im Spiel war. Die gewährten Rechte: nur GET, auf neun Ressourcen.

php
// Rechte, die dem Labor-Schlüssel zugewiesen wurden: nichts außer GET.
$permissions = [];
foreach (['products', 'categories', 'stock_availables', 'orders', 'order_states',
          'combinations', 'manufacturers', 'languages', 'currencies'] as $resource) {
    $permissions[$resource] = ['GET' => 1];
}

Die Prüfung erfolgt nicht auf Zuruf. Drei Anfragen genügen, wobei der Schlüssel als HTTP-Basic-Benutzername mit leerem Passwort übergeben wird:

bash
# Erlaubte Ressource: 200
curl -s -u "$PS_WS_KEY:" \
  "http://127.0.0.1:8097/api/products?output_format=JSON&limit=3"
{"products":[{"id":1},{"id":2},{"id":3}]}

# Ressource nicht in den Rechten enthalten: 401
curl -s -u "$PS_WS_KEY:" "http://127.0.0.1:8097/api/customers?output_format=JSON"
{"errors":[{"code":26,"message":"Resource of type \"customers\" is not allowed
 with this authentication key"}]}

# Schreiben auf eine Ressource, die eigentlich zum Lesen erlaubt ist: 405
curl -s -X PUT -u "$PS_WS_KEY:" "http://127.0.0.1:8097/api/products/1"
<code><![CDATA[25]]></code>
<message><![CDATA[Method PUT is not allowed for the resource products
 with this authentication key]]></message>

DELETE liefert dasselbe 405. Und der Preis von Produkt 1 lag bei 23,90 € vor diesen Versuchen, bei 23,90 € danach. Das ist die einzige Kontrolle, die zählt.

Schritt 1, ein Webservice-Client, der nur lesen kann

Die zweite Barriere steckt im Code. Die Klasse, die mit dem Shop spricht, gibt nur eine einzige öffentliche Methode frei, get(): Selbst wenn der Schlüssel eines Tages versehentlich Schreibrechte erhielte, hätte der MCP-Server keine Möglichkeit, sie zu nutzen. Sie erzwingt außerdem output_format=JSON, wir werden weiter unten sehen, dass dieses Detail seinen Preis hat.

php
final class PrestaShopWebservice
{
    public function __construct(
        string $baseUrl,
        private string $key,
        private int $timeout = 10
    ) {
        $this->baseUrl = rtrim($baseUrl, '/');
    }

    public function get(string $resource, array $query = []): array
    {
        $query['output_format'] = 'JSON';
        $url = $this->baseUrl . '/api/' . ltrim($resource, '/') . '?' . http_build_query($query);

        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPGET        => true,
            CURLOPT_HTTPAUTH       => CURLAUTH_BASIC,
            CURLOPT_USERPWD        => $this->key . ':',   // Schlüssel als Benutzername, leeres Passwort
            CURLOPT_TIMEOUT        => $this->timeout,
            CURLOPT_FOLLOWLOCATION => false,
        ]);
        $body   = curl_exec($ch);
        $status = (int) curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
        curl_close($ch);

        // 404 bei einer gefilterten Kollektion bedeutet null Ergebnisse, kein Ausfall.
        if ($status === 404) {
            return [];
        }
        if ($status !== 200) {
            throw new RuntimeException(self::readableError((string) $body, $status));
        }

        return json_decode((string) $body, true) ?: [];
    }
}

Das Webservice hat eine eigene Anfragesyntax, die man einzeln prüfen muss, bevor man sie in Code schreibt. Diese hier wurden auf PrestaShop 9.1.4 validiert: display=[id,name,price], um Felder auszuwählen, filter[name]=%[colibri]% für ein „enthält“, filter[quantity]=[0,2000] für ein Intervall, filter[id]=[1|2|3] für ein „oder“, sort=[price_DESC], und date=1, das jeden Filter auf date_add begleiten muss.

Schritt 2, vier Werkzeuge, die auf Deutsch antworten, nicht in JSON

Hier entscheidet sich das Wesentliche, und viele MCP-Server verpassen es. Ein Werkzeug soll die API nicht einfach in den Kontext des Modells kippen, es soll eine Frage beantworten. Die vier Werkzeuge des Servers sind: search_products, get_product, orders_summary und stock_alerts. Jedes liefert einen kurzen Text und parallel dazu ein structuredContent für Code, der es weiterlesen möchte.

get_product veranschaulicht die Idee: Statt die Rohdaten der Produktseite zu liefern, berechnet es das, was der Agent sonst selbst ableiten müsste.

php
// Die Lücken, die der Agent sofort sehen soll, ohne über das JSON nachzudenken.
$gaps = [];
if ($summary['meta_title'] === '') {
    $gaps[] = 'méta-titre vide';
}
if ($summary['meta_description'] === '') {
    $gaps[] = 'méta-description vide';
}
if ($longLen < 300) {
    $gaps[] = 'description longue de ' . $longLen . ' caractères';
}
if ($summary['reference'] === '') {
    $gaps[] = 'référence absente';
}
$summary['gaps'] = $gaps;

Auf dem Demo-Shop liefert der Aufruf dies, einen Text, den ein Mensch genauso schnell liest wie ein Modell:

markdown
#1 T-shirt imprimé colibri (réf. demo_1)
Prix HT : 23,90 €  ·  Stock : 2400  ·  Actif : oui
Méta-titre : (vide)
Description courte : 94 caractères  ·  longue : 367 caractères
À corriger : méta-titre vide, méta-description vide

Der Gewinn lässt sich messen. Für denselben Katalog von neunzehn Produkten landet je nach gewählter Methode Folgendes im Kontext.

Was der Agent erhält Byte
GET /api/products?display=full (XML, Standardformat) 139.350
GET /api/products?display=full&output_format=JSON 41.126
Vom Werkzeug search_products gelieferter Text 1.137

Hundertzweiundzwanzig Mal weniger als das rohe XML. Ein MCP-Server, der sich damit begnügt, die Endpunkte der API nachzubilden, lässt den Client diese gesamte Differenz bei jedem Aufruf bezahlen. Die Überlegung wird im Leitfaden zur Erstellung eines MCP-Servers in PHP ausgeführt, der auch die gesamte Protokolltheorie trägt, die dieses Tutorial als bekannt voraussetzt.

Schritt 3, der HTTP-Server: ein Token, eine Origin, eine Methode

Der Transport passt in eine Datei und drei Ablehnungen. Ein lokaler MCP-Server lauscht auf der Loopback-Schnittstelle, was ihn nicht vor einer im Browser derselben Maschine geöffneten Webseite schützt: daher die Prüfung des Origin-Headers. Da die Revision 2026-07-28 der Spezifikation den GET-Stream gestrichen hat, läuft alles über POST. Und das Bearer-Token ist vom Webservice-Schlüssel getrennt: Man kann es widerrufen, ohne den Shop anzufassen.

php
// 1. Origin: Ohne diese Prüfung könnte eine im Browser geöffnete Webseite
//    der Maschine mit dem lokalen Server sprechen (DNS-Rebinding).
$origin = $_SERVER['HTTP_ORIGIN'] ?? null;
if ($origin !== null && !in_array($origin, $origins, true)) {
    respond(403, ['jsonrpc' => '2.0', 'error' => ['code' => -32600, 'message' => 'Origine refusée.']]);
}

// 2. Die Revision 2026-07-28 hat den GET-Stream gestrichen: Alles läuft über POST.
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    header('Allow: POST');
    respond(405, ['jsonrpc' => '2.0', 'error' => ['code' => -32600, 'message' => 'POST uniquement.']]);
}

// 3. Bearer-Token. Der Webservice-Schlüssel verlässt den Server nie.
$header = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
$sent   = preg_match('/^Bearer\s+(.+)$/i', trim((string) $header), $m) === 1 ? $m[1] : '';
if ($mcpToken !== '' && !hash_equals($mcpToken, $sent)) {
    header('WWW-Authenticate: Bearer');
    respond(401, jsonrpcError($id, -32001, 'Jeton MCP absent ou invalide.'));
}

Eine letzte Feinheit ist es wert, festgehalten zu werden: Ein Werkzeugfehler wird nicht als JSON-RPC-Fehler zurückgegeben. Die Spezifikation unterscheidet „protocol errors“ von „tool execution errors“, wobei Letztere im Ergebnis mit isError: true zurückkommen müssen, damit sich das Modell korrigieren kann. Nach Produkt 9999 zu fragen liefert also ein HTTP 200 mit dem Text „Produit 9999 introuvable.“.

Der Server startet mit dem integrierten Server von PHP:

bash
php -S 127.0.0.1:8110 server.php

Die Antworten unten wurden alle auf dieser Instanz erfasst.

Anfrage Antwort
GET /mcp 405
POST /mcp ohne Token 401, -32001
Origin: https://exemple-malveillant.test 403
initialize (protocolVersion 2025-06-18) 200, Version identisch zurückgegeben
tools/list 200, vier Werkzeuge, 1.928 Byte
notifications/initialized (ohne id) 202, leerer Body
MCP-Protocol-Version: 1900-01-01 400, -32022 mit der Liste der unterstützten Versionen

Codex anbinden, ohne seine Konfiguration anzufassen

Codex liest seine Datei ~/.codex/config.toml, akzeptiert aber auch Konfigurationsschlüssel spontan mit -c. Das ist der richtige Weg, einen Server auszuprobieren: Nichts wird auf die Platte geschrieben, und der Versuch überlebt den Befehl nicht. Der Fingerabdruck meiner config.toml war im Übrigen vor und nach den vier folgenden Ausführungen identisch. Das Token wiederum bleibt in einer Umgebungsvariable statt in der Kommandozeile: Die Codex-Dokumentation sieht dafür bearer_token_env_var vor.

bash
export MCP_TOKEN="…"          # Token des MCP-Servers, nie der Webservice-Schlüssel

codex exec \
  -c 'mcp_servers.ps.url="http://127.0.0.1:8110/mcp"' \
  -c 'mcp_servers.ps.bearer_token_env_var="MCP_TOKEN"' \
  -c 'mcp_servers.ps.default_tools_approval_mode="writes"' \
  -m gpt-6-astra -s read-only --skip-git-repo-check \
  "Avec les outils ps, trouve la référence en alerte de stock sous 150 unités,
   puis dis ce qui manque dans sa fiche produit."

Meine erste Version des Servers kam nicht durch. Codex sah den Server durchaus, listete auch die vier Werkzeuge auf, aber jeder Aufruf blieb hängen bei:

markdown
mcp: ps/stock_alerts (failed)
MCP tool call requires approval, but approval policy is never

Der Reflex ist, nach der Codex-Einstellung zu suchen, die das freischaltet. Das ist die falsche Stelle. Ich habe die beiden Variablen über vier Ausführungen gekreuzt, gleicher Befehl, gleiches Modell, gleicher Shop, nur der Server änderte sich, mit oder ohne Annotationen.

Server-Annotationen default_tools_approval_mode Ergebnis
readOnlyHint nicht angegeben (Standard) completed
readOnlyHint "writes" completed
keine nicht angegeben (Standard) failed
keine "writes" failed

Die entscheidende Spalte ist die der Annotationen, also das Protokoll, und nicht die Einstellung des Clients. Die MCP-Spezifikation sieht optionale Annotationen vor, die das Verhalten eines Werkzeugs beschreiben, mit der Deklaration von readOnlyHint sagt der Server dem Client, dass kein Aufruf den entfernten Zustand verändert, und Codex glaubt das, ohne dass man ihm irgendetwas einstellen müsste. Vier Zeilen genügen.

php
// Die vier Werkzeuge sind schreibgeschützt: Das wird ein für alle Mal erklärt.
// Genau diese Annotation lesen Clients, um zu entscheiden, ob sie den Nutzer
// vor jedem Aufruf um Zustimmung bitten müssen.
$readOnly = [
    'readOnlyHint'    => true,
    'destructiveHint' => false,
    'idempotentHint'  => true,
    'openWorldHint'   => false,
];

Mit ihnen kommt derselbe Befehl durch.

markdown
mcp: ps/stock_alerts (completed)
mcp: ps/get_product (completed)

Référence : demo_21 — Pack Mug + Affiche encadrée (ID 15).
Stock : 100 unités, sous le seuil de 150.
Fiche incomplète : méta-titre, méta-description et description longue absents.

Zwei Werkzeugaufrufe, 11 263 Tokens. Eine Sicherheitsanmerkung drängt sich jedoch auf, und die Spezifikation formuliert sie selbst: Clients „MUST consider tool annotations to be untrusted unless they come from trusted servers“. Eine readOnlyHint-Annotation ist eine Erklärung des Servers, keine technische Garantie. Diese hier war wahr, weil ich den Server gerade selbst geschrieben hatte. Sie ersetzt weder den auf GET beschränkten Schlüssel noch den PHP-Client ohne Schreibmethode. Sie kommt danach, und bei einem fremden Server ist sie nichts wert.

Und in Claude Code?

Die Deklaration erfolgt in einem Befehl, wobei das Token als Variable belassen wird, damit die Datei versionierbar bleibt.

bash
claude mcp add --scope project --transport http ps http://127.0.0.1:8110/mcp \
  --header 'Authorization: Bearer ${MCP_TOKEN}'

Die im Wurzelverzeichnis des Projekts geschriebene Datei .mcp.json enthält tatsächlich ${MCP_TOKEN} und nicht den Wert des Tokens.

json
{
  "mcpServers": {
    "ps": {
      "type": "http",
      "url": "http://127.0.0.1:8110/mcp",
      "headers": {
        "Authorization": "Bearer ${MCP_TOKEN}"
      }
    }
  }
}

Ein Server im Projekt-Geltungsbereich ist deswegen noch nicht aktiv. claude mcp list zeigt ihn als wartend, und die Dokumentation erklärt warum: „Claude Code prompts for approval in interactive sessions before using project-scoped servers from .mcp.json files“. Das ist das richtige Verhalten, ein geklontes Repository sollte niemals von allein einen Server anbinden.

markdown
ps: http://127.0.0.1:8110/mcp (HTTP) - ⏸ Pending approval (run `claude` to approve)

Das Vorgehen ist dasselbe wie bei einem für WordPress bestimmten MCP-Server, mit dem Unterschied, dass WordPress inzwischen eine Abilities-API und einen offiziellen Adapter bereitstellt, während PrestaShop das Webservice als Grundlage belässt.

Zwei Fallen, die der Agent nie sehen wird

Die Webservice-Wurzel antwortet in JSON mit 500. Auf PrestaShop 9.1.4 mit PHP 8.5 liefert GET /api/?output_format=JSON ein 500, während dieselbe Wurzel in XML ein 200 liefert. Der Fehler 34794 im PrestaShop-Repository beschreibt genau das, „Uncaught TypeError: array_filter()“ bei JSON-Ausgabe, und er ist noch immer offen: gemeldet am 9. Dezember 2023, letzte Aktivität am 10. August 2026. Lass einen Agenten deshalb niemals die verfügbaren Ressourcen über die JSON-Wurzel entdecken, codiere die Liste fest.

Der Zeitzonenversatz ist lautlos, und das ist das Schlimmste daran. PrestaShop schreibt seine Daten in der Zeitzone des Shops (PS_TIMEZONE, hier Europe/Paris), während das PHP, das meinen Server ausführte, in UTC lief. Meine erste Version von orders_summary begrenzte das Fenster auf now() - 30 jours: Sie lieferte null Bestellungen bei einem Shop, der fünf zählte. Kein Fehler, keine Warnung, eine vollkommen glaubwürdige Null, die der Agent unverändert gemeldet hätte. Die Korrektur besteht darin, auf ganze Tage zu begrenzen.

php
// PrestaShop schreibt seine Daten in der Zeitzone des Shops (PS_TIMEZONE), nicht in
// der des PHP-Prozesses, der diesen Server ausführt. Wir begrenzen deshalb auf ganze
// Tage, sonst verschwinden einige Stunden an Bestellungen ohne ein Wort.
$from = (new DateTimeImmutable('today -' . $days . ' days'))->format('Y-m-d 00:00:00');
$to   = (new DateTimeImmutable('tomorrow'))->format('Y-m-d 00:00:00');

Das ist die teuerste Fehlerklasse bei einem Agenten: diejenige, die eine plausible Antwort erzeugt. Ein aggregierender MCP-Server muss an Daten getestet werden, deren Anzahl du im Voraus kennst.

Wozu das konkret dient

Drei Anwendungen tragen mit diesen vier schreibgeschützten Werkzeugen. Zuerst die Prüfung von Produktseiten: get_product liefert bereits die Liste der Lücken, der Agent muss nur noch durchgehen und zusammenfassen. Dann die Überwachung von Lagerengpässen, mit stock_alerts, aufgerufen von einem geplanten Agenten statt von einem Menschen, der das Backoffice öffnet. Schließlich die Vorbereitung einer Content-Baustelle: die fünfzig zu überarbeitenden Produktseiten zu finden ist eine Lesearbeit, sie im großen Stil neu zu schreiben eine andere, die einem eigenen Modul wie WizardAI zufällt.

Füge kein fünftes, schreibendes Werkzeug hinzu. An dem Tag, an dem du eines brauchst, schreibe einen zweiten Server, mit eigenem Schlüssel, eigenem Token und eigener Freigabe-Richtlinie. Zwei getrennte Server sind besser als ein Server, bei dem die Hälfte der Werkzeuge gefährlich ist.

Was du dir merken solltest

  • PrestaShop bringt seit April 2026 tatsächlich ein offizielles MCP-Modul heraus, proprietär und an sein OAuth gebunden, die vier gefundenen Community-Projekte sind alle seit ihrer Erstellungswoche verlassen.
  • Die Sicherheit besteht aus drei unabhängigen Schichten: ein auf GET beschränkter Webservice-Schlüssel für neun Ressourcen, ein PHP-Client ohne Schreibmethode, ein eigenes, widerrufbares MCP-Token.
  • Ein Werkzeug soll eine Frage beantworten, nicht eine API weiterreichen: 1.137 Byte nützlicher Text gegenüber 139.350 Byte rohem XML für denselben Katalog.
  • Ohne readOnlyHint-Annotation verweigert Codex den Aufruf eines Werkzeugs im nicht interaktiven Modus, unabhängig von der Freigabe-Einstellung. Es ist das Protokoll, das freischaltet, nicht der Client, aber eine Annotation bleibt eine Erklärung des Servers, keine Garantie.
  • Teste deine Aggregationen an Daten, deren Anzahl du kennst: Ein Zeitzonenversatz liefert eine glaubwürdige Null, die niemand nachprüfen wird.

Häufige Fehler

Ressourcen über die JSON-Wurzel entdecken GET /api/?output_format=JSON antwortet mit 500 auf PrestaShop 9.1.4 mit PHP 8.5 (offener Fehler seit Dezember 2023), während dieselbe Wurzel in XML mit 200 antwortet. Codiere die Ressourcenliste, statt sie entdecken zu lassen.
Eine Aggregation auf die aktuelle Uhrzeit begrenzen PrestaShop schreibt seine Daten in PS_TIMEZONE, dein PHP läuft vielleicht in UTC. Das Fenster now() - 30 jours lieferte null Bestellungen bei einem Shop, der fünf zählte. Begrenze auf ganze Tage.
Die Werkzeug-Annotationen vergessen Ohne readOnlyHint verweigert Codex den Aufruf im nicht interaktiven Modus: MCP tool call requires approval, but approval policy is never. Geprüft mit vier gekreuzten Ausführungen: Keine Einstellung von default_tools_approval_mode ersetzt die Annotation.
Dem Webservice-Schlüssel mehr als GET geben Die Rechte werden pro Ressource und pro HTTP-Methode geregelt. Ein Schlüssel, der schreiben kann, macht die ganze Sorgfalt im PHP-Code zunichte.
Das Token im Befehl oder in .mcp.json niederschreiben Verwende bearer_token_env_var auf der Codex-Seite und ${MCP_TOKEN} auf der Claude-Code-Seite, damit die Datei versionierbar bleibt.

Claude CodeCodexMCPPHPPrestaShopSécurité

Damien Flandrin Webentwickler seit 2010, Gründer von Gekkode und Email Impact. Jeder Artikel wird vor der Veröffentlichung an einem echten Projekt getestet. Kontakt
Newsletter

Neue Tests, Tutorials und Projekte, per E-Mail.

Reproduzierbare Tests, versionierter Code, datierte Ergebnisse. Niemals Spam.