Skip to main content
Glama
Toumi-Elyes

MCP Assemblée nationale

by Toumi-Elyes

🏛️ MCP Assemblée nationale

Demandez à Claude, ChatGPT ou Gemini comment ont voté les députés, en français, avec les sources.

CI Python 3.14+ Licence MIT MCP

« Comment a voté ma députée sur la réforme des retraites ? » « Quels groupes ont voté contre le dernier budget ? » « Résume-moi le scrutin sur l'aide à mourir, avec le détail par groupe. »

Ce projet branche votre assistant IA sur les données publiques de l'Assemblée nationale, via l'API publique CIVIX référencée sur data.gouv.fr. L'IA va chercher les vrais chiffres au lieu de répondre de mémoire, et elle cite le lien de chaque scrutin.

Gratuit, sans compte, sans clé, en lecture seule. Les données restent celles de l'Assemblée nationale : rien n'est interprété ni noté.

L'adresse à coller dans votre assistant :

https://mcp-assemblee-nationale.vercel.app/mcp

Sommaire


Related MCP server: Poligraph MCP Server

🧭 Comment ça marche

  1. Vous posez une question en français à votre assistant (Claude, ChatGPT…).

  2. L'assistant appelle ce serveur : il lui demande les scrutins, les députés ou les groupes concernés.

  3. Le serveur interroge CIVIX, qui republie les données ouvertes de l'Assemblée nationale, et renvoie les chiffres tels quels. L'assistant rédige alors sa réponse et cite la source.

flowchart LR
    A[Vous] --> B[Claude / ChatGPT]
    B --> C[Ce serveur MCP]
    C --> D[API CIVIX]
    D --> E[(Données de l'Assemblée nationale)]

💡 Exemple de conversation

Illustration : le texte et les chiffres ci-dessous sont inventés pour montrer la forme d'une réponse. Les vraies réponses reprennent les données de l'Assemblée.

Vous : Comment a voté la députée [Prénom Nom] sur [sujet] ?

Assistant : Sur [sujet], il existe plusieurs scrutins (amendements, articles, vote sur l'ensemble du texte). Voici sa position sur chacun :

Scrutin

Date

Position

[Titre du scrutin 1]

[date]

Pour

[Titre du scrutin 2]

[date]

Contre

Ce sont les positions enregistrées par l'Assemblée nationale, sans interprétation. Source : [lien vers la page du scrutin]


⚡ Installer en 2 minutes (sans rien coder)

Vous n'avez besoin que de l'adresse en haut de cette page, à copier-coller dans votre assistant :

https://mcp-assemblee-nationale.vercel.app/mcp

Claude (claude.ai et application Claude)

  1. Ouvrez claude.ai et allez dans Paramètres → Connecteurs.

  2. Cliquez sur Ajouter un connecteur personnalisé.

  3. Nom : Assemblée nationale. URL : collez l'adresse ci-dessus.

  4. Cliquez sur Ajouter. Aucune connexion n'est demandée.

  5. Dans une nouvelle conversation, cliquez sur le bouton + (ou l'icône des outils) et vérifiez que Assemblée nationale est activé.

Le connecteur est ensuite disponible dans l'application Claude sur ordinateur et sur téléphone.

Le plan gratuit de Claude autorise un connecteur personnalisé. Les plans payants en autorisent plusieurs. Sur un compte Team ou Enterprise, c'est l'administrateur qui l'ajoute pour l'organisation.

ChatGPT

Les connecteurs personnalisés demandent un abonnement payant (Plus, Pro, Business, Enterprise ou Edu) et se configurent sur chatgpt.com, dans le navigateur.

  1. Ouvrez Paramètres → Applications et connecteurs → Paramètres avancés et activez le Mode développeur. Selon la version, ce réglage peut aussi se trouver dans Paramètres → Sécurité.

  2. Revenez dans Applications et connecteurs et cliquez sur Créer.

  3. Nom : Assemblée nationale. URL du serveur MCP : collez l'adresse ci-dessus. Authentification : Aucune.

  4. Cochez la case de confiance puis validez.

  5. Dans une conversation, cliquez sur + → Mode développeur et activez Assemblée nationale.

ChatGPT affiche « non vérifié par OpenAI » pour toute application ajoutée soi-même : c'est normal. Ce serveur ne fait que lire des données publiques.

Gemini

  • Application Gemini (gemini.google.com) : à notre connaissance, elle ne permet pas encore d'ajouter son propre serveur MCP. Dès que ce sera possible, la même adresse fonctionnera.

  • Gemini CLI (dans un terminal) : ajoutez ceci dans ~/.gemini/settings.json, puis tapez /mcp dans Gemini CLI pour vérifier.

{
  "mcpServers": {
    "assemblee-nationale": {
      "httpUrl": "https://mcp-assemblee-nationale.vercel.app/mcp"
    }
  }
}

Claude Desktop, Cursor et autres (en local)

La méthode recommandée reste l'adresse ci-dessus : Claude Desktop reprend vos connecteurs claude.ai. Pour faire tourner le serveur sur votre ordinateur, installez uv puis utilisez cette configuration :

{
  "mcpServers": {
    "assemblee-nationale": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Toumi-Elyes/mcp-assemblee-nationale", "mcp-assemblee-nationale"]
    }
  }
}
  • Claude Desktop : Paramètres → Développeur → Modifier la configuration, collez le bloc, redémarrez l'application.

  • Cursor : ~/.cursor/mcp.json.

  • Gemini CLI : ~/.gemini/settings.json.

Ça ne marche pas ?

Partout

  • Le connecteur doit être activé dans la conversation en cours (bouton +) : l'ajouter dans les réglages ne suffit pas.

  • Demandez explicitement : « Utilise l'outil Assemblée nationale pour… ». Sans cela, l'IA répond parfois de mémoire.

  • Les noms des menus changent d'une version à l'autre. Si vous ne trouvez pas Connecteurs ou Applications et connecteurs, cherchez « connecteur », « MCP » ou « développeur » dans les paramètres.

  • Vérifiez l'adresse : elle doit se terminer par /mcp, sans espace ni guillemet.

Claude

  • Le plan gratuit n'autorise qu'un seul connecteur personnalisé : retirez-en un autre pour ajouter celui-ci.

  • Sur un compte d'organisation, seul l'administrateur peut ajouter un connecteur.

ChatGPT

  • Il faut un plan payant et le Mode développeur activé, depuis le navigateur (pas depuis l'application mobile).

  • Le connecteur n'est actif que dans les conversations où vous l'avez choisi via + → Mode développeur.

Gemini

  • L'application Gemini grand public ne prend pas en charge les serveurs MCP personnalisés, à notre connaissance. Utilisez Gemini CLI.

  • Dans Gemini CLI, /mcp doit lister assemblee-nationale. Sinon, vérifiez que le JSON est valide et redémarrez Gemini CLI.

En local (uvx)

  • Installez uv, puis redémarrez l'application pour qu'elle retrouve la commande uvx.


💬 Exemples de questions

Posez vos questions normalement, en français :

  • « Quels sont les derniers scrutins sur l'immigration ? »

  • « Comment a voté [nom du député] sur la loi de finances ? »

  • « Détaille le vote par groupe sur [sujet]. »

  • « Quels députés du groupe Écologiste se sont abstenus sur ce scrutin ? »

  • « Qu'ont déclaré les groupes avant le vote sur [sujet] ? »

  • « Liste les groupes parlementaires et leur nombre de députés. »

  • « Qui est le député de la 2e circonscription de l'Ariège ? »

Astuce : si l'IA ne trouve rien, reformulez avec un mot-clé du titre officiel (« retraites » plutôt que « la réforme de Borne »).

Le serveur propose aussi trois questions prêtes à l'emploi (menu des prompts dans Claude) : Résumer un scrutin, Mon député, Comparer les groupes.


🧰 Ce que l'IA peut faire

Vous voulez…

L'IA utilise

Ce qu'elle obtient

Chercher sans savoir si c'est un vote, un député ou un groupe

rechercher

Scrutins, députés, groupes et dossiers qui correspondent

Trouver les votes sur un thème

rechercher_scrutins

Date, résultat, titre et identifiant de chaque scrutin

Voir le résultat d'un vote

obtenir_scrutin

Adopté ou rejeté, pour, contre, abstentions, détail par groupe

Savoir qui a voté quoi

votes_scrutin

Vote de chaque député, filtrable par groupe, position ou nom

Lire les explications de vote des groupes

declarations_groupes

Déclarations publiées par les groupes (souvent aucune)

Savoir comment UN député a voté

comment_a_vote

Sa position sur les scrutins d'un sujet, avec les sources

Trouver un député et sa fiche

rechercher_deputes, obtenir_depute

Groupe, circonscription, liens officiels

Connaître les groupes politiques

lister_groupes, obtenir_groupe

Sigles, noms complets, effectifs

Utiliser la recherche approfondie de ChatGPT

search, fetch

Les mêmes données, au format attendu par ChatGPT

Tous les outils sont en lecture seule : l'IA ne peut rien modifier, ni nulle part.


📚 D'où viennent les données

  • Source : les données ouvertes de l'Assemblée nationale, mises à disposition par CIVIX, une initiative indépendante, non officielle et neutre (API sur data.gouv.fr).

  • Licence des données : Licence Ouverte Etalab 2.0.

  • Neutralité : ce serveur transmet les chiffres tels quels. Il n'ajoute aucune analyse politique et chaque réponse renvoie vers la source.

  • Fraîcheur : les réponses sont gardées en mémoire 10 minutes pour ménager l'API CIVIX. Un vote du jour peut mettre un peu de temps à apparaître, selon la mise à jour des données de l'Assemblée.

Ce projet n'est affilié ni à l'Assemblée nationale, ni à CIVIX.


🔒 Vie privée et limites

Vie privée

  • Le serveur ne reçoit que la requête envoyée par l'IA (par exemple « retraites » ou un nom de député), jamais votre conversation.

  • Il n'enregistre pas les conversations, n'utilise aucun cookie et ne demande aucun compte.

  • Les réponses de CIVIX sont gardées 10 minutes en mémoire, puis oubliées.

  • Votre assistant (Claude, ChatGPT, Gemini) applique de son côté sa propre politique de confidentialité. L'hébergeur du serveur peut aussi tenir des journaux techniques d'accès : ce code n'y écrit pas vos questions.

Limites

  • Assemblée nationale uniquement : pas de Sénat, pas de Parlement européen.

  • Fraîcheur : elle dépend de la publication des données par l'Assemblée et de leur reprise par CIVIX.

  • Disponibilité : si CIVIX est indisponible, le serveur le dit et il faut réessayer plus tard.

  • Couverture : seule la législature en cours (la 17e) est bien couverte pour les députés.

  • Plusieurs scrutins par texte : un texte donne souvent plusieurs votes (amendements, articles, ensemble). Vérifiez toujours lequel est cité.


❓ Questions fréquentes

Est-ce gratuit ? Oui. Le serveur, l'API CIVIX et l'hébergement sont gratuits. Seul l'abonnement à votre assistant (ChatGPT par exemple) peut être payant.

Est-ce officiel ? Non. C'est un projet personnel, indépendant de l'Assemblée nationale. Les données viennent de l'Assemblée, via CIVIX, qui est lui aussi indépendant.

Mes conversations sont-elles enregistrées ? Le serveur ne reçoit que la recherche envoyée par l'IA (par exemple « retraites »), jamais votre conversation. Il ne garde aucun historique et n'utilise aucun cookie. Voir Vie privée et limites.

L'IA dit qu'elle n'a pas accès à l'outil. Vérifiez que le connecteur est activé dans la conversation (bouton +), puis demandez explicitement : « Utilise l'outil Assemblée nationale pour… ».

J'ai un message d'erreur. « CIVIX momentanément indisponible » : réessayez dans quelques minutes. « Aucune donnée trouvée » : l'identifiant ou le nom est inconnu, reformulez la question.

L'IA s'est trompée. Ouvrez le lien « Source » de la réponse : il mène à la page du scrutin. Les chiffres viennent du serveur, mais c'est l'IA qui rédige la phrase : elle peut mal les résumer.

Comment signaler une erreur ?

  • Les données elles-mêmes semblent fausses (vote ou député mal enregistré) : signalez-le à CIVIX, ou à l'Assemblée nationale pour la donnée d'origine.

  • Le serveur se comporte mal (outil en erreur, réponse mal formée) : ouvrez une issue en indiquant votre question et la réponse obtenue.

Et le Sénat ? Pas pour l'instant : l'API CIVIX couvre uniquement l'Assemblée nationale.


🔧 Pour les développeurs

Serveur MCP en Python, construit avec FastMCP 4. Les réponses de l'API CIVIX sont validées par des modèles Pydantic v2, les appels passent par httpx, et les dépendances sont gérées avec Poetry.

Architecture

src/assemblee_mcp/
├── civix/
│   ├── client.py     client HTTP async (cache TTL, une nouvelle tentative, erreurs en français)
│   ├── models.py     modèles Pydantic des réponses CIVIX
│   ├── lookup.py     recherches composées (députés, groupes, sigles)
│   └── errors.py     erreurs lisibles pour l'utilisateur
├── tools/
│   ├── recherche.py  rechercher
│   ├── scrutins.py   rechercher_scrutins, obtenir_scrutin, votes_scrutin, declarations_groupes
│   ├── deputes.py    rechercher_deputes, obtenir_depute, comment_a_vote
│   ├── groupes.py    lister_groupes, obtenir_groupe
│   ├── chatgpt.py    search, fetch (format ChatGPT)
│   └── common.py     types de paramètres, annotations lecture seule, conversion d'erreurs
├── formatting.py     mise en forme des réponses en français
├── links.py          liens vers CIVIX et l'Assemblée nationale
├── textutils.py      utilitaires de texte
├── prompts.py        questions prêtes à l'emploi
├── config.py         réglages (variables d'environnement)
├── server.py         assemble le serveur (`mcp`) et la route /health
└── __main__.py       lancement en stdio ou en HTTP

Modèles Pydantic

Fichier src/assemblee_mcp/civix/models.py. Tous héritent de CivixModel : champs inconnus ignorés, modèles immuables.

  • Enveloppe générique CivixResponse[AttributesT] : answer, summary, canonical_url, meta (avec Pagination), source (liens vers l'Assemblée et CIVIX), citation et data (Data[AttributesT], dont le bloc attributes). Seul data.attributes est modélisé en détail.

  • Modèles par point d'accès, instanciés en alias : ScrutinListResponse, ScrutinResponse, ScrutinVotesResponse, StatementsResponse, DeputeListResponse, DeputeDetailResponse, GroupeListResponse, GroupeDetailResponse, SearchResponse.

  • Objets métier : ScrutinSummary, ScrutinDetail, Scrutin, Vote, VoteCounts, GroupVoteCounts, Depute, Groupe, GroupeStatement, ainsi que les résultats de recherche (DeputeSearchHit, ScrutinSearchHit, GroupeSearchHit, DossierSearchHit).

  • Position : StrEnum (pour, contre, abstention, non_votant, unknown). Toute valeur inconnue devient unknown au lieu de faire échouer la validation.

Une réponse qui ne respecte pas le modèle est transformée en message d'erreur lisible (« réponse inattendue »), jamais en trace d'appel.

Référence des outils

Tous les outils sont annotés readOnlyHint, idempotentHint et openWorldHint à vrai, destructiveHint à faux. Ils renvoient du texte (markdown français), sauf search et fetch qui renvoient du JSON sérialisé. Une erreur CIVIX devient une ToolError au message clair. Taille de page par défaut : 10.

Types partagés (tools/common.py) : page entier de 1 à 500 (défaut 1) ; legislature entier de 1 à 30 ; uid de scrutin : chaîne de 3 à 64 caractères [A-Za-z0-9_-] ; groupe / abbr : sigle de 1 à 32 caractères ; position : pour, contre, abstention ou non_votant.

Outil

Paramètres (type, défaut)

Rôle

rechercher

requete: str (2 à 200 car., requis), page: int = 1

Recherche globale ; jusqu'à 8 résultats par catégorie

rechercher_scrutins

mots_cles: str | None = None (max 200), legislature: int | None = None, page: int = 1

Scrutins par sujet ; sans mots-clés, les plus récents

obtenir_scrutin

uid: str (requis)

Détail et décomptes, global et par groupe

votes_scrutin

uid: str (requis), groupe: str | None = None, position: "pour" | "contre" | "abstention" | "non_votant" | None = None, nom: str | None = None (max 100)

Votes individuels ; liste limitée à 60 noms, totaux officiels toujours indiqués

declarations_groupes

uid: str (requis)

Explications de vote publiées par les groupes

rechercher_deputes

nom: str | None = None (max 100), groupe: str | None = None, legislature: int | None = None, page: int = 1

Députés par nom, groupe ou législature ; nom insensible aux accents et à la casse

obtenir_depute

uid: str (3 à 32 car. alphanumériques, requis)

Fiche d'un député

comment_a_vote

depute: str (2 à 100 car., requis), sujet: str | None = None (max 200), scrutin_uid: str | None = None

Position d'un député ; exactement un de sujet ou scrutin_uid ; jusqu'à 5 scrutins ; en cas de nom ambigu, liste jusqu'à 10 candidats

lister_groupes

aucun

Groupes, sigles et effectifs

obtenir_groupe

abbr: str (requis)

Fiche d'un groupe

search

query: str (2 à 200 car., requis)

JSON {"results": [{"id", "title", "url"}]} ; ids scrutin:<uid>, depute:<uid>, groupe:<sigle>

fetch

id: str (3 à 100 car., requis)

JSON {"id", "title", "text", "url", "metadata"} pour un id renvoyé par search

Prompts MCP (src/assemblee_mcp/prompts.py) :

Prompt

Paramètre

Enchaînement demandé à l'IA

resumer_scrutin

sujet: str

rechercher_scrutins puis obtenir_scrutin

mon_depute

nom: str

rechercher_deputes puis obtenir_depute, puis propose comment_a_vote

comparer_groupes

sujet: str

rechercher_scrutins, obtenir_scrutin et declarations_groupes

Le serveur expose aussi une route GET /health qui répond {"status": "ok"} (utile pour la supervision de l'hébergeur).

Lancer en local

Il faut Python 3.14 ou plus récent (le projet est développé en 3.15) et Poetry 2.

poetry install
poetry run mcp-assemblee-nationale                    # stdio
poetry run mcp-assemblee-nationale --http --port 8000 # HTTP sur http://127.0.0.1:8000/mcp
npx @modelcontextprotocol/inspector poetry run mcp-assemblee-nationale  # tester les outils

Options : --http (HTTP streamable sans état, chemin /mcp), --host (défaut 127.0.0.1, ou variable HOST), --port (défaut 8000, ou variable PORT). Sans --http, le serveur parle en stdio.

Vérifier

poetry run ruff check . && poetry run ruff format --check .
poetry run mypy src tests
poetry run pytest                          # tests hors ligne, sur des réponses CIVIX enregistrées
CIVIX_LIVE=1 poetry run pytest tests/live  # tests contre la vraie API CIVIX

Les réponses enregistrées sont dans tests/fixtures/ ; la spécification OpenAPI de CIVIX y est aussi (civix-openapi.json).

Réglages

Variable

Défaut

Rôle

CIVIX_BASE_URL

https://www.civix.fr/api/v1

Adresse de l'API

CIVIX_TIMEOUT

15

Délai max d'un appel, en secondes

CIVIX_CACHE_TTL

600

Durée du cache, en secondes

CIVIX_CACHE_MAX_ENTRIES

500

Nombre max de réponses gardées en cache

CIVIX_USER_AGENT

mcp-assemblee-nationale (+https://github.com/Toumi-Elyes/mcp-assemblee-nationale)

En-tête User-Agent envoyé à CIVIX

HOST

127.0.0.1

Hôte d'écoute en mode --http

PORT

8000

Port d'écoute en mode --http

En cas d'échec réseau ou d'erreur 5xx, le client refait un seul essai après 0,3 s.

Héberger votre propre copie

Le serveur public tourne sur Vercel, gratuitement (plan Hobby) et sans compte à créer pour les utilisateurs. Le dépôt contient déjà tout le nécessaire : api/index.py expose l'application ASGI sur /mcp et vercel.json y redirige toutes les requêtes.

  1. Forkez ce dépôt et importez-le dans Vercel (Add New → Project). Gardez la racine du dépôt comme dossier racine et laissez le framework sur Other.

  2. Déployez. Vercel lit les dépendances et la version de Python dans pyproject.toml.

  3. Votre adresse à partager est https://<votre-projet>.vercel.app/mcp. Vérifiez avec https://<votre-projet>.vercel.app/health.

Chaque push sur main redéploie le serveur. Pour déployer en ligne de commande, utilisez un token Vercel dans la variable VERCEL_TOKEN, rangée dans un fichier .env ignoré par git.

Pour un autre hébergeur (Render, Fly.io, un VPS…), lancez :

mcp-assemblee-nationale --http --host 0.0.0.0 --port $PORT

🤝 Contribuer

Voir CONTRIBUTING.md. Les issues et pull requests sont les bienvenues : nouvel outil, meilleure formulation des réponses, correction. Une règle : des faits sourcés, aucune interprétation politique.


🙏 Crédits et licences

  • Données : Assemblée nationale, en open data, sous Licence Ouverte Etalab 2.0.

  • API : CIVIX, par Arnaud Bergeret, référencée sur data.gouv.fr. CIVIX est une initiative indépendante et non officielle.

  • Outils : FastMCP, Pydantic, httpx.

  • Code : licence MIT, © Elyes Toumi. Données : Licence Ouverte Etalab 2.0.


🇬🇧 English

An MCP server that lets Claude, ChatGPT or Gemini answer questions about French National Assembly votes (scrutins, individual votes by deputy, parliamentary groups), using the open CIVIX API. Free, no account, no API key, read-only, every answer links to its source.

  • Remote URL (Claude custom connectors, ChatGPT developer mode, Gemini CLI httpUrl): https://mcp-assemblee-nationale.vercel.app/mcp

  • Local: uvx --from git+https://github.com/Toumi-Elyes/mcp-assemblee-nationale mcp-assemblee-nationale (stdio), or --http for streamable HTTP.

  • Stack: Python 3.14+ (developed on 3.15), FastMCP 4, Pydantic v2 models, httpx, Poetry.

  • Scope: National Assembly only (no Senate). Tool outputs are in French, since the underlying data is French.

  • Privacy: the server only receives the tool query, keeps no conversation history, sets no cookies; CIVIX responses are cached for 10 minutes.

  • Not official: independent project, not affiliated with the Assemblée nationale or CIVIX.

  • Licence: code under MIT; data under Licence Ouverte Etalab 2.0 (Assemblée nationale, via CIVIX).

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables querying the French National Assembly data, including deputies, interventions, questions, and votes, through natural language.
    12 npm
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI assistants to query official Polish Sejm data and the ELI legal acts database for deputies, clubs, committees, votes, interpellations, bills, proceedings, transcripts, and legal acts, with source links.
    29
    31 npm
    1
    Apache 2.0