Integration Python - Installation

Utilisez OpenLegi MCP dans vos applications Python

Intégration Python - OpenLegi MCP

🎯 Recommandation importante

Pour une intégration simple et robuste, nous recommandons d'utiliser les librairies officielles MCP :

La classe OpenLegiClient ci-dessous est fournie à titre éducatif et pour les cas d'usage avancés nécessitant un contrôle fin du protocole.


Installation

pip install requests

Configuration

URLs de base

Environnement URL
Production https://mcp.openlegi.fr
Local http://localhost:3000

Services disponibles

Service Endpoint Description
Légifrance /legifrance/mcp Codes, jurisprudences, JORF, textes légaux
INPI /inpi/mcp Registre du commerce et des sociétés
EUR-Lex /eurlex/mcp Droit européen

Authentification

Trois méthodes supportées :

1. Header Authorization (recommandé)

session.headers.update({
    "Authorization": "Bearer VOTRE_TOKEN_ICI"
})

2. Query Parameter

url = f"https://mcp.openlegi.fr/legifrance/mcp?token=VOTRE_TOKEN"

3. Path Token

url = "https://mcp.openlegi.fr/legifrance/mcp/token/VOTRE_TOKEN"

Client Python OpenLegiClient

Classe complète

import requests
import json


class OpenLegiClient:
    """Client Python pour l'API OpenLegi MCP.

    Gère le protocole MCP avec support du format SSE (Server-Sent Events).
    """

    def __init__(
        self,
        token: str,
        service: str = "legifrance",
        base_url: str = "https://mcp.openlegi.fr"
    ):
        """Initialise le client MCP.

        Args:
            token: Token d'authentification OpenLegi
            service: Service à utiliser ('legifrance', 'inpi', 'eurlex')
            base_url: URL de base du serveur MCP
        """
        self.base_url = base_url
        self.service = service
        self.endpoint = f"{base_url}/{service}/mcp"
        self.session = requests.Session()

        # Headers requis par le protocole MCP
        self.session.headers.update({
            "Content-Type": "application/json",
            "Accept": "application/json, text/event-stream",  # Les deux types sont requis
            "Authorization": f"Bearer {token}"
        })
        # Initialiser la session MCP
        self._initialize()

    def _initialize(self):
        """Initialise la session MCP et récupère le session ID."""
        payload = {
            "jsonrpc": "2.0",
            "id": 0,
            "method": "initialize",
            "params": {
                "protocolVersion": "2024-11-05",
                "capabilities": {},
                "clientInfo": {
                    "name": "OpenLegiClient",
                    "version": "1.0.0"
                }
            }
        }

        response = self.session.post(self.endpoint, json=payload)
        response.raise_for_status()

        # Récupérer le session ID du header
        session_id = response.headers.get('mcp-session-id')
        if session_id:
            self.session.headers.update({"mcp-session-id": session_id})


    @staticmethod
    def _parse_sse_response(text: str) -> dict:
        """Parse une réponse SSE et extrait le JSON de la ligne data:.

        Le serveur MCP renvoie les réponses au format SSE :
        event: message
        data: {"jsonrpc":"2.0","id":1,"result":{...}}

        Args:
            text: Texte brut de la réponse HTTP

        Returns:
            Dictionnaire JSON extrait de la ligne 'data:'

        Raises:
            ValueError: Si aucune ligne 'data:' n'est trouvée
        """
        lines = text.strip().split('\n')
        for line in lines:
            if line.startswith('data: '):
                return json.loads(line[6:])  # Retire 'data: ' et parse le JSON
        raise ValueError("Aucune ligne 'data:' trouvée dans la réponse SSE")

    def call_tool(self, tool_name: str, arguments: dict) -> dict:
        """Appelle un tool MCP avec les arguments fournis.

        Args:
            tool_name: Nom du tool à appeler (ex: 'rechercher_code')
            arguments: Dictionnaire des arguments du tool

        Returns:
            Résultat du tool (contenu du champ 'result')

        Raises:
            requests.HTTPError: Si la requête HTTP échoue
            Exception: Si le serveur renvoie une erreur JSON-RPC
        """
        payload = {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "tools/call",
            "params": {
                "name": tool_name,
                "arguments": arguments
            }
        }

        response = self.session.post(self.endpoint, json=payload)
        response.raise_for_status()

        # Parser la réponse SSE
        result = self._parse_sse_response(response.text)

        if "error" in result:
            raise Exception(f"Erreur MCP: {result['error']}")

        return result["result"]

    def list_tools(self) -> list[dict]:
        """Liste tous les tools disponibles sur le serveur.

        Returns:
            Liste des tools avec leurs métadonnées (name, description, inputSchema)

        Raises:
            requests.HTTPError: Si la requête HTTP échoue
        """
        payload = {
            "jsonrpc": "2.0",
            "id": 1,
            "method": "tools/list",
            "params": {}
        }

        response = self.session.post(self.endpoint, json=payload)
        response.raise_for_status()

        # Parser la réponse SSE
        result = self._parse_sse_response(response.text)
        return result["result"]["tools"]

    def close(self):
        """Ferme la session HTTP."""
        self.session.close()

    def __enter__(self):
        """Support du context manager (with statement)."""
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Fermeture automatique de la session."""
        self.close()

Exemples d'utilisation

1. Lister les tools disponibles

from openlegi_client import OpenLegiClient

# Créer le client avec votre token
token = "votre_token_ici"

with OpenLegiClient(token=token) as client:
    # Récupérer la liste des tools
    tools = client.list_tools()

    print(f"📋 {len(tools)} tools disponibles:\n")

    for tool in tools:
        print(f"🔧 {tool['name']}")
        print(f"   {tool['description'][:100]}...")
        print()

Sortie attendue :

📋 12 tools disponibles:

🔧 rechercher_dans_texte_legal
   Recherche dans les textes légaux consolidés depuis légifrance...

🔧 rechercher_code
   Recherche des articles juridiques dans les codes juridiques français...

🔧 rechercher_jurisprudence_judiciaire
   Recherche des jurisprudences judiciaires avec validation MCP...

🔧 rechercher_jurisprudence_administrative
   Recherche dans la jurisprudence administrative (Conseil d'État...

🔧 rechercher_decisions_cnil
   Recherche dans les délibérations et décisions de la CNIL...

🔧 rechercher_conventions_collectives
   Recherche dans les conventions collectives (KALI)...

🔧 rechercher_decisions_constitutionnelles
   Recherche dans les décisions du Conseil constitutionnel...

🔧 recherche_journal_officiel
   Recherche dans le Journal Officiel français...

🔧 dernier_journal_officiel
   Récupère le(s) dernier(s) Journal(aux) Officiel(s) publiés...

🔧 lister_codes_juridiques
   Liste tous les codes juridiques disponibles sur Legifrance...

🔧 lister_emetteurs_jorf
   Liste tous les émetteurs/autorités disponibles pour les recherches JORF...

🔧 lister_natures_textes_jorf
   Liste toutes les natures de textes disponibles pour les recherches JORF...

2. Rechercher un article dans un code

from openlegi_client import OpenLegiClient

token = "votre_token_ici"

with OpenLegiClient(token=token) as client:
    # Rechercher l'article 9 du Code civil
    result = client.call_tool(
        tool_name="rechercher_code",
        arguments={
            "search": "9",
            "code_name": "Code civil",
            "champ": "NUM_ARTICLE"
        }
    )

    print("📖 Résultat de la recherche:\n")
    print(result)

3. Rechercher dans la jurisprudence

from openlegi_client import OpenLegiClient

token = "votre_token_ici"

with OpenLegiClient(token=token) as client:
    # Rechercher des décisions sur la responsabilité civile
    result = client.call_tool(
        tool_name="rechercher_jurisprudence_judiciaire",
        arguments={
            "search": "responsabilité civile",
            "juridiction_judiciaire": ["Cour de cassation"],
            "publication_bulletin": ["T"],
            "sort": "DATE_DESC",
            "page_size": 5
        }
    )

    print("⚖️ Jurisprudences trouvées:\n")
    print(result)

4. Consulter le dernier Journal Officiel

from openlegi_client import OpenLegiClient

token = "votre_token_ici"

with OpenLegiClient(token=token) as client:
    # Récupérer les 3 derniers JO
    result = client.call_tool(
        tool_name="dernier_journal_officiel",
        arguments={
            "nb_jo": 3
        }
    )

    print("📰 Derniers Journaux Officiels:\n")
    print(result)

5. Rechercher dans les conventions collectives

from openlegi_client import OpenLegiClient

token = "votre_token_ici"

with OpenLegiClient(token=token) as client:
    # Rechercher des conventions sur le télétravail
    result = client.call_tool(
        tool_name="rechercher_conventions_collectives",
        arguments={
            "search": "télétravail",
            "panorama": True,  # Vue d'ensemble sans texte intégral
            "page_size": 10
        }
    )

    print("📄 Conventions collectives:\n")
    print(result)

6. Lister les codes juridiques disponibles

from openlegi_client import OpenLegiClient

token = "votre_token_ici"

with OpenLegiClient(token=token) as client:
    # Lister tous les codes disponibles
    result = client.call_tool(
        tool_name="lister_codes_juridiques",
        arguments={}
    )

    print("📚 Codes juridiques disponibles:\n")
    for code in result:
        print(f"  • {code}")

Gestion des erreurs

Erreurs HTTP

from openlegi_client import OpenLegiClient
import requests

token = "votre_token_ici"

try:
    with OpenLegiClient(token=token) as client:
        result = client.call_tool("rechercher_code", {"search": "test"})
except requests.HTTPError as e:
    print(f"❌ Erreur HTTP: {e}")
    print(f"Status: {e.response.status_code}")
    print(f"Détails: {e.response.text}")

Erreurs JSON-RPC

from openlegi_client import OpenLegiClient

token = "votre_token_ici"

try:
    with OpenLegiClient(token=token) as client:
        # Tool inexistant
        result = client.call_tool("tool_qui_nexiste_pas", {})
except Exception as e:
    print(f"❌ Erreur MCP: {e}")

Notes importantes

Format SSE (Server-Sent Events)

Le serveur MCP renvoie les réponses au format SSE, même pour les requêtes JSON-RPC simples :

event: message
data: {"jsonrpc":"2.0","id":1,"result":{...}}

C'est pourquoi : 1. Le header Accept doit inclure text/event-stream 2. La réponse doit être parsée ligne par ligne 3. On ne peut pas utiliser directement response.json()

Performance

  • Toujours utiliser requests.Session() pour réutiliser la connexion HTTP
  • Le context manager (with statement) garantit la fermeture de la session
  • Les credentials PISTE personnels éliminent les limitations de rate limiting

Authentification

  • Le token est obligatoire pour tous les endpoints
  • Format recommandé : Header Authorization: Bearer <token>
  • Testez votre token avec list_tools() avant d'appeler des tools complexes

Alternatives recommandées

Pour une intégration production, considérez :

  1. MCP Python SDK - SDK officiel avec :
  2. Support complet du protocole MCP
  3. Gestion automatique des sessions
  4. Streaming SSE natif
  5. Types Python stricts

  6. Claude Desktop - Pour une utilisation interactive :

  7. Configuration via claude_desktop_config.json
  8. Interface graphique native
  9. Pas de code nécessaire

  10. Claude Code CLI - Pour l'automatisation :

  11. Intégration Git
  12. Exécution de tâches complexes
  13. Support natif des serveurs MCP

Support


Licence

Ce code est fourni sous licence MIT à titre d'exemple éducatif.

Derniere mise a jour : 04 février 2026