Définir des ressources MCP
Sur cette page
Les ressources constituent la deuxième primitive du protocole. Elles permettent à un serveur MCP d’exposer des données aux clients, de façon comparable aux handlers GET d’un serveur HTTP classique : on demande quelque chose par son adresse, on reçoit un contenu, et rien n’est modifié au passage. Cette parenté n’est pas qu’une image pédagogique : elle indique le bon terrain d’emploi des ressources, à savoir les scénarios où vous avez besoin de récupérer des informations plutôt que d’effectuer des actions. À la fin de cette leçon, vous saurez déclarer une ressource directe et une ressource avec template, annoncer leur type de contenu, et les tester dans l’inspecteur.
Le besoin concret derrière la primitive
Prenons un cas que vous avez déjà vu dans d’autres interfaces. Vous voulez construire une fonctionnalité de mention de documents, où l’utilisateur tape @nom_du_document pour référencer un fichier. Cette petite fonctionnalité demande en réalité deux opérations distinctes : obtenir la liste de tous les documents disponibles, afin d’alimenter l’autocomplétion pendant la frappe, puis récupérer le contenu d’un document précis une fois qu’il a été mentionné.
Le point décisif se joue à la seconde opération. Quand un utilisateur mentionne un document, votre système injecte automatiquement son contenu dans le prompt envoyé à Claude — sans que Claude ait besoin d’utiliser des outils pour récupérer l’information. Le modèle reçoit le texte déjà présent dans sa fenêtre de contexte, comme si l’utilisateur l’avait collé lui-même.
Mécaniquement, les ressources suivent un modèle requête-réponse familier. Quand votre client a besoin de données, il envoie une ReadResourceRequest accompagnée d’un URI qui identifie la ressource souhaitée ; le serveur MCP traite cette requête et retourne les données dans un ReadResourceResult. Vous reconnaissez la convention de nommage croisée dans la première partie du cours.
Ressources directes et ressources avec templates
Les ressources directes ont des URIs statiques qui ne changent jamais. Elles conviennent aux opérations sans paramètres, typiquement celle qui répond à la question « qu’est-ce qui existe ? » :
@mcp.resource(
"docs://documents",
mime_type="application/json"
)
def list_docs() -> list[str]:
return list(docs.keys())
Cette ressource répond à l’URI docs://documents et retourne la liste des identifiants, exactement ce dont l’autocomplétion a besoin. Les ressources avec templates, elles, incluent des paramètres dans leurs URIs. Le SDK Python analyse automatiquement ces paramètres et les passe comme arguments mot-clé à votre fonction, ce qui vous évite tout travail de parsing :
from mcp.server.mcpserver.exceptions import ResourceError
@mcp.resource(
"docs://documents/{doc_id}",
mime_type="text/plain"
)
def fetch_doc(doc_id: str) -> str:
if doc_id not in docs:
raise ResourceError(f"Document avec l'id {doc_id} introuvable")
return docs[doc_id]
Le segment {doc_id} de l’URI devient le paramètre doc_id de la fonction. Le contrôle d’existence suit la même logique que pour les outils, avec l’exception dédiée du SDK : nous l’avons vérifié sur la version 2.3.0, une ValueError remonte au client comme une erreur opaque (« Error creating resource from template docs://documents/… »), alors qu’une ResourceError transmet votre message. Côté client, l’erreur arrive sous forme d’une exception MCPError.
Déclarer le type de contenu
Les ressources peuvent retourner n’importe quel type de données. Le paramètre mime_type sert à indiquer aux clients à quoi s’attendre, et donc comment interpréter ce qu’ils reçoivent.
| mime_type | Usage |
|---|---|
"application/json" | Données structurées |
"text/plain" | Texte brut |
"application/pdf" | Fichiers binaires |
Le SDK MCP Python sérialise automatiquement vos valeurs de retour. Dans l’exemple list_docs, vous retournez une liste Python et non une chaîne JSON : il n’y a aucune conversion manuelle à écrire, il suffit de retourner la structure de données et de laisser le SDK s’en occuper.
Tester ce que vous venez d’écrire
L’inspecteur reste votre boucle de vérification la plus courte :
uv run mcp dev mcp_server.py
Une fois connecté, l’onglet Resources distingue deux groupes : URIs liste vos ressources directes, Templates vos ressources paramétrées. Cliquez sur list_docs : l’inspecteur envoie resources/read et affiche le JSON renvoyé, le type MIME annoncé et l’heure de lecture, avec un bouton Refresh.
docs://documents renvoie la liste des identifiants en application/json, sérialisée par le SDK à partir d'une simple liste Python.Pour une ressource avec template, l’inspecteur demande d’abord une valeur pour chaque paramètre de l’URI (« Still needed: doc_id ») avant d’activer Read Resource :
doc_id saisi devient l'URI docs://documents/plan.md, lu en text/plain.Ce qui distingue une ressource d’un outil
Le tableau suivant résume les quatre différences à garder en tête au moment de choisir la primitive adaptée.
| Ressource | Outil |
|---|---|
| Lecture seule | Peut modifier l’état |
| Contrôlée par l’application | Contrôlé par Claude |
| Contexte pré-chargé | Exécuté à la demande |
| URI statique ou paramétré | Schéma d’arguments |
Les ressources offrent donc un moyen propre d’exposer des données en lecture seule depuis votre serveur MCP, et rendent la récupération d’informations plus simple qu’un appel d’outil. Reste à les consommer côté client : c’est l’objet de la leçon suivante.
À vous de jouer
- Ajoutez les deux ressources au serveur, relancez
mcp dev mcp_server.pyet lisez-les toutes les deux dans l’inspecteur ; vérifiez le type MIME affiché pour chacune. - Ajoutez une ressource directe
docs://statsenapplication/jsonqui renvoie, pour chaque document, sa longueur en caractères. Combien de lignes de code ? - Demandez
docs://documents/inconnu.mddans l’inspecteur, d’abord avecValueError, puis avecResourceError: comparez les messages.
Sources officielles : Defining resources (Claude Academy) · Concepts côté serveur : ressources · Client web de l’Inspector : Resources
Points clés à retenir
- Une ressource expose une donnée en lecture seule par URI, comme un GET : on la lit, rien n’est modifié.
- Ressource directe (URI fixe,
docs://documents) pour « qu’est-ce qui existe ? » ; ressource avec template (docs://documents/{doc_id}) pour « donne-moi celui-ci », le paramètre devenant un argument de la fonction. mime_typedit au client comment interpréter le contenu ; le SDK sérialise vos listes et dictionnaires.- Levez
ResourceErrorpour une erreur lisible ; l’inspecteur sépare URIs et Templates et demande les paramètres avant de lire.