Le WordPress d'aujourd'hui, décodé pour les développeurs

IA & MCP

rest_api_init : une action pour exposer un point d’entrée dédié à un agent

Ajouter une route dédiée à un agent sans passer par un serveur MCP, quand un projet n'a pas encore basculé vers une version de WordPress plus récente.

Par WordPress Développement • 30 septembre 2026 • 6 min de lecture • Aucun commentaire
rest_api_init : un filtre pour exposer un point d'entrée dédié à un agent

Tous les projets ne peuvent pas basculer immédiatement vers un serveur MCP dès qu’un besoin d’exposer une fonctionnalité à un agent se présente. Sur un site qui n’a pas encore prévu cette migration, une route REST classique, enregistrée via le hook rest_api_init, reste une solution parfaitement fonctionnelle pour donner à un agent un accès contrôlé à une action précise.

Cette recette décrit comment construire un point d’entrée dédié, avec ses propres règles de permission, sans dépendre d’un protocole plus récent que le projet n’a pas encore intégré.

Le besoin : une action simple exposée à un agent externe

Le cas concret retenu ici est celui d’un agent de support, développé en dehors de WordPress, qui doit pouvoir consulter le statut d’une commande à partir de sa référence, sans disposer d’un accès complet à l’API REST WooCommerce existante, jugée trop large pour ce cas d’usage précis.

Étape 1 : enregistrer la route sur rest_api_init

L'essentiel à retenir : Une route REST classique reste une option valable en attendant l'adoption d'un serveur MCP ; Le hook rest_api_init permet d'enregistrer un point d'entrée avec ses propres règles de permission ; Cette route peut ensuite être décrite manuellement à un agent existant

Une précision de vocabulaire avant le code : rest_api_init est une action, et non un filtre. On s’y accroche avec add_action(), et il se déclenche lorsque le serveur REST s’initialise, au moment où chaque extension peut enregistrer ses routes. C’est l’unique endroit où register_rest_route() doit être appelée.

add_action( 'rest_api_init', 'support_enregistrer_route_commande' );

function support_enregistrer_route_commande() {
    register_rest_route( 'support/v1', '/commande/(?P<reference>\d+)/statut', array(
        'methods'             => WP_REST_Server::READABLE,
        'callback'            => 'support_lire_statut_commande',
        'permission_callback' => 'support_verifier_droit',
        'args'                => array(
            'reference' => array(
                'description'       => 'Numéro de la commande.',
                'type'              => 'integer',
                'required'          => true,
                'sanitize_callback' => 'absint',
            ),
        ),
    ) );
}

L’expression (?P<reference>\d+) capture le numéro dans l’adresse, et la restriction à des chiffres évite d’accepter autre chose dès la résolution de la route. Le paramètre est ensuite déclaré dans args : cette déclaration sert à la fois à l’assainissement et à la description de la route, nous y reviendrons.

Étape 2 : des règles de permission strictes

Le permission_callback est l’élément le plus important de la route. Il ne se contente pas de demander « l’appelant est-il connecté ? » : il vérifie une capacité précise, créée pour cet usage. On définit un rôle dédié, qui ne possède que la lecture du statut des commandes :

register_activation_hook( __FILE__, 'support_creer_role_agent' );

function support_creer_role_agent() {
    add_role( 'agent_support', 'Agent de support', array(
        'read'                        => true,
        'consulter_statut_commande'   => true,
    ) );
}

function support_verifier_droit() {
    if ( current_user_can( 'consulter_statut_commande' ) ) {
        return true;
    }

    return new WP_Error(
        'support_interdit',
        'Vous n\'avez pas le droit de consulter le statut des commandes.',
        array( 'status' => rest_authorization_required_code() )
    );
}

L’agent s’authentifie avec un mot de passe d’application rattaché à un utilisateur de ce rôle, transmis en authentification HTTP de base, exclusivement en HTTPS. Si le compte est compromis, l’attaquant ne peut lire que des statuts : pas de modification, pas d’accès aux clients, pas de connexion à l’interface d’administration avec ce mot de passe. La révocation se fait depuis le profil de l’utilisateur, sans changer le mot de passe principal.

Étape 3 : une réponse minimale

La fonction de rappel ne renvoie que ce dont l’agent a besoin. Ni nom, ni adresse, ni adresse électronique : le statut et la date de dernière modification suffisent pour répondre à un client :

function support_lire_statut_commande( WP_REST_Request $requete ) {
    $commande = wc_get_order( $requete['reference'] );

    if ( ! $commande ) {
        return new WP_Error(
            'support_commande_introuvable',
            'Commande introuvable.',
            array( 'status' => 404 )
        );
    }

    $statut = $commande->get_status();

    return rest_ensure_response( array(
        'reference'    => $commande->get_id(),
        'statut'       => $statut,
        'libelle'      => wc_get_order_status_name( $statut ),
        'modifiee_le'  => $commande->get_date_modified()
            ? $commande->get_date_modified()->date( 'c' )
            : null,
    ) );
}

La fonction wc_get_order() renvoie false pour un identifiant inconnu, ce qui permet de répondre par un 404 explicite plutôt que par une erreur fatale. Attention : le numéro de commande affiché au client peut différer de l’identifiant interne si une extension modifie la numérotation ; précisez dans la description de la route lequel des deux est attendu.

Étape 4 : décrire la route à l’agent

Un agent existant, construit en dehors de WordPress, ne découvre pas la route tout seul : il faut la lui décrire. La REST API fournit déjà une partie du travail, puisqu’une requête OPTIONS sur la route renvoie les méthodes acceptées et la description des arguments déclarés plus haut. On peut en tirer, à la main, une définition d’outil sous forme de schéma JSON, que l’on colle dans la configuration de l’agent :

{
    "name": "statut_commande",
    "description": "Retourne le statut actuel d'une commande à partir de son numéro. Ne fournit aucune donnée personnelle.",
    "input_schema": {
        "type": "object",
        "properties": {
            "reference": {
                "type": "integer",
                "description": "Numéro de la commande."
            }
        },
        "required": [ "reference" ]
    }
}

L’agent, ou la petite couche qui le pilote, transforme alors un appel d’outil en requête GET /wp-json/support/v1/commande/1234/statut accompagnée de l’authentification. La description textuelle compte autant que le schéma : elle doit dire ce que l’outil fait, mais aussi ce qu’il ne fait pas.

Donner à un agent une route précise et étroite vaut mieux que lui confier une clé qui ouvre toute la maison.

Les pièges à éviter

  • Laisser __return_true comme permission. Depuis WordPress 5.5, l’absence de permission_callback déclenche un avertissement, mais l’écrire avec __return_true sur une route qui expose des données d’activité revient à la publier sur Internet.
  • Réutiliser un compte d’administrateur. Un agent n’a pas besoin de tous les droits : un rôle dédié limite les dégâts en cas de fuite d’un mot de passe d’application.
  • Renvoyer trop de données. Ce que l’agent reçoit peut se retrouver dans ses réponses : ne lui transmettez que ce qu’il a le droit de dire.
  • Oublier la journalisation et la limitation de débit. Un agent qui boucle peut saturer le site : journalisez les appels et plafonnez-les au niveau du serveur ou d’une extension de sécurité.
  • Bâtir toute la logique dans la fonction de rappel. Isolez le calcul métier dans une fonction indépendante de la route : si le projet adopte plus tard un serveur MCP, cette logique sera réutilisable telle quelle.

Conclusion

En attendant une éventuelle bascule vers un serveur MCP, une route REST classique, enregistrée sur l’action rest_api_init, donne à un agent un accès précis et contrôlé : un espace de noms dédié, un permission_callback fondé sur une capacité propre, une réponse minimale et une description écrite à la main. La solution reste simple, testable avec curl et entièrement sous votre contrôle, ce qui est exactement ce que l’on attend d’une porte ouverte à un programme autonome.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi