anthropics / anthropics/claude-code
HTTP MCP server: \ in --header Authorization not consistently resolved across tool calls in the same session
- Lenguaje dominante
- Python
- Estrellas
- 145k
- Forks
- 23.1k
- Métricas de merge de PR
- Métricas de PR pendientes
Descripción
# Bug : en-tête `Authorization` d'un serveur MCP HTTP (`${VAR}`) non réinjecté de façon fiable entre appels d'outils
## Résumé
Un serveur MCP HTTP ajouté en scope `local` avec un en-tête `Authorization: Bearer ${VAR}`
(syntaxe d'expansion de variable d'environnement) ne voit son en-tête correctement résolu et
envoyé que sur le **premier** appel d'outil de la session. Les appels suivants dans la même
session échouent côté serveur avec une authentification refusée (401), alors que :
- la variable d'environnement est présente, stable et inchangée pendant toute la session ;
- le jeton qu'elle contient est valide, non expiré, non révoqué (vérifié côté serveur) ;
- un appel HTTP direct (hors Claude Code) utilisant exactement le même en-tête réussit à
chaque tentative, y compris juste après un échec via l'outil MCP.
Le défaut est donc isolé au client MCP de Claude Code : soit l'expansion `${VAR}` n'est
effectuée qu'une fois (par ex. à l'établissement de la connexion) puis n'est pas rejouée sur
les appels suivants, soit l'en-tête résolu n'est pas systématiquement réattaché à chaque
requête sortante du transport HTTP.
## Environnement
- Claude Code CLI : `2.1.222` (`claude --version`)
- Composant client MCP tel que rapporté par le serveur dans ses propres logs :
`claude-code 2.1.258` (chaîne `clientInfo` reçue lors du handshake `initialize`) — la
divergence de numéro avec `claude --version` n'a pas été creusée, elle vient peut-être d'un
composant versionné séparément.
- OS : Windows 11 Pro (10.0.26200), shell PowerShell / Git Bash.
- Serveur MCP : transport `http`, ajouté ainsi :
```bash
claude mcp add --transport http shiftcrm_recette https://crm-recette.shiftc.fr/mcp \
--header 'Authorization: Bearer ${SHIFTC_RECETTE_MCP_TOKEN}' \
--scope local
```
Config résultante (extrait de `~/.claude.json`, projet courant) :
```json
"shiftcrm_recette": {
"url": "https://crm-recette.shiftc.fr/mcp",
"headers": { "Authorization": "Bearer ${SHIFTC_RECETTE_MCP_TOKEN}" }
}
```
- `SHIFTC_RECETTE_MCP_TOKEN` : variable d'environnement **utilisateur** Windows (posée via
`[Environment]::SetEnvironmentVariable(name, value, "User")`), confirmée présente dans le
processus Claude Code après un redémarrage complet du client (`claude mcp list` ne remonte
plus d'avertissement « Missing environment variables » une fois la session relancée).
## Reproduction
1. Redémarrer entièrement Claude Code (fermeture complète, pas juste une nouvelle
conversation) après avoir posé/modifié la variable d'environnement portant le jeton.
2. Premier appel d'un outil du serveur MCP concerné (ici `cra_get_month`, qui déclenche côté
serveur un `GET /api/cra/months/2026-09`) → **succès**, réponse `200`, ~250-300 ms côté
serveur (chemin métier complet exécuté, confirmé dans les logs applicatifs).
3. Tout appel suivant du même outil, ou d'un autre outil du même serveur, dans la **même**
session (aucun redémarrage entre-temps, variable d'environnement inchangée) → **échec**,
`401` renvoyé par l'API, en 7-45 ms côté serveur (temps compatible avec un rejet précoce à
l'authentification, avant toute logique métier — voir « Isolation » ci-dessous).
4. Répété sur plusieurs cycles complets de redémarrage : le schéma se reproduit à chaque fois
— un seul appel réussi juste après le redémarrage, puis échec systématique des suivants.
## Isolation de la cause
Trois vérifications indépendantes écartent une cause côté jeton ou côté serveur ShiftCRM :
1. **Le jeton est valide.** Lecture directe en base (`assistant_accesses`) : `expires_at_utc`
à echéance normale (~90 jours), `revoked_at_utc` NULL au moment des échecs.
2. **L'appel direct est fiable à 100 %.** Plusieurs appels `curl` consécutifs, construits avec
le même en-tête `Authorization: Bearer $SHIFTC_RECETTE_MCP_TOKEN` (résolu par le shell, pas
par Claude Code), contre les mêmes routes (`GET /api/cra/months/2026-09`,
`PUT /api/cra/months/2026-09/entries/bulk`) → `200` à chaque tentative, y compris
immédiatement après un `401` obtenu via l'outil MCP avec, en théorie, le même jeton.
3. **Le relais serveur ne fait aucune mise en cache.** Le code source du conteneur `mcp`
(`CallerIdentityHandler.cs`) lit l'en-tête `Authorization` de la requête HTTP entrante
*à chaque requête* via `HttpContext.Request.Headers.Authorization` et le retransmet tel
quel vers l'API — aucune résolution de variable d'environnement ni aucun état conservé
entre deux appels côté serveur. Le serveur ShiftCRM se contente de refuser un en-tête reçu
invalide ou absent ; il n'invente rien.
Ces trois points convergent vers une seule explication plausible : le client Claude Code
n'envoie pas systématiquement, à chaque appel d'outil MCP de cette session, un en-tête
`Authorization` correctement résolu depuis `${SHIFTC_RECETTE_MCP_TOKEN}` — que ce soit parce
que l'expansion n'a lieu qu'une fois (à la connexion) et n'est pas rejouée, ou parce que la
requête sortante réutilise une configuration d'en-têtes capturée trop tôt sur une connexion
persistante.
## Impact
Ce comportement touche directement l'usage documenté et recommandé (y compris par
Anthropic) de `${VAR}` dans les en-têtes d'un serveur MCP HTTP pour éviter d'écrire un secret
en clair dans un fichier de configuration. Avec ce bug, n'importe quel serveur MCP HTTP
protégé par un jeton Bearer via variable d'environnement devient utilisable de façon
non fiable au-delà du tout premier appel d'une session — sans message d'erreur explicite
côté client (juste le rejet renvoyé par le serveur distant), ce qui rend le diagnostic difficile
pour qui n'a pas accès aux logs du serveur en question.
## Contournement utilisé
En l'absence de correctif, l'appel HTTP a été reproduit manuellement (même route, même
schéma de payload que l'outil MCP concerné, même jeton, avec une clé d'idempotence) plutôt
que de continuer à dépendre de l'outil MCP dans cette session.
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Línea de trabajo
Reproduce the issue with the documented `claude mcp add --transport http` command and repeated tool calls in one session. Inspect the HTTP MCP client path that expands `Authorization` headers and compare the first and subsequent outgoing requests; done means the resolved header is sent consistently and repeated calls no longer return 401, with a regression test covering the sequence.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- python
- Área
- api, authentication
- Tipo de issue
- Error
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Estado de actividad
- Activo
- Claridad
- Bastante claro
- Aptitud para principiantes
- 45/100