Le problème : un outil qui pousse tout le contenu
« La spécification distingue le contenu qu’un agent doit lire maintenant du contenu qu’il pourra lire plus tard » : cette phrase, tirée de la documentation du protocole MCP (Model Context Protocol), résume un choix de conception que beaucoup de serveurs maison ignorent encore. Un outil de recherche relié à WordPress qui retrouve un article correspondant à une requête a le réflexe naturel de renvoyer son contenu complet dans le résultat : titre, corps HTML, métadonnées, parfois même les commentaires associés. L’agent reçoit alors un bloc de texte volumineux pour une question qui, souvent, ne portait que sur l’existence ou l’identifiant de l’article.
Ce réflexe vient d’une confusion entre deux rôles distincts d’un résultat d’outil : signaler qu’une ressource existe, et transmettre son contenu. Le protocole MCP sépare ces deux rôles depuis l’introduction du type de contenu resource_link dans un résultat d’outil tools/call.
La forme exacte d’un contenu resource_link

Un bloc resource_link à l’intérieur du tableau content d’un CallToolResult ressemble à ceci :
{
"type": "resource_link",
"uri": "https://exemple.fr/wp-json/wp/v2/posts/482",
"name": "Migrer un site Joomla vers WordPress",
"mimeType": "text/html",
"description": "Article publié le 12/03/2024, catégorie migration"
}
Aucun champ text, aucun contenu binaire encodé : uniquement une adresse et des indices pour que l’agent, ou l’humain derrière lui, choisisse de la suivre ou non. C’est la même forme qu’un lien hypertexte dans une page web, transposée au dialogue entre un serveur MCP et un agent.
Ce que gagne l’agent en fenêtre de contexte
La différence se mesure directement en jetons consommés. Un outil de recherche qui renvoie dix résultats sous forme de contenus complets peut facilement occuper vingt ou trente mille caractères dans la fenêtre de contexte, avant même que l’agent n’ait décidé lequel de ces dix résultats l’intéresse réellement. La même recherche, exprimée sous forme de dix blocs resource_link, tient en quelques centaines de caractères. L’agent parcourt la liste, repère le ou les éléments pertinents à leur titre et à leur description, puis ne demande le contenu complet que pour ceux-là, via un appel resources/read distinct.
Cette séparation a un effet secondaire appréciable : elle réduit aussi le nombre d’articles hors sujet que l’agent est tenté de résumer ou de citer, puisqu’il ne les a simplement pas lus en détail.
Un résultat d’outil n’a pas à prouver qu’il a bien lu un contenu ; il n’a qu’à prouver qu’il sait où ce contenu se trouve, et à laisser l’agent décider s’il vaut la peine d’aller le lire.
Un cas concret avec du code
Voici un outil MCP simplifié, écrit en PHP au sein d’une extension WordPress, qui expose une recherche d’articles sous forme de références plutôt que de contenus :
function wpmoderne_mcp_tool_search_posts( array $arguments ): array {
$query = new WP_Query( array(
's' => sanitize_text_field( $arguments['q'] ?? '' ),
'post_type' => 'post',
'posts_per_page' => 10,
) );
$links = array();
foreach ( $query->posts as $post ) {
$links[] = array(
'type' => 'resource_link',
'uri' => rest_get_route_for_post( $post ),
'name' => get_the_title( $post ),
'mimeType' => 'text/html',
'description' => wp_trim_words( $post->post_excerpt, 20 ),
);
}
return array( 'content' => $links );
}
Chaque élément du tableau content est autonome : l’agent peut afficher la liste à l’utilisateur, la trier, ou choisir d’ouvrir un seul de ces articles en appelant une ressource resources/read correspondant à l’URI fournie.
Quand ne pas s’en servir
Un contenu resource_link suppose que l’agent puisse effectivement rappeler resources/read sur l’URI fournie, ce qui exige que cette URI corresponde à une ressource réellement exposée par le serveur, pas à une simple adresse publique quelconque. Il suppose aussi un aller-retour supplémentaire : pour une tâche où l’agent a de toute façon besoin du contenu complet dans la foulée, par exemple relire intégralement un article avant de le corriger, transmettre directement le texte dans un bloc text évite un appel réseau inutile.
- Recherche ou liste de résultats où seule une minorité sera consultée en détail
- Réponses volumineuses dont le contenu complet dépasse ce que la tâche exige
- Contenus binaires ou trop lourds pour transiter dans une réponse JSON
À l’inverse, un outil qui renvoie une seule valeur courte, un statut, un identifiant ou un court message de confirmation n’a aucune raison d’emprunter ce format : la référence coûterait alors plus cher à interpréter que le contenu lui-même.
Conclusion
La différence entre un contenu et une référence à ce contenu paraît triviale une fois énoncée, mais elle change concrètement la facture de jetons d’un agent connecté à un site WordPress qui héberge des milliers d’articles. Concevoir un outil MCP en se demandant systématiquement « l’agent a-t-il besoin du contenu maintenant, ou seulement de savoir qu’il existe » évite de construire des résultats disproportionnés par rapport à la question posée.