Installer des serveurs MCP dans Claude Code
Les commandes exactes, les trois portees, ou vivent les secrets, et quoi faire quand le serveur refuse de se connecter.
Temps de lecture : 15 min | Niveau : Intermediaire
Ce que tu sauras faire apres
- Ajouter un serveur MCP local ou distant avec la bonne commande.
- Choisir la portee locale, projet ou utilisateur selon ce que tu veux partager.
- Gerer tes secrets sans jamais les ecrire dans un fichier versionne.
- Verifier en trente secondes qu'un serveur est bien connecte.
- Diagnostiquer les erreurs les plus frequentes sans tatonner.
🧭 Les trois commandes que tu utiliseras 90 % du temps
claude mcp add --transport stdio <nom> -- <commande> [arguments...]
claude mcp add --transport http <nom> <url>
claude mcp listLe detail qui fait perdre une heure a tout le monde : le double tiret -- separe les options de Claude Code de la commande de ton serveur. Tout ce qui vient apres -- est passe au serveur sans modification.
# Le -- est obligatoire ici
claude mcp add --env VAR=value --transport stdio mon-serveur -- python server.py --port 8080Sans le --, Claude Code essaierait de lire --port 8080 comme une option a lui, et refuserait la commande.
Deuxieme piege, moins connu.
--envaccepte plusieurs pairesCLE=valeur. Si le nom du serveur arrive juste apres--env, la commande lit ce nom comme une paire de plus et le rejette. Place toujours au moins une autre option entre--envet le nom du serveur, par exemple--transport stdio.
Les quatre transports acceptes par --transport sont stdio, http, sse et ws. En pratique tu n'utiliseras que les deux premiers.
📦 Ajouter un serveur selon son transport
Serveur local (stdio)
Le serveur est un programme qui tourne sur ta machine. Claude Code le lance lui-meme.
# Forme de base
claude mcp add --transport stdio mon-serveur -- npx server.js
# Avec une variable d'environnement
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
-- npx -y airtable-mcp-server
# Avec des arguments pour le serveur
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
--dsn "postgresql://readonly:pass@prod.db.com:5432/analytics"Serveur distant (HTTP)
Le serveur tourne ailleurs, tu lui donnes une URL.
# Forme de base
claude mcp add --transport http notion https://mcp.notion.com/mcp
# Avec un en-tete d'authentification
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer YOUR_GITHUB_PAT"
# Plusieurs en-tetes
claude mcp add --transport http api https://api.example.com/mcp \
--header "Authorization: Bearer token" \
--header "X-API-Key: key"Le transport
sseexiste encore mais la doc le signale comme deprecie au profit dehttp.
Depuis une configuration JSON
Pratique quand un editeur te donne directement un bloc de configuration.
claude mcp add-json weather-api '{"type":"http","url":"https://api.weather.com/mcp"}'Depuis Claude Desktop
Si tu as deja configure des serveurs dans l'application de bureau :
claude mcp add-from-claude-desktop🗂️ Les trois portees : local, projet, utilisateur
C'est le choix qui structure tout. Pose-toi une seule question : qui doit avoir ce serveur ?
| Portee | Option | Charge dans | Partage avec l'equipe | Stockage |
|---|---|---|---|---|
| Local (defaut) | --scope local | Le projet courant seulement | Non | ~/.claude.json |
| Projet | --scope project | Le projet courant seulement | Oui, via Git | .mcp.json a la racine du projet |
| Utilisateur | --scope user | Tous tes projets | Non | ~/.claude.json |
# Local : par defaut, juste pour toi sur ce projet
claude mcp add --transport http stripe https://mcp.stripe.com
# Projet : partage via Git avec toute l'equipe
claude mcp add --transport http shared-server --scope project https://example.com/mcp
# Utilisateur : disponible dans tous tes projets
claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropicMa regle de decision pour un projet data :
- Le serveur qui expose l'entrepot de l'equipe : portee projet, pour que chaque collegue ait la meme configuration en clonant le depot.
- Ton serveur experimental en cours d'ecriture : portee locale, pour ne rien imposer aux autres.
- Un outil personnel que tu utilises partout (ta documentation, tes notes) : portee utilisateur.
Quand le meme serveur est defini a plusieurs endroits, Claude Code s'y connecte une seule fois. Il prend la definition de la source la plus prioritaire, en entier : les champs ne sont pas fusionnes entre portees.
L'ordre documente, du plus prioritaire au moins prioritaire :
- Portee locale
- Portee projet
- Portee utilisateur
- Serveurs fournis par un plugin
- Connecteurs claude.ai
Retiens le sens : ta portee locale gagne toujours. C'est voulu. Tu peux redefinir chez toi un serveur declare dans le .mcp.json de l'equipe sans toucher au depot.
📄 Le fichier .mcp.json
C'est le fichier a la racine du projet, celui que tu commites.
{
"mcpServers": {
"shared-server": {
"type": "http",
"url": "https://example.com/mcp"
},
"database-tools": {
"type": "stdio",
"command": "${CLAUDE_PROJECT_DIR}/servers/db-server",
"args": ["--config", "${CLAUDE_PROJECT_DIR}/config.json"],
"env": {
"DB_URL": "${DB_URL}"
}
}
}
}Attention a un piege signale dans la doc : un serveur HTTP qui a une url mais pas de type provoque une erreur. Ecris toujours "type": "http" (ou "sse", ou "ws").
Approbation des serveurs de projet
Un serveur declare en portee projet demande une approbation de confiance :
- En session interactive, tu es invite a approuver a la premiere utilisation.
- En session non interactive (
claude -p, Agent SDK, sessions cloud), Claude Code ne peut pas afficher l'invite : il charge les serveurs du projet sans rien demander. Souviens-toi-en avant de faire tourner unclaude -pdans une CI sur un depot que tu n'as pas relu. - Pour remettre a zero tes choix d'approbation :
claude mcp reset-project-choices. - Pour empecher un serveur du
.mcp.jsonde se charger quel que soit le mode : ajoute son nom dansdisabledMcpjsonServers.
🔐 Secrets et variables d'environnement
Regle absolue : aucun secret en clair dans .mcp.json, puisque ce fichier est versionne.
Claude Code sait developper des variables d'environnement dans ce fichier :
| Syntaxe | Effet |
|---|---|
${VAR} | Remplace par la valeur de la variable d'environnement |
${VAR:-defaut} | Utilise la valeur par defaut si la variable n'est pas definie |
${CLAUDE_PROJECT_DIR} | Racine stable du projet |
${CLAUDE_PLUGIN_ROOT} | Dossier d'installation du plugin |
${CLAUDE_PLUGIN_DATA} | Dossier de donnees persistantes du plugin |
Precision d'honnetete : la doc documente les trois derniers substituts de chemin dans la section consacree aux serveurs fournis par un plugin. Pour un
.mcp.jsonde projet ordinaire, ce qui est garanti c'est que Claude Code metCLAUDE_PROJECT_DIRdans l'environnement du serveur qu'il lance, a la racine du projet : ton code peut donc le lire lui-meme. Si${CLAUDE_PROJECT_DIR}ne se developpe pas chez toi, verifie avecclaude mcp get <nom>et replie-toi sur un chemin absolu. C'est d'ailleurs ce que fait le tutoriel officiel.
{
"mcpServers": {
"entrepot": {
"type": "stdio",
"command": "uv",
"args": ["--directory", "${CLAUDE_PROJECT_DIR}/mcp/entrepot", "run", "serveur.py"],
"env": {
"DATABASE_URL": "${ENTREPOT_DSN}"
}
}
}
}Chaque developpeur met ENTREPOT_DSN dans son propre environnement. Le depot ne contient que le nom de la variable.
La substitution marche dans command, args et env pour tous les serveurs, et dans url et headers pour les serveurs distants.
Le piege des variables de credentials
Detail important et facile a rater. Dans l'url et les headers d'un serveur distant, Claude Code lit certaines variables comme vides au lieu de les developper. Le but : empecher un .mcp.json ou un plugin d'envoyer tes identifiants a un serveur qu'il choisit lui-meme.
Les noms couverts, tels que la doc les decrit :
- Les identifiants de Claude Code, comme
ANTHROPIC_API_KEYetANTHROPIC_AUTH_TOKEN. - Les identifiants de ton fournisseur cloud, comme
AWS_BEARER_TOKEN_BEDROCK. - D'autres identifiants presents dans l'environnement, comme
HTTPS_PROXYetNPM_TOKEN.
Trois precisions qui comptent :
- Un nom couvert est vide que la variable soit definie ou non, et une valeur par defaut
${VAR:-defaut}sur ce nom est ignoree. - Le symptome typique est un
401: le serveur recoitBearersans rien derriere. Claude Code l'affiche comme une connexion en echec. - Une URL de base comme
ANTHROPIC_BASE_URLse developpe normalement.
Un nom qui n'est pas dans cet ensemble, par exemple API_KEY, se developpe normalement. Le contournement documente pour donner malgre tout un identifiant couvert au serveur : le recopier dans une variable dont tu choisis le nom.
# 1. Dans ton profil de shell, recopie le credential sous un nom a toi
export MON_JETON_API="$ANTHROPIC_AUTH_TOKEN"
# 2. Enregistre le serveur avec le PLACEHOLDER, pas la valeur.
# Les guillemets simples sont importants : ils empechent le shell
# de remplacer ${MON_JETON_API} avant que Claude Code le voie.
claude mcp add --transport http api \
--header 'Authorization: Bearer ${MON_JETON_API}' https://example.com/mcpLe principe general vaut pour tous tes serveurs distants : stocke le nom de la variable dans la configuration, jamais sa valeur. C'est ce qui te permet de commiter le fichier sans risque.
A ne pas confondre avec une autre regle, qui concerne le script
headersHelper(voir le fichier 06). Quand ce script vient d'un depot ou d'un plugin, Claude Code le lance sans les variables dont le nom ressemble a un credential : celles qui contiennentTOKEN,SECRET,PASSWORD,KEYouAUTH, dans n'importe quelle casse. Ce filtre-la porte sur l'environnement du script, pas sur la substitution dansurletheaders.
OAuth
Pour les serveurs qui utilisent OAuth :
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
claude mcp login sentry # lance le flux OAuth depuis le terminal
claude mcp login sentry --no-browser # affiche l'URL au lieu d'ouvrir le navigateur
claude mcp logout sentry # efface les identifiants stockesTu peux aussi restreindre les scopes demandes, ce qui est une bonne pratique de moindre privilege :
{
"mcpServers": {
"slack": {
"type": "http",
"url": "https://mcp.slack.com/mcp",
"oauth": {
"scopes": "channels:read chat:write search:read"
}
}
}
}✅ Verifier que ca marche
claude mcp list # liste tous les serveurs et leur statut
claude mcp get <nom> # details d'un serveur precis
claude mcp remove <nom> # retire un serveurDans une session Claude Code, tape /mcp pour ouvrir le panneau de gestion.
Les statuts documentes et ce qu'ils veulent dire :
| Statut | Signification | Action |
|---|---|---|
Connected | Le serveur fonctionne | Rien a faire |
Needs authentication | OAuth requis | claude mcp login <nom> |
Failed to connect | Erreur de connexion | Voir le depannage ci-dessous |
Pending approval | Serveur de portee projet que tu n'as pas encore approuve | Lance claude et approuve |
Rejected | Serveur du .mcp.json bloque par disabledMcpjsonServers | Retire-le de la liste si c'est une erreur |
Disabled for this project | Nom present dans disabledMcpServers du projet | Reactive via /mcp |
not configured | Serveur distant dont le champ url est vide | Renseigne l'url |
cached ... · connects on first use | Serveur HTTP dont la liste d'outils vient du cache de decouverte | Normal, rien a faire |
🛠️ Depannage
Les avertissements et erreurs que la documentation decrit, et ce qu'ils veulent dire :
| Message | Cause | Correction |
|---|---|---|
MCP server "<nom>" has a "url" but no "type" | Serveur distant sans type de transport | Ajoute "type": "http" (ou "sse", ou "ws") |
Skipped — ... declares type "sdk" | Entree "type": "sdk", reservee aux applications SDK | Retire l'entree, ce n'est pas une config Claude Code |
| Avertissement d'espace invisible | Espace en debut ou fin d'une valeur de configuration | Nettoie la valeur, souvent un jeton colle |
| Avertissement de variable manquante | ${VAR} non definie et sans valeur par defaut | Definis la variable ou ecris ${VAR:-defaut} |
| Avertissement de nom en double | Le meme nom de serveur dans deux portees avec deux URL differentes | Renomme, ou supprime la definition en trop |
| Nom reserve refuse | Noms reserves par Claude Code : workspace, claude-in-chrome, computer-use, Claude Preview, Claude Browser | Choisis un autre nom |
Deux pannes tres frequentes ne viennent pas de Claude Code mais de ta machine, et ne produisent donc pas de message particulier : la commande du serveur stdio n'existe pas ou ses dependances ne sont pas installees, et l'authentification du serveur distant a expire. Dans le premier cas, lance la commande du serveur a la main dans un terminal. Dans le second, refais claude mcp login <nom>.
La sequence de diagnostic que j'applique dans l'ordre :
claude mcp list # 1. le serveur est-il bien enregistre ?
claude mcp get mon-serveur # 2. quels sont ses parametres exacts ?
# 3. lancer la commande du serveur a la main dans le terminal
# pour voir ses erreurs sur stderr
claude mcp logout mon-serveur && claude mcp login mon-serveur # 4. si c'est de l'authDelais d'attente et taille des sorties
Utile quand un serveur interroge un entrepot lent. Toutes les valeurs sont en millisecondes.
| Variable | A quoi elle sert | Valeur par defaut |
|---|---|---|
MCP_TIMEOUT | Delai de demarrage du serveur | tres long (environ 28 heures) |
MCP_TOOL_TIMEOUT | Delai global par appel d'outil | tres long (environ 28 heures) |
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT | Duree sans reponse avant d'abandonner l'appel | 5 min en HTTP / SSE / WebSocket et pour les connecteurs, 30 min en stdio. 0 desactive |
CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS | Seuil de bascule automatique en arriere-plan | 2 min. 0 desactive |
MAX_MCP_OUTPUT_TOKENS | Taille de sortie avant sauvegarde sur disque | 25 000 tokens |
MCP_TOOL_TIMEOUT=600000 claude
MAX_MCP_OUTPUT_TOKENS=50000 claude
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT=900000 claudeContre-intuitif mais important : ce n'est presque jamais MCP_TOOL_TIMEOUT qui coupe ton appel, puisque son defaut est enorme. C'est le delai d'inactivite. Un serveur qui met huit minutes a repondre sans rien envoyer entre-temps sera coupe a la cinquieme minute en HTTP. C'est CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT qu'il faut augmenter.
Un delai par serveur peut aussi se mettre dans .mcp.json. Minimum 1000 ms. Il remplace MCP_TOOL_TIMEOUT et sert de plancher au delai d'inactivite :
{
"mcpServers": {
"slow-server": {
"type": "http",
"url": "https://example.com/mcp",
"timeout": 600000
}
}
}Sur les sorties : le seuil d'avertissement est a 10 000 tokens, la limite par defaut a 25 000 tokens. Au-dela, le resultat est sauvegarde dans un fichier du dossier tool-results de la session, sous ~/.claude/projects/, et le chemin apparait dans la conversation. Retiens-le pour la conception de tes outils : ne renvoie jamais 50 000 lignes de resultat SQL. Agrege, limite, pagine.
Si tu ecris toi-meme un serveur qui doit renvoyer un gros document (un schema complet, un manifest.json dbt), tu peux relever la limite outil par outil. Le serveur ajoute _meta["anthropic/maxResultSizeChars"] dans l'entree de l'outil renvoyee par tools/list. Le plafond dur est de 500 000 caracteres.
{
"name": "get_schema",
"description": "Returns the full database schema",
"_meta": {
"anthropic/maxResultSizeChars": 200000
}
}🧰 Des serveurs utiles quand tu fais de la data
Serveurs de reference officiels
Le depot modelcontextprotocol/servers maintient ces implementations de reference :
| Serveur | Ce qu'il fait |
|---|---|
| Filesystem | Operations sur les fichiers avec controles d'acces configurables |
| Git | Lire, chercher et manipuler des depots Git |
| Fetch | Recuperer et convertir du contenu web pour un usage efficace par le LLM |
| Memory | Memoire persistante basee sur un graphe de connaissances |
| Sequential Thinking | Resolution de probleme par sequences de pensees |
| Time | Conversion d'heure et de fuseau horaire |
| Everything | Serveur de demonstration avec prompts, resources et tools |
Attention : plusieurs serveurs qui trainent encore dans de vieux tutoriels (PostgreSQL, SQLite, GitHub, Slack, Google Drive, Puppeteer, Redis, Sentry...) ont ete deplaces dans un depot archive. Ne copie pas aveuglement une commande d'un article de blog de 2025.
Pour les autres, passe par le registre officiel : registry.modelcontextprotocol.io.
Exemples cites dans la doc Claude Code
# Base de donnees PostgreSQL, via un compte en lecture seule
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
--dsn "postgresql://readonly:pass@prod.db.com:5432/analytics"
# GitHub
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer YOUR_GITHUB_PAT"
# Notion, pour la documentation d'equipe
claude mcp add --transport http notion https://mcp.notion.com/mcp
# Sentry, pour les erreurs applicatives
claude mcp add --transport http sentry https://mcp.sentry.dev/mcpRemarque le readonly dans le DSN de l'exemple officiel. Ce n'est pas un detail decoratif, c'est la bonne pratique. Voir le fichier 06.
🔒 Restreindre ce qu'un serveur a le droit de faire
Les regles de permission de Claude Code nomment les outils MCP ainsi :
mcp__puppeteer: n'importe quel outil fourni par le serveurpuppeteermcp__puppeteer__*: la meme chose, avec la syntaxe jokermcp__puppeteer__puppeteer_navigate: l'outilpuppeteer_navigatede ce serveur
Pour tout refuser d'un coup :
{
"permissions": {
"deny": [
"mcp__*"
]
}
}Deux precisions documentees, utiles :
- Les regles allow n'acceptent un joker qu'apres un prefixe litteral
mcp__<serveur>__. Une regle comme"mcp__*"en allow est ignoree avec un avertissement. - Les outils des connecteurs que Claude Code recupere lui-meme apparaissent sous la forme
mcp__claude_ai_<serveur>__<outil>.
Desactiver des serveurs
Quatre reglages existent, et ils se ressemblent dangereusement. Voici ce qui les distingue.
| Reglage | Ce qu'il controle |
|---|---|
enabledMcpServers | Liste d'adhesion pour les serveurs integres desactives par defaut, comme computer-use |
disabledMcpServers | Liste d'exclusion pour les serveurs de ta configuration, ceux d'un plugin, ceux de ton organisation et les connecteurs claude.ai |
enabledMcpjsonServers | Approbation des serveurs declares dans le .mcp.json du projet |
disabledMcpjsonServers | Rejet des serveurs declares dans le .mcp.json du projet, dans tous les modes de permission |
La regle pour ne pas se tromper : les deux noms qui contiennent mcpjson parlent uniquement du fichier .mcp.json du projet. Les deux autres parlent de tout le reste.
{
"enabledMcpServers": ["computer-use"],
"disabledMcpServers": ["optional-server"],
"enabledMcpjsonServers": ["approved-server"],
"disabledMcpjsonServers": ["local-server"]
}Et pour n'utiliser que les serveurs passes explicitement en ligne de commande avec --mcp-config :
claude --strict-mcp-config --mcp-config ./ma-config.json📋 Templates prets a copier
Template 1 : ajouter un serveur de base de donnees en lecture seule
claude mcp add --scope [local|project|user] --transport stdio [NOM_DU_SERVEUR] \
-- npx -y @bytebase/dbhub \
--dsn "postgresql://[UTILISATEUR_LECTURE_SEULE]:[MOT_DE_PASSE]@[HOTE]:[PORT]/[BASE]"Template 2 : bloc .mcp.json sans secret en clair
{
"mcpServers": {
"[NOM_DU_SERVEUR]": {
"type": "stdio",
"command": "[COMMANDE]",
"args": ["[ARG_1]", "[ARG_2]"],
"env": {
"[NOM_DE_LA_VARIABLE]": "${[NOM_DE_LA_VARIABLE]}"
}
}
}
}Template 3 : bloc .mcp.json d'equipe pour un projet data
A commiter a la racine du depot. Chaque collegue ne renseigne que ses variables d'environnement.
{
"mcpServers": {
"[NOM_DU_SERVEUR_ENTREPOT]": {
"type": "stdio",
"command": "[CHEMIN_ABSOLU_VERS_UV_OU_PYTHON]",
"args": ["--directory", "[CHEMIN_ABSOLU_DU_DOSSIER_SERVEUR]", "run", "[FICHIER_SERVEUR].py"],
"env": {
"[NOM_VARIABLE_DSN]": "${[NOM_VARIABLE_DSN]}",
"[NOM_VARIABLE_SCHEMA_AUTORISE]": "${[NOM_VARIABLE_SCHEMA_AUTORISE]:-[SCHEMA_PAR_DEFAUT]}"
},
"timeout": [DELAI_EN_MS]
},
"[NOM_DU_SERVEUR_DISTANT]": {
"type": "http",
"url": "[URL_DU_SERVEUR]",
"oauth": {
"scopes": "[SCOPE_1] [SCOPE_2]"
}
}
}
}A mettre dans le README du depot, en face :
Avant de lancer Claude Code sur ce projet, definis :
- [NOM_VARIABLE_DSN] = chaine de connexion du compte LECTURE SEULE [NOM_DU_COMPTE]
- [NOM_VARIABLE_SCHEMA_AUTORISE] = [LISTE_DES_SCHEMAS_AUTORISES]
Ne mets jamais ces valeurs dans le depot.Template 4 : demander de l'aide a Claude Code sur une panne MCP
Mon serveur MCP [NOM_DU_SERVEUR] ne se connecte pas.
Contexte :
- Transport : [stdio ou http]
- Commande ou URL : [COMMANDE_OU_URL]
- Portee : [local / project / user]
- Systeme : [Windows / macOS / Linux]
Voici la sortie de `claude mcp get [NOM_DU_SERVEUR]` :
[COLLER_LA_SORTIE]
Voici ce que j'obtiens quand je lance la commande du serveur a la main :
[COLLER_LA_SORTIE_D_ERREUR]
Aide-moi a identifier si le probleme vient du transport ou de la configuration.
Propose-moi les trois hypotheses les plus probables, classees, avec la commande
exacte pour tester chacune.A retenir
- Trois commandes suffisent :
claude mcp add --transport stdio|http,claude mcp list,/mcp. - Le
--separe les options de Claude Code de la commande du serveur. Oublie frequente. Et ne colle jamais le nom du serveur juste apres--env. - Priorite des portees, du plus fort au plus faible : locale, projet, utilisateur, plugin, connecteurs claude.ai. Ta portee locale gagne toujours.
- La portee projet (
.mcp.json) sert a partager avec l'equipe via Git. Jamais de secret dedans : utilise${VARIABLE}. - Les identifiants connus de Claude Code et du cloud (
ANTHROPIC_API_KEY,NPM_TOKEN...) ne sont pas developpes dans l'urlet lesheaders. Recopie-les dans une variable dont tu choisis le nom. - En session non interactive (
claude -p), les serveurs du.mcp.jsonse chargent sans approbation. - Limite les sorties de tes outils : la limite par defaut est de 25 000 tokens, avec un avertissement des 10 000.
- Quand un outil est coupe, c'est presque toujours le delai d'inactivite, pas
MCP_TOOL_TIMEOUT. - Les regles de permission s'ecrivent
mcp__<serveur>__<outil>.