Skip to main content
Glama

search_tenders

Read-onlyIdempotent

Recherche des appels d'offres publics français (BOAMP) et européens (TED).

Environ 3 millions d'avis, mis à jour plusieurs fois par jour. Accès anonyme et
gratuit, limité à 30 appels par jour et par IP ; chaque réponse indique le solde
restant dans sa clé `quota`.

Cinq pièges, tous rencontrés en production :
1. Filtrez toujours. Sans aucun filtre la recherche porte sur tout le stock depuis
   2015, avis clos compris. Posez au minimum un `keyword`, un `cpv_family`,
   un `country` ou un `status`.
2. `keyword` cherche une sous-chaîne et exige que TOUS les mots soient présents
   dans le même avis. « défibrillateur cabinet » ne rend rien ; cherchez un seul
   mot, puis affinez.
3. Le mot-clé balaie le titre ET la description, noms d'acheteurs compris. Un terme
   métier qui est aussi un toponyme sur-capte donc beaucoup : « littoral » remonte
   une maintenance de portes au « GHT Somme Littoral Sud ». Quand un mot est ambigu,
   préférez un code CPV, ou une expression que ne peut pas porter un nom de lieu.
4. Les avis TED sont indexés dans leur langue de publication : pour couvrir un
   marché européen, interrogez le terme dans chaque langue utile, ou passez par
   le code CPV, qui lui est indépendant de la langue.
5. Environ 40 % des avis BOAMP arrivent sans aucun code CPV : un filtre CPV seul
   les laisse de côté. Croisez avec `keyword` quand la couverture compte.

Chaque paramètre est décrit dans le schéma d'entrée ; les valeurs invalides rendent
une erreur qui liste les valeurs acceptées, et cette erreur ne consomme pas de quota.

Les attributions (qui a gagné, pour quel montant) et le winner intelligence
ne sont PAS disponibles ici : ils demandent une clé. Voir https://tenderapi.fr/?via=mcp

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cpvNoCode CPV exact à 8 chiffres, ex. '72000000' pour les services informatiques. Environ 40 % des avis BOAMP n'ont aucun CPV : un filtre CPV seul les écarte.
pageNoNuméro de page, à partir de 1.
sortNo'date' (antéchronologique, défaut), 'relevance' (classement BM25) ou 'deadline' (date limite la plus proche d'abord, avis sans date limite en dernier). 'relevance' n'a de sens qu'avec un keyword et est refusé sans lui. 'deadline' se combine avec status='open' ou deadline_after, sinon la liste commence par des avis clos depuis des années.
regionNoRégion française en slug, ex. 'bretagne', 'ile-de-france', 'occitanie'. Une valeur inconnue rend une erreur qui suggère le slug le plus proche.
sourceNo'boamp' (avis français) ou 'ted' (avis européens). Sans valeur, les deux.
statusNo'open' (date limite non dépassée, évaluée à l'instant de la requête) ou 'closed'. ⚠️ SANS ce filtre la recherche porte sur tout le stock depuis 2015, avis clos compris (~2,9 millions) : posez 'open' si vous cherchez des avis auxquels il est encore possible de répondre.
countryNoCode pays ISO à 2 lettres, ex. 'FR', 'DE', 'ES'. Utile pour ne garder que le français ('FR') ou cibler un pays sur le corpus TED.
keywordNoRecherche plein texte sur titre et description, insensible aux accents. TOUS les mots doivent figurer dans le même avis : préférez un seul mot puis affinez. L'opérateur OR de FTS5 est accepté, ex. 'BIM OR "maquette numerique"'.
page_sizeNoNombre d'avis par page, 10 par défaut, plafonné à 20 en anonyme. Un avis pèse environ 1 300 caractères : montez à 20 seulement si vous comptez les lire tous.
budget_maxNoMontant maximum en euros.
budget_minNoMontant minimum en euros. Les avis sans budget renseigné sont écartés, sauf include_null_budget=true.
cpv_familyNoPréfixe CPV à 2 chiffres, ex. '72' = toute l'informatique, '45' = travaux.
departmentNoCode de département, ex. '35', '2A', '974'. Plusieurs valeurs séparées par des virgules.
buyer_siretNoSIRET de l'acheteur, 14 chiffres exactement (l'établissement, pas l'entreprise).
descripteurNoCode descripteur BOAMP (nomenclature DILA), alternative au CPV côté français.
buyer_keywordNoFragment du nom de l'acheteur, 3 caractères minimum, ex. 'metropole', 'CHU'.
contract_typeNo'services', 'works' ou 'supplies'. Les formes françaises 'travaux' et 'fournitures' sont acceptées comme alias.
deadline_afterNoDate limite de remise postérieure à cette date ISO (AAAA-MM-JJ).
procedure_typeNoType de procédure, ex. 'open', 'restricted', 'negotiated'. Valeur inconnue = erreur listant les valeurs acceptées.
deadline_beforeNoDate limite de remise antérieure à cette date ISO (AAAA-MM-JJ).
published_afterNoPublié après cette date ISO (AAAA-MM-JJ). C'est le filtre d'une veille quotidienne.
include_planningNoInclure les avis de pré-information (marchés simplement envisagés, non encore ouverts). Exclus par défaut.
published_beforeNoPublié avant cette date ISO (AAAA-MM-JJ).
include_null_budgetNoGarder les avis dont le budget n'est pas renseigné malgré un filtre de montant. Beaucoup d'avis BOAMP n'annoncent aucun montant.
include_null_deadlineNoGarder les avis sans date limite malgré un filtre de date limite. Sans cela, un filtre deadline_* les écarte silencieusement.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
hintNoExplication des raisons pour lesquelles la requête rend peu ou pas de résultats, et comment la corriger. Souvent renseigné sur un total de 0 : LISEZ-LE avant de conclure qu'il n'existe aucun avis, et reformulez en conséquence.
pageNoPage rendue.
quotaNoSolde du palier anonyme : {restant, plafond}. Surveillez-le plutôt que de découvrir le plafond en le heurtant.
totalNoNombre total d'avis correspondant aux filtres, toutes pages confondues.
resultsNoLes avis. Champs utiles : id (entier, à passer à get_tender), title, buyer_name, deadline, budget_max, region, source, source_url.
warningNoAvertissement sur l'interprétation des résultats (filtre ignoré, jeu tronqué).
page_sizeNoNombre d'avis par page.
client_updateNoNotice de mise à jour, uniquement pour le paquet pip `tenderapi-mcp`. Sans objet pour ce serveur hébergé, qui n'a rien à installer.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / sort / description
      Previous value: -"'date' (antéchronologique, défaut) ou 'relevance' (classement BM25). 'relevance' n'a de sens qu'avec un keyword et est refusé sans lui."New value: +"'date' (antéchronologique, défaut), 'relevance' (classement BM25) ou 'deadline' (date limite la plus proche d'abord, avis sans date limite en dernier). 'relevance' n'a de sens qu'avec un keyword et est refusé sans lui. 'deadline' se combine avec status='open' ou deadline_after, sinon la liste commence par des avis clos depuis des années."
  2. Changed29 schema fields changed
    • addedInput schema / properties / budget_max / description
      Added value: +"Montant maximum en euros."
    • addedInput schema / properties / budget_min / description
      Added value: +"Montant minimum en euros. Les avis sans budget renseigné sont écartés, sauf include_null_budget=true."
    • addedInput schema / properties / buyer_keyword / description
      Added value: +"Fragment du nom de l'acheteur, 3 caractères minimum, ex. 'metropole', 'CHU'."
    • addedInput schema / properties / buyer_siret / description
      Added value: +"SIRET de l'acheteur, 14 chiffres exactement (l'établissement, pas l'entreprise)."
    • addedInput schema / properties / contract_type / description
      Added value: +"'services', 'works' ou 'supplies'. Les formes françaises 'travaux' et 'fournitures' sont acceptées comme alias."
    • addedInput schema / properties / country / description
      Added value: +"Code pays ISO à 2 lettres, ex. 'FR', 'DE', 'ES'. Utile pour ne garder que le français ('FR') ou cibler un pays sur le corpus TED."
    • addedInput schema / properties / cpv / description
      Added value: +"Code CPV exact à 8 chiffres, ex. '72000000' pour les services informatiques. Environ 40 % des avis BOAMP n'ont aucun CPV : un filtre CPV seul les écarte."
    • addedInput schema / properties / cpv_family / description
      Added value: +"Préfixe CPV à 2 chiffres, ex. '72' = toute l'informatique, '45' = travaux."
    • addedInput schema / properties / deadline_after / description
      Added value: +"Date limite de remise postérieure à cette date ISO (AAAA-MM-JJ)."
    • addedInput schema / properties / deadline_before / description
      Added value: +"Date limite de remise antérieure à cette date ISO (AAAA-MM-JJ)."
    • addedInput schema / properties / department / description
      Added value: +"Code de département, ex. '35', '2A', '974'. Plusieurs valeurs séparées par des virgules."
    • addedInput schema / properties / descripteur / description
      Added value: +"Code descripteur BOAMP (nomenclature DILA), alternative au CPV côté français."
    • addedInput schema / properties / include_null_budget / description
      Added value: +"Garder les avis dont le budget n'est pas renseigné malgré un filtre de montant. Beaucoup d'avis BOAMP n'annoncent aucun montant."
    • addedInput schema / properties / include_null_deadline / description
      Added value: +"Garder les avis sans date limite malgré un filtre de date limite. Sans cela, un filtre deadline_* les écarte silencieusement."
    • addedInput schema / properties / include_planning / description
      Added value: +"Inclure les avis de pré-information (marchés simplement envisagés, non encore ouverts). Exclus par défaut."
    • addedInput schema / properties / keyword / description
      Added value: +"Recherche plein texte sur titre et description, insensible aux accents. TOUS les mots doivent figurer dans le même avis : préférez un seul mot puis affinez. L'opérateur OR de FTS5 est accepté, ex. 'BIM OR \"maquette numerique\"'."
    • addedInput schema / properties / page / description
      Added value: +"Numéro de page, à partir de 1."
    • changedInput schema / properties / page_size / default
      Previous value: -20New value: +10
    • addedInput schema / properties / page_size / description
      Added value: +"Nombre d'avis par page, 10 par défaut, plafonné à 20 en anonyme. Un avis pèse environ 1 300 caractères : montez à 20 seulement si vous comptez les lire tous."
    • addedInput schema / properties / procedure_type / description
      Added value: +"Type de procédure, ex. 'open', 'restricted', 'negotiated'. Valeur inconnue = erreur listant les valeurs acceptées."
    • addedInput schema / properties / published_after / description
      Added value: +"Publié après cette date ISO (AAAA-MM-JJ). C'est le filtre d'une veille quotidienne."
    • addedInput schema / properties / published_before / description
      Added value: +"Publié avant cette date ISO (AAAA-MM-JJ)."
    • addedInput schema / properties / region / description
      Added value: +"Région française en slug, ex. 'bretagne', 'ile-de-france', 'occitanie'. Une valeur inconnue rend une erreur qui suggère le slug le plus proche."
    • addedInput schema / properties / sort / description
      Added value: +"'date' (antéchronologique, défaut) ou 'relevance' (classement BM25). 'relevance' n'a de sens qu'avec un keyword et est refusé sans lui."
    • addedInput schema / properties / source / description
      Added value: +"'boamp' (avis français) ou 'ted' (avis européens). Sans valeur, les deux."
    • addedInput schema / properties / status / description
      Added value: +"'open' (date limite non dépassée, évaluée à l'instant de la requête) ou 'closed'. ⚠️ SANS ce filtre la recherche porte sur tout le stock depuis 2015, avis clos compris (~2,9 millions) : posez 'open' si vous cherchez des avis auxquels il est encore possible de répondre."
    • addedOutput schema / description
      Added value: +"Enveloppe d'une page de resultats. Sert d'outputSchema : il etait declare mais\nvide (`additionalProperties: true`), donc l'agent ne savait pas ou regarder.\n\n⚠️ Le SDK VALIDE la valeur rendue contre ce modele puis la RE-SERIALISE depuis lui\n(func_metadata.py:129). D'ou deux precautions, sans lesquelles un simple ajout de\nchamp cote API casserait tous les appels :\n· `extra=allow` — les champs non declares traversent au lieu d'etre effaces ;\n· tous les champs optionnels — un champ qui disparait ne fait pas echouer l'appel.\nLe detail d'un avis reste volontairement `dict` : sa forme appartient a l'API, la\nfiger ici reviendrait a maintenir deux fois le meme schema."
    • addedOutput schema / properties
      Added value: +{
      +  "client_update": {
      +    "anyOf": [
      +      {
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Notice de mise à jour, uniquement pour le paquet pip `tenderapi-mcp`. Sans objet pour ce serveur hébergé, qui n'a rien à installer.",
      +    "title": "Client Update"
      +  },
      +  "hint": {
      +    "anyOf": [
      +      {
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Explication des raisons pour lesquelles la requête rend peu ou pas de résultats, et comment la corriger. Souvent renseigné sur un total de 0 : LISEZ-LE avant de conclure qu'il n'existe aucun avis, et reformulez en conséquence.",
      +    "title": "Hint"
      +  },
      +  "page": {
      +    "anyOf": [
      +      {
      +        "type": "integer"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Page rendue.",
      +    "title": "Page"
      +  },
      +  "page_size": {
      +    "anyOf": [
      +      {
      +        "type": "integer"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Nombre d'avis par page.",
      +    "title": "Page Size"
      +  },
      +  "quota": {
      +    "anyOf": [
      +      {
      +        "additionalProperties": true,
      +        "type": "object"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Solde du palier anonyme : {restant, plafond}. Surveillez-le plutôt que de découvrir le plafond en le heurtant.",
      +    "title": "Quota"
      +  },
      +  "results": {
      +    "description": "Les avis. Champs utiles : id (entier, à passer à get_tender), title, buyer_name, deadline, budget_max, region, source, source_url.",
      +    "items": {
      +      "additionalProperties": true,
      +      "type": "object"
      +    },
      +    "title": "Results",
      +    "type": "array"
      +  },
      +  "total": {
      +    "anyOf": [
      +      {
      +        "type": "integer"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Nombre total d'avis correspondant aux filtres, toutes pages confondues.",
      +    "title": "Total"
      +  },
      +  "warning": {
      +    "anyOf": [
      +      {
      +        "type": "string"
      +      },
      +      {
      +        "type": "null"
      +      }
      +    ],
      +    "default": null,
      +    "description": "Avertissement sur l'interprétation des résultats (filtre ignoré, jeu tronqué).",
      +    "title": "Warning"
      +  }
      +}
    • changedOutput schema / title
      Previous value: -"search_tendersDictOutput"New value: +"TenderSearchPage"
  3. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (readOnly/idempotent/openWorld/non-destructive) by disclosing anonymous free access capped at 30 calls/day/IP, a `quota` key in every response, multi-daily refresh cadence, and that invalid-value errors list accepted values without consuming quota. This is exactly the operational context an agent needs before calling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with what the tool is, then a numbered list of five production pitfalls that is easy to scan. It is long, and pitfalls 2 and 5 overlap the schema descriptions, but given 25 parameters and a zero-required-args signature the length is largely justified.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be explained; the description still covers authentication, quota economics, filter requirements, corpus caveats, and an explicit exclusion of winner data. Nothing needed to invoke it correctly appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema carries the per-parameter burden and baseline would be 3; the description earns extra credit by documenting cross-parameter interactions (sort='relevance' requires a keyword, sort='deadline' pairs with status='open', CPV-only filters silently drop ~40% of BOAMP notices). Some pitfalls merely restate the schema text for keyword and cpv.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Recherche des appels d'offres publics français (BOAMP) et européens (TED)', and quantifies the corpus (~3 million avis). The search scope is immediately distinguishable from a by-id lookup like get_tender without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use guidance ('Filtrez toujours', posez au minimum un keyword/cpv_family/country/status) and when-not boundaries (attributions and winner intelligence are not available here). It does not name the sibling tools get_tender or preview_alerts as alternatives, so routing between the three is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.