Blog

Erreurs de WordPress MCP Adapter et comment les corriger

Presque toutes les erreurs de WordPress MCP Adapter tombent dans cinq catégories : une route manquante, une erreur 401, aucun outil, une session brisée ou une connexion interrompue. Voici chaque réponse exacte, sa cause et la solution.

Red error messages on a black computer screen indicating blocked web resources

Le WordPress MCP Adapter ajoute un seul point de terminaison REST à votre site, /wp-json/mcp/mcp-adapter-default-server, et presque toutes les erreurs qu’il produit tombent dans cinq catégories : la route est absente (rest_no_route), WordPress refuse de connecter le client (401 avec rest_forbidden), le client se connecte mais ne voit aucun outil, la session se brise (Session not found, code -32005), ou le transport lui-même plante.

Ce guide passe en revue les erreurs une par une : la réponse exacte, la cause et la correction. Chacune a été reproduite sur WordPress 7.1 avec MCP Adapter 0.7.0, à partir du zip de la version GitHub, avec curl, WP-CLI 2.12 et le proxy @automattic/mcp-wordpress-remote. Lorsqu’une cause provient d’un ticket ouvert plutôt que d’un test, l’article le précise.

Key takeaways

  • Nearly every WordPress MCP Adapter error falls into five groups. The route is missing (rest_no_route), WordPress will not log the client in (401 rest_forbidden), the client sees no tools, the session breaks (-32005), or the transport drops. arvindkumar.ca
  • A 404 rest_no_route means the REST API is running but nothing registered that path. Check that /wp-json/mcp lists the route, then look for an inactive plugin, a wrong path, plain permalinks, or the default server being disabled by the mcp_adapter_create_default_server filter. arvindkumar.ca
  • WordPress gives every authentication failure the same 401 rest_forbidden response. Work through it in order: HTTPS, the Authorization header, the credentials, and plugins that disable Application Passwords, and test with /wp-json/wp/v2/users/me. arvindkumar.ca
  • A client that looks connected but has no tools often has a proxy hiding an upstream 401 or 404, so read the proxy log. It can also be by design: the default server exposes only three discovery tools, and your own abilities need meta.public set and a valid category and schema. arvindkumar.ca
  • Over HTTP, every request after initialize must send back the Mcp-Session-Id header. Since 0.7.0 it must also send MCP-Protocol-Version: 2025-11-25, and a -32005 Session not found error means the session expired, was evicted or ended, or belongs to another user, so run initialize again. arvindkumar.ca
  • The claude.ai message « no MCP server was found at the provided URL » means sign-in worked but the handshake at the URL failed. Test the exact URL with curl from outside your network and look for redirects, private addresses or firewall blocks. arvindkumar.ca
  • The STDIO server stops after 60 seconds because PHP’s default_socket_timeout applies to the socket Claude Code passes in. Start PHP with php -d default_socket_timeout=-1, or use HTTP instead. arvindkumar.ca

Summarised from this post, formatted for answer engines.

Ce que vous voyezCause probableCorrectif
rest_no_route (HTTP 404)Plugin inactif, mauvais chemin, permaliens simples ou serveur par défaut désactivéVérifiez /wp-json/mcp; corrigez le chemin ou les permaliens
rest_forbidden (HTTP 401)Mauvais identifiants, en-tête Authorization supprimé ou absence de HTTPSTestez avec /wp-json/wp/v2/users/me; servez le site en HTTPS
Connecté, mais aucun outilLe proxy masque un 401 ou un 404 en amont, ou aucune capacité n’est publiqueLisez le journal du proxy; définissez meta.public
-32600 Missing Mcp-Session-Id headerEn-tête non envoyé après initialize, ou supprimé par un proxyEnvoyez-le à chaque requête suivante
-32600 MCP-Protocol-Version header is requiredObligatoire depuis la version 0.7.0Envoyez MCP-Protocol-Version: 2025-11-25
-32005 Session not found (HTTP 404)Session expirée, évincée, terminée ou appartenant à un autre utilisateurRelancez initialize; un utilisateur par client
« Your account was authorized, but no MCP server was found at the provided URL »La connexion à claude.ai a réussi, mais la négociation initiale à l’URL a échouéTestez l’URL exacte avec curl depuis l’extérieur
Le serveur STDIO s’arrête après 60 secondesdefault_socket_timeout de PHP sur un stdin de type socketphp -d default_socket_timeout=-1
HPE_INVALID_CHUNK_SIZE (proxy)Node n’a pas pu analyser le découpage de la réponse; non confirméCapturez la réponse brute avec curl -v

Pourquoi le point de terminaison renvoie-t-il 404 rest_no_route?

WordPress répond {"code":"rest_no_route","message":"No route was found matching the URL and request method.","data":{"status":404}} quand l’API REST fonctionne, mais que rien n’a enregistré ce chemin. Commencez par confirmer que la route existe (aucune connexion requise) :

curl -s https://example.com/wp-json/mcp

Vous devriez voir /mcp/mcp-adapter-default-server avec POST, GET et DELETE. Si l’espace de noms est absent, c’est que le plugin est inactif, ou que quelque chose a renvoyé false sur le filtre mcp_adapter_create_default_server, ce qui supprime le serveur par défaut et sa route. L’auteur du ticket #367 accusait un autre plugin qui embarquait sa propre copie de l’adapter; les mainteneurs ne l’ont pas confirmé, mais la version 0.7.0 déprécie les copies intégrées et affiche un avertissement quand deux copies se chargent. Si la route figure dans la liste, comparez les chemins caractère par caractère.

Les permaliens simples sont l’autre cause classique : sans règles de réécriture, /wp-json/ n’est pas une adresse REST, et un site de test a renvoyé le HTML de la page d’accueil avec un statut 200, ce que les clients signalent par « not a valid MCP endpoint ». Choisissez n’importe quel autre réglage de permaliens, ou utilisez https://example.com/?rest_route=/mcp/mcp-adapter-default-server, qui fonctionne partout.

Pourquoi un mot de passe d’application valide donne-t-il un 401 rest_forbidden?

Parce que WordPress donne la même réponse à tous les échecs d’authentification à cet endroit : {"code":"rest_forbidden","message":"Sorry, you are not allowed to do that.","data":{"status":401}}. Un mauvais mot de passe, un nom d’utilisateur inconnu, l’absence d’identifiants et un bon mot de passe sur un site sans HTTPS ont tous produit exactement cette réponse lors de mes tests. Vérifiez ces points dans l’ordre :

  1. HTTPS est-il activé? Le noyau ne prend en charge les mots de passe d’application que si is_ssl() est vrai ou si WP_ENVIRONMENT_TYPE vaut local (voir wp_is_application_passwords_supported()). Sinon, le mot de passe n’est jamais vérifié, et votre écran de profil affiche The application password feature requires HTTPS, which is not enabled on this site. Test : curl -s https://example.com/wp-json/ devrait lister application-passwords sous authentication. Derrière un proxy qui termine le TLS, ajoutez l’extrait ci-dessous dans wp-config.php, au-dessus de la ligne wp-settings.php.
  2. L’en-tête est-il arrivé jusqu’à PHP? Certaines configurations Apache et FastCGI suppriment Authorization. Le .htaccess de WordPress contient RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] pour le transmettre; rétablissez-le s’il a été remplacé, ou demandez à votre hébergeur.
  3. Les identifiants sont-ils corrects? Utilisez l’identifiant de connexion ou le courriel, pas le nom affiché. curl -s https://example.com/wp-json/wp/v2/users/me --user "editor:xxxx xxxx xxxx xxxx xxxx xxxx" renvoie votre fiche d’utilisateur quand l’authentification fonctionne, et rest_not_logged_in quand elle échoue.
  4. Un plugin ou l’hébergeur les a-t-il désactivés? Les plugins de sécurité se branchent sur wp_is_application_passwords_available, et la section disparaît alors complètement du profil; le test de l’index REST permet aussi de le repérer.
// Behind a proxy or load balancer that terminates TLS, tell WordPress the request was HTTPS.
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
	$_SERVER['HTTPS'] = 'on';
}

Pourquoi le client est-il connecté mais sans outils?

La première cause est une défaillance cachée. Avec @automattic/mcp-wordpress-remote (version 0.5.1 testée), un 401 ou un 404 de WordPress ne coupe pas la connexion : le proxy répond lui-même à initialize avec "serverInfo":{"name":"WordPress MCP Remote Proxy"} et "capabilities":{"experimental":{"connectionFailed":{}}}. Le client semble donc connecté, et seul l’appel suivant échoue avec Cannot process tools/list: WordPress connection failed during initialization, l’erreur de WordPress se trouvant dans data. Définissez LOG_FILE et LOG_LEVEL=3 sur le proxy, ou ouvrez le journal MCP de votre client, repérez WordPress API error (401) ou (404), et corrigez cette erreur.

La seconde cause est voulue. Le serveur par défaut expose trois outils, mcp-adapter-discover-abilities, mcp-adapter-get-ability-info et mcp-adapter-execute-ability, et vos capacités n’apparaissent jamais dans tools/list; l’assistant doit d’abord appeler discover, ce qui est à l’origine de la plainte du ticket #213. Demandez-lui de lister les capacités de votre site; avec WordPress 6.9 ou une version plus récente, core/get-site-info, core/get-user-info et core/get-environment-info devraient apparaître. La vôtre est absente quand :

  • elle n’est pas publique. Les capacités sont privées par défaut; get-ability-info répond Ability "mysite/private-hello" is not exposed via MCP (mcp.public!=true). Définissez 'meta' => array( 'public' => true ), ou 'mcp' => array( 'public' => false ) dans meta pour en masquer une uniquement à MCP.
  • elle ne s’est jamais enregistrée. wp_register_ability() renvoie null quand category est absente ou non enregistrée, ou quand la fonction est appelée en dehors de wp_abilities_api_init. Avec WP_DEBUG activé, un avis nomme le problème (The ability properties must contain a `category` string.); désactivé, c’est le silence.
  • son schéma échoue à la validation. Depuis la version 0.7.0, un outil qu’aucune révision de MCP ne peut représenter est retiré de tools/list, avec un avertissement dans debug.log comme Tool "mysite-bad-schema" is unavailable for MCP revision 2025-11-25: /inputSchema/properties/q: Expected object, got string.

Une capacité publique minimale pour un plugin à chargement obligatoire (must-use) :

add_action( 'wp_abilities_api_init', function () {
	wp_register_ability( 'mysite/public-hello', array(
		'label'               => 'Public hello',
		'description'         => 'Says hello to the current user.',
		'category'            => 'site',
		'input_schema'        => array(
			'type'       => 'object',
			'properties' => array( 'name' => array( 'type' => 'string' ) ),
		),
		'execute_callback'    => function ( $input ) {
			$name = isset( $input['name'] ) ? sanitize_text_field( $input['name'] ) : wp_get_current_user()->display_name;
			return array( 'message' => sprintf( 'Hello, %s.', $name ) );
		},
		'permission_callback' => function () {
			return current_user_can( 'read' );
		},
		'meta'                => array( 'public' => true ),
	) );
} );

Si votre client a besoin de l’abilité directement dans tools/list, ajoutez-la au serveur par défaut avec le filtre mcp_adapter_default_server_config; elle apparaît sous le nom mysite-public-hello (les barres obliques deviennent des tirets) avec son propre schéma.

add_filter( 'mcp_adapter_default_server_config', function ( $config ) {
	$config['tools'][] = 'mysite/public-hello';
	return $config;
} );

Pourquoi le serveur répond-il Session not found (-32005)?

Par HTTP, initialize renvoie un en-tête de réponse Mcp-Session-Id que chaque requête suivante doit renvoyer. Les sessions sont stockées dans les métadonnées de l’utilisateur, limitées à 32 par utilisateur, et elles expirent après 24 heures d’inactivité. La séquence complète de la poignée de main:

URL="https://example.com/wp-json/mcp/mcp-adapter-default-server"
AUTH="editor:xxxx xxxx xxxx xxxx xxxx xxxx"

SID=$(curl -s -D - -o /dev/null -X POST "$URL" --user "$AUTH" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}' \
  | grep -i '^mcp-session-id' | awk '{print $2}' | tr -d '\r')

curl -s -X POST "$URL" --user "$AUTH" \
  -H "Content-Type: application/json" \
  -H "Mcp-Session-Id: $SID" \
  -H "MCP-Protocol-Version: 2025-11-25" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'

Trois erreurs peuvent survenir dans ce flux:

  • -32600 Invalid Request: Missing Mcp-Session-Id header (HTTP 400). Le client ne l’envoie pas, ou un proxy, un WAF ou un cache supprime les en-têtes qu’il ne reconnaît pas.
  • -32600 Invalid Request: MCP-Protocol-Version header is required for a 2025-11-25 session (HTTP 400). Nouveau dans la version 0.7.0; seules les sessions 2024-11-05 peuvent l’omettre. Les clients qui respectent la spécification l’envoient; les scripts écrits à la main et les exemples de la documentation de l’adaptateur ne le font pas, et échouent maintenant.
  • -32005 Session not found: Invalid or expired session (HTTP 404). L’identifiant ne correspond à rien pour cet utilisateur. On peut le reproduire de quatre façons: un identifiant inventé, une session terminée avec DELETE, un 33e initialize qui évince la plus ancienne session, et une session créée par un utilisateur puis envoyée avec les identifiants d’un autre, ce qui arrive quand des gens partagent une même configuration de connecteur.

Le ticket #312 signale un -32005 sur prompts/list juste après initialize dans la version 0.5.0, avec trois appels de liste en parallèle. Aucun mainteneur n’a répondu, mais la version 0.6.0 a ajouté des tentatives bornées autour des écritures de session concurrentes, et les mêmes requêtes parallèles ne l’ont pas reproduit sur la 0.7.0. Mettez à jour d’abord; si le problème reste intermittent, interceptez -32005, relancez initialize et réessayez.

Pourquoi claude.ai indique-t-il qu’aucun serveur MCP n’a été trouvé à l’URL?

« Your account was authorized, but no MCP server was found at the provided URL, or your account doesn’t have access to it », accompagné d’une référence ofid_, est un message du connecteur de claude.ai, pas de WordPress. La page de dépannage des connecteurs d’Anthropic donne la séquence: d’abord OAuth, puis une poignée de main MCP des serveurs d’Anthropic vers l’URL que vous avez saisie. WordPress n’a pas de serveur OAuth et l’adaptateur n’en ajoute aucun (son guide pour les propriétaires de site le dit), donc un plugiciel OAuth sur votre site a mené la connexion à terme, puis la poignée de main a échoué. Raisons habituelles: un caractère parasite dans l’URL, une redirection vers https ou www (les clients HTTP abandonnent généralement l’en-tête Authorization quand une redirection change d’hôte), un nom d’hôte qui se résout vers une adresse privée, un pare-feu qui bloque la plage d’adresses IP d’Anthropic, ou un utilisateur OAuth sans compte WordPress correspondant. Depuis l’extérieur de votre réseau, exécutez curl -sI https://example.com/wp-json/mcp/mcp-adapter-default-server: toute réponse autre que 401 ou 405, ou tout en-tête Location, est à corriger. Le ticket #361 n’a pas encore de commentaires; ce sont donc des vérifications, pas un diagnostic.

Pourquoi le serveur STDIO s’arrête-t-il après 60 secondes?

Quand Claude Code lance wp mcp-adapter serve comme serveur local, il donne au processus une paire de sockets plutôt qu’un tube. Le default_socket_timeout de PHP (60 secondes par défaut) s’applique aux sockets; fgets( STDIN ) renvoie donc false après une minute de silence. Le pont interprète cela comme la fin de l’entrée, journalise MCP STDIO Bridge stopped et se termine avec le code 0. Le ticket #308 le signale, et on le reproduit avec WP-CLI 2.12 et une paire de sockets Python: un délai de 5 secondes a arrêté le serveur après 5,0 secondes, et -1 l’a gardé actif. La boucle de lecture dans trunk n’a toujours pas de stream_set_timeout(); démarrez donc PHP sans délai, comme dans php -d default_socket_timeout=-1 /usr/local/bin/wp mcp-adapter serve --user=editor --server=mcp-adapter-default-server, ou utilisez HTTP. Un autre changement de la 0.7.0: un tools/list seul sur STDIO renvoie maintenant -32600 Invalid Request: The 2025 lifecycle requires initialization before this request; envoyez donc initialize d’abord.

Que doit couvrir la liste de vérification pour la production?

  • HTTPS de bout en bout, avec l’extrait X-Forwarded-Proto ci-dessus derrière un proxy qui termine le TLS, et l’URL finale enregistrée, jamais une URL qui redirige.
  • Un utilisateur et un mot de passe d’application par client, avec le rôle le plus restreint qui fait le travail. Les sessions appartiennent à un utilisateur, donc des identifiants partagés causent des -32005, et la révocation reste précise.
  • Aucune mise en cache ni réécriture d’en-têtes sur /wp-json/mcp/. Authorization, Mcp-Session-Id et MCP-Protocol-Version doivent parvenir à PHP sans modification, et l’en-tête de réponse Mcp-Session-Id doit parvenir au client.
  • Des abilités exposées volontairement. meta.public seulement avec un vrai permission_callback, meta.mcp.public = false pour les abilités sensibles, et un audit de tout ce qui est promu par mcp_adapter_default_server_config, qui est appelable qu’elle soit publique ou non.

Commencez par les deux vérifications qui ne coûtent rien: curl -s https://example.com/wp-json/mcp prouve que la route existe, et users/me prouve que le mot de passe fonctionne. Exécutez ensuite la poignée de main ci-dessus et gardez le script; chaque erreur de cet article s’y manifeste avant d’atteindre une fenêtre de clavardage.

4 questions about WordPress MCP Adapter errors, answered

Why does my WordPress MCP endpoint return rest_no_route?

The REST API is running but nothing registered that path. The plugin may be inactive, the path may be wrong, permalinks may be set to plain, or the default server may be disabled. Checking /wp-json/mcp shows whether the route exists.

Why do I get 401 rest_forbidden with a valid Application Password?

WordPress returns the same 401 for any authentication failure, including a correct password on a site without HTTPS. Check that HTTPS is on, that the Authorization header reaches PHP, that you used the login name or email, and that no plugin has switched Application Passwords off.

Why does my MCP client connect but show no tools?

The proxy may be hiding a 401 or 404 from WordPress, which the proxy log will show. Otherwise your abilities are private by default, so they need meta.public set and must be reached through the discover tool, since the default server lists only three tools.

How do I fix the MCP error Session not found (-32005)?

The session ID matches nothing for that user, because it expired, was evicted, was ended, or was created by a different user. Run initialize again and use one user per client.

Read next