Définir des ressources
Mis à jour le 30 juillet 2026
Notre serveur expose des outils ; passons à la deuxième primitive MCP. Les ressources permettent d’exposer des données aux clients, similairement aux gestionnaires de requêtes GET dans un serveur HTTP : une adresse, des données en retour, aucun effet de bord. Elles sont idéales pour récupérer des informations plutôt que d’effectuer des actions — la frontière exacte qui les sépare des outils, et qu’il faut garder nette dans la conception d’un serveur.
Comprendre les ressources
Les ressources sont des endpoints en lecture seule qui peuvent renvoyer tout type de données : chaînes, JSON, fichiers binaires. Vous définissez un mime_type pour indiquer au client le type de données renvoyé — c’est ce qui lui permettra, comme nous l’avons vu côté client, de parser du JSON ou de transmettre du texte brut sans deviner.
L’adressage fonctionne via des URI — essentiellement des adresses, dont le schéma est libre : nos documents vivront sous docs://. Quand un client a besoin de données, il envoie une ReadResourceRequest avec l’URI spécifique, et le serveur route la demande vers la fonction correspondante.
Deux types de ressources
| Type | URI | Description |
|---|---|---|
| Directe | docs://documents | URI statique sans paramètre |
| Modèle (template) | docs://documents/{doc_id} | URI avec paramètres |
La ressource directe est une adresse fixe — toujours la même donnée de retour, ici la liste des documents. La ressource à modèle couvre une famille entière d’adresses avec une seule définition : docs://documents/report.pdf, docs://documents/plan.md, et toute autre valeur de doc_id. Pour ces ressources à modèle, le SDK parse automatiquement les paramètres de l’URI et les passe comme arguments à votre fonction — même confort que les décorateurs d’outils, appliqué à l’adressage.
Implémentation
Nos deux ressources, une de chaque type :
@mcp.resource(
"docs://documents",
mime_type="application/json"
)
def list_docs() -> list[str]:
return list(docs.keys())
@mcp.resource(
"docs://documents/{doc_id}",
mime_type="text/plain"
)
def fetch_doc(doc_id: str) -> str:
if doc_id not in docs:
raise ValueError(f"Document avec l'id {doc_id} introuvable")
return docs[doc_id]
Le pattern décorateur vous est familier depuis les outils : la fonction fait le travail, le décorateur déclare l’adresse et le format. Notez la correspondance obligatoire entre le paramètre de l’URI ({doc_id}) et celui de la fonction (doc_id: str) — c’est elle qui permet l’injection automatique. La garde d’entrée reste de rigueur : un identifiant inconnu lève une erreur explicite plutôt qu’un obscur échec de dictionnaire. Et un confort à connaître : le SDK sérialise automatiquement ce que vous renvoyez — la liste Python de list_docs devient du JSON sans conversion manuelle.
Tester avec l’inspecteur
Le réflexe de validation ne change pas : mcp dev et l’inspecteur. Celui-ci sépare les ressources directes des ressources à modèle en deux sections — pour ces dernières, l’interface propose de saisir les paramètres avant l’appel. Cliquez sur n’importe quelle ressource pour la tester et voir la structure exacte de la réponse ; testez aussi un doc_id inexistant pour vérifier que l’erreur remonte proprement.
Cas d’usage
Le registre d’emploi des ressources est large mais cohérent : fournir des données d’auto-complétion (listes de documents), récupérer le contenu de fichiers ou d’enregistrements de base de données, exposer des données de configuration — et plus généralement servir toute information en lecture seule. Le fil conducteur : les ressources permettent aux clients de récupérer proactivement des données sans passer par les outils, donc sans mobiliser Claude. C’est ce qui les rend idéales pour des fonctionnalités comme les mentions de documents — l’objet de la prochaine leçon côté client : l’application ira chercher la liste pour l’autocomplétion, puis le contenu du document choisi, en deux lectures de ressources.
Points clés à retenir
- Les ressources sont les GET de MCP : lecture seule, aucun effet de bord — les actions restent aux outils
- Adressage par URI ; le
mime_typeannonce le format au client (JSON parsé, texte brut…) - Directe = adresse fixe ; modèle = famille d’adresses, paramètres injectés automatiquement dans la fonction
- Le SDK sérialise les retours tout seul — renvoyez vos structures Python telles quelles
- L’inspecteur teste les deux types, paramètres compris — y compris les cas d’erreur