> ## Content Index
> Fetch the complete content index at: https://www.sfeir.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# 7 pannes de serveur MCP qui ressemblent à des bugs OAuth
- URL: https://www.sfeir.dev/ia/serveur-mcp-production-pannes-oauth/
- Published: 2026-10-20T12:46:38.000Z
- Updated: 2026-10-20T12:46:38.000Z
- Description: invalid_client intermittent, clients déconnectés, 500 sur /authorize, 403 Cloud Run : 7 pannes de serveur MCP en production et leur vraie cause.
- Author: Baptiste PIRAULT
- Tags: IA, MCP, Agent IA, Agentic

# Serveur MCP en production : ces pannes qui ressemblent à des bugs d'authentification

[](https://github.com/batou9150/writing-workspace/blob/main/blog/drafts/3%5FMCP%2C%20les%20pannes%20qui%20ressemblent%20%C3%A0%20des%20bugs%20d'auth%20%28FR%29.md?ref=sfeir.dev#serveur-mcp-en-production--ces-pannes-qui-ressemblent-%C3%A0-des-bugs-dauthentification)

Faire fonctionner un serveur MCP sur son poste prend une heure. Le faire tenir en production, derrière OAuth, sur un runtime autoscalé comme **Cloud Run**, prend nettement plus longtemps. Et la plupart des incidents que j'ai rencontrés partagent une signature trompeuse : ils se présentent comme des erreurs d'authentification alors que la cause est opérationnelle. Résultat, on débogue la mauvaise couche. Voici les pannes que j'ai vécues, avec leur symptôme exact et leur vraie cause.

## Panne 1 : erreurs `invalid_client` intermittentes et reconnexion après chaque déploiement

[](https://github.com/batou9150/writing-workspace/blob/main/blog/drafts/3%5FMCP%2C%20les%20pannes%20qui%20ressemblent%20%C3%A0%20des%20bugs%20d'auth%20%28FR%29.md?ref=sfeir.dev#panne-1--erreurs-invalid%5Fclient-intermittentes-et-reconnexion-apr%C3%A8s-chaque-d%C3%A9ploiement)

**Symptôme :** un utilisateur se connecte, son client fonctionne, puis échoue au rafraîchissement du token avec un `invalid_client` ou un `401 Unauthorized`. Une minute plus tard, cela remarche. Et après chaque déploiement, tous les clients doivent se reconnecter.

**Cause :** le stockage par défaut des clients OAuth de la bibliothèque (ici FastMCP) était un fichier sur le disque local. Sur Cloud Run, ce disque est éphémère et propre à chaque instance : selon l'instance qui recevait la requête, le client enregistré existait ou non, et un déploiement effaçait tout.

**Correctif :** un store partagé, externe à l'instance (Firestore, Redis, base SQL), avec les tokens amont chiffrés. Attention : le passage du protocole en mode stateless avec la révision `2026-07-28` ne concerne pas cet état-là. La spécification a cessé de gérer les sessions de transport ; vos enregistrements OAuth n'en ont jamais fait partie, et un serveur "stateless" a toujours besoin d'un store partagé pour eux.

## Panne 2 : tous les clients MCP déconnectés d'un coup après une rotation de secret

[](https://github.com/batou9150/writing-workspace/blob/main/blog/drafts/3%5FMCP%2C%20les%20pannes%20qui%20ressemblent%20%C3%A0%20des%20bugs%20d'auth%20%28FR%29.md?ref=sfeir.dev#panne-2--tous-les-clients-mcp-d%C3%A9connect%C3%A9s-dun-coup-apr%C3%A8s-une-rotation-de-secret)

**Symptôme :** un matin, tous les clients connectés reçoivent `invalid_token` et doivent se réauthentifier. Aucun déploiement de code la veille.

**Cause :** la bibliothèque dérivait la clé de signature des tokens à partir du secret du client OAuth amont. Ce secret avait été tourné. Aucun lien visible entre la cause (une rotation de secret, considérée comme une bonne pratique) et l'effet (une déconnexion générale).

**Correctif :** une clé de signature **dédiée et épinglée** dans Secret Manager, indépendante de tout autre secret. Et un déchiffrement des tokens stockés qui, en cas d'échec, traite l'entrée comme absente (nouvelle authentification) plutôt que de lever une exception qui produit un `500`.

## Panne 3 : la collection de stockage OAuth est vide

[](https://github.com/batou9150/writing-workspace/blob/main/blog/drafts/3%5FMCP%2C%20les%20pannes%20qui%20ressemblent%20%C3%A0%20des%20bugs%20d'auth%20%28FR%29.md?ref=sfeir.dev#panne-3--la-collection-de-stockage-oauth-est-vide)

**Symptôme :** pour diagnostiquer la panne 1, j'inspecte les enregistrements dans la collection Firestore configurée. Elle est vide, alors que les clients fonctionnent.

**Cause :** la bibliothèque codait en dur ses noms de collection tout en semblant honorer le paramètre de configuration. L'état existait, ailleurs.

**Correctif :** vérifier l'emplacement **réellement** utilisé, pas celui configuré. Une lecture du code source de la bibliothèque aurait évité une demi-journée.

## Panne 4 : `500 Internal Server Error` sur `/authorize` pour certains clients seulement

[](https://github.com/batou9150/writing-workspace/blob/main/blog/drafts/3%5FMCP%2C%20les%20pannes%20qui%20ressemblent%20%C3%A0%20des%20bugs%20d'auth%20%28FR%29.md?ref=sfeir.dev#panne-4--500-internal-server-error-sur-authorize-pour-certains-clients-seulement)

**Symptôme :** la plupart des clients MCP se connectent ; deux d'entre eux reçoivent une erreur 500 à l'autorisation. Les logs montrent une erreur de clé de stockage (`lacks a collection id`, clé illégale).

**Cause :** ces clients utilisaient déjà les **Client ID Metadata Documents** (CIMD) : leur `client_id` est une URL (`https://app.example.com/oauth/client.json`). Le store clé-valeur interprétait les `/` de la clé comme des séparateurs de chemin. Et l'erreur sortait en 500 plutôt qu'en erreur OAuth, car le chemin de gestion d'erreur relisait le même client et échouait à nouveau.

**Correctif :** assainir les clés de stockage (hash ou encodage). Avec la dépréciation de Dynamic Client Registration dans la révision `2026-07-28`, un `client_id` en forme d'URL devient la norme, pas l'exception.

## Panne 5 : correctif OAuth déployé, mais le client MCP renvoie toujours la même erreur

[](https://github.com/batou9150/writing-workspace/blob/main/blog/drafts/3%5FMCP%2C%20les%20pannes%20qui%20ressemblent%20%C3%A0%20des%20bugs%20d'auth%20%28FR%29.md?ref=sfeir.dev#panne-5--correctif-oauth-d%C3%A9ploy%C3%A9-mais-le-client-mcp-renvoie-toujours-la-m%C3%AAme-erreur)

**Symptôme :** je corrige une erreur `invalid_scope: Client was not registered with scope email`, je déploie, le client renvoie exactement la même erreur.

**Cause :** le client avait mis en cache un `client_id` obtenu **avant** le correctif, et les droits accordés étaient stockés côté serveur pour ce `client_id`. Les nouveaux enregistrements fonctionnaient ; l'ancien ne pouvait plus fonctionner. C'est la panne qui m'a coûté le plus de temps sur l'ensemble du projet.

**Correctif :** vérifier côté serveur et côté client séparément. Enregistrer un client neuf exactement comme le fait le CLI (`curl -X POST .../register`) ; si cela fonctionne, vider le cache OAuth du client (`codex mcp logout`, fichiers `~/.copilot/mcp-oauth-config/`, "Clear authentication" dans le menu `/mcp` de Claude Code). La révision `2026-07-28` va dans le même sens en imposant aux clients d'indexer leurs identifiants par **issuer** et de se réenregistrer si celui-ci change. Les clients qui ne le font pas vous présentent le problème comme un bug de votre serveur.

## Panne 6 : la révision Cloud Run ne démarre pas (`Permission denied on secret`)

[](https://github.com/batou9150/writing-workspace/blob/main/blog/drafts/3%5FMCP%2C%20les%20pannes%20qui%20ressemblent%20%C3%A0%20des%20bugs%20d'auth%20%28FR%29.md?ref=sfeir.dev#panne-6--la-r%C3%A9vision-cloud-run-ne-d%C3%A9marre-pas-permission-denied-on-secret)

**Symptôme :** le déploiement échoue, la nouvelle révision ne reçoit jamais de trafic. Rien dans les logs applicatifs. Seuls les logs de la révision indiquent `Permission denied on secret`.

**Cause :** un nouveau secret avait été ajouté, mais le compte de service d'exécution n'avait pas le rôle `roles/secretmanager.secretAccessor` dessus. Une policy vide sur un seul secret suffit à empêcher le démarrage.

**Correctif :** accorder l'accès à chaque nouveau secret dans le même changement qui l'introduit (idéalement en Terraform), et lire les logs de révision avant les logs applicatifs.

## Panne 7 : `403` en HTML sur `/.well-known/oauth-authorization-server` après un redéploiement

[](https://github.com/batou9150/writing-workspace/blob/main/blog/drafts/3%5FMCP%2C%20les%20pannes%20qui%20ressemblent%20%C3%A0%20des%20bugs%20d'auth%20%28FR%29.md?ref=sfeir.dev#panne-7--403-en-html-sur-well-knownoauth-authorization-server-apr%C3%A8s-un-red%C3%A9ploiement)

**Symptôme :** du jour au lendemain, plus aucun client ne peut se connecter. Les endpoints de découverte et `/register` répondent `403` avec une page HTML Google.

**Cause :** un redéploiement sans `--allow-unauthenticated` a retiré le binding IAM `allUsers` → `roles/run.invoker`. Cloud Run bloque alors les requêtes avant votre code, alors que votre serveur MCP gère lui-même l'authentification OAuth.

**Correctif :** réaffirmer ce binding dans la CI à chaque déploiement, et faire échouer le job si un `403` persiste sur `/.well-known/oauth-protected-resource`.

## Deux fuites qui ne cassent rien

[](https://github.com/batou9150/writing-workspace/blob/main/blog/drafts/3%5FMCP%2C%20les%20pannes%20qui%20ressemblent%20%C3%A0%20des%20bugs%20d'auth%20%28FR%29.md?ref=sfeir.dev#deux-fuites-qui-ne-cassent-rien)

Ces deux-là ne provoquent aucune panne, ce qui les rend plus dangereuses :

- **Les codes OAuth dans les access logs.** Un serveur qui journalise la ligne de requête complète écrit `code=` et `state=` dans Cloud Logging. Ce sont des identifiants à usage unique, mais ils n'ont rien à faire là. Masquez-les.
- **Le niveau de log livré.** Un `LOG_LEVEL=DEBUG` oublié dans un Dockerfile a envoyé des documents entiers dans les logs cloud. Vérifiez la valeur réellement déployée, pas celle de votre `.env`.

## Le tableau de diagnostic

[](https://github.com/batou9150/writing-workspace/blob/main/blog/drafts/3%5FMCP%2C%20les%20pannes%20qui%20ressemblent%20%C3%A0%20des%20bugs%20d'auth%20%28FR%29.md?ref=sfeir.dev#le-tableau-de-diagnostic)

| Symptôme                                                           | Cause probable                                         |
| ------------------------------------------------------------------ | ------------------------------------------------------ |
| invalid\_client intermittent, reconnexion après chaque déploiement | État OAuth sur disque local, runtime autoscalé         |
| Tous les clients en invalid\_token d'un coup                       | Clé de signature changée via un secret amont tourné    |
| Collection de stockage vide                                        | Nom de collection codé en dur par la bibliothèque      |
| 500 à l'autorisation pour certains clients                         | client\_id en URL (CIMD) utilisé comme clé de stockage |
| Correctif déployé, client inchangé                                 | Enregistrement client en cache                         |
| Révision qui ne démarre pas, Permission denied on secret           | Secret sans droit d'accès pour le compte de service    |
| 403 HTML sur /.well-known/\*                                       | Binding IAM allUsers perdu au redéploiement            |

## Conclusion

[](https://github.com/batou9150/writing-workspace/blob/main/blog/drafts/3%5FMCP%2C%20les%20pannes%20qui%20ressemblent%20%C3%A0%20des%20bugs%20d'auth%20%28FR%29.md?ref=sfeir.dev#conclusion)

Le protocole MCP est la partie facile. Ce qui casse en production, c'est tout ce qui l'entoure : le stockage, les secrets, l'IAM, les logs, les caches des clients. Mon réflexe aujourd'hui, face à une "erreur d'authentification" sur un serveur MCP, est de vérifier d'abord trois choses : où vit l'état OAuth, quelle clé signe les tokens, et si le client parle avec un enregistrement antérieur à mon dernier déploiement. Dans la majorité des cas, la réponse est là, et pas dans le code OAuth.