diff --git a/src/mcp/queries.py b/src/mcp/queries.py index 851ac9d..76f9887 100644 --- a/src/mcp/queries.py +++ b/src/mcp/queries.py @@ -131,8 +131,10 @@ def search_marches( invalid = [c for c in colonnes if c not in SELECTABLE_COLUMNS] if invalid: return {"error": f"colonne inconnue: {invalid[0]}", "champ": invalid[0]} - # uid toujours présent (clé primaire + nécessaire au lien), sans doublon. - out_columns = ["uid"] + [c for c in colonnes if c != "uid"] + # uid toujours présent (clé primaire + nécessaire au lien) ; dédoublonne + # toute la liste (un client peut répéter une colonne malgré l'enum, ce + # qui produirait des noms de colonnes dupliqués au SELECT). + out_columns = list(dict.fromkeys(["uid", *colonnes])) page = max(1, int(page)) offset = (page - 1) * PAGE_SIZE diff --git a/tests/mcp/test_queries.py b/tests/mcp/test_queries.py index 774262c..cdcf7d4 100644 --- a/tests/mcp/test_queries.py +++ b/tests/mcp/test_queries.py @@ -182,6 +182,14 @@ def test_search_marches_custom_columns_include_uid_only_once(monkeypatch): assert set(m.keys()) == {"uid", "objet", "lien"} +def test_search_marches_duplicate_columns_deduped(monkeypatch): + monkeypatch.setenv("APP_BASE_URL", "https://colibre.fr") + # Un client peut répéter une colonne malgré l'enum : pas de doublon au SELECT. + result = search_marches(acheteur_id="123", colonnes=["objet", "objet"]) + m = result["marches"][0] + assert set(m.keys()) == {"uid", "objet", "lien"} + + def test_search_marches_invalid_column_rejected(): result = search_marches(acheteur_id="123", colonnes=["nexiste_pas"]) assert result["error"] == "colonne inconnue: nexiste_pas"