Guide d'installation / LangChain / LangGraph

Connecter Normi à un agent LangChain ou LangGraph

Chargez les outils Normi dans un agent Python : chaque outil MCP devient un outil LangChain, utilisable par create_agent (construit sur LangGraph) ou dans votre propre graphe.

https://mcp.normi.fr/mcp

Testé le 10 octobre 2026 avec langchain 1.4.4 et fastmcp 4.1.0 (import, connexion et authentification par clé sur mcp.normi.fr), et vérifié avec la documentation officielle LangChain. Documentation LangChain MCP

Avant de commencer

  • Un compte Normi : connexion avec Google, 500 crédits gratuits par mois.
  • Pour la connexion par clé API ou le paquet STDIO : une clé normi_…, créée dans Tableau de bord → Tokens. Elle n'est affichée qu'une fois.
  • Pour le paquet STDIO : Node.js 18 ou plus récent (npx).
langchain-mcp-adapters est archivé
LangChain a intégré les adaptateurs MCP dans langchain[mcp] (module langchain.mcp, en bêta). Cette page part de la nouvelle API ; l'ancienne figure plus bas pour les projets existants.

Installation

pip install "langchain[mcp]>=1.4" langchain-anthropic
export NORMI_API_KEY=normi_VOTRE_TOKEN
export ANTHROPIC_API_KEY=...

Connexion distante (HTTP Streamable)Recommandé

MCPAdapter ouvre la session MCP, convertit les outils Normi en outils LangChain, puis les referme proprement. Les outils restent utilisables après le bloc async with.

import asyncio
import os

from fastmcp.client import Client
from langchain.agents import create_agent
from langchain.mcp import MCPAdapter

NORMI_URL = "https://mcp.normi.fr/mcp"


async def main() -> None:
    # La clé passée à auth= part en "Authorization: Bearer normi_…"
    async with MCPAdapter(Client(NORMI_URL, auth=os.environ["NORMI_API_KEY"])) as adapter:
        tools = await adapter.list_tools()

    agent = create_agent("anthropic:claude-sonnet-5-5", tools)
    result = await agent.ainvoke(
        {"messages": [{"role": "user", "content": "Avec Normi, compare le prix au m² des appartements à Paris 11 selon leur classe DPE."}]}
    )
    print(result["messages"][-1].content)


asyncio.run(main())

Même chose avec un dictionnaire de configuration au format mcpServers :

config = {
    "mcpServers": {
        "normi": {
            "url": "https://mcp.normi.fr/mcp",
            "headers": {"Authorization": f"Bearer {os.environ['NORMI_API_KEY']}"},
        }
    }
}

async with MCPAdapter(config) as adapter:
    tools = await adapter.list_tools()

Alternative : paquet STDIO

Pour lancer le paquet npm @normi/mcp-dvf comme sous-processus (Node.js requis), passez ce dictionnaire à MCPAdapter.

config = {
    "mcpServers": {
        "normi": {
            "command": "npx",
            "args": ["-y", "@normi/mcp-dvf"],
            "env": {"NORMI_API_KEY": os.environ["NORMI_API_KEY"]},
        }
    }
}

Ancienne API : langchain-mcp-adapters

Projets existants sur MultiServerMCPClient : le transport http accepte les en-têtes.

# pip install langchain-mcp-adapters  (archivé : préférez langchain[mcp])
from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient(
    {
        "normi": {
            "transport": "http",
            "url": "https://mcp.normi.fr/mcp",
            "headers": {"Authorization": f"Bearer {os.environ['NORMI_API_KEY']}"},
        }
    }
)
tools = await client.get_tools()

Premier prompt à essayer

“Avec Normi, compare le prix au m² des appartements à Paris 11 selon leur classe DPE.”

L'agent appelle analyze_dpe_price_premium (10 crédits). Extrait de la réponse réelle, relevée le 10 octobre 2026 sur les données DVF 2014–2025 :

{
  "classes": {
    "B": { "count": 241,  "median_prix_m2": 9543, "vs_median_pct": 2.7 },
    "D": { "count": 5303, "median_prix_m2": 9354, "vs_median_pct": 0.7 },
    "E": { "count": 6418, "median_prix_m2": 9219, "vs_median_pct": -0.7 },
    "F": { "count": 4366, "median_prix_m2": 9206, "vs_median_pct": -0.9 },
    "G": { "count": 1808, "median_prix_m2": 9286, "vs_median_pct": 0 }
  },
  "methodology": "Each DVF sale is matched to the nearest geocoded DPE within 200 m, issued between 10 years before and 1 year after the sale (one DPE per sale)."
}

Les écarts restent faibles à Paris 11 (de -0,9 % à +2,7 % autour de la médiane). Le champ methodology accompagne chaque réponse : passez-le à votre agent pour qu'il cite la méthode et ses limites au lieu de surinterpréter l'écart.

Dépannage

ImportError: cannot import name 'MCPAdapter'↓
Le module langchain.mcp demande langchain[mcp] 1.4 ou plus récent. Mettez à jour, et désinstallez langchain-mcp-adapters s'il traîne dans l'environnement.
LangChainBetaWarning à l'import↓
Normal : langchain.mcp est encore en bêta. L'API peut évoluer ; épinglez la version de langchain dans vos dépendances.
KeyError: 'NORMI_API_KEY'↓
La variable n'est pas exportée dans le processus Python. Exportez-la dans le shell, ou chargez un .env (python-dotenv) avant de créer le client.
L'agent multiplie les appels et consomme beaucoup de crédits↓
Ne passez à l'agent que les outils utiles (filtrez la liste renvoyée par list_tools par nom), et donnez-lui un message système qui impose resolve_location avant toute analyse.
Erreur 401 — Unauthorized↓
Clé API : elle est absente, mal recopiée ou révoquée (le préfixe normi_ fait partie de la clé). Vérifiez que la variable d'environnement est bien visible du client. OAuth : l'accès a expiré ou a été révoqué, relancez la connexion depuis le client.
« no active API key » (403) sur chaque appel↓
Votre compte n'a plus de clé active. Créez-en une dans le tableau de bord : une connexion OAuth reprend dès l'appel suivant, une config par clé doit recevoir la nouvelle clé.
Crédits insuffisants↓
Le message arrive dans la réponse de l'outil, pas en HTTP 402. Le plan gratuit recharge 500 crédits le 1er du mois ; vous pouvez aussi acheter des crédits depuis le tableau de bord.
Erreur 429 — Rate limited↓
Vous dépassez la limite de requêtes par minute de votre plan. Attendez quelques secondes, ou limitez les appels en parallèle de votre agent.

Étapes suivantes