Skip to content

Le build n'est pas reproductible depuis son tag : mcp déclaré sans borne majeure #30

Description

@alex-lata

Contexte

requirements.txt:8 déclare mcp>=1.8.0 — un plancher sans borne haute. Il n'existe pas de
requirements.lock, et Dockerfile:32-33 installe requirements.txt directement :

COPY requirements.txt .
RUN pip install --no-cache-dir --upgrade pip \
    && pip install --no-cache-dir -r requirements.txt

Conséquence : le tag applicatif est immuable, son build ne l'est pas. Reconstruire un tag déjà
publié résout les dernières versions amont et produit une image différente de celle qui a été
qualifiée.

⚠️ Point secondaire dans le même bloc : --upgrade pip non borné ajoute une seconde source de
dérive. mcp-tools a documenté ce cas — c'est le setuptools ancien de l'image de base qui portait
PYSEC-2026-3447, et un lock généré sans pip freeze --all ne le voyait pas. Un lock complet fige
aussi l'outillage de build et rend ce --upgrade inutile.

Mesure

Reconstruction à froid du local_deployment (cache Docker vide, résolution pip neuve), le
2026-08-20 :

  • pip résout mcp 2.0.0 ;
  • 2.0.0 a supprimé mcp.server.fastmcp, importé par src/mcp_memory/server.py:23 ;
  • l'image démarre en ModuleNotFoundError → conteneur non fonctionnel.

Verdict littéral de l'outil de contrôle du déploiement local :

  import FastMCP incompatible → couche MCP SDK <2
  image      : graph-memory-mcp-memory:latest
  SDK mcp    : 2.0.0
⚠ l'import mcp.server.fastmcp échoue : le conteneur crasherait en boucle

Le déploiement local n'a survécu que via son propre contournement,
local_deployment/bin/pin-mcp-sdk.sh, qui sauvegarde l'image en :pre-pin puis réinstalle
mcp[cli]>=1.8.0,<2 (1.29.0) dans une couche supplémentaire. Ce contournement est externe au
dépôt
et ne protège que ce poste.

Contrairement à mcp-agent, un seul point d'impact a été identifié : graph-memory n'utilise pas
streamablehttp_client.

Ce que ce ticket n'affirme pas

Il n'y a pas d'incident de production. Le composant est actif en v3.2.0 sur graph-01 et son
code est inchangé depuis le 2026-06-04 ; l'image en service a été construite avant la parution de
mcp 2.0.0. Le risque ne se matérialise qu'à la prochaine reconstruction.

À noter, et cela relativise l'urgence : la chaîne de build plateforme a reconstruit et activé
mcp-agent — dépôt affecté du même défaut — trois fois sans incident entre le 23 et le
24 août (LIF-20260823-418, LIF-20260824-419, LIF-20260824-420, toutes en succès, aucune
mention de fastmcp). Elle résout donc encore une version 1.x là où un poste résout 2.0.0. La cause
n'est pas établie de notre côté (miroir PyPI interne, cache, index épinglé). Si cette protection
vient d'un miroir, elle est involontaire et cessera à sa prochaine synchronisation.

Le sujet est donc la reproductibilité du build, pas un risque de panne imminent.

Précédents dans le parc

  • mcp-tools#2 — « [BLOCKER] v0.4.1 non reproductible avec MCP SDK 2.0.0 », corrigé en 0.5.0
    (2026-08-06) ;
  • mcp-vault#125 — « bug(release): v0.10.1 résout MCP 2.0 et ne démarre plus », corrigé en
    0.10.2 (2026-08-11).

Sur les huit MCP du catalogue, six traitent ce risque. graph-memory et mcp-agent sont les deux
seuls sans aucun garde-fou.

Correction proposée

  1. Borner : mcp>=1.29.0,<2 dans requirements.txt.

  2. Publier un requirements.lock, généré dans l'image cible (python:3.11.12-slim,
    linux/amd64) avec pip freeze --all pour figer aussi pip/setuptools/wheel.
    mcp-tools/scripts/lock_requirements.sh est réutilisable en changeant l'image de base.

  3. Installer le lock dans le Dockerfile au lieu de requirements.txt, et retirer le
    --upgrade pip non borné
    devenu inutile.

  4. Poser une garde d'import :

    RUN python -c "from mcp.server.fastmcp import FastMCP"

Critère de sortie

Une reconstruction à froid ne produit plus aucune ligne pin-mcp-sdk pour ce composant.

Le déclencheur est déjà planifié dans ce dépôt

L'issue #10 — « Roadmap upgrade Python : 3.11 → 3.12 » impose, par construction, une
reconstruction complète de l'image et une résolution pip neuve. C'est exactement la condition dans
laquelle le défaut se manifeste. Traiter le présent ticket avant #10 évite de diagnostiquer un
ModuleNotFoundError au milieu d'une migration d'interpréteur, où il serait naturellement — et à
tort — imputé au changement de version de Python.

Voisin également : #9 — « Audit des dépendances Python inutilisées dans requirements.txt »
touche le même fichier. Les deux peuvent être traités dans la même passe.

Priorité suggérée

Moyenne–basse en isolation, mais à séquencer avant #10. Le dépôt est stable depuis juin, donc
rarement reconstruit — c'est précisément ce qui rend le défaut invisible jusqu'au jour où une
reconstruction devient nécessaire.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions