docs: publish translated docs in twelve languages and the tool that maintains them (#3280)
This commit is contained in:
parent
14aa889992
commit
52ad0a8876
5 changed files with 89737 additions and 54 deletions
144
i18n/fr/pages/get-started/first-steps.md
Normal file
144
i18n/fr/pages/get-started/first-steps.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
---
|
||||
translation:
|
||||
sections: [0d6c05bcbf836bf3, 59a7b14eeefc68c1, 7114d8d6daba203f, e8bbb56a98ba7bc9, 5138010f6159901c, f78da7c7c363d4c6, 220a939cab348686]
|
||||
tool: 1
|
||||
---
|
||||
# Premiers pas {#first-steps}
|
||||
|
||||
La **[page d’accueil](../index.md)** va vite : écrire un serveur, l’exécuter, appeler un outil.
|
||||
|
||||
Cette page prend son temps, avec les trois choses qu’un serveur peut exposer, et un nom pour chaque notion rencontrée en chemin.
|
||||
|
||||
## Hôte, client et serveur {#host-client-and-server}
|
||||
|
||||
Trois mots que vous verrez sur chaque page à partir d’ici :
|
||||
|
||||
* Un **hôte** est l’application LLM : Claude, un IDE, un environnement d’exécution d’agents. C’est ce à quoi l’utilisateur parle.
|
||||
* Un **client** vit à l’intérieur de l’hôte et parle MCP. L’hôte exécute un client par serveur auquel il est connecté.
|
||||
* Un **serveur** est ce que vous construisez avec ce SDK. Il expose des choses aux clients. Il ne parle jamais directement au modèle.
|
||||
|
||||
Vous écrivez le serveur. Les hôtes sont le produit de quelqu’un d’autre. Le SDK vous fournit aussi un `Client`. Vous l’utiliserez pour tester vos serveurs, et il apparaît plus loin sur cette page.
|
||||
|
||||
## Les trois primitives {#the-three-primitives}
|
||||
|
||||
Un serveur expose exactement trois sortes de choses. Ce qui les distingue, c’est **qui décide de les utiliser** :
|
||||
|
||||
| Primitive | Contrôlée par | Ce que c’est | Exemple |
|
||||
|----------------|-----------------|----------------------------------------------------------------------|------------------------------------------------|
|
||||
| **Outils** | Le modèle | Une fonction que le modèle appelle pour agir | Un appel d’API, une écriture en base de données |
|
||||
| **Ressources** | L’application | Des données que l’hôte charge dans le contexte du modèle | Le contenu d’un fichier, une réponse d’API |
|
||||
| **Prompts** | L’utilisateur | Un modèle de message réutilisable que l’utilisateur invoque par son nom | Une commande slash, une entrée de menu |
|
||||
|
||||
« Contrôlée par » est tout l’intérêt de la distinction. Un outil s’exécute parce que le **modèle** a décidé de l’appeler. Une ressource est jointe parce que l’**application** a décidé que le modèle en avait besoin. Un prompt s’exécute parce que l’**utilisateur** l’a choisi.
|
||||
|
||||
!!! info
|
||||
Si vous avez déjà construit une API web, vous avez l’essentiel de l’intuition : une **ressource** est un `GET`
|
||||
(elle charge des données et ne modifie rien) et un **outil** est un `POST` (il effectue un travail et peut avoir
|
||||
des effets de bord). Un **prompt** n’a pas d’équivalent HTTP ; il se rapproche d’une requête enregistrée que
|
||||
l’utilisateur exécute par son nom.
|
||||
|
||||
## Un serveur, les trois à la fois {#one-server-all-three}
|
||||
|
||||
```python title="server.py" hl_lines="6 12 18"
|
||||
--8<-- "docs_src/first_steps/tutorial001.py"
|
||||
```
|
||||
|
||||
Trois fonctions ordinaires, trois décorateurs. Chaque décorateur constitue à lui seul tout l’enregistrement :
|
||||
|
||||
* `@mcp.tool()` fait de `add` un **outil**.
|
||||
* `@mcp.resource("greeting://{name}")` fait de `greeting` un **modèle de ressource** (resource template) : le `{name}` dans l’URI est le paramètre de la fonction.
|
||||
* `@mcp.prompt()` fait de `summarize` un **prompt**. La chaîne qu’il renvoie devient un message utilisateur.
|
||||
|
||||
Tout le reste (le nom, la description, le schéma des arguments), le SDK le lit dans la fonction elle-même : son nom, sa docstring, ses annotations de type. Vous n’avez rien déclaré de tout cela séparément.
|
||||
|
||||
!!! tip
|
||||
Les deux moitiés du SDK ont deux chemins d’import : `from mcp import Client` et
|
||||
`from mcp.server import MCPServer`. Il n’existe pas de `from mcp import MCPServer`.
|
||||
|
||||
### Essayer {#try-it}
|
||||
|
||||
Lancez-le avec le MCP Inspector :
|
||||
|
||||
```console
|
||||
uv run mcp dev server.py
|
||||
```
|
||||
|
||||
Ouvrez l’URL qu’il affiche. L’Inspector a un onglet par primitive ; parcourez-les dans l’ordre.
|
||||
|
||||
**Tools.** Une entrée : `add`, décrite comme *Add two numbers.* Le formulaire comporte un champ entier obligatoire pour `a` et un autre pour `b`. Remplissez-les, lancez l’appel, et le résultat est `3`. L’Inspector a construit ce formulaire à partir de `a: int, b: int`. Tous les autres clients font de même.
|
||||
|
||||
**Resources.** La liste *Resources* est vide. `greeting` se trouve sous **Resource Templates**, parce que `greeting://{name}` a un paramètre : il n’y a aucune ressource unique à lister tant que personne n’a fourni de `name`. Donnez-lui `World` et lisez-la :
|
||||
|
||||
```text
|
||||
Hello, World!
|
||||
```
|
||||
|
||||
**Prompts.** Une entrée : `summarize`, avec un seul argument obligatoire, `text`. Récupérez-le avec un peu de texte et vous recevez un message avec `role: user` et votre chaîne rendue comme contenu. Un prompt n’est rien d’autre que cela : une fonction qui construit des messages.
|
||||
|
||||
L’Inspector a exécuté votre serveur via **stdio**, l’un des transports qu’un serveur MCP peut parler. Vous n’en choisissez pas encore un ; **[Exécuter votre serveur](../run/index.md)** est la page consacrée à ce sujet.
|
||||
|
||||
## Capacités {#capabilities}
|
||||
|
||||
Vous avez vu trois onglets dans l’Inspector. Comment savait-il qu’il y en avait trois ?
|
||||
|
||||
Lorsqu’un client se connecte, le serveur déclare ses **capacités** (capabilities) : les familles de requêtes auxquelles il répondra. Le client utilise cette déclaration pour décider de ce qu’il peut même demander. Vous ne l’avez jamais écrite ; `MCPServer` la déclare pour vous.
|
||||
|
||||
Regardez par vous-même. Le `Client` du SDK accepte directement l’objet serveur et s’y connecte **en mémoire** (ni sous-processus, ni port) :
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
|
||||
from mcp import Client
|
||||
|
||||
from server import mcp
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
async with Client(mcp) as client:
|
||||
print(client.server_capabilities.model_dump(exclude_none=True))
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
```text
|
||||
{'prompts': {'list_changed': True}, 'resources': {'subscribe': True, 'list_changed': True}, 'tools': {'list_changed': True}}
|
||||
```
|
||||
|
||||
Ce dictionnaire, ce sont les **capacités** déclarées de votre serveur. C’est la première chose qu’apprend chaque client qui se connecte :
|
||||
|
||||
| Capacité | Le client peut désormais appeler |
|
||||
|-------------|---------------------------------------------------------------|
|
||||
| `tools` | `tools/list`, `tools/call` |
|
||||
| `resources` | `resources/list`, `resources/templates/list`, `resources/read` |
|
||||
| `prompts` | `prompts/list`, `prompts/get` |
|
||||
|
||||
`MCPServer` sert les trois primitives, donc les trois sont toujours déclarées.
|
||||
|
||||
Remarquez ce qui n’y figure pas. `completions` (la complétion automatique des arguments pour les modèles de ressources et les prompts) nécessite un gestionnaire que vous écrivez ; ce serveur n’en a pas, donc la capacité est absente et un client bien élevé ne demandera rien. C’est la règle pour tout ce qui est facultatif : enregistrez la chose et la capacité apparaît ; **[Complétions](../servers/completions.md)** le prouve.
|
||||
|
||||
!!! info
|
||||
`Client(mcp)` est le même client en mémoire avec lequel chaque exemple de cette documentation est testé, et
|
||||
c’est ainsi que vous testerez les vôtres. Il a droit à une page entière : **[Tester](testing.md)**.
|
||||
|
||||
## Ce que vous n’avez pas écrit {#what-you-did-not-write}
|
||||
|
||||
Reprenez cette page depuis le début. Vous avez écrit trois petites fonctions Python. Vous n’avez **pas** écrit :
|
||||
|
||||
* De JSON Schema. `a: int, b: int` *est* le schéma de `add`.
|
||||
* De gestionnaire de requêtes. `tools/list`, `resources/read`, `prompts/get` : tous servis pour vous.
|
||||
* De déclaration de capacités. `MCPServer` l’a faite pour vous.
|
||||
* Une seule ligne de protocole. La négociation de version, l’encapsulation JSON-RPC, l’échange de capacités : tout cela s’est passé à l’intérieur de `mcp dev` et de `Client(mcp)`, et vous n’en avez rien vu.
|
||||
|
||||
Ce rapport est tout l’intérêt du SDK.
|
||||
|
||||
## Récapitulatif {#recap}
|
||||
|
||||
* Un **hôte** est l’application LLM, un **client** est sa moitié qui parle MCP, un **serveur** est ce que vous construisez.
|
||||
* Les outils sont contrôlés par le **modèle**, les ressources par l’**application**, les prompts par l’**utilisateur**.
|
||||
* Un décorateur par primitive : `@mcp.tool()`, `@mcp.resource(uri)`, `@mcp.prompt()`. Le nom, la description et le schéma viennent de la fonction.
|
||||
* Un URI avec un `{param}` crée un **modèle** de ressource, listé séparément des ressources concrètes.
|
||||
* Les **capacités** du serveur sont déclarées pour vous, et un client ne demande que ce qu’un serveur déclare.
|
||||
* `Client(mcp)` se connecte à l’objet serveur en mémoire : votre banc d’essai dès le premier jour.
|
||||
|
||||
La suite, c’est **[Se connecter à un vrai hôte](real-host.md)** : ce serveur dans Claude Desktop ou un IDE, pour de vrai. Puis **[Tester](testing.md)** : une page, un client en mémoire, et vous n’aurez plus jamais à deviner si cela fonctionne. Ensuite, chaque primitive a droit à sa propre page, en commençant par celle que pilote le modèle : **[Outils](../servers/tools.md)**.
|
||||
57
i18n/fr/pages/get-started/index.md
Normal file
57
i18n/fr/pages/get-started/index.md
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
translation:
|
||||
sections: [ed4a756b4c53c585, 97e2fb315b7fe398, 4d04f1c6f4bf6c1d, 577d73078fc62baf]
|
||||
tool: 1
|
||||
---
|
||||
# Prise en main {#get-started}
|
||||
|
||||
Vous débutez avec MCP, ou avec ce SDK ? Commencez ici. Ces pages vous mènent de zéro à un
|
||||
serveur fonctionnel et testé : [installez le SDK](installation.md), construisez votre
|
||||
[premier serveur](first-steps.md), [connectez-le à un hôte réel](real-host.md) et
|
||||
[testez-le](testing.md) avec un client en mémoire.
|
||||
|
||||
## Exécuter le code {#run-the-code}
|
||||
|
||||
Tous les blocs de code peuvent être copiés et utilisés tels quels : ce sont des fichiers complets et fonctionnels.
|
||||
|
||||
Pour suivre, collez un bloc dans un fichier `server.py` et ouvrez-le dans le MCP Inspector :
|
||||
|
||||
```console
|
||||
uv run mcp dev server.py
|
||||
```
|
||||
|
||||
Il est **FORTEMENT recommandé** d’écrire (ou de copier) le code, de le modifier et de l’exécuter localement. C’est en l’utilisant dans votre propre éditeur que vous en saisirez vraiment l’intérêt : le peu de code à écrire, l’autocomplétion, les vérifications de type qui détectent les erreurs avant même que vous n’exécutiez quoi que ce soit.
|
||||
|
||||
## Vous n’aurez pas à deviner {#you-will-not-be-guessing}
|
||||
|
||||
Chaque exemple de cette documentation est un fichier complet sous [`docs_src/`](https://github.com/modelcontextprotocol/python-sdk/tree/main/docs_src) dans le dépôt du SDK lui-même, et chacun d’eux est exécuté par la suite de tests du SDK via un **client en mémoire** :
|
||||
|
||||
```python
|
||||
import pytest
|
||||
from mcp import Client
|
||||
|
||||
from server import mcp
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_add() -> None:
|
||||
async with Client(mcp) as client:
|
||||
result = await client.call_tool("add", {"a": 1, "b": 2})
|
||||
assert result.structured_content == {"result": 3}
|
||||
```
|
||||
|
||||
Aucun sous-processus, aucun port, aucun transport. `Client(mcp)` se connecte directement à l’objet serveur.
|
||||
|
||||
Si une modification du SDK casse un exemple de l’une de ces pages, la CI passe au rouge avant la page. Le code que vous lisez ici est le code qui s’exécute.
|
||||
|
||||
Vous l’utiliserez vous-même dans [Tester](testing.md) ; c’est aussi ainsi que vous testez vos propres serveurs.
|
||||
|
||||
## Où aller ensuite {#where-to-go-next}
|
||||
|
||||
Une fois qu’un serveur tourne, le reste de cette documentation est une référence, pas un cours.
|
||||
Chaque page se suffit à elle-même, alors allez directement à ce dont vous avez besoin :
|
||||
|
||||
* Ce qu’un serveur expose (outils, ressources, prompts), c’est **[Serveurs](../servers/index.md)**.
|
||||
* Ce qui est disponible dans les fonctions que vous enregistrez, c’est **[Dans votre gestionnaire](../handlers/index.md)**.
|
||||
* Le mettre à disposition des clients (stdio, HTTP, votre application FastAPI existante), c’est **[Exécuter votre serveur](../run/index.md)**.
|
||||
* Construire l’autre côté, une application qui *utilise* des serveurs MCP, c’est **[Clients](../client/index.md)**.
|
||||
47
i18n/fr/pages/get-started/installation.md
Normal file
47
i18n/fr/pages/get-started/installation.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
translation:
|
||||
sections: [6e2f9bab94d5ed36, 8cf653388f69e28b, 6fd9ea2f65de0df6]
|
||||
tool: 1
|
||||
---
|
||||
# Installation {#installation}
|
||||
|
||||
Le SDK Python est disponible sur PyPI sous le nom [`mcp`](https://pypi.org/project/mcp/). Il nécessite **Python 3.10+**.
|
||||
|
||||
Cette documentation décrit la **v2**, la ligne de versions stable actuelle :
|
||||
|
||||
=== "uv"
|
||||
|
||||
```bash
|
||||
uv add "mcp[cli]"
|
||||
```
|
||||
|
||||
=== "pip"
|
||||
|
||||
```bash
|
||||
pip install "mcp[cli]"
|
||||
```
|
||||
|
||||
!!! note "Vous venez de la v1 ?"
|
||||
La v2 est une version majeure avec des changements incompatibles ; le **[Guide de migration](../migration.md)**
|
||||
les couvre tous. Si votre *paquet* dépend de `mcp` et n’est pas prêt à migrer, conservez une
|
||||
borne supérieure `<2` (par exemple `mcp>=1.28,<2`) pour qu’une résolution sans version épinglée reste sur la ligne 1.x.
|
||||
|
||||
## Ce qui est installé {#what-gets-installed}
|
||||
|
||||
Vous n’avez pas besoin de connaître tout cela pour utiliser le SDK, mais si vous vous demandez à quoi sert chaque dépendance :
|
||||
|
||||
* `mcp-types` : tous les types du protocole (requêtes, résultats, blocs de contenu) dans un paquet à part, versionné au même rythme que le SDK. Le code qui dépend de `mcp` l’importe via l’alias `mcp.types` (tous les `from mcp.types import ...` de cette documentation) ; n’importez `mcp_types` directement que dans un projet qui installe `mcp-types` sans le SDK.
|
||||
* [`anyio`](https://anyio.readthedocs.io/) : le runtime asynchrone. Tout le SDK est écrit au-dessus d’anyio, il fonctionne donc aussi bien avec `asyncio` qu’avec `trio`.
|
||||
* [`pydantic`](https://docs.pydantic.dev/) : la base de tous les modèles `mcp.types`, ainsi que toute la génération et la validation de schémas.
|
||||
* [`httpx2`](https://pypi.org/project/httpx2/) : le client HTTP derrière les transports *client* Streamable HTTP et SSE, avec prise en charge intégrée des server-sent events.
|
||||
* [`starlette`](https://www.starlette.io/), [`uvicorn`](https://www.uvicorn.org/), [`sse-starlette`](https://pypi.org/project/sse-starlette/) et [`python-multipart`](https://pypi.org/project/python-multipart/) : les transports HTTP *serveur*.
|
||||
* [`jsonschema`](https://pypi.org/project/jsonschema/) : valide la sortie structurée d’un outil par rapport au schéma de sortie qu’il déclare.
|
||||
* [`pyjwt[crypto]`](https://pyjwt.readthedocs.io/) : gestion des jetons OAuth pour l’autorisation.
|
||||
* [`opentelemetry-api`](https://opentelemetry-python.readthedocs.io/) : l’API légère uniquement, de sorte que le middleware de traçage du SDK ne coûte rien tant que vous n’installez pas vous-même un SDK OpenTelemetry et un exporteur.
|
||||
* [`typing-extensions`](https://typing-extensions.readthedocs.io/) et [`typing-inspection`](https://pypi.org/project/typing-inspection/) : les fonctionnalités de typage modernes sous Python 3.10.
|
||||
* [`pywin32`](https://pypi.org/project/pywin32/) : Windows uniquement, utilisé pour la gestion des sous-processus `stdio`.
|
||||
|
||||
## Extras optionnels {#optional-extras}
|
||||
|
||||
* `mcp[cli]` ajoute [`typer`](https://typer.tiangolo.com/) et [`python-dotenv`](https://pypi.org/project/python-dotenv/) pour l’outil en ligne de commande `mcp` (`mcp dev`, `mcp run`, `mcp install`). Vous en aurez besoin pendant le développement ; vous pouvez vous en passer sur un serveur déployé.
|
||||
* `mcp[rich]` ajoute [`rich`](https://rich.readthedocs.io/) pour des journaux de serveur plus lisibles.
|
||||
186
i18n/fr/pages/get-started/real-host.md
Normal file
186
i18n/fr/pages/get-started/real-host.md
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
---
|
||||
translation:
|
||||
sections: [3c4f2f06b4e978b6, 22520eecae3d1961, f4e1709db18d635a, 2eb57992049671d9, 1ba83e9af37cc1b4, 4822586344b08d9e, 1c93afef72478992, b6b448f9eddd51dc, fe55370fd931815b]
|
||||
tool: 1
|
||||
---
|
||||
# Se connecter à un véritable hôte {#connect-to-a-real-host}
|
||||
|
||||
Un **hôte** est l’application dans laquelle votre serveur finit par vivre : Claude Desktop, Claude Code, un IDE. L’hôte est ce à quoi l’utilisateur parle. À l’intérieur, un **client** MCP lance votre serveur comme processus enfant et lui parle via le stdin et le stdout de ce processus.
|
||||
|
||||
Se connecter à un hôte se résume donc à un seul geste : vous lui indiquez **la commande qui démarre votre serveur**. Tout ce qui figure sur cette page (deux commandes CLI, trois fichiers JSON) n’est qu’un endroit différent où placer cette même commande.
|
||||
|
||||
## Un serveur, tous les hôtes {#one-server-every-host}
|
||||
|
||||
```python title="server.py" hl_lines="3 33-34"
|
||||
--8<-- "docs_src/real_host/tutorial001.py"
|
||||
```
|
||||
|
||||
Deux outils et une ressource, un seul fichier. Trois points concernant ce fichier comptent pour chaque hôte ci-dessous :
|
||||
|
||||
* `mcp.run()` sans argument démarre un serveur **stdio** : il bloque, lit les messages du protocole sur stdin et les écrit sur stdout. C’est le transport que parlent tous les hôtes de cette page. L’hôte démarre votre fichier comme processus enfant et possède ces deux tubes, c’est pourquoi se connecter ne revient jamais qu’à « voici la commande ». Vous ne choisissez jamais de port, et rien n’écoute sur un port.
|
||||
* `run()` est placé sous `if __name__ == "__main__":`. Tout ce qui suit **importe** ce fichier au lieu de l’exécuter ; un `run()` non protégé démarrerait donc un serveur dès que quoi que ce soit chargerait le module.
|
||||
* L’objet serveur est une variable globale de niveau module nommée `mcp`. C’est le nom que `mcp run` recherche (`server` et `app` fonctionnent aussi). Si vous l’appelez autrement, vous le nommez explicitement : `mcp run server.py:bookshop`.
|
||||
|
||||
C’est la dernière ligne de Python de cette page. À partir d’ici, tout n’est que configuration d’hôte.
|
||||
|
||||
## La commande de lancement {#the-launch-command}
|
||||
|
||||
Chaque hôte ci-dessous reçoit la même commande :
|
||||
|
||||
```bash
|
||||
uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py
|
||||
```
|
||||
|
||||
Une seule commande pour tous, parce que `uv run --with` résout le SDK dans un environnement neuf, à la volée : elle fonctionne depuis n’importe quel répertoire et n’a besoin d’aucun projet ni d’aucun environnement virtuel à activer. Cela compte ici plus qu’ailleurs, car un hôte lance votre serveur depuis *son* répertoire de travail avec un environnement presque vide, et non depuis votre shell.
|
||||
|
||||
C’est aussi la commande que `mcp install` écrit pour vous dans la configuration de Claude Desktop (ci-dessous) : ce que vous tapez à la main et ce que l’outil génère concordent, à l’exception de l’épinglage de version exact que l’outil ajoute.
|
||||
|
||||
!!! tip "Si un hôte ne trouve pas `uv`"
|
||||
Un hôte lance votre serveur avec un `PATH` minimal, et `uv` n’y figure peut-être pas.
|
||||
Remplacez le `uv` seul par le chemin absolu donné par `which uv` (macOS/Linux) ou `where uv`
|
||||
(Windows). C’est exactement ce qu’écrit `mcp install`.
|
||||
|
||||
!!! note "Cette page traite du cas local"
|
||||
Tout ici exécute votre serveur sur la machine où se trouve l’hôte : l’hôte lance votre
|
||||
fichier, via stdio. C’est exactement ce qu’il faut pour un outil personnel ou limité à une
|
||||
seule machine. Pour mettre un serveur à disposition de personnes qui n’ont *pas* votre
|
||||
fichier, vous distribuez une **URL**, pas une commande : le même objet `mcp`, servi via
|
||||
Streamable HTTP. **[Exécuter votre serveur](../run/index.md)** résume cette décision en un
|
||||
tableau, et **[Déployer et passer à l’échelle](../run/deploy.md)** est le chemin qui mène de
|
||||
là à un véritable nom d’hôte.
|
||||
|
||||
Et un hôte n’est rien de plus qu’une application contenant un client MCP ; votre propre
|
||||
code Python peut donc jouer le rôle de l’hôte : **[Transports du client](../client/transports.md)**
|
||||
lance ce même fichier comme sous-processus avec `stdio_client(...)`, et **[Tests](testing.md)**
|
||||
s’y connecte en mémoire, sans aucun processus.
|
||||
|
||||
## Claude Desktop {#claude-desktop}
|
||||
|
||||
Le seul hôte que le SDK peut configurer pour vous :
|
||||
|
||||
```bash
|
||||
uv run mcp install server.py
|
||||
```
|
||||
|
||||
C’est tout. `mcp install` importe le fichier pour lire le nom du serveur, trouve le fichier de configuration de Claude Desktop et y écrit la commande de lancement. Au passage, il convertit votre chemin en chemin absolu, pour que vous n’ayez pas à le faire.
|
||||
|
||||
Il n’y a là rien de mystérieux. Voici l’entrée qu’il écrit :
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"Bookshop": {
|
||||
"command": "/absolute/path/to/uv",
|
||||
"args": [
|
||||
"run",
|
||||
"--frozen",
|
||||
"--with",
|
||||
"mcp[cli]==2.0.0",
|
||||
"mcp",
|
||||
"run",
|
||||
"/absolute/path/to/server.py"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
C’est la commande de lancement de la section précédente avec trois ajouts : le chemin absolu vers `uv`, `--frozen` pour que `uv` ne réécrive jamais un fichier de verrouillage qui se trouverait à proximité, et un épinglage exact de la version de `mcp` que vous avez installée. Elle atterrit dans `claude_desktop_config.json`, qui se trouve ici :
|
||||
|
||||
* **macOS** : `~/Library/Application Support/Claude/claude_desktop_config.json`
|
||||
* **Windows** : `%APPDATA%\Claude\claude_desktop_config.json`
|
||||
|
||||
Vous pouvez écrire ce fichier à la main. `mcp install` existe pour vous éviter l’erreur classique (un chemin relatif) en le faisant.
|
||||
|
||||
Quittez complètement Claude Desktop (pas seulement sa fenêtre), puis rouvrez-le.
|
||||
|
||||
!!! warning
|
||||
`mcp install` échoue avec `Claude app not found` si le *répertoire* de configuration de
|
||||
Claude Desktop n’existe pas encore. Installez Claude Desktop et lancez-le une fois : c’est
|
||||
ce qui crée le répertoire.
|
||||
|
||||
!!! tip
|
||||
Claude Desktop démarre votre serveur dans son propre processus ; les variables
|
||||
d’environnement de votre shell n’y sont donc pas. `uv run mcp install server.py -v API_KEY=abc123`
|
||||
(ou `-f .env`) les enregistre dans le champ `env` de l’entrée. `--name` remplace le nom de
|
||||
l’entrée ; par défaut, c’est le `name` du serveur.
|
||||
|
||||
## Claude Code {#claude-code}
|
||||
|
||||
Il n’y a aucun fichier à modifier. Enregistrez le serveur avec la CLI `claude` ; tout ce qui suit `--` est la commande de lancement.
|
||||
|
||||
```bash
|
||||
claude mcp add bookshop -- uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py
|
||||
```
|
||||
|
||||
Exécutez `/mcp` dans une session Claude Code pour confirmer que `bookshop` est connecté et que ses outils sont listés.
|
||||
|
||||
## Cursor {#cursor}
|
||||
|
||||
Créez `.cursor/mcp.json` à la racine de votre projet.
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"bookshop": {
|
||||
"command": "uv",
|
||||
"args": ["run", "--with", "mcp[cli]", "mcp", "run", "/absolute/path/to/server.py"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Les mêmes `command` et `args`, sous la même clé `mcpServers` que celle qu’utilise Claude Desktop. Le serveur apparaît dans les paramètres MCP de Cursor avec les deux outils listés.
|
||||
|
||||
## VS Code {#vs-code}
|
||||
|
||||
Créez `.vscode/mcp.json` à la racine de votre projet.
|
||||
|
||||
```json
|
||||
{
|
||||
"servers": {
|
||||
"bookshop": {
|
||||
"type": "stdio",
|
||||
"command": "uv",
|
||||
"args": ["run", "--with", "mcp[cli]", "mcp", "run", "/absolute/path/to/server.py"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Deux différences avec le fichier de Cursor, et ce sont les deux seules : la clé englobante est `servers`, et non `mcpServers`, et chaque entrée déclare son `type`. Acceptez la demande de confiance, puis **MCP: List Servers** dans la palette de commandes affiche `bookshop` en cours d’exécution.
|
||||
|
||||
!!! note
|
||||
Il vous faut VS Code 1.99 ou ultérieur avec l’extension **GitHub Copilot** connectée
|
||||
(Copilot Free suffit), et Copilot Chat doit être en mode **Agent**, car aucun autre mode
|
||||
n’appelle d’outils.
|
||||
|
||||
## Le serveur n’apparaît pas {#it-doesnt-show-up}
|
||||
|
||||
Avant de toucher à la moindre configuration d’hôte, exécutez vous-même la commande de lancement :
|
||||
|
||||
```bash
|
||||
uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py
|
||||
```
|
||||
|
||||
Rien ne s’affiche, et la commande ne rend pas la main. Ce silence est normal : un serveur stdio attend qu’un hôte parle en premier sur stdin (`Ctrl-C` pour l’arrêter). Une trace d’erreur ou une sortie immédiate, voilà le vrai bogue, et vous pouvez désormais le lire au lieu de le deviner à travers un hôte.
|
||||
|
||||
Une fois que cette commande se contente d’attendre, ce qui reste est presque toujours l’une de ces trois causes :
|
||||
|
||||
* **Un chemin relatif.** L’hôte lance votre serveur depuis *son* répertoire de travail, pas depuis celui d’où vous l’avez enregistré. `server.py` là où il faut `/absolute/path/to/server.py` est, de loin, l’échec le plus fréquent. Si l’hôte ne trouve pas `uv` non plus, ce chemin doit lui aussi être absolu.
|
||||
* **L’hôte utilise encore son ancienne configuration.** Les hôtes lisent leur configuration au démarrage. Claude Desktop, en particulier, doit être *complètement quitté* (pas seulement sa fenêtre fermée) puis rouvert avant qu’une modification de `claude_desktop_config.json` prenne effet.
|
||||
* **Quelque chose a atteint stdout en dehors de la fenêtre de redirection.** En stdio, stdout *est* le protocole. Le SDK redirige vers stderr la sortie parasite vidée pendant qu’il sert, mais une sortie vidée sur stdout avant cela (un script d’enrobage qui fait un echo, un `print()` à l’import dans un processus sans tampon), ou un `print()` mis en tampon et vidé à la sortie de l’interpréteur, remet à l’hôte un message corrompu et celui-ci coupe la connexion. Journalisez avec la configuration `logging` par défaut, dont le gestionnaire stderr vide chaque enregistrement ; les gestionnaires personnalisés doivent eux aussi éviter stdout. Tous les détails sont dans **[Journalisation](../handlers/logging.md)**.
|
||||
|
||||
Claude Desktop tient un journal par serveur : `mcp-server-<NAME>.log` est le stderr de votre serveur, à côté de `mcp.log` pour les connexions, sous `~/Library/Logs/Claude` sur macOS et `%APPDATA%\Claude\logs` sur Windows.
|
||||
|
||||
Pour tout ce qui dépasse ces trois cas, la page à consulter est **[Dépannage](../troubleshooting.md)**.
|
||||
|
||||
## Récapitulatif {#recap}
|
||||
|
||||
* Un **hôte** (Claude Desktop, un IDE) exécute un client MCP qui lance votre serveur comme processus enfant via stdio. Se connecter, c’est lui donner une commande de lancement.
|
||||
* Cette commande est `uv run --with "mcp[cli]" mcp run /absolute/path/to/server.py` : aucun venv à activer, elle fonctionne depuis n’importe quel répertoire.
|
||||
* **Claude Desktop** est le seul hôte que `mcp install` configure pour vous. Il écrit cette même commande (plus le chemin absolu vers `uv`, `--frozen` et un épinglage exact de la version que vous avez installée) dans `claude_desktop_config.json`, pour que vous n’ayez jamais à le faire.
|
||||
* **Claude Code**, c’est `claude mcp add bookshop -- <launch command>`. **Cursor**, c’est `.cursor/mcp.json` sous `mcpServers`. **VS Code**, c’est `.vscode/mcp.json` sous `servers`, chaque entrée avec un `type`.
|
||||
* Des chemins absolus partout, redémarrez l’hôte après avoir modifié sa configuration, et ne laissez jamais rien d’autre que le SDK écrire sur stdout.
|
||||
|
||||
Tous les hôtes de cette page se sont connectés au même fichier, avec la même commande. Ce que ce fichier peut *exposer*, c’est le reste de cette documentation : **[Outils](../servers/tools.md)**, **[Ressources](../servers/resources.md)**, et tous les transports autres que stdio dans **[Exécuter votre serveur](../run/index.md)**.
|
||||
117
i18n/fr/pages/get-started/testing.md
Normal file
117
i18n/fr/pages/get-started/testing.md
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
---
|
||||
translation:
|
||||
sections: ['4926721070127497', c52a1de2b6b32f40, 2e410b412c25f314, 627195f7159e24ef]
|
||||
tool: 1
|
||||
---
|
||||
# Tests {#testing}
|
||||
|
||||
Le SDK Python fournit une classe `Client` dotée d’un **transport en mémoire** : passez-lui votre objet serveur et il s’y connecte directement.
|
||||
|
||||
Pas de sous-processus. Pas de port. Pas de transport du tout. C’est la même idée que le `TestClient` de FastAPI.
|
||||
|
||||
## Utilisation de base {#basic-usage}
|
||||
|
||||
Supposons que vous ayez un serveur simple avec un seul outil (tool) :
|
||||
|
||||
```python title="server.py"
|
||||
--8<-- "docs_src/testing/tutorial001.py"
|
||||
```
|
||||
|
||||
Pour exécuter le test ci-dessous, vous aurez besoin de deux dépendances (de développement) supplémentaires :
|
||||
|
||||
=== "uv"
|
||||
|
||||
```bash
|
||||
uv add --dev pytest inline-snapshot
|
||||
```
|
||||
|
||||
=== "pip"
|
||||
|
||||
```bash
|
||||
pip install pytest inline-snapshot
|
||||
```
|
||||
|
||||
!!! info
|
||||
Cette documentation suppose que vous connaissez déjà [`pytest`](https://docs.pytest.org/en/stable/).
|
||||
|
||||
[`inline-snapshot`](https://15r10nk.github.io/inline-snapshot/latest/) est ce que le test
|
||||
ci-dessous utilise pour vérifier l’objet résultat entier en une seule ligne. Il enregistre la
|
||||
sortie d’un test sous la forme du littéral `snapshot(...)` que vous voyez. Si vous préférez vous
|
||||
en passer, supprimez l’import et vérifiez les champs qui vous intéressent
|
||||
(`result.content[0].text == "3"`) comme dans n’importe quel autre test.
|
||||
|
||||
Voici maintenant le test :
|
||||
|
||||
```python title="test_server.py"
|
||||
import pytest
|
||||
from inline_snapshot import snapshot
|
||||
from mcp import Client
|
||||
from mcp.types import CallToolResult, TextContent
|
||||
|
||||
from server import mcp
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def anyio_backend(): # (1)!
|
||||
return "asyncio"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def client(): # (2)!
|
||||
async with Client(mcp, raise_exceptions=True) as c:
|
||||
yield c
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_call_add_tool(client: Client):
|
||||
result = await client.call_tool("add", {"a": 1, "b": 2})
|
||||
# Drop the server identity stamp in `_meta`; it is not what this test is about.
|
||||
result.meta = None
|
||||
assert result == snapshot(
|
||||
CallToolResult(
|
||||
content=[TextContent(type="text", text="3")],
|
||||
structured_content={"result": 3},
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
1. Si vous utilisez `trio`, renvoyez `"trio"` à la place. Consultez la [documentation d’anyio](https://anyio.readthedocs.io/en/stable/testing.html#specifying-the-backends-to-run-on) pour les détails.
|
||||
2. La fixture produit un client connecté. Chaque test qui prend `client` en paramètre obtient une nouvelle connexion en mémoire vers le même serveur.
|
||||
|
||||
Et voilà. Vous pouvez maintenant étendre vos tests pour couvrir davantage de scénarios.
|
||||
|
||||
## Pourquoi `raise_exceptions=True` ? {#why-raise_exceptionstrue}
|
||||
|
||||
Deux choses différentes peuvent mal tourner, et cet indicateur n’en concerne qu’une seule.
|
||||
|
||||
Une exception dans l’un de **vos outils** n’est pas un échec du protocole. Elle devient un résultat
|
||||
normal avec `is_error=True`, et le modèle lit le message. `raise_exceptions` n’y change rien : avec
|
||||
ou sans lui, `call_tool` renvoie le même résultat `is_error=True`. Une page entière y est
|
||||
consacrée : **[Gérer les erreurs](../servers/handling-errors.md)**.
|
||||
|
||||
Un échec **en dehors** du corps d’un outil est différent. Sur la connexion que vous donne
|
||||
`Client(mcp)`, le serveur le neutralise en un `"Internal server error"` générique avant que le
|
||||
client ne le voie. Vous ne devriez jamais divulguer les détails d’un plantage inattendu à un
|
||||
appelant distant. Dans un test, c’est exactement ce que vous ne voulez *pas*, et c’est ce que
|
||||
change `raise_exceptions=True` : votre test voit le vrai message au lieu de la version neutralisée.
|
||||
|
||||
Laissez-le activé dans les tests. Il n’a aucun sens dans du code de production.
|
||||
|
||||
## Dans le processus par défaut {#in-process-by-default}
|
||||
|
||||
!!! note
|
||||
`Client(mcp)` se connecte dans le processus et est **neutre vis-à-vis de la génération du
|
||||
protocole** par défaut : il sonde le serveur et choisit le chemin de protocole approprié. Fixez
|
||||
`mode="legacy"` si votre test exerce une sémantique propre aux connexions historiques (push
|
||||
d’échantillonnage (sampling) ou d’élicitation (elicitation), `message_handler`), et retirez alors
|
||||
`raise_exceptions=True` : une connexion historique ne neutralise jamais rien, et l’indicateur
|
||||
relève l’échec dans la tâche du serveur plutôt que dans votre test.
|
||||
|
||||
Cette unique ligne est aussi la raison pour laquelle cette documentation peut vous promettre que
|
||||
ses exemples fonctionnent : chaque fichier d’exemple est exercé par la propre suite de tests du
|
||||
SDK, presque tous via ce client précisément. Vous utilisez le même outil que le SDK utilise sur
|
||||
lui-même.
|
||||
|
||||
Vous avez un serveur qui fonctionne et qui est testé. L’intégrer dans une véritable application
|
||||
(Claude Desktop, un IDE), c’est **[Se connecter à un hôte réel](real-host.md)** ; toutes les autres
|
||||
manières de le servir sont dans **[Exécuter votre serveur](../run/index.md)**.
|
||||
Loading…
Reference in a new issue