# Colonnes configurables pour `rechercher_marches` (MCP) — Design **Issue liée :** connecteur MCP colibre (#114). ## Objectif Rendre la sélection des colonnes du tool MCP `rechercher_marches` souple, au lieu de la liste figée `MARCHES_COLUMNS`. Trois besoins : 1. Un **choix par défaut** (les colonnes actuelles), comportement inchangé si le client ne demande rien. 2. Un **champ de lien** dynamique vers chaque marché, ajouté à chaque résultat : `APP_BASE_URL/marche/{uid}`. 3. La possibilité pour l'agent/l'utilisateur de **choisir d'autres colonnes** parmi celles disponibles, avec la meilleure UX atteignable dans l'interface tool MCP. ## Contexte UX (ce qui est possible, ce qui ne l'est pas) - **Cases à cocher rendues par le serveur : impossible.** dash 4.4 n'implémente pas l'_élicitation_ MCP (le serveur n'annonce que les capacités `tools` et `resources`). Aucun widget interactif ne peut être poussé dans le client. - **Levier retenu : un `enum` dans le schéma du paramètre.** En typant `colonnes` avec un `Literal` des colonnes disponibles, l'agent reçoit la liste fermée valide directement dans le schéma du tool (pas de tâtonnement, pas besoin d'appeler `schema_donnees` au préalable). Beaucoup de clients (dont Claude) rendent un paramètre enum comme un sélecteur cochable. C'est aussi une validation au niveau schéma. ## Source de vérité des colonnes `DATA_SCHEMA` (issu du TableSchema `base_schema.json`) est la référence, déjà utilisée par `describe_schema()`. L'ensemble sélectionnable part de l'intersection `DATA_SCHEMA ∩ duckdb_schema` (exactement le set déjà exposé comme `colonnes_filtrables`), **unie** aux colonnes du défaut `MARCHES_COLUMNS` — pour que toute colonne du jeu par défaut reste re-sélectionnable même si elle est enrichie et absente de `DATA_SCHEMA` (ex. `acheteur_nom`). Ces colonnes du défaut sont toutes présentes dans la table DuckDB (elles fonctionnent déjà), donc sûres à `SELECT` : ```python _filtrables = tuple(name for name in DATA_SCHEMA if name in duckdb_schema) SELECTABLE_COLUMNS = tuple(dict.fromkeys((*MARCHES_COLUMNS, *_filtrables))) ``` Source de vérité unique (schéma de référence + défaut), ni liste « raw DuckDB », ni sous-ensemble à maintenir à la main. ## Modifications ### `src/mcp/queries.py` - Construire à l'import (cf. section « Source de vérité ») : ```python _filtrables = tuple(name for name in DATA_SCHEMA if name in duckdb_schema) SELECTABLE_COLUMNS = tuple(dict.fromkeys((*MARCHES_COLUMNS, *_filtrables))) ColonneMarche = Literal[SELECTABLE_COLUMNS] ``` - `search_marches(..., colonnes: list[str] | None = None)` : - `colonnes is None` → `MARCHES_COLUMNS` (comportement inchangé). - liste fournie → **exactement** ces colonnes (remplace le défaut). - **Validation runtime conservée** (défense en profondeur : le `enum` du schéma n'est pas toujours imposé par le client). Toute colonne absente de `SELECTABLE_COLUMNS` → retour `{"error": "colonne inconnue: