Skip to main content
Glama
nickdesi

FFBB MCP Server

🏀 FFBB MCP Server

Le basket français officiel, directement dans vos assistants IA.

Serveur MCP pour consulter calendriers, classements, bilans, résultats, scores live et règlements officiels de la FFBB (Fédération Française de Basketball).

🇺🇸 English Summary: Official Model Context Protocol (MCP) server for French Basketball (FFBB). Connect your AI assistants (Claude, Cursor, Copilot, ChatGPT, Antigravity) to live French basketball schedules, standings, scores, team records, club directories, and official federal regulations via Streamable HTTP or Stdio.

🌐 Site · 🧩 Extension VS Code · 📚 Documentation · 💬 Support

Version Python CI MCP Glama License: Apache 2.0 GitHub stars



⚡ Démarrage express (< 2 min)

TIP

Aucune installation requise : le serveur est hébergé publiquement. Ajoutez simplement l'endpoint MCP à votre client :

https://ffbb.desimone.fr/mcp

Puis posez vos questions en langage naturel :

« Quel est le prochain match des U15 de mon club (nommer le club) ? » « Donne-moi le classement de la poule des U15M2 du Stade Clermontois et le dernier résultat. » « Y a-t-il des matchs en direct ce soir ? »

👉 Voir la section Installation pour brancher l'endpoint sur VS Code, Claude, Cursor, etc.


Related MCP server: SportScore

✨ Fonctionnalités

  • 🗓️ Calendriers & résultats — matchs passés et à venir, par club ou par équipe.

  • 🏆 Classements — poules complètes avec points, différentiel et forme.

  • 📊 Bilans agrégés — toutes phases confondues en un seul appel.

  • 🔴 Scores live — matchs en cours, mis à jour toutes les 30 s.

  • 🔎 Recherche universelle — clubs, compétitions, salles, engagements.

  • 🚀 Optimisé pour les LLM — réponses agrégées et cache TTL pour réduire le contexte et le nombre d'appels.


🚀 Installation

VS Code / GitHub Copilot

Option recommandée — installer l'extension FFBB Basketball MCP depuis les releases, puis ouvrir Copilot Chat en mode agent.

Alternative sans extension — ➕ Installer FFBB MCP en un clic

Claude Desktop

  1. Ouvrez les Paramètres de Claude, puis Connecteurs (ou Plugins).

  2. Cliquez sur Ajouter un connecteur personnalisé.

  3. Renseignez l'URL publique https://ffbb.desimone.fr/mcp et validez.

Claude Desktop n'accepte que le transport stdio local : on utilise donc le bridge SSE officiel via npx.

WARNING

Prérequis : Node.js (inclut npm et npx). Sans Node.js, privilégiez l'Option A.

{
  "mcpServers": {
    "ffbb": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/client-sse", "https://ffbb.desimone.fr/mcp"]
    }
  }
}

Cursor / autres clients MCP

Configurez un serveur MCP distant :

Champ

Valeur

Type

Streamable HTTP

URL

https://ffbb.desimone.fr/mcp

Google Antigravity

Configurez directement l'URL distante dans mcp_config.json via la directive native serverUrl :

{
  "mcpServers": {
    "ffbb_mcp": {
      "serverUrl": "https://ffbb.desimone.fr/mcp"
    }
  }
}

🧰 Outils principaux (19 outils exposés)

Le serveur expose 19 outils MCP optimisés pour les LLMs (réponses compactes, cache SWR, déduplication automatique) :

🏀 Matchs, Résultats & Calendriers

Outil

Usage

ffbb_last_result

Dernier résultat connu d'une équipe avec score précis et détails du match.

ffbb_next_match

Prochaine rencontre programmée (date, heure, gymnase et adversaire).

ffbb_team_summary

Synthèse complète d'une équipe (matchs passés, à venir, classement et dynamique).

ffbb_bilan

Bilan synthétique victoires / défaites, points marqués / encaissés et différentiel.

ffbb_bilan_saison

Synthèse exhaustive d'un club sur toute la saison toutes phases confondues.

ffbb_head_to_head

Confrontation directe et historique récent entre deux clubs ou équipes.

ffbb_match_lookup

Recherche ciblée d'une rencontre par identifiant ou critères.

ffbb_lives

Scores en direct des rencontres en cours (rafraîchi toutes les 30s).

🏢 Clubs, Équipes & Découverte

Outil

Usage

ffbb_search

Recherche universelle plein texte (clubs, compétitions, salles, tournois).

ffbb_club

Fiche complète d'un club, coordonnées et calendrier de toutes ses équipes.

ffbb_resolve_team

Résolution canonique d'un libellé d'équipe (catégorie, genre, numéro d'équipe).

ffbb_find_team_candidates

Liste des équipes candidates pour un nom de club ou d'organisme.

ffbb_get

Extraction brute d'un objet Directus / Meilisearch par identifiant.

ffbb_saisons

Liste des saisons sportives fédérales disponibles.

📜 Règlements Officiels FFBB (Index FTS5)

Outil

Usage

ffbb_search_regulations

Recherche sémantique dans les Règlements Sportifs Généraux (RSG 2026-2027) et comités.

ffbb_get_regulation_article

Consultation intégrale et inaltérée d'un article réglementaire officiel (ex: Art. 28).

ffbb_explain_tiebreak_rules

Explication certifiée des règles de départage d'égalité (point-average, quotient).

ffbb_list_regulations

Catalogue hiérarchique des règlements fédéraux et départementaux indexés.

ffbb_version

Diagnostic, transport actif, version FastMCP et SDK.

NOTE

Référence complète des schémas et paramètres :docs/TOOLS_REFERENCE.md.


🌐 Instance publique

Endpoint MCP (transport Streamable HTTP) :

https://ffbb.desimone.fr/mcp

Endpoint

URL

📊 Dashboard

https://ffbb.desimone.fr/dashboard

📈 Métriques

https://ffbb.desimone.fr/metrics.json

❤️ Santé

https://ffbb.desimone.fr/health


🏗️ Architecture & Résilience Réseau

flowchart LR
    A[Client MCP<br/>Claude · Cursor · Antigravity] -->|Streamable HTTP / Stdio| B[FFBB MCP Server<br/>FastMCP Streamable]
    B --> C[Services métier<br/>Cache SWR & Agrégation]
    C --> D[ffbb-data-client<br/>SDK Python v2.4.37]
    D --> E[(Directus bo.ffbb.com<br/>Origine officielle non filtrée)]
    D --> F[(Meilisearch Nginx<br/>meilisearch-prod.ffbb.app)]

Points clés :

  • Résilience WAF & Directus : Les requêtes Directus sont routées nativement vers https://bo.ffbb.com/ (et fallback miroir https://bo.ffbb.app/), éliminant définitivement les erreurs 403 HTML de l'ancienne pullzone BunnyCDN api.ffbb.app ;

  • Auto-résolution des tokens : Découverte dynamique et transparente des jetons de session sans clé API requise ;

  • Double transport : Streamable HTTP distant (spec 2026-07-28, Stateless Core) ou Stdio local (uvx) ;

  • SDK Python découplé : Requêtes vers les sources fédérales et parsing Pydantic v2 délégués à ffbb-data-client ;

  • Cache intelligent & SWR : Stale-While-Revalidate avec TTL par type de donnée (30 s lives, 1 h bilans, 24 h clubs) ;

  • Observabilité complète : Dashboard HTML, métriques Prometheus, snapshot JSON et healthcheck intégrés.

Détails : docs/ARCHITECTURE.md et docs/PERFORMANCE.md.


⚙️ Variables d'Environnement

Variable

Description

Valeur par défaut

API_FFBB_BASE_URL

Base URL du backend Directus FFBB

https://bo.ffbb.com/

FFBB_USER_AGENT

User-Agent authentique transmis à Directus

iOS Safari Mobile

API_FFBB_APP_BEARER_TOKEN

Jeton Directus explicite (override l'auto-résolution)

Auto-résolu dynamiquement

MEILISEARCH_BEARER_TOKEN

Jeton Meilisearch explicite (override l'auto-résolution)

Auto-résolu dynamiquement

MCP_MODE

Mode de transport du serveur

streamable-http (ou stdio)

PORT

Port d'écoute HTTP

9123


💻 Développement local

uv sync --extra dev       # installer les dépendances
uv run ruff format .      # formater
uv run ruff check --fix . # linter
uv run mypy src           # vérifier les types
uv run pytest             # lancer les tests

Voir CONTRIBUTING.md pour les règles de contribution.


🧪 Tests

uv run pytest             # tests unitaires + couverture
uv run pytest tests/      # ciblé

Le pipeline CI (.github/workflows/ci.yml) exécute ruff, mypy, pytest et le contrôle de couverture à chaque push/PR.


📚 Documentation


🤝 Communauté


❓ Dépannage

Symptôme

Cause probable

Solution

FFBB access blocked by CDN (403 BunnyCDN)

Ancien domaine api.ffbb.app (pullzone 5204911) verrouillé par le CDN

Vérifier que le serveur est à jour (≥ v1.16.9) ou définir API_FFBB_BASE_URL=https://bo.ffbb.com/

Missing session ID / deadline exceeded

Wrapper mcp-remote ou mauvais transport

Utiliser serverUrl natif dans mcp_config.json (voir Google Antigravity)

Claude Desktop refuse l'URL http

Claude Desktop impose stdio

Utiliser le bridge @modelcontextprotocol/client-sse via npx (voir Claude Desktop)

Données live obsolètes

Cache TTL

Attendre le rafraîchissement (≤ 30 s) ou interroger l'endpoint /health


🌟 Stargazers & Communauté

Star History Chart


Available Tools

19 tools
ffbb_bilanBilan complet toutes phasesA
Read-onlyIdempotent

Bilan statistique brut (V/D, paniers, répartition par équipe).

Pour une vue d'ensemble avec calendrier/classement, préférer `ffbb_team_summary`.
Pour le parcours multi-phases/coupes, préférer `ffbb_bilan_saison`.
ParametersJSON Schema
NameRequiredDescriptionDefault
poule_idNoID FFBB de la poule pour désambiguïser.
categorieNoCatégorie/genre/numéro (ex: 'U11M1', 'Senior').
club_nameNoNom du club (ex: 'Stade Clermontois', 'ASVEL'). Requis si organisme_id absent.
season_idNoID de la saison FFBB (optionnel).
organisme_idNoID FFBB du club (ex: '9326' ou 'ARA0063058'). Requis si club_name absent.
engagement_idNoID FFBB de l'engagement (prioritaire pour désambiguïser).
force_refreshNoSi True, contourne le cache.
numero_equipeNoNuméro d'équipe (ex: 1, 2).
competition_idNoID FFBB de la compétition pour désambiguïser.
competition_typeNoType de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, open-world). The description adds useful behavioral context by specifying what the payload contains (raw win/loss and points statistics), which matters because there is no output schema. It does not cover caching behavior despite a `force_refresh` param.

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?

Three short sentences, front-loaded with the core purpose followed by the two routing rules. Slightly terse on return shape but every sentence earns its place.

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

Completeness4/5

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

For a read-only stats tool with no output schema, the description conveys the returned content and disambiguates from both sibling report tools. The remaining gap is that it says nothing about how to choose among the five anyOf identifier parameters, which for a 10-parameter tool is a minor but real omission.

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

Parameters3/5

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

Schema description coverage is 100%, so all ten parameters are already documented in the schema. The description adds no parameter-level guidance (e.g. which of the five alternative identifiers is preferred), so the baseline 3 applies.

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 resource and scope: 'Bilan statistique brut' with the concrete contents enumerated (V/D, paniers, répartition par équipe). It also names the two siblings it is NOT, so an agent can distinguish it 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 Guidelines5/5

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

Explicit routing: for an overview with calendar/standings use `ffbb_team_summary`, and for multi-phase/cup journeys use `ffbb_bilan_saison`. Both alternatives come with the condition that selects them, leaving nothing to inference.

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

ffbb_bilan_saisonBilan détaillé de saisonA
Read-onlyIdempotent

Bilan multi-phases approfondi d'une équipe sur la saison (phases 1/2, coupes, play-offs).

Agrège le parcours successif avec cumul saisonnier. Pour une synthèse rapide, préférer `ffbb_team_summary`.
ParametersJSON Schema
NameRequiredDescriptionDefault
poule_idNoID FFBB de la poule pour désambiguïser.
categorieNoCatégorie + genre + numéro d'équipe facultatif (ex: 'U11M', 'U11M1', 'U13F2', 'SeniorM'). Cette valeur sert à filtrer les engagements et les poules.
club_nameNoNom du club (ex: 'Stade Clermontois', 'ASVEL').
season_idNoID de la saison FFBB (optionnel).
organisme_idNoID FFBB du club (alternative plus rapide à club_name).
engagement_idNoID FFBB de l'engagement (prioritaire pour désambiguïser).
force_refreshNoSi True, contourne le cache pour récupérer des données fraîches.
numero_equipeNoNuméro d'équipe (1, 2, ...) pour identifier l'équipe précise dans la catégorie (défaut: 1).
competition_idNoID FFBB de la compétition pour désambiguïser.
competition_typeNoType de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.

TDQS

A3.9/5.0
Behavior3/5

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

Annotations already declare readOnly, idempotent, openWorld and non-destructive, so the safety profile is covered. The description adds the aggregation behaviour ('parcours successif avec cumul saisonnier'), which is real context, but says nothing about cost, latency, caching behaviour (despite a `force_refresh` param), or result shape.

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

Conciseness5/5

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

Three short lines: scope first, behaviour second, alternative routing last. No filler, and the most decision-relevant information is front-loaded.

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

Completeness3/5

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

With 10 parameters, an anyOf-required identity resolution scheme and no output schema, the description leaves the agent to infer how to pick among the five identity inputs and what the report actually returns beyond 'multi-phases'. The routing hint helps, but for this complexity the description is thin.

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

Parameters3/5

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

Schema description coverage is 100%, so every parameter is documented in the schema (including the identity-resolution alternatives and `force_refresh`). The description adds no parameter-level guidance, so the baseline 3 applies.

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?

The description names a specific operation (a detailed multi-phase season report for a team) and scopes the content to phases 1/2, cups and play-offs. It also explicitly distinguishes itself from `ffbb_team_summary`, so an agent can tell the two apart without opening either 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?

It gives an explicit routing rule: for a quick synthesis, prefer `ffbb_team_summary`, which implies this tool is for the deep, multi-phase analysis. No exclusion or prerequisite is stated for this tool itself, so it falls short of a full when/when-not pair.

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

ffbb_clubOutils agrégés clubA
Read-onlyIdempotent

Outils agrégés club : calendrier (matchs pluriels), équipes engagées ou classement.

Pour 'classement' : Classement seul d'une poule ou d'un club. Utiliser uniquement si poule_id est connu et que team_summary n'a pas été appelé.
ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoNombre max de matchs retournés (1-100, pagination).
phaseNoNom ou numéro de phase (ex: 'Phase 2').
scopeNoScope : 'team' (équipe résolue), 'club' (global club) ou 'competition'.
actionNoAction : 'calendrier' (matchs pluriels/restants), 'equipes' ou 'classement'. Pour 'calendrier' : Renvoie les rencontres programmées. Restituer factuellement les matchs sans spéculer sur de futures journées non publiées, des repos ou des forfaits. Pour 'classement' : Classement seul d'une poule ou d'un club. Utiliser uniquement si poule_id est connu et que team_summary n'a pas été appelé.calendrier
filtreNoFiltre catégorie/genre (alias pour 'categorie', ex: 'U11M', 'Senior', 'NM3').
offsetNoIndex de départ pour pagination calendrier (défaut 0).
date_finNoDate fin YYYY-MM-DD (action='calendrier').
group_byNoRegroupement : competition, team ou date.
poule_idNoID poule (action='classement' ou 'calendrier'). Optionnel si club et catégorie sont fournis.
categorieNoCatégorie, division ou filtre d'équipe (alias pour 'filtre', ex: 'NM3', 'U15M', 'Senior').
club_nameNoNom du club (ex: 'Stade Clermontois'). Requis si organisme_id absent.
season_idNoID de la saison FFBB (optionnel).
adversaireNoNom adversaire pour filtrer les confrontations directes (action='calendrier').
date_debutNoDate début YYYY-MM-DD (action='calendrier').
organisme_idNoID FFBB du club (ex: '9326'). Requis si club_name absent.
engagement_idNoID FFBB de l'engagement (prioritaire pour désambiguïser).
force_refreshNoSi True, contourne le cache.
include_youthNoInclut les équipes jeunes si demande senior.
numero_equipeNoNuméro d'équipe (ex: 1, 2) pour action='calendrier' ou 'classement'.
status_filterNoFiltre statuts : scheduled, live, final.
competition_idNoID FFBB de la compétition pour désambiguïser.
strict_filtersNoFiltrage strict sans extrapolation (défaut True).
competition_typeNoType de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.
include_reservesNoInclut les réserves si demande équipe 1.
include_friendliesNoInclut les amicaux (exclus par défaut).
exclude_competition_typesNoTypes de compétition exclus (ex: ['PLAT']).
include_competition_typesNoTypes de compétition inclus (ex: ['DIV']).

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so the safety profile is covered. The description adds a useful factuality constraint for 'calendrier' ('Restituer factuellement les matchs sans spéculer sur de futures journées non publiées, des repos ou des forfaits') but says nothing about caching (the force_refresh param implies one) or return shape.

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?

Two short, front-loaded sentences with no padding; the capability list comes first and the routing caveat second. It is efficient, though arguably too terse for a 27-parameter multi-action tool rather than verbose.

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

Completeness2/5

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

For a 27-parameter tool with three distinct actions and no output schema, the description explains only 'classement' in any depth and gives no guidance on 'equipes' or when 'calendrier' should be chosen over ffbb_next_match/ffbb_last_result. The identifier prerequisites (anyOf on organisme_id/club_name/poule_id/etc.) are left entirely to the schema.

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

Parameters3/5

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

Schema description coverage is 100%, so the 27 parameters are already documented in the schema and the baseline is 3. The description merely restates the classement precondition that already appears in the action parameter's own description, adding no new parameter semantics.

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

Purpose4/5

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

The description states the resource (club) and enumerates the three aggregated actions it performs ('calendrier', 'equipes', 'classement'), so an agent knows the tool's scope. It does not, however, differentiate itself strongly from siblings like ffbb_team_summary or ffbb_next_match beyond the classement caveat.

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?

For the 'classement' action it gives an explicit precondition ('Utiliser uniquement si poule_id est connu') and names an alternative to avoid ('et que team_summary n'a pas été appelé'). This is real routing guidance, but it covers only one of the three actions; 'calendrier' and especially 'equipes' get no when-to-use or alternative guidance.

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

ffbb_explain_tiebreak_rulesRègles de départage et calcul de classement FFBBA
Read-onlyIdempotent

Fournit les règles officielles de départage en cas d'égalité (Article 28 du RSG FFBB).

Explique le calcul du point-average particulier (confrontations directes),
du quotient particulier, et du mini-championnat à 3 équipes ou plus.
Lecture seule, idempotent, sans effet de bord ; cache SWR court.

Utilise cet outil uniquement quand deux équipes ou plus sont à égalité de points
dans une poule et que tu dois expliquer pourquoi l'une est classée devant l'autre.
Avec `poule_id`, les règles sont appliquées à la poule concrète ; sans, tu obtiens
les règles génériques. Ne pas utiliser pour rechercher un extrait réglementaire —
utilise `ffbb_search_regulations` à la place ; pour récupérer le texte d'un article
précis — utilise `ffbb_get_regulation_article` ; pour lister les règlements
disponibles — utilise `ffbb_list_regulations`. Ne pas utiliser non plus pour
obtenir le classement brut — utilise `ffbb_club(action="classement")` — ni pour
le bilan chiffré — utilise `ffbb_bilan`. Utilise `ffbb_explain_tiebreak_rules`
au lieu de `ffbb_search_regulations` quand la question porte sur le départage
et non sur le texte réglementaire.
ParametersJSON Schema
NameRequiredDescriptionDefault
seasonNoSaison sportive (défaut '2026-2027')2026-2027
poule_idNoID optionnel de la poule FFBB pour appliquer les règles de départage

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so restating 'lecture seule, idempotent, sans effet de bord' adds little. However, the description contributes genuinely new behavioral context the annotations cannot carry: the short SWR cache and, importantly, that passing poule_id switches the output from generic rules to rules applied to that concrete poule.

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 purpose, then behavior, then routing — a sensible order. It is on the long side and the closing sentence ('Utilise ffbb_explain_tiebreak_rules au lieu de ffbb_search_regulations quand la question porte sur le départage...') partially repeats the earlier exclusion of ffbb_search_regulations, but the redundancy is mild and the rest earns its place.

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

Completeness4/5

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

There is no output schema, and the description compensates by naming the concepts the answer will cover (point-average, quotient, mini-championnat), which is adequate for a two-parameter read-only explainer. Season defaulting is left to the schema, so the definition is complete enough for correct invocation.

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 description coverage is 100%, so the baseline is 3. The description goes further by explaining the semantic difference between supplying poule_id (rules instantiated on the concrete poule) versus omitting it (generic rules), which is behavioral meaning the schema only hints at.

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+resource (official FFBB tiebreak rules, Article 28 RSG) and enumerates the sub-concepts it covers: point-average particulier, quotient particulier, mini-championnat. An agent can distinguish it from every sibling without opening a schema.

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

Usage Guidelines5/5

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

Explicit when-to-use (two or more teams tied on points and you must explain the ranking) plus an unusually complete set of exclusions naming the correct alternative for each case: ffbb_search_regulations, ffbb_get_regulation_article, ffbb_list_regulations, ffbb_club(action="classement"), and ffbb_bilan. Nothing 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.

ffbb_find_team_candidatesRecherche et désambiguïsation d'équipes candidatesA
Read-onlyIdempotent

Recherche et ordonne les équipes candidates d'un club/CTC pour désambiguïser avant tout calendrier/résultat.

Évite la confusion entre équipe fanion sans numéro (ex: U13F en régional) et équipe réserve (ex: U13F2 en départemental).
Retourne la liste des candidats triés avec confiance, motif, détails de compétition et prochain match.

Politique : contrairement à `ffbb_resolve_team` (garde-fou strict), recommande l'équipe fanion (confiance 0.85) en l'absence de numéro.
ParametersJSON Schema
NameRequiredDescriptionDefault
sexeNoGenre de l'équipe ('M', 'F' ou 'MIXTE').
categorieNoCatégorie, étiquette ou division demandée (ex: 'U13F1', 'U13F', 'U15M', 'NM3', 'Senior'). L'outil extrait tranche d'âge, genre et numéro recherchés pour isoler les candidats.
club_nameNoNom du club ou de la CTC (ex: 'Cournon', 'Stade Clermontois'). Requis si organisme_id absent.
season_idNoID de la saison FFBB (optionnel).
organisme_idNoID FFBB du club (ex: '9289'). Requis si club_name absent.
force_refreshNoSi True, force le rafraîchissement des données.
numero_equipeNoNuméro d'équipe facultatif (ex: 1, 2).
include_next_matchNoSi True (défaut), récupère le prochain match programmé pour chaque candidat.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive). The description adds real behavior: it returns the sorted candidate list with confidence, motif, competition details, and next match, and discloses the tie-breaking policy (fanion recommended with confidence 0.85 absent a number). It stops short of any rate-limit or pagination note, but the disclosure is well beyond the annotations.

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?

Four sentences, front-loaded with purpose and disambiguation rationale, then return contents, then policy. Each sentence carries information, though the policy sentence slightly overlaps the usage guidance.

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

Completeness4/5

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

With no output schema, the description carries the return-value burden and does so (sorted candidates with confidence, motif, competition details, next match). Combined with 100% schema coverage and full annotation set, an agent has what it needs to call it correctly; only pagination/limits are unaddressed.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents all 8 parameters including categorie extraction logic and the numero_equipe/fanion distinction. The description reinforces the no-number policy but adds no parameter syntax or format detail beyond the schema. Baseline 3 is appropriate.

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+resource ('Recherche et ordonne les équipes candidates d'un club/CTC') with explicit scope and purpose (disambiguation before any calendar/result). It names the sibling ffbb_resolve_team and contrasts its policy, so the agent can distinguish it without opening either schema.

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

Usage Guidelines5/5

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

Explicitly says to use it before any calendrier/résultat to disambiguate, and names the alternative `ffbb_resolve_team` along with the differing policy (recommend fanion at 0.85 confidence vs strict guardrail). Both the when and the alternative-selection condition are given.

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

ffbb_getRessource FFBB par identifiantC
Read-onlyIdempotent

Recupere une ressource FFBB par identifiant.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesIdentifiant FFBB exact (string opaque, ex: '200000003057825'). Ne pas passer un nom de club: utiliser d'abord ffbb_search pour résoudre l'id.
clubNoNom ou ID du club à localiser dans les poules (si type='competition'). Permet de trouver directement l'ID et le nom de poule d'un club dans une compétition multi-poules.
typeYesType de ressource a charger.
force_refreshNoSi True et type='poule', contourne le cache pour recuperer la poule en temps reel (scores live).

TDQS

C2.5/5.0
Behavior2/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is covered. The description adds nothing beyond that: no note about caching (the schema's force_refresh mentions a cache), no mention of live-data behavior, auth needs, or rate limits. With annotations carrying the burden, the description still contributes essentially zero extra behavioral context.

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

Conciseness3/5

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

A single sentence with no bloat and no filler, which satisfies 'concise'. However, it is so thin that it conveys almost nothing beyond the title, so it is under-specification rather than efficient front-loading.

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

Completeness2/5

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

For a polymorphic getter covering eight resource types with four parameters and no output schema, the description omits what a returned 'ressource' looks like, that structure varies by type, and how the optional club scoping interacts with type='competition'. The schema compensates for parameters, but the description leaves the tool's overall behavior largely unexplained.

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

Parameters3/5

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

Schema description coverage is 100%, so all four parameters (id, club, type, force_refresh) are already well documented, including the enum for type and the cache-bypass semantics of force_refresh. The description adds no parameter meaning beyond the schema, so the baseline of 3 applies.

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

Purpose3/5

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

The description gives a verb ('Recupere') and a resource ('ressource FFBB') scoped by identifier, so the basic action is clear. But 'ressource' is generic despite the eight resource types in the enum, and it restates the title almost verbatim without distinguishing this tool from siblings like ffbb_search or ffbb_club. An agent cannot tell from the text alone which resource flavors or scoping rules apply.

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

Usage Guidelines2/5

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

The description contains no when-to-use, when-not-to-use, or alternative guidance. Useful routing advice ('use ffbb_search first to resolve the id') exists only in the schema's parameter description, not in the tool description, so the description itself provides no selection help.

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

ffbb_get_regulation_articleLecture exacte d'un article de règlement FFBBA
Read-onlyIdempotent

Récupère le texte intégral et exact d'un article spécifique de règlement sans troncature.

Retourne `dict` avec `document_id`, `article_number`, `titre`, `contenu` et
`saison` ; lecture seule, idempotent, sans effet de bord, cache SWR.
Utilise cet outil quand tu connais le numéro d'article et le document (obtenu via
`ffbb_list_regulations` ou `ffbb_search_regulations`) et que tu veux le contenu
verbatim. Ne pas utiliser pour rechercher par mot-clé — utilise
`ffbb_search_regulations` à la place ; pour lister les documents disponibles —
utilise `ffbb_list_regulations` ; pour expliquer un départage — utilise
`ffbb_explain_tiebreak_rules`. Si `document_id` est omis, précise `organizer`
et `season` pour lever l'ambiguïté.
ParametersJSON Schema
NameRequiredDescriptionDefault
seasonNoSaison sportive (défaut '2026-2027')2026-2027
organizerNoOrganisateur du texte (ex: 'FFBB', 'Ligue AURA', 'Comité 63')
document_idNoIdentifiant du document source (ex: 'rsg_ffbb_2026_2027', 'rsp_u15_elite_2026_2027', 'reglement_aura_2026_2027', 'reglement_comite_63_2026_2027')
article_numberYesNuméro ou référence de l'article (ex: 'Article 28', 'Article 51', 'Article 4.1', 'Article 7')

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive, and the description partly restates them ('lecture seule, idempotent, sans effet de bord'), which earns no extra credit. It does add genuine context beyond the annotations: the no-truncation guarantee, the returned dict fields, and SWR caching behavior.

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 the verb and the no-truncation promise, then return shape, then routing. Efficient, though the safety restatement ('sans effet de bord') is mild redundancy against the annotations.

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?

No output schema exists, and the description compensates by enumerating the returned dict keys. Combined with the explicit alternative-tool routing and the ambiguity-resolution rule, an agent has everything needed to call this correctly.

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 baseline is 3, but the description adds real routing semantics: when document_id is omitted the caller must supply organizer and season to disambiguate. That is decision-relevant information the schema alone does not convey.

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 ('récupère le texte intégral et exact d'un article spécifique de règlement') plus the key differentiator 'sans troncature'. An agent can distinguish it from the search/list siblings 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 Guidelines5/5

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

Explicitly gives the when condition (article number known, document obtained via ffbb_list_regulations or ffbb_search_regulations) and names three alternatives by exact tool name with the condition that selects each. Also covers the fallback case when document_id is omitted.

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

ffbb_head_to_headFace-à-Face & Comparaison d'équipes (H2H)A
Read-onlyIdempotent

Compare deux équipes et analyse leurs confrontations directes (H2H) et dynamiques.

ParametersJSON Schema
NameRequiredDescriptionDefault
club_aNoNom du premier club (ex: 'Stade Clermontois').
club_bNoNom du second club / adversaire (ex: 'Vichy', 'Roanne').
poule_idNoID FFBB de la poule pour désambiguïser.
categorieNoCatégorie d'équipe commune à comparer (ex: 'SEM1', 'U18M', 'Senior').
club_nameNoAlias pour club_a : nom du premier club (ex: 'Stade Clermontois').
season_idNoID de la saison FFBB (optionnel).
adversaireNoAlias pour club_b : nom du second club / adversaire (ex: 'Vichy').
organisme_idNoAlias pour organisme_id_a : ID FFBB du premier club.
adversaire_idNoAlias pour organisme_id_b : ID FFBB du second club / adversaire.
engagement_idNoID FFBB de l'engagement partagé ou équipe A (alias pour engagement_id_a).
force_refreshNoSi True, force le rafraîchissement des données
competition_idNoID FFBB de la compétition pour désambiguïser.
organisme_id_aNoID FFBB du premier club (ex: '9326').
organisme_id_bNoID FFBB du second club / adversaire.
engagement_id_aNoID FFBB de l'engagement équipe A (prioritaire).
engagement_id_bNoID FFBB de l'engagement équipe B (prioritaire).
competition_typeNoType de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.

TDQS

A3.7/5.0
Behavior3/5

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

The annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is well covered. The description adds no behavioral context such as data source, caching, or return semantics, but it does not contradict the annotations either.

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?

The description is a single front-loaded sentence with no filler. The word 'dynamiques' is slightly ambiguous and prevents a perfect score, but the structure is efficient.

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

Completeness2/5

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

This is a high-complexity tool with 17 parameters, multiple alias groups, no output schema, and no required fields. The description only states the purpose and leaves the agent to infer which parameter combination to supply and what the response will contain, so it is incomplete for correct invocation.

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

Parameters3/5

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

All 17 parameters have schema descriptions, so the schema carries the semantic load and the baseline is 3. The description adds no guidance on alias groups or preferred identification methods (names vs IDs vs engagement IDs), which is a missed opportunity but not a deficiency given 100% schema coverage.

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?

The description uses 'Compare' as a specific verb, identifies 'deux équipes' as the resource, and explicitly mentions H2H, which distinguishes this tool from the single-team sibling tools like ffbb_team_summary or ffbb_last_result. The word 'dynamiques' is slightly vague, but the core purpose is unmistakable.

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?

The imperative 'Compare deux équipes' and the mention of 'confrontations directes (H2H)' make the intended use case clear: any request for a two-team head-to-head comparison. It does not explicitly name alternatives or give when-not-to-use conditions, so it falls short of full routing guidance.

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

ffbb_last_resultDernier résultat d'équipeA
Read-onlyIdempotent

Dernier résultat d'une équipe précise.

SINGULIER UNIQUEMENT: retourne le dernier match joué d'une seule équipe.
Recommendation LLM : Si la categorie est imprécise ou sans numéro (ex: 'U11M'),
appeler d'abord `ffbb_resolve_team` pour obtenir le `numero_equipe` reel.
ParametersJSON Schema
NameRequiredDescriptionDefault
poule_idNoID FFBB de la poule pour désambiguïser.
categorieNoCatégorie de l'équipe précise (ex: 'U11M1', 'U11M', 'SEM1', 'NM3').
club_nameNoNom du club (ex: 'Stade Clermontois')
season_idNoID de la saison FFBB (optionnel).
organisme_idNoIdentifiant FFBB du club (organisme_id, ex: '9326' ou 'ARA0063058').
engagement_idNoID FFBB de l'engagement (prioritaire pour désambiguïser).
force_refreshNoSi True, force un rafraichissement des donnees de poule
numero_equipeNoNuméro d'équipe dans la catégorie. Résoudre avec ffbb_resolve_team si ambigu.
competition_idNoID FFBB de la compétition pour désambiguïser.
competition_typeNoType de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive, openWorld. The description adds a genuine behavioral constraint beyond them: it returns a single team's last match only (singular scope), which shapes how the agent must call it. It omits return format/pagination, but the safety profile is already covered.

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?

Purpose is front-loaded, followed by the singular scope constraint and then the resolution recommendation in three short sentences. There is mild redundancy between 'dernier résultat d'une équipe précise' and 'le dernier match joué d'une seule équipe', but nothing wasteful.

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

Completeness4/5

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

For a read-only, idempotent tool with full schema coverage and no output schema, the definition covers purpose, scope and the disambiguation workflow adequately. It stops short of describing what the result payload contains, which is the only real gap given the absence of an output schema.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents all 10 parameters, including the numero_equipe resolution hint. The description repeats the resolve_team cross-reference but adds no syntax or format detail beyond what the schema provides, so it sits at the baseline.

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

Purpose4/5

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

The description states a specific verb and resource ('retourne le dernier match joué') and reinforces scope with 'SINGULIER UNIQUEMENT'. It implies a plural/batch counterpart but never names the sibling (e.g. next_match or team_summary) that an agent should compare against.

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?

It gives an explicit workflow condition: when the categorie is imprecise or numeric, call ffbb_resolve_team first to obtain the real numero_equipe. That names an alternative and the condition selecting it, though it does not contrast this tool against ffbb_next_match or ffbb_match_lookup.

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

ffbb_list_regulationsListe des règlements et juridictions FFBB disponiblesA
Read-onlyIdempotent

Liste l'ensemble des textes réglementaires fédéraux (RSG, RSP Élite, NM1-NM3, LF2-NF3), régionaux (Ligues IDF, Hauts-de-France, AURA...) et départementaux (Comités Paris, Nord, Rhône, Puy-de-Dôme...) indexés.

Retourne l'inventaire complet sous forme `dict` avec `documents[]`
(`document_id`, `titre`, `organizer`, `level`, `season`) trié par juridiction.
Lecture seule, idempotent, sans effet de bord ; cache SWR (TTL ≈24h).

Utilise cet outil pour découvrir les `document_id` disponibles avant d'appeler
`ffbb_get_regulation_article` ou pour choisir un périmètre avant
`ffbb_search_regulations`. Ne pas utiliser pour rechercher un extrait textuel —
utilise `ffbb_search_regulations` à la place ; pour obtenir le texte d'un article
précis — utilise `ffbb_get_regulation_article` ; pour expliquer un départage —
utilise `ffbb_explain_tiebreak_rules`. Avec `season`, filtre l'inventaire à la
saison ciblée (défaut `2026-2027`).
ParametersJSON Schema
NameRequiredDescriptionDefault
seasonNoSaison sportive (défaut '2026-2027')2026-2027

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the 'lecture seule, idempotent, sans effet de bord' sentence largely restates them. However, the description goes beyond annotations by disclosing the SWR cache with a ~24h TTL and the return shape (dict with documents[] sorted by jurisdiction), which is genuine behavioral context.

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?

The description is front-loaded with purpose, then return contract, then routing guidance, and every section is functional. The long parenthetical enumerations of leagues/committees are domain-useful but slightly verbose for a single-parameter list tool.

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 no output schema, the description compensates by naming the return type, the documents[] fields, and the sort order. For a one-parameter read-only listing tool, nothing an agent needs to invoke it correctly is missing.

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

Parameters3/5

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

There is a single optional parameter with 100% schema description coverage, so the schema already documents season and its default. The description adds only a restatement of the filtering behaviour and the same '2026-2027' default, no extra syntax or semantics.

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?

The description states a specific verb (Liste) and resource (textes réglementaires fédéraux/régionaux/départementaux) with precise scope, enumerating the categories covered. It is immediately distinguishable from siblings like ffbb_search_regulations and ffbb_get_regulation_article, which are named explicitly.

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

Usage Guidelines5/5

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

It gives explicit when-to-use cases (discover document_id before calling ffbb_get_regulation_article, or choose a perimeter before ffbb_search_regulations) and explicit when-not-to-use cases, routing to three named alternative tools for search, article retrieval, and tiebreak explanation.

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

ffbb_livesScores en directC
Read-onlyIdempotent

Flux live FFBB, éventuellement complété par un calendrier ciblé et prudent.

ParametersJSON Schema
NameRequiredDescriptionDefault
categorieNoCatégorie de l'équipe ciblée, par exemple U18M ou NM2.
club_nameNoNom du club si son identifiant n'est pas connu.
organisme_idNoID du club pour cibler et compléter le flux live.
engagement_idNoID d'engagement précis de l'équipe ciblée.
numero_equipeNoNuméro de l'équipe ciblée dans la catégorie.
include_scheduledNoSi True, inclut aussi les matchs programmés à venir (statut SCHEDULED). Par défaut (False), ne retourne que les matchs réellement en cours de jeu.
include_calendar_fallbackNoPour une cible club/équipe, complète le flux FFBB avec les matchs dont l'horaire est dépassé, sans les présenter comme live confirmés.

TDQS

C2.9/5.0
Behavior3/5

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

The annotations already declare the operation read-only, idempotent, non-destructive, and open-world, so the safety profile is covered. The description adds a weak behavioral hint that the live stream may be supplemented by a 'ciblé et prudent' calendar, indicating not all returned entries are confirmed live. But it lacks detail about data freshness, response shape, or why the fallback is cautious, and it partly duplicates the include_calendar_fallback parameter description.

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

Conciseness2/5

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

The description is extremely short, but it is an under-specified noun phrase rather than a useful sentence. It spends its only clause on vague marketing-like wording ('ciblé et prudent') instead of concrete behavior. For a tool with 7 optional parameters, this is under-specification, not effective conciseness.

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

Completeness2/5

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

With no output schema and 7 optional parameters, an agent receives almost no help on what the response contains or how to build a valid request. The description omits return values, data source restrictions, and any example usage patterns. The annotations cover safety but not operational completeness, so the description is insufficient.

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

Parameters3/5

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

All 7 parameters are described in the input schema (100% coverage), so the schema carries the semantic load. The description itself provides no additional parameter-level meaning beyond the vague 'calendrier ciblé' phrase, which maps to include_calendar_fallback. Baseline 3 is appropriate.

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

Purpose4/5

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

The description identifies the tool as a live FFBB feed and hints at calendar augmentation, so an agent can infer it returns live basketball scores. However, it is a noun phrase with no explicit verb such as 'retrieves' or 'returns,' and it does not directly distinguish itself from sibling tools like ffbb_last_result or ffbb_next_match. This is clear but not fully specified.

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

Usage Guidelines2/5

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

The description contains no guidance on when to prefer ffbb_lives over the many sibling tools. It neither states 'use for current in-progress games' nor mentions alternatives or exclusion conditions. A user must infer usage from the word 'live' and the title 'Scores en direct.'

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

ffbb_match_lookupRecherche directe de match entre 2 clubsA
Read-onlyIdempotent

Recherche directe d'un match entre 2 clubs : date, heure, salle, adresse et poule.

Outil haut niveau idéal pour répondre aux questions du type :
'Où se joue U18M2 Thiers vs Gerzat ce week-end ?' ou 'Quand a lieu le match X contre Y ?'.
ParametersJSON Schema
NameRequiredDescriptionDefault
club_aYesNom ou identifiant du premier club (ex: 'Thiers', 'SA Thiers Vaillante').
club_bYesNom ou identifiant du second club / adversaire (ex: 'Gerzat', 'Gerzat Basket').
date_maxNoDate de fin facultative au format 'YYYY-MM-DD'.
date_minNoDate de début facultative au format 'YYYY-MM-DD'.
categorieNoCatégorie ou division de l'équipe (ex: 'U18M2', 'U18M', 'DMU18', 'Senior', 'NM3'). Permet de cibler la confrontation exacte.
force_refreshNoSi True, force le rafraîchissement des données.

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is fully covered structurally. The description adds the returned field set but says nothing about ambiguous club-name resolution, empty results, or the effect of force_refresh — useful gaps remain with a lower bar due to annotations.

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 the core definition in the first clause, then illustrative examples. The two example questions partially overlap in what they convey, so it is efficient but not maximally tight.

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

Completeness4/5

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

With no output schema, the description usefully enumerates the returned fields, and all six parameters are documented in the schema. It stops short of covering failure/ambiguity behavior (no match found, name vs id input), which would matter for a lookup tool of this type.

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

Parameters3/5

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

Schema description coverage is 100%, with each parameter documented inline including examples and the 'YYYY-MM-DD' format, so the schema carries the full burden. The description only implicitly references club pairing and category via its example questions, adding no syntax or semantics beyond the schema. Baseline 3 applies.

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

Purpose4/5

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

States a specific verb and resource ('Recherche directe d'un match entre 2 clubs') and enumerates the returned fields (date, heure, salle, adresse, poule), so the agent knows exactly what it retrieves. It does not differentiate itself from close siblings like ffbb_head_to_head or ffbb_next_match, which is the only thing keeping it out of the top band.

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?

Concrete example questions ('Où se joue U18M2 Thiers vs Gerzat ce week-end ?') give a clear picture of when this tool is the right call. However, it never states when *not* to use it or names an alternative such as ffbb_head_to_head for history between two clubs.

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

ffbb_next_matchProchain match d'équipeA
Read-onlyIdempotent

Prochain match à jouer pour une équipe précise.

⚠️ SINGULIER UNIQUEMENT. Si la demande est au pluriel
("matchs restants", "derniers matchs à jouer", "calendrier"),
utiliser ffbb_club(action="calendrier") à la place.

⚠️ ATTENTION LLM : Cet outil retourne STRICTEMENT LE PROCHAIN MATCH UNIQUE.
Ne l'utilise JAMAIS si l'utilisateur demande "les prochains matchs" au pluriel.
Pour toute requête au pluriel, utilise OBLIGATOIREMENT `ffbb_club(action="calendrier")`
et filtre les résultats toi-même.

Recommendation LLM : Si la categorie est imprécise ou sans numéro (ex: 'U11M'),
appeler d'abord `ffbb_resolve_team` pour obtenir le `numero_equipe` reel.
ParametersJSON Schema
NameRequiredDescriptionDefault
poule_idNoID FFBB de la poule pour désambiguïser.
categorieNoCatégorie de l'équipe précise (ex: 'U11M1', 'U11M', 'SEM1', 'NM3').
club_nameNoNom du club (ex: 'Stade Clermontois')
season_idNoID de la saison FFBB (optionnel).
organisme_idNoIdentifiant FFBB du club (organisme_id, ex: '9326' ou 'ARA0063058').
engagement_idNoID FFBB de l'engagement (prioritaire pour désambiguïser).
force_refreshNoSi True, force un rafraichissement des donnees de poule
numero_equipeNoNuméro d'équipe dans la catégorie. Résoudre avec ffbb_resolve_team si ambigu.
competition_idNoID FFBB de la compétition pour désambiguïser.
competition_typeNoType de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive, open-world, so the safety profile is covered. The description adds real behavioral context beyond them — that the return is strictly a single next match (not a list), and that team resolution should be performed upstream. It does not mention caching/refresh behavior even though the schema exposes a force_refresh flag.

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?

The constraint is front-loaded and the alternative routing is given immediately. However, the singular-only rule is restated three times across two warning blocks, which is redundant text that inflates the definition.

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?

For a 10-parameter disambiguation tool with no output schema and no required fields (anyOf), the definition supplies the missing pieces an agent needs: the singular scope, the fallback tool for plural queries, and the team-resolution prerequisite. Nothing essential to correct invocation is absent.

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 description coverage is 100%, so the baseline is 3, but the description adds genuine parameter-level guidance: it warns that an imprecise category (e.g. 'U11M' without a number) requires resolving numero_equipe via ffbb_resolve_team first. It does not explain disambiguation precedence among the many optional IDs beyond what the schema already says.

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+resource in the first line: the next match to play for a precise team. It explicitly bounds the scope to a single next match and names the sibling it must not be confused with (ffbb_club with action="calendrier"), so an agent can route correctly 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 Guidelines5/5

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

Explicitly covers when NOT to use it (any plural request such as 'matchs restants', 'calendrier'), names the exact alternative tool and action to use instead, and adds a prerequisite step (call ffbb_resolve_team first when the category lacks a number). This is about as complete as usage guidance gets.

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

ffbb_resolve_teamRésolution d'équipeA
Read-onlyIdempotent

Identifie une equipe unique (Pivot central).

DOIT etre utilise avant `ffbb_next_match` ou `ffbb_last_result` si l'agent
ne connait pas le numero d'equipe exact ou si la categorie est ambiguë (ex: 'U11M').
Pour une équipe senior au niveau national ou régional, la catégorie FFBB interne est souvent `SEM1` ou `SEF1` ;
le serveur résout désormais `NM3`, `NM2`, `NF1`, `PNM`, `R2`, etc. vers la bonne équipe et sa poule.

Politique : si une catégorie sans numéro (ex: 'U18M') correspond à plusieurs équipes (ex: U18M1, U18M2),
retourne 'ambiguous' (confiance 0.5) sans trancher arbitrairement.
Pour des suggestions heuristiques ordonnées (U18M1 à 0.85), utiliser `ffbb_find_team_candidates`.
ParametersJSON Schema
NameRequiredDescriptionDefault
poule_idNoID FFBB de la poule pour désambiguïser.
categorieNoCatégorie + genre + numéro d'équipe (ex: 'U11M1', 'U13F2', 'SEM1') ou division (ex: 'NM3', 'R2', 'PNM'). Si le numéro manque, cet outil retourne la bonne équipe ou des candidats.
club_nameNoNom du club (ex: 'Stade Clermontois', 'ASVEL').
season_idNoID de la saison FFBB (optionnel).
organisme_idNoID FFBB du club (alternative plus rapide à club_name).
engagement_idNoID FFBB de l'engagement (prioritaire pour désambiguïser).
force_refreshNoSi True, force le rafraîchissement des données.
numero_equipeNoNuméro d'équipe facultatif (ex: 1, 2).
competition_idNoID FFBB de la compétition pour désambiguïser.
competition_typeNoType de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, openWorld, non-destructive), so the bar is lower, yet the description still adds real behavior: on an ambiguous category it returns 'ambiguous' with confidence 0.5 rather than guessing, and it documents which external division codes (NM3, NM2, NF1, PNM, R2) the server now resolves. It does not describe caching/force_refresh effects, so it stops short of a 5.

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?

Purpose and the pre-requisite order are front-loaded, and the ambiguity policy is stated crisply. The 'le serveur résout désormais ...' sentence reads like a changelog note and could be trimmed without losing instruction value.

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

Completeness4/5

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

For a 10-parameter resolver with no output schema and no required fields, the description covers the essential contract: it says a single team is returned, that disambiguation inputs exist, and what happens on ambiguity. It stops short of describing the full return shape (fields for success, team id, candidate lists), which the absent output schema would otherwise have carried.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents category formats, IDs and disambiguation roles; the baseline is 3. The description's category example ('SEM1'/'SEF1', division codes) largely restates the schema field description, adding only marginal meaning beyond it.

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?

The description opens with a specific verb+resource ('Identifie une equipe unique') and frames the tool as the central pivot of team resolution. It explicitly distinguishes itself from siblings ffbb_next_match, ffbb_last_result and ffbb_find_team_candidates, so an agent can pick it 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 Guidelines5/5

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

It states the trigger condition precisely: use before ffbb_next_match/ffbb_last_result when the exact team number is unknown or the category is ambiguous (e.g. 'U11M'). It also routes to the correct alternative for a different need ('Pour des suggestions heuristiques ordonnées ... utiliser ffbb_find_team_candidates'), covering both when-to-use and when-to-use-something-else.

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

ffbb_saisonsListe des saisons FFBBB
Read-onlyIdempotent

Liste des saisons FFBB (référentiel temporel).

ParametersJSON Schema
NameRequiredDescriptionDefault
active_onlyNoTrue = saison active uniquement.
force_refreshNoSi True, contourne le cache.

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is fully covered without the description. The description adds only the referential framing and says nothing about caching behavior, which the force_refresh parameter implies exists.

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?

A single short sentence, front-loaded with the verb and resource, with no filler. It is arguably too terse for a tool with a cache-control parameter, but every word does earn its place.

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

Completeness3/5

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

For a simple two-optional-boolean reference list with rich annotations and 100% schema coverage, the description is minimally sufficient to call the tool. It leaves clear gaps around sibling routing and cache/refresh semantics that an agent might need in this crowded toolset.

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

Parameters3/5

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

Schema description coverage is 100%, so active_only and force_refresh are already fully documented in the schema. The description adds no syntax, format, or default details beyond that baseline.

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

Purpose4/5

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

States a specific verb ("Liste") and resource ("saisons FFBB"), so the agent knows exactly what it returns. However, it does not differentiate itself from siblings such as ffbb_bilan_saison or ffbb_version, which a season-reference tool arguably should.

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

Usage Guidelines2/5

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

There is no when-to-use or when-not-to-use guidance and no named alternative. The parenthetical "référentiel temporel" faintly implies this is the canonical season list, but an agent gets no explicit routing rule against the many sibling tools.

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

ffbb_search_regulationsRecherche dans les règlements sportifs FFBBA
Read-onlyIdempotent

Recherche plein texte déterministe dans les règlements officiels FFBB, régionaux et départementaux.

Permet de retrouver les articles pertinents sur les qualifications, montées/descentes,
brassages jeunes, règles techniques (durée, ballons, zone), forfaits et brûlage.
Retourne `dict` avec `results[]` (`id`, `document_id`, `article_number`, `article_title`, `relevance_score`, `content`, `topics[]`, `source_url`)
triés par pertinence ; lecture seule, idempotent, cache SWR.

Utilise cet outil quand tu ne connais pas le numéro d'article et que tu cherches par
mots-clés. Ne pas utiliser pour récupérer un article précis — utilise
`ffbb_get_regulation_article` à la place ; pour lister les documents — utilise
`ffbb_list_regulations` ; pour expliquer un départage — utilise
`ffbb_explain_tiebreak_rules` au lieu de chercher le texte. Affûte avec `level`,
`organizer`, `category` et `limit` pour réduire le bruit.
ParametersJSON Schema
NameRequiredDescriptionDefault
levelNoNiveau de compétition ciblé : 'federal' (FFBB national / RSG / Élite), 'regional' (Ligues, ex: AURA), 'departmental' (Comités, ex: Comité 63)
limitNoNombre maximal d'extraits d'articles à retourner (défaut 5, max 10)
queryNoTerme ou question de recherche dans les règlements (ex: 'brûlage équipe réserve', 'défense de zone U13', 'brassages départementaux', 'barrages accession')
topicNoMots-clés thématiques (ex: 'departages', 'brulage', 'forfaits', 'poule_haute')
seasonNoSaison sportive ciblée (par défaut '2026-2027')2026-2027
categoryNoCatégorie d'âge ou division (ex: 'U13', 'U15', 'U18', 'seniors', 'elite')
organizerNoNom ou sigle de l'organisateur (ex: 'FFBB', 'Ligue AURA', 'Comité 63')

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint/idempotentHint/destructiveHint, so the description's restatement of 'lecture seule, idempotent' earns no credit. It does add genuinely new behavior: deterministic search semantics, an SWR cache, and the full return shape (results[] sorted by relevance with id, document_id, article_number, relevance_score, content, topics, source_url). Minor deduction for the redundant safety restatement.

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

Conciseness5/5

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

Front-loaded with what the tool does, then return shape, then routing exclusions, then parameter tuning. Dense but every sentence carries a distinct payload; the result-field enumeration is justified since there is no output schema.

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 no output schema, the description supplies the return structure itself; with 7 optional parameters, it supplies the tuning strategy. Combined with the explicit sibling routing, an agent has everything needed to call this correctly on the first try.

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 description coverage is 100%, so the baseline is 3 and the schema already carries syntax/defaults for all seven parameters. The description goes beyond it by telling the agent which parameters actually matter for noise reduction ('Affûte avec level, organizer, category et limit'), which is actionable guidance the schema does not provide.

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 plein texte déterministe dans les règlements officiels FFBB, régionaux et départementaux'), enumerates the subject matter covered (qualifications, montées/descentes, brassages, règles techniques, forfaits, brûlage), and is instantly distinguishable from the three named siblings.

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

Usage Guidelines5/5

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

Explicitly states when to use it ('quand tu ne connais pas le numéro d'article et que tu cherches par mots-clés') and then names three alternatives with the condition that selects each: ffbb_get_regulation_article for a known article, ffbb_list_regulations for listing, ffbb_explain_tiebreak_rules for tiebreak explanations. Nothing 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.

ffbb_team_summaryRésumé complet d'équipeA
Read-onlyIdempotent

Synthèse recommandée d'une équipe (résultats, prochain match, classement, dynamique en 1 appel).

Préférer cet outil pour toute question d'équipe ('Comment vont les U13M2 ?', 'NM3', etc.).
Pour une analyse multi-phases ou coupes, utiliser `ffbb_bilan_saison`.
Restituer strictement les chiffres officiels sans présumer de forfaits ou d'anomalies sur la seule base de scores faibles (fréquents en catégories jeunes).
ParametersJSON Schema
NameRequiredDescriptionDefault
detailNoSi True, inclut les colonnes détaillées du classement (pénalités, forfaits, logos).
includeNoSections à inclure : 'bilan', 'last', 'next', 'classement', 'dynamique'. Défaut: ['bilan', 'last', 'next', 'classement'].
poule_idNoID FFBB de la poule pour désambiguïser.
categorieNoCatégorie/division + genre + numéro d'équipe (ex: 'U11M1', 'U13F2', 'SEM1', 'NM3', 'PNM').
club_nameNoNom du club (ex: 'Stade Clermontois', 'ASVEL').
season_idNoID de la saison FFBB (optionnel).
organisme_idNoID FFBB du club (alternative plus rapide à club_name).
engagement_idNoID FFBB de l'engagement (prioritaire pour désambiguïser).
force_refreshNoSi True, force un rafraichissement des donnees
numero_equipeNoNuméro d'équipe dans la catégorie (ex: 1, 2).
competition_idNoID FFBB de la compétition pour désambiguïser.
competition_typeNoType de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), so the bar is lower. The description still adds genuine behavioural guidance beyond them: the single-call aggregation promise and the caution to report only official figures rather than inferring forfeits/anomalies from low scores in youth categories. It does not mention caching or what force_refresh actually re-fetches, which is the one remaining gap.

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

Conciseness5/5

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

Four short, front-loaded lines: what it returns, when to prefer it, which sibling to use instead, and one interpretive caveat. Nothing is restated and the scope statement comes first.

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

Completeness4/5

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

For a 12-parameter, identifier-flexible aggregation tool, the description covers scope, routing and interpretation but never sketches the shape of the assembled response (no output schema exists), leaving the agent to guess how bilan/last/next/classement are returned. Otherwise complete enough given 100% parameter documentation.

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

Parameters3/5

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

Schema description coverage is 100% and every one of the 12 parameters carries its own description (include sections, categorie format, id-vs-name alternatives, force_refresh), so the schema does the heavy lifting. The description echoes the section list parenthetically but adds no syntax or precedence semantics beyond that, which matches the baseline 3.

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+resource ('Synthèse d'une équipe') and enumerates the exact payload (résultats, prochain match, classement, dynamique en 1 appel), which lets an agent distinguish it from the narrower siblings ffbb_last_result, ffbb_next_match and ffbb_bilan without opening any schema. It also explicitly names ffbb_bilan_saison as the multi-phase variant.

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

Usage Guidelines5/5

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

'Préférer cet outil pour toute question d'équipe' with two worked example queries gives an explicit when-to-use, and 'Pour une analyse multi-phases ou coupes, utiliser `ffbb_bilan_saison`' names the alternative and the condition that selects it. Routing is unambiguous.

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

ffbb_versionVersion et diagnostics serveurA
Read-onlyIdempotent

Version et configuration runtime du serveur FFBB MCP.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is fully covered. The description adds only the scope of the payload (version plus runtime configuration), which is useful but thin — no mention of whether the config could expose sensitive values or whether auth is required.

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?

A single short sentence with no filler and the resource front-loaded. It is efficient, though it omits the 'diagnostics' aspect advertised in the title, so the sentence is not earning every bit of value it could.

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

Completeness4/5

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

For a zero-parameter, non-destructive read with no output schema, the description conveys enough to call it correctly: it names the returned content (version and runtime configuration). Missing only minor context such as cost/latency or auth expectations.

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?

The tool takes zero parameters, so the baseline is 4. Nothing in the description is needed to disambiguate inputs, and no param detail is missing.

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

Purpose4/5

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

States a specific resource — server version and runtime configuration of the FFBB MCP server — which is unmistakably distinct from every sibling (saisons, lives, bilan, search, regulations, team tools) that deal with FFBB data rather than server metadata. It is clear what the tool does, though it never explicitly contrasts itself with siblings.

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

Usage Guidelines3/5

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

No explicit when-to-use or when-not-to-use guidance is given. Usage is only implied by the title ('Version et diagnostics serveur'), letting an agent infer this is a diagnostic call rather than a data lookup. No prerequisites or alternatives are named.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv1.16.11
    • Changedffbb_club1 field changed
      • changedInput schema / properties / action / description
        Previous value: -"Action : 'calendrier' (matchs pluriels/restants), 'equipes' ou 'classement'."New value: +"Action : 'calendrier' (matchs pluriels/restants), 'equipes' ou 'classement'. Pour 'calendrier' : Renvoie les rencontres programmées. Restituer factuellement les matchs sans spéculer sur de futures journées non publiées, des repos ou des forfaits. Pour 'classement' : Classement seul d'une poule ou d'un club. Utiliser uniquement si poule_id est connu et que team_summary n'a pas été appelé."
    • Addedffbb_match_lookup
    • Changedffbb_search4 fields changed
      • addedInput schema / properties / code_postal
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Filtrer par code postal à 5 chiffres (ex: '63300').",
        +  "title": "Code Postal"
        +}
      • addedInput schema / properties / commune
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Filtrer par commune/ville (ex: 'Thiers').",
        +  "title": "Commune"
        +}
      • addedInput schema / properties / compact
        Added value: +{
        +  "default": false,
        +  "description": "Si True, réponse compacte allégée pour agents IA.",
        +  "title": "Compact",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / filter_by / description
        Previous value: -"Filtre Meilisearch natif (ex: 'codePostal = \"63000\"', 'codePostal IN [\"63000\", \"63100\"]', 'departement = \"Puy-de-Dôme\"')."New value: +"Filtre Meilisearch natif (ex: 'codePostal = \"63000\"')."
    • Changedffbb_team_summary2 fields changed
      • addedInput schema / properties / detail
        Added value: +{
        +  "default": false,
        +  "description": "Si True, inclut les colonnes détaillées du classement (pénalités, forfaits, logos).",
        +  "title": "Detail",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / include
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Sections à inclure : 'bilan', 'last', 'next', 'classement', 'dynamique'. Défaut: ['bilan', 'last', 'next', 'classement'].",
        +  "title": "Include"
        +}
  2. 2 tool updatesv1.16.4
    • Changedffbb_get1 field changed
      • changedInput schema / properties / type / enum
        Previous value: -[
        -  "competition",
        -  "poule",
        -  "organisme",
        -  "rencontre",
        -  "officiel",
        -  "entraineur",
        -  "salle"
        -]New value: +[
        +  "competition",
        +  "poule",
        +  "organisme",
        +  "rencontre",
        +  "officiel",
        +  "entraineur",
        +  "salle",
        +  "engagement"
        +]
    • Changedffbb_search2 fields changed
      • changedInput schema / properties / sort / description
        Previous value: -"Tri Meilisearch (ex: ['libelle:asc'])."New value: +"Tri Meilisearch (ex: ['nom:asc'])."
      • changedInput schema / properties / type / enum
        Previous value: -[
        -  "all",
        -  "competitions",
        -  "organismes",
        -  "rencontres",
        -  "salles",
        -  "pratiques",
        -  "terrains",
        -  "tournois",
        -  "engagements",
        -  "formations",
        -  "officiels",
        -  "entraineurs",
        -  "communes"
        -]New value: +[
        +  "all",
        +  "competitions",
        +  "organismes",
        +  "rencontres",
        +  "salles",
        +  "pratiques",
        +  "terrains",
        +  "tournois",
        +  "engagements",
        +  "formations",
        +  "news",
        +  "galeries",
        +  "rss"
        +]
  3. 3 tool updatesv1.15.0
    • Changedffbb_club9 fields changed
      • addedInput schema / properties / exclude_competition_types
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Types de compétition exclus (ex: ['PLAT']).",
        +  "title": "Exclude Competition Types"
        +}
      • addedInput schema / properties / group_by
        Added value: +{
        +  "anyOf": [
        +    {
        +      "enum": [
        +        "competition",
        +        "team",
        +        "date"
        +      ],
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Regroupement : competition, team ou date.",
        +  "title": "Group By"
        +}
      • addedInput schema / properties / include_competition_types
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Types de compétition inclus (ex: ['DIV']).",
        +  "title": "Include Competition Types"
        +}
      • addedInput schema / properties / include_friendlies
        Added value: +{
        +  "default": false,
        +  "description": "Inclut les amicaux (exclus par défaut).",
        +  "title": "Include Friendlies",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / include_reserves
        Added value: +{
        +  "default": false,
        +  "description": "Inclut les réserves si demande équipe 1.",
        +  "title": "Include Reserves",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / include_youth
        Added value: +{
        +  "default": false,
        +  "description": "Inclut les équipes jeunes si demande senior.",
        +  "title": "Include Youth",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / scope
        Added value: +{
        +  "anyOf": [
        +    {
        +      "enum": [
        +        "team",
        +        "club",
        +        "competition"
        +      ],
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Scope : 'team' (équipe résolue), 'club' (global club) ou 'competition'.",
        +  "title": "Scope"
        +}
      • addedInput schema / properties / status_filter
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Filtre statuts : scheduled, live, final.",
        +  "title": "Status Filter"
        +}
      • addedInput schema / properties / strict_filters
        Added value: +{
        +  "default": true,
        +  "description": "Filtrage strict sans extrapolation (défaut True).",
        +  "title": "Strict Filters",
        +  "type": "boolean"
        +}
    • Addedffbb_find_team_candidates
    • Changedffbb_lives6 fields changed
      • addedInput schema / properties / categorie
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Catégorie de l'équipe ciblée, par exemple U18M ou NM2.",
        +  "title": "Categorie"
        +}
      • addedInput schema / properties / club_name
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Nom du club si son identifiant n'est pas connu.",
        +  "title": "Club Name"
        +}
      • addedInput schema / properties / engagement_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID d'engagement précis de l'équipe ciblée.",
        +  "title": "Engagement Id"
        +}
      • addedInput schema / properties / include_calendar_fallback
        Added value: +{
        +  "default": true,
        +  "description": "Pour une cible club/équipe, complète le flux FFBB avec les matchs dont l'horaire est dépassé, sans les présenter comme live confirmés.",
        +  "title": "Include Calendar Fallback",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / numero_equipe
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Numéro de l'équipe ciblée dans la catégorie.",
        +  "title": "Numero Equipe"
        +}
      • addedInput schema / properties / organisme_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID du club pour cibler et compléter le flux live.",
        +  "title": "Organisme Id"
        +}
  4. 1 tool updatev1.14.5
    • Changedffbb_head_to_head1 field changed
      • changedInput schema / anyOf
        Previous value: -[
        -  {
        -    "required": [
        -      "club_a"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "organisme_id_a"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "club_name"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "organisme_id"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "engagement_id_a"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "engagement_id"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "poule_id"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "required": [
        +      "club_a"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "organisme_id_a"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id_a"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id_b"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "poule_id"
        +    ]
        +  }
        +]
  5. 16 tool updatesv1.13.0
    • Changedffbb_bilan8 fields changed
      • changedInput schema / anyOf
        Previous value: -[
        -  {
        -    "required": [
        -      "club_name"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "organisme_id"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "poule_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "competition_id"
        +    ]
        +  }
        +]
      • changedInput schema / properties / club_name / description
        Previous value: -"Nom du club (ex: 'Stade Clermontois', 'ASVEL')."New value: +"Nom du club (ex: 'Stade Clermontois', 'ASVEL'). Requis si organisme_id absent."
      • addedInput schema / properties / competition_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la compétition pour désambiguïser.",
        +  "title": "Competition Id"
        +}
      • addedInput schema / properties / competition_type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Type de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.",
        +  "title": "Competition Type"
        +}
      • addedInput schema / properties / engagement_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de l'engagement (prioritaire pour désambiguïser).",
        +  "title": "Engagement Id"
        +}
      • changedInput schema / properties / organisme_id / description
        Previous value: -"ID FFBB du club (ex: 9326)."New value: +"ID FFBB du club (ex: '9326' ou 'ARA0063058'). Requis si club_name absent."
      • addedInput schema / properties / poule_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la poule pour désambiguïser.",
        +  "title": "Poule Id"
        +}
      • addedInput schema / properties / season_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID de la saison FFBB (optionnel).",
        +  "title": "Season Id"
        +}
    • Changedffbb_bilan_saison7 fields changed
      • changedInput schema / anyOf
        Previous value: -[
        -  {
        -    "required": [
        -      "club_name"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "organisme_id"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "poule_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "competition_id"
        +    ]
        +  }
        +]
      • addedInput schema / properties / competition_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la compétition pour désambiguïser.",
        +  "title": "Competition Id"
        +}
      • addedInput schema / properties / competition_type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Type de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.",
        +  "title": "Competition Type"
        +}
      • addedInput schema / properties / engagement_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de l'engagement (prioritaire pour désambiguïser).",
        +  "title": "Engagement Id"
        +}
      • changedInput schema / properties / numero_equipe / default
        Previous value: -1New value: +null
      • addedInput schema / properties / poule_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la poule pour désambiguïser.",
        +  "title": "Poule Id"
        +}
      • addedInput schema / properties / season_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID de la saison FFBB (optionnel).",
        +  "title": "Season Id"
        +}
    • Changedffbb_club14 fields changed
      • changedInput schema / anyOf
        Previous value: -[
        -  {
        -    "required": [
        -      "club_name"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "organisme_id"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "poule_id"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "poule_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "competition_id"
        +    ]
        +  }
        +]
      • addedInput schema / properties / action / default
        Added value: +"calendrier"
      • addedInput schema / properties / competition_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la compétition pour désambiguïser.",
        +  "title": "Competition Id"
        +}
      • addedInput schema / properties / competition_type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Type de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.",
        +  "title": "Competition Type"
        +}
      • addedInput schema / properties / engagement_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de l'engagement (prioritaire pour désambiguïser).",
        +  "title": "Engagement Id"
        +}
      • changedInput schema / properties / filtre / description
        Previous value: -"Filtre catégorie/genre (ex: 'U11M', 'Senior', 'NM3')."New value: +"Filtre catégorie/genre (alias pour 'categorie', ex: 'U11M', 'Senior', 'NM3')."
      • changedInput schema / properties / limit / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "maximum": 100,
        +    "minimum": 1,
        +    "type": "integer"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / limit / description
        Previous value: -"Nombre max de matchs retournés (pagination)."New value: +"Nombre max de matchs retournés (1-100, pagination)."
      • addedInput schema / properties / offset
        Added value: +{
        +  "anyOf": [
        +    {
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Index de départ pour pagination calendrier (défaut 0).",
        +  "title": "Offset"
        +}
      • changedInput schema / properties / organisme_id / description
        Previous value: -"ID FFBB du club (ex: 9326). Requis si club_name absent."New value: +"ID FFBB du club (ex: '9326'). Requis si club_name absent."
      • changedInput schema / properties / poule_id / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / poule_id / description
        Previous value: -"ID poule (action='classement'). Optionnel si club et catégorie sont fournis."New value: +"ID poule (action='classement' ou 'calendrier'). Optionnel si club et catégorie sont fournis."
      • addedInput schema / properties / season_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID de la saison FFBB (optionnel).",
        +  "title": "Season Id"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "action"
        -]
    • Addedffbb_explain_tiebreak_rules
    • Changedffbb_get3 fields changed
      • addedInput schema / properties / id / anyOf
        Added value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "string"
        +  }
        +]
      • changedInput schema / properties / id / description
        Previous value: -"Identifiant numérique FFBB exact. Ne pas passer un nom de club: utiliser d'abord ffbb_search pour résoudre l'id."New value: +"Identifiant FFBB exact (string opaque, ex: '200000003057825'). Ne pas passer un nom de club: utiliser d'abord ffbb_search pour résoudre l'id."
      • removedInput schema / properties / id / type
        Removed value: -"integer"
    • Addedffbb_get_regulation_article
    • Changedffbb_head_to_head15 fields changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "club_a"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "organisme_id_a"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id_a"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "poule_id"
        +    ]
        +  }
        +]
      • addedInput schema / properties / adversaire
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Alias pour club_b : nom du second club / adversaire (ex: 'Vichy').",
        +  "title": "Adversaire"
        +}
      • addedInput schema / properties / adversaire_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Alias pour organisme_id_b : ID FFBB du second club / adversaire.",
        +  "title": "Adversaire Id"
        +}
      • changedInput schema / properties / club_b / description
        Previous value: -"Nom du second club (ex: 'Vichy', 'Roanne')."New value: +"Nom du second club / adversaire (ex: 'Vichy', 'Roanne')."
      • addedInput schema / properties / club_name
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Alias pour club_a : nom du premier club (ex: 'Stade Clermontois').",
        +  "title": "Club Name"
        +}
      • addedInput schema / properties / competition_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la compétition pour désambiguïser.",
        +  "title": "Competition Id"
        +}
      • addedInput schema / properties / competition_type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Type de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.",
        +  "title": "Competition Type"
        +}
      • addedInput schema / properties / engagement_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de l'engagement partagé ou équipe A (alias pour engagement_id_a).",
        +  "title": "Engagement Id"
        +}
      • addedInput schema / properties / engagement_id_a
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de l'engagement équipe A (prioritaire).",
        +  "title": "Engagement Id A"
        +}
      • addedInput schema / properties / engagement_id_b
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de l'engagement équipe B (prioritaire).",
        +  "title": "Engagement Id B"
        +}
      • addedInput schema / properties / organisme_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Alias pour organisme_id_a : ID FFBB du premier club.",
        +  "title": "Organisme Id"
        +}
      • changedInput schema / properties / organisme_id_a / description
        Previous value: -"ID FFBB du premier club (ex: 9326)."New value: +"ID FFBB du premier club (ex: '9326')."
      • changedInput schema / properties / organisme_id_b / description
        Previous value: -"ID FFBB du second club."New value: +"ID FFBB du second club / adversaire."
      • addedInput schema / properties / poule_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la poule pour désambiguïser.",
        +  "title": "Poule Id"
        +}
      • addedInput schema / properties / season_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID de la saison FFBB (optionnel).",
        +  "title": "Season Id"
        +}
    • Changedffbb_last_result15 fields changed
      • changedInput schema / anyOf
        Previous value: -[
        -  {
        -    "required": [
        -      "club_name"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "organisme_id"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "poule_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "competition_id"
        +    ]
        +  }
        +]
      • addedInput schema / properties / categorie / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / categorie / default
        Added value: +null
      • changedInput schema / properties / categorie / description
        Previous value: -"Catégorie de l'équipe précise (ex: 'U11M1', 'U11M', 'U11F')"New value: +"Catégorie de l'équipe précise (ex: 'U11M1', 'U11M', 'SEM1', 'NM3')."
      • removedInput schema / properties / categorie / type
        Removed value: -"string"
      • addedInput schema / properties / competition_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la compétition pour désambiguïser.",
        +  "title": "Competition Id"
        +}
      • addedInput schema / properties / competition_type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Type de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.",
        +  "title": "Competition Type"
        +}
      • addedInput schema / properties / engagement_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de l'engagement (prioritaire pour désambiguïser).",
        +  "title": "Engagement Id"
        +}
      • addedInput schema / properties / numero_equipe / anyOf
        Added value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / numero_equipe / default
        Previous value: -1New value: +null
      • removedInput schema / properties / numero_equipe / type
        Removed value: -"integer"
      • changedInput schema / properties / organisme_id / description
        Previous value: -"Identifiant FFBB du club (organisme_id, ex: 1234 ou 'ARA0063058')"New value: +"Identifiant FFBB du club (organisme_id, ex: '9326' ou 'ARA0063058')."
      • addedInput schema / properties / poule_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la poule pour désambiguïser.",
        +  "title": "Poule Id"
        +}
      • addedInput schema / properties / season_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID de la saison FFBB (optionnel).",
        +  "title": "Season Id"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "categorie"
        -]
    • Addedffbb_list_regulations
    • Changedffbb_lives1 field changed
      • addedInput schema / properties / include_scheduled
        Added value: +{
        +  "default": false,
        +  "description": "Si True, inclut aussi les matchs programmés à venir (statut SCHEDULED). Par défaut (False), ne retourne que les matchs réellement en cours de jeu.",
        +  "title": "Include Scheduled",
        +  "type": "boolean"
        +}
    • Changedffbb_next_match15 fields changed
      • changedInput schema / anyOf
        Previous value: -[
        -  {
        -    "required": [
        -      "club_name"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "organisme_id"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "poule_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "competition_id"
        +    ]
        +  }
        +]
      • addedInput schema / properties / categorie / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / categorie / default
        Added value: +null
      • changedInput schema / properties / categorie / description
        Previous value: -"Catégorie de l'équipe précise (ex: 'U11M1', 'U11M', 'U11F')"New value: +"Catégorie de l'équipe précise (ex: 'U11M1', 'U11M', 'SEM1', 'NM3')."
      • removedInput schema / properties / categorie / type
        Removed value: -"string"
      • addedInput schema / properties / competition_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la compétition pour désambiguïser.",
        +  "title": "Competition Id"
        +}
      • addedInput schema / properties / competition_type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Type de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.",
        +  "title": "Competition Type"
        +}
      • addedInput schema / properties / engagement_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de l'engagement (prioritaire pour désambiguïser).",
        +  "title": "Engagement Id"
        +}
      • addedInput schema / properties / numero_equipe / anyOf
        Added value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / numero_equipe / default
        Previous value: -1New value: +null
      • removedInput schema / properties / numero_equipe / type
        Removed value: -"integer"
      • changedInput schema / properties / organisme_id / description
        Previous value: -"Identifiant FFBB du club (organisme_id, ex: 1234 ou 'ARA0063058')"New value: +"Identifiant FFBB du club (organisme_id, ex: '9326' ou 'ARA0063058')."
      • addedInput schema / properties / poule_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la poule pour désambiguïser.",
        +  "title": "Poule Id"
        +}
      • addedInput schema / properties / season_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID de la saison FFBB (optionnel).",
        +  "title": "Season Id"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "categorie"
        -]
    • Changedffbb_resolve_team7 fields changed
      • changedInput schema / anyOf
        Previous value: -[
        -  {
        -    "required": [
        -      "club_name"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "organisme_id"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "poule_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "competition_id"
        +    ]
        +  }
        +]
      • addedInput schema / properties / competition_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la compétition pour désambiguïser.",
        +  "title": "Competition Id"
        +}
      • addedInput schema / properties / competition_type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Type de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.",
        +  "title": "Competition Type"
        +}
      • addedInput schema / properties / engagement_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de l'engagement (prioritaire pour désambiguïser).",
        +  "title": "Engagement Id"
        +}
      • addedInput schema / properties / force_refresh
        Added value: +{
        +  "default": false,
        +  "description": "Si True, force le rafraîchissement des données.",
        +  "title": "Force Refresh",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / poule_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la poule pour désambiguïser.",
        +  "title": "Poule Id"
        +}
      • addedInput schema / properties / season_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID de la saison FFBB (optionnel).",
        +  "title": "Season Id"
        +}
    • Changedffbb_saisons1 field changed
      • addedInput schema / properties / force_refresh
        Added value: +{
        +  "default": false,
        +  "description": "Si True, contourne le cache.",
        +  "title": "Force Refresh",
        +  "type": "boolean"
        +}
    • Changedffbb_search4 fields changed
      • changedInput schema / properties / filter_by / description
        Previous value: -"Filtre Meilisearch natif (ex: 'codePostal = \"63000\"')."New value: +"Filtre Meilisearch natif (ex: 'codePostal = \"63000\"', 'codePostal IN [\"63000\", \"63100\"]', 'departement = \"Puy-de-Dôme\"')."
      • addedInput schema / properties / force_refresh
        Added value: +{
        +  "default": false,
        +  "description": "Si True, force le rafraîchissement des données.",
        +  "title": "Force Refresh",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / limit / description
        Previous value: -"Nombre maximum de résultats à retourner."New value: +"Nombre maximum de résultats à retourner (1-100)."
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "description": "Index de départ pour pagination (défaut: 0).",
        +  "title": "Offset",
        +  "type": "integer"
        +}
    • Addedffbb_search_regulations
    • Changedffbb_team_summary9 fields changed
      • changedInput schema / anyOf
        Previous value: -[
        -  {
        -    "required": [
        -      "club_name"
        -    ]
        -  },
        -  {
        -    "required": [
        -      "organisme_id"
        -    ]
        -  }
        -]New value: +[
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "engagement_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "poule_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "competition_id"
        +    ]
        +  }
        +]
      • addedInput schema / properties / competition_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la compétition pour désambiguïser.",
        +  "title": "Competition Id"
        +}
      • addedInput schema / properties / competition_type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Type de compétition ('PLAT', 'COUPE', etc.) pour désambiguïser.",
        +  "title": "Competition Type"
        +}
      • addedInput schema / properties / engagement_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de l'engagement (prioritaire pour désambiguïser).",
        +  "title": "Engagement Id"
        +}
      • addedInput schema / properties / numero_equipe / anyOf
        Added value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / numero_equipe / default
        Previous value: -1New value: +null
      • removedInput schema / properties / numero_equipe / type
        Removed value: -"integer"
      • addedInput schema / properties / poule_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID FFBB de la poule pour désambiguïser.",
        +  "title": "Poule Id"
        +}
      • addedInput schema / properties / season_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "ID de la saison FFBB (optionnel).",
        +  "title": "Season Id"
        +}
  6. 4 tool updatesv1.10.0
    • Changedffbb_club4 fields changed
      • addedInput schema / properties / categorie
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Catégorie, division ou filtre d'équipe (alias pour 'filtre', ex: 'NM3', 'U15M', 'Senior').",
        +  "title": "Categorie"
        +}
      • changedInput schema / properties / filtre / description
        Previous value: -"Filtre catégorie/genre (ex: 'U11M', 'Senior')."New value: +"Filtre catégorie/genre (ex: 'U11M', 'Senior', 'NM3')."
      • changedInput schema / properties / numero_equipe / description
        Previous value: -"Numéro d'équipe (ex: 1, 2) pour action='calendrier'."New value: +"Numéro d'équipe (ex: 1, 2) pour action='calendrier' ou 'classement'."
      • changedInput schema / properties / poule_id / description
        Previous value: -"ID poule (action='classement')."New value: +"ID poule (action='classement'). Optionnel si club et catégorie sont fournis."
    • Changedffbb_get2 fields changed
      • addedInput schema / properties / club
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Nom ou ID du club à localiser dans les poules (si type='competition'). Permet de trouver directement l'ID et le nom de poule d'un club dans une compétition multi-poules.",
        +  "title": "Club"
        +}
      • changedInput schema / properties / type / enum
        Previous value: -[
        -  "competition",
        -  "poule",
        -  "organisme",
        -  "rencontre",
        -  "officiel",
        -  "entraineur"
        -]New value: +[
        +  "competition",
        +  "poule",
        +  "organisme",
        +  "rencontre",
        +  "officiel",
        +  "entraineur",
        +  "salle"
        +]
    • Changedffbb_resolve_team1 field changed
      • changedInput schema / properties / categorie / description
        Previous value: -"Catégorie + genre + numéro d'équipe (ex: 'U11M1', 'U13F2', 'U15M'). Si le numéro manque, cet outil retourne la bonne équipe ou des candidats."New value: +"Catégorie + genre + numéro d'équipe (ex: 'U11M1', 'U13F2', 'SEM1') ou division (ex: 'NM3', 'R2', 'PNM'). Si le numéro manque, cet outil retourne la bonne équipe ou des candidats."
    • Changedffbb_team_summary1 field changed
      • changedInput schema / properties / categorie / description
        Previous value: -"Catégorie + genre + numéro d'équipe (ex: 'U11M1', 'U13F2', 'U15M', 'Senior')."New value: +"Catégorie/division + genre + numéro d'équipe (ex: 'U11M1', 'U13F2', 'SEM1', 'NM3', 'PNM')."
  7. 13 tool updatesv1.9.0
    • Changedffbb_bilan6 fields changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  }
        +]
      • changedInput schema / properties / categorie / description
        Previous value: -"Catégorie + genre + numéro d'équipe (ex: 'U11M1', 'U13F2', 'U15M', 'Senior')."New value: +"Catégorie/genre/numéro (ex: 'U11M1', 'Senior')."
      • changedInput schema / properties / force_refresh / description
        Previous value: -"Si True, contourne le cache pour récupérer des données fraîches."New value: +"Si True, contourne le cache."
      • changedInput schema / properties / numero_equipe / description
        Previous value: -"Numéro d'équipe facultatif (ex: 1, 2)."New value: +"Numéro d'équipe (ex: 1, 2)."
      • changedInput schema / properties / organisme_id / description
        Previous value: -"ID FFBB du club (alternative plus rapide à club_name)."New value: +"ID FFBB du club (ex: 9326)."
      • changedOutput schema / (root)
        Previous value: -{
        -  "$defs": {
        -    "BilanResponse": {
        -      "description": "Réponse structurée et typée pour le bilan d'une équipe.",
        -      "properties": {
        -        "_meta": {
        -          "additionalProperties": true,
        -          "description": "Métadonnées de fraîcheur et de cache.",
        -          "title": "Meta",
        -          "type": "object"
        -        },
        -        "bilan_total": {
        -          "$ref": "#/$defs/BilanTotal",
        -          "description": "Totaux cumulés toutes phases."
        -        },
        -        "categorie": {
        -          "description": "Catégorie d'âge/genre.",
        -          "title": "Categorie",
        -          "type": "string"
        -        },
        -        "club": {
        -          "description": "Nom officiel du club.",
        -          "title": "Club",
        -          "type": "string"
        -        },
        -        "competitions_incluses": {
        -          "description": "Liste des noms de compétitions incluses dans le bilan.",
        -          "items": {
        -            "type": "string"
        -          },
        -          "title": "Competitions Incluses",
        -          "type": "array"
        -        },
        -        "dynamique": {
        -          "anyOf": [
        -            {
        -              "$ref": "#/$defs/FormeRecente"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Dynamique et forme récente de l'équipe principale sur les 5 derniers matchs."
        -        },
        -        "equipes_bilan": {
        -          "additionalProperties": true,
        -          "description": "Bilans ventilés par numéro d'équipe.",
        -          "title": "Equipes Bilan",
        -          "type": "object"
        -        },
        -        "phase_courante": {
        -          "anyOf": [
        -            {
        -              "$ref": "#/$defs/PhaseBilan"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Détails de la dernière phase en cours."
        -        },
        -        "phases": {
        -          "description": "Liste de toutes les phases jouées.",
        -          "items": {
        -            "$ref": "#/$defs/PhaseBilan"
        -          },
        -          "title": "Phases",
        -          "type": "array"
        -        },
        -        "profil_avance": {
        -          "anyOf": [
        -            {
        -              "additionalProperties": true,
        -              "type": "object"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Profil tactique avancé : rangs attaque/défense, style de jeu, clutch index et bilans domicile/extérieur.",
        -          "title": "Profil Avance"
        -        },
        -        "saison_terminee": {
        -          "default": true,
        -          "description": "Indique si la saison est terminée pour cette équipe (toutes les phases jouées).",
        -          "title": "Saison Terminee",
        -          "type": "boolean"
        -        }
        -      },
        -      "required": [
        -        "club",
        -        "categorie",
        -        "bilan_total"
        -      ],
        -      "title": "BilanResponse",
        -      "type": "object"
        -    },
        -    "BilanTotal": {
        -      "description": "Statistiques cumulées d'une équipe (victoires, défaites, paniers).",
        -      "properties": {
        -        "difference": {
        -          "default": 0,
        -          "description": "Différence de paniers (marqués - encaissés).",
        -          "title": "Difference",
        -          "type": "integer"
        -        },
        -        "gagnes": {
        -          "default": 0,
        -          "description": "Nombre de matchs gagnés.",
        -          "title": "Gagnes",
        -          "type": "integer"
        -        },
        -        "match_joues": {
        -          "default": 0,
        -          "description": "Nombre de matchs joués.",
        -          "title": "Match Joues",
        -          "type": "integer"
        -        },
        -        "nuls": {
        -          "default": 0,
        -          "description": "Nombre de matchs nuls.",
        -          "title": "Nuls",
        -          "type": "integer"
        -        },
        -        "paniers_encaisses": {
        -          "default": 0,
        -          "description": "Total des paniers encaissés.",
        -          "title": "Paniers Encaisses",
        -          "type": "integer"
        -        },
        -        "paniers_marques": {
        -          "default": 0,
        -          "description": "Total des paniers marqués.",
        -          "title": "Paniers Marques",
        -          "type": "integer"
        -        },
        -        "perdus": {
        -          "default": 0,
        -          "description": "Nombre de matchs perdus.",
        -          "title": "Perdus",
        -          "type": "integer"
        -        }
        -      },
        -      "title": "BilanTotal",
        -      "type": "object"
        -    },
        -    "FormeRecente": {
        -      "description": "Indicateur complet de dynamique et de forme récente (5 derniers matchs).",
        -      "properties": {
        -        "defaites_5_derniers": {
        -          "default": 0,
        -          "description": "Nombre de défaites sur les 5 derniers matchs.",
        -          "title": "Defaites 5 Derniers",
        -          "type": "integer"
        -        },
        -        "diff_moyenne_5": {
        -          "default": 0,
        -          "description": "Différentiel moyen de points sur les 5 derniers matchs.",
        -          "title": "Diff Moyenne 5",
        -          "type": "number"
        -        },
        -        "forme": {
        -          "description": "Résultats des 5 derniers matchs par ordre chronologique (ex: ['V', 'V', 'D', 'V', 'V']).",
        -          "items": {
        -            "type": "string"
        -          },
        -          "title": "Forme",
        -          "type": "array"
        -        },
        -        "forme_str": {
        -          "default": "",
        -          "description": "Représentation texte compacte de la forme (ex: 'V-V-D-V-V').",
        -          "title": "Forme Str",
        -          "type": "string"
        -        },
        -        "matchs": {
        -          "description": "Détail des matchs récents analysés.",
        -          "items": {
        -            "$ref": "#/$defs/MatchForme"
        -          },
        -          "title": "Matchs",
        -          "type": "array"
        -        },
        -        "meilleure_victoire": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Plus large victoire récente (ex: '+24 vs ASPTT (84-60)').",
        -          "title": "Meilleure Victoire"
        -        },
        -        "nuls_5_derniers": {
        -          "default": 0,
        -          "description": "Nombre de nuls sur les 5 derniers matchs.",
        -          "title": "Nuls 5 Derniers",
        -          "type": "integer"
        -        },
        -        "pire_defaite": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Plus lourde défaite récente (ex: '-12 vs US Chauriat (62-74)').",
        -          "title": "Pire Defaite"
        -        },
        -        "pts_encaisses_moyenne_5": {
        -          "default": 0,
        -          "description": "Moyenne de points encaissés par match sur les 5 derniers matchs.",
        -          "title": "Pts Encaisses Moyenne 5",
        -          "type": "number"
        -        },
        -        "pts_marques_moyenne_5": {
        -          "default": 0,
        -          "description": "Moyenne de points marqués par match sur les 5 derniers matchs.",
        -          "title": "Pts Marques Moyenne 5",
        -          "type": "number"
        -        },
        -        "ratio_victoires_5_derniers": {
        -          "default": 0,
        -          "description": "Pourcentage de victoires sur les 5 derniers matchs (0-100%).",
        -          "title": "Ratio Victoires 5 Derniers",
        -          "type": "number"
        -        },
        -        "serie_actuelle": {
        -          "$ref": "#/$defs/SerieEnCours",
        -          "description": "Série globale en cours toutes compétitions."
        -        },
        -        "serie_domicile": {
        -          "$ref": "#/$defs/SerieEnCours",
        -          "description": "Série en cours pour les matchs à domicile."
        -        },
        -        "serie_exterieur": {
        -          "$ref": "#/$defs/SerieEnCours",
        -          "description": "Série en cours pour les matchs à l'extérieur."
        -        },
        -        "tendance": {
        -          "default": "Stable ➡️",
        -          "description": "Tendance de la forme ('En hausse ↗️', 'Stable ➡️', 'En baisse ↘️').",
        -          "title": "Tendance",
        -          "type": "string"
        -        },
        -        "victoires_5_derniers": {
        -          "default": 0,
        -          "description": "Nombre de victoires sur les 5 derniers matchs.",
        -          "title": "Victoires 5 Derniers",
        -          "type": "integer"
        -        }
        -      },
        -      "title": "FormeRecente",
        -      "type": "object"
        -    },
        -    "MatchForme": {
        -      "description": "Détail d'un match pris en compte dans la forme récente.",
        -      "properties": {
        -        "adversaire": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Nom de l'adversaire.",
        -          "title": "Adversaire"
        -        },
        -        "date": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Date et heure du match.",
        -          "title": "Date"
        -        },
        -        "domicile": {
        -          "default": true,
        -          "description": "True si domicile, False si déplacement.",
        -          "title": "Domicile",
        -          "type": "boolean"
        -        },
        -        "ecart": {
        -          "default": 0,
        -          "description": "Différence de points (+13 ou -8).",
        -          "title": "Ecart",
        -          "type": "integer"
        -        },
        -        "journee": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Nom ou numéro de journée.",
        -          "title": "Journee"
        -        },
        -        "resultat": {
        -          "description": "'V' (Victoire), 'D' (Défaite) ou 'N' (Nul).",
        -          "title": "Resultat",
        -          "type": "string"
        -        },
        -        "salle": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Nom de la salle.",
        -          "title": "Salle"
        -        },
        -        "score": {
        -          "description": "Score du match (ex: '78 - 65').",
        -          "title": "Score",
        -          "type": "string"
        -        },
        -        "score_contre": {
        -          "anyOf": [
        -            {
        -              "type": "integer"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Points encaissés.",
        -          "title": "Score Contre"
        -        },
        -        "score_pour": {
        -          "anyOf": [
        -            {
        -              "type": "integer"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Points marqués.",
        -          "title": "Score Pour"
        -        }
        -      },
        -      "required": [
        -        "resultat",
        -        "score"
        -      ],
        -      "title": "MatchForme",
        -      "type": "object"
        -    },
        -    "PhaseBilan": {
        -      "description": "Bilan détaillé pour une phase de compétition spécifique.",
        -      "properties": {
        -        "competition": {
        -          "description": "Nom de la compétition.",
        -          "title": "Competition",
        -          "type": "string"
        -        },
        -        "difference": {
        -          "default": 0,
        -          "description": "Différence de paniers.",
        -          "title": "Difference",
        -          "type": "integer"
        -        },
        -        "gagnes": {
        -          "default": 0,
        -          "description": "Matchs gagnés.",
        -          "title": "Gagnes",
        -          "type": "integer"
        -        },
        -        "match_joues": {
        -          "default": 0,
        -          "description": "Matchs joués dans cette phase.",
        -          "title": "Match Joues",
        -          "type": "integer"
        -        },
        -        "nuls": {
        -          "default": 0,
        -          "description": "Matchs nuls.",
        -          "title": "Nuls",
        -          "type": "integer"
        -        },
        -        "numero_equipe": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Numéro de l'équipe (ex: '1', '2').",
        -          "title": "Numero Equipe"
        -        },
        -        "paniers_encaisses": {
        -          "default": 0,
        -          "description": "Paniers encaissés.",
        -          "title": "Paniers Encaisses",
        -          "type": "integer"
        -        },
        -        "paniers_marques": {
        -          "default": 0,
        -          "description": "Paniers marqués.",
        -          "title": "Paniers Marques",
        -          "type": "integer"
        -        },
        -        "perdus": {
        -          "default": 0,
        -          "description": "Matchs perdus.",
        -          "title": "Perdus",
        -          "type": "integer"
        -        },
        -        "phase_terminee": {
        -          "default": false,
        -          "description": "Indique si la phase est terminée.",
        -          "title": "Phase Terminee",
        -          "type": "boolean"
        -        },
        -        "phase_type": {
        -          "default": "poule",
        -          "description": "Type de phase (poule ou élimination).",
        -          "title": "Phase Type",
        -          "type": "string"
        -        },
        -        "position": {
        -          "anyOf": [
        -            {
        -              "type": "integer"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Position actuelle au classement.",
        -          "title": "Position"
        -        },
        -        "poule_id": {
        -          "description": "ID de la poule.",
        -          "title": "Poule Id",
        -          "type": "string"
        -        },
        -        "total_equipes": {
        -          "anyOf": [
        -            {
        -              "type": "integer"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Nombre total d'équipes dans la poule.",
        -          "title": "Total Equipes"
        -        }
        -      },
        -      "required": [
        -        "competition",
        -        "poule_id"
        -      ],
        -      "title": "PhaseBilan",
        -      "type": "object"
        -    },
        -    "SerieEnCours": {
        -      "description": "Série actuelle de victoires, défaites ou invincibilité.",
        -      "properties": {
        -        "count": {
        -          "default": 0,
        -          "description": "Nombre de matchs consécutifs dans la série.",
        -          "title": "Count",
        -          "type": "integer"
        -        },
        -        "label": {
        -          "default": "",
        -          "description": "Description lisible (ex: '3 victoires consécutives').",
        -          "title": "Label",
        -          "type": "string"
        -        },
        -        "type": {
        -          "default": "aucune",
        -          "description": "'victoires', 'defaites', 'nuls' ou 'aucune'.",
        -          "title": "Type",
        -          "type": "string"
        -        }
        -      },
        -      "title": "SerieEnCours",
        -      "type": "object"
        -    }
        -  },
        -  "properties": {
        -    "result": {
        -      "anyOf": [
        -        {
        -          "additionalProperties": true,
        -          "type": "object"
        -        },
        -        {
        -          "$ref": "#/$defs/BilanResponse"
        -        }
        -      ],
        -      "title": "Result"
        -    }
        -  },
        -  "required": [
        -    "result"
        -  ],
        -  "title": "ffbb_bilanOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_bilan_saison2 fields changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  }
        +]
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": true,
        -  "title": "ffbb_bilan_saisonDictOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_club14 fields changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "poule_id"
        +    ]
        +  }
        +]
      • changedInput schema / properties / action / description
        Previous value: -"Action club. Utiliser 'calendrier' pour les demandes au pluriel (matchs restants, calendrier, prochaines journées)."New value: +"Action : 'calendrier' (matchs pluriels/restants), 'equipes' ou 'classement'."
      • changedInput schema / properties / adversaire / description
        Previous value: -"Nom de l'équipe adversaire pour filtrer uniquement les confrontations directes (ex: 'Royat Orcines', 'Stade Clermontois'). Utilisé avec action='calendrier'. Insensible à la casse et aux accents."New value: +"Nom adversaire pour filtrer les confrontations directes (action='calendrier')."
      • changedInput schema / properties / club_name / description
        Previous value: -"Nom du club (recommande, ex: 'Stade Clermontois'). Si absent, `organisme_id` doit etre fourni."New value: +"Nom du club (ex: 'Stade Clermontois'). Requis si organisme_id absent."
      • changedInput schema / properties / date_debut / description
        Previous value: -"Date de début de filtrage au format YYYY-MM-DD (ex: '2026-05-01')."New value: +"Date début YYYY-MM-DD (action='calendrier')."
      • changedInput schema / properties / date_fin / description
        Previous value: -"Date de fin de filtrage au format YYYY-MM-DD (ex: '2026-05-31')."New value: +"Date fin YYYY-MM-DD (action='calendrier')."
      • changedInput schema / properties / filtre / description
        Previous value: -"Filtre facultatif de categorie/genre (ex: 'U11', 'U11M', 'U11F'). Pour une équipe précise, compléter avec numero_equipe."New value: +"Filtre catégorie/genre (ex: 'U11M', 'Senior')."
      • changedInput schema / properties / force_refresh / description
        Previous value: -"Si True, contourne le cache pour les donnees de calendrier ou de classement (utile les jours de match)."New value: +"Si True, contourne le cache."
      • changedInput schema / properties / limit / description
        Previous value: -"Nombre maximum de matchs de calendrier à retourner (pagination/limite)."New value: +"Nombre max de matchs retournés (pagination)."
      • changedInput schema / properties / numero_equipe / description
        Previous value: -"Numéro d'équipe facultatif (ex: 1, 2, 3). Utilisé avec action='calendrier' pour ne récupérer que les matchs de cette équipe précise."New value: +"Numéro d'équipe (ex: 1, 2) pour action='calendrier'."
      • changedInput schema / properties / organisme_id / description
        Previous value: -"Identifiant FFBB du club (ex: 1234 ou 'ARA0063058'). Si absent, `club_name` est utilise pour effectuer une recherche."New value: +"ID FFBB du club (ex: 9326). Requis si club_name absent."
      • changedInput schema / properties / phase / description
        Previous value: -"Nom ou numéro de la phase (ex: 'Phase 3', '2'). Utilisé avec action='classement' pour auto-résoudre la poule."New value: +"Nom ou numéro de phase (ex: 'Phase 2')."
      • changedInput schema / properties / poule_id / description
        Previous value: -"Identifiant de la poule (obligatoire pour action='classement' si aucun filtre ne permet de determiner la poule)."New value: +"ID poule (action='classement')."
      • changedOutput schema / (root)
        Previous value: -{
        -  "$defs": {
        -    "CalendrierMatch": {
        -      "description": "Structure de données typée représentant un match de calendrier.",
        -      "properties": {
        -        "adresse": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Adresse complète de la salle.",
        -          "title": "Adresse"
        -        },
        -        "adresse_salle": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Adresse de la salle.",
        -          "title": "Adresse Salle"
        -        },
        -        "competition_nom": {
        -          "default": "",
        -          "description": "Nom de la compétition associée.",
        -          "title": "Competition Nom",
        -          "type": "string"
        -        },
        -        "competition_type": {
        -          "default": "poule",
        -          "description": "Type de phase (poule ou élimination).",
        -          "title": "Competition Type",
        -          "type": "string"
        -        },
        -        "date": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Date et heure du match en ISO format.",
        -          "title": "Date"
        -        },
        -        "equipe1": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Nom de l'équipe 1 (domicile).",
        -          "title": "Equipe1"
        -        },
        -        "equipe2": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Nom de l'équipe 2 (extérieur).",
        -          "title": "Equipe2"
        -        },
        -        "id": {
        -          "anyOf": [
        -            {
        -              "type": "integer"
        -            },
        -            {
        -              "type": "string"
        -            }
        -          ],
        -          "description": "ID unique de la rencontre.",
        -          "title": "Id"
        -        },
        -        "is_last_match": {
        -          "default": false,
        -          "description": "Indique s'il s'agit du dernier match joué.",
        -          "title": "Is Last Match",
        -          "type": "boolean"
        -        },
        -        "is_next_match": {
        -          "default": false,
        -          "description": "Indique s'il s'agit du prochain match à venir.",
        -          "title": "Is Next Match",
        -          "type": "boolean"
        -        },
        -        "joue": {
        -          "anyOf": [
        -            {
        -              "type": "integer"
        -            },
        -            {
        -              "type": "boolean"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Indique si le match a été joué (1 ou True) ou non (0 ou False).",
        -          "title": "Joue"
        -        },
        -        "lieu_complet": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Adresse formatée complète : 'Nom Salle - Adresse, CP Ville'.",
        -          "title": "Lieu Complet"
        -        },
        -        "nom_salle": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Nom de la salle (libelle).",
        -          "title": "Nom Salle"
        -        },
        -        "num_journee": {
        -          "anyOf": [
        -            {
        -              "type": "integer"
        -            },
        -            {
        -              "type": "string"
        -            }
        -          ],
        -          "default": "",
        -          "description": "Numéro de la journée de championnat.",
        -          "title": "Num Journee"
        -        },
        -        "played": {
        -          "default": false,
        -          "description": "Indique si le match est déjà joué.",
        -          "title": "Played",
        -          "type": "boolean"
        -        },
        -        "salle": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "additionalProperties": true,
        -              "type": "object"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Nom de la salle de sport ou dictionnaire d'informations.",
        -          "title": "Salle"
        -        },
        -        "salle_details": {
        -          "anyOf": [
        -            {
        -              "additionalProperties": true,
        -              "type": "object"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Détails enrichis de la salle de sport.",
        -          "title": "Salle Details"
        -        },
        -        "score_equipe1": {
        -          "anyOf": [
        -            {
        -              "type": "integer"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Score de l'équipe 1.",
        -          "title": "Score Equipe1"
        -        },
        -        "score_equipe2": {
        -          "anyOf": [
        -            {
        -              "type": "integer"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Score de l'équipe 2.",
        -          "title": "Score Equipe2"
        -        },
        -        "ville": {
        -          "anyOf": [
        -            {
        -              "type": "string"
        -            },
        -            {
        -              "type": "null"
        -            }
        -          ],
        -          "default": null,
        -          "description": "Ville où se situe la salle.",
        -          "title": "Ville"
        -        }
        -      },
        -      "required": [
        -        "id"
        -      ],
        -      "title": "CalendrierMatch",
        -      "type": "object"
        -    }
        -  },
        -  "properties": {
        -    "result": {
        -      "anyOf": [
        -        {
        -          "items": {
        -            "additionalProperties": true,
        -            "type": "object"
        -          },
        -          "type": "array"
        -        },
        -        {
        -          "items": {
        -            "$ref": "#/$defs/CalendrierMatch"
        -          },
        -          "type": "array"
        -        }
        -      ],
        -      "title": "Result"
        -    }
        -  },
        -  "required": [
        -    "result"
        -  ],
        -  "title": "ffbb_clubOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_get1 field changed
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": true,
        -  "title": "ffbb_getDictOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_head_to_head1 field changed
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": true,
        -  "title": "ffbb_head_to_headDictOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_last_result2 fields changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  }
        +]
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": true,
        -  "title": "ffbb_last_resultDictOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_lives1 field changed
      • changedOutput schema / (root)
        Previous value: -{
        -  "properties": {
        -    "result": {
        -      "items": {
        -        "additionalProperties": true,
        -        "type": "object"
        -      },
        -      "title": "Result",
        -      "type": "array"
        -    }
        -  },
        -  "required": [
        -    "result"
        -  ],
        -  "title": "ffbb_get_livesOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_next_match2 fields changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  }
        +]
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": true,
        -  "title": "ffbb_next_matchDictOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_resolve_team2 fields changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  }
        +]
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": true,
        -  "title": "ffbb_resolve_teamDictOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_saisons1 field changed
      • changedOutput schema / (root)
        Previous value: -{
        -  "properties": {
        -    "result": {
        -      "items": {
        -        "additionalProperties": true,
        -        "type": "object"
        -      },
        -      "title": "Result",
        -      "type": "array"
        -    }
        -  },
        -  "required": [
        -    "result"
        -  ],
        -  "title": "ffbb_get_saisonsOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_search1 field changed
      • changedOutput schema / (root)
        Previous value: -{
        -  "properties": {
        -    "result": {
        -      "items": {
        -        "additionalProperties": true,
        -        "type": "object"
        -      },
        -      "title": "Result",
        -      "type": "array"
        -    }
        -  },
        -  "required": [
        -    "result"
        -  ],
        -  "title": "ffbb_searchOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_team_summary2 fields changed
      • addedInput schema / anyOf
        Added value: +[
        +  {
        +    "required": [
        +      "club_name"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "organisme_id"
        +    ]
        +  }
        +]
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": true,
        -  "title": "ffbb_team_summaryDictOutput",
        -  "type": "object"
        -}New value: +null
    • Changedffbb_version1 field changed
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": true,
        -  "title": "ffbb_versionDictOutput",
        -  "type": "object"
        -}New value: +null
  8. 5 tool updatesv1.8.0
    • Changedffbb_bilan6 fields changed
      • addedInput schema / properties / numero_equipe
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Numéro d'équipe facultatif (ex: 1, 2).",
        +  "title": "Numero Equipe"
        +}
      • addedOutput schema / $defs / BilanResponse / properties / dynamique
        Added value: +{
        +  "anyOf": [
        +    {
        +      "$ref": "#/$defs/FormeRecente"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Dynamique et forme récente de l'équipe principale sur les 5 derniers matchs."
        +}
      • addedOutput schema / $defs / BilanResponse / properties / profil_avance
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": true,
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Profil tactique avancé : rangs attaque/défense, style de jeu, clutch index et bilans domicile/extérieur.",
        +  "title": "Profil Avance"
        +}
      • addedOutput schema / $defs / FormeRecente
        Added value: +{
        +  "description": "Indicateur complet de dynamique et de forme récente (5 derniers matchs).",
        +  "properties": {
        +    "defaites_5_derniers": {
        +      "default": 0,
        +      "description": "Nombre de défaites sur les 5 derniers matchs.",
        +      "title": "Defaites 5 Derniers",
        +      "type": "integer"
        +    },
        +    "diff_moyenne_5": {
        +      "default": 0,
        +      "description": "Différentiel moyen de points sur les 5 derniers matchs.",
        +      "title": "Diff Moyenne 5",
        +      "type": "number"
        +    },
        +    "forme": {
        +      "description": "Résultats des 5 derniers matchs par ordre chronologique (ex: ['V', 'V', 'D', 'V', 'V']).",
        +      "items": {
        +        "type": "string"
        +      },
        +      "title": "Forme",
        +      "type": "array"
        +    },
        +    "forme_str": {
        +      "default": "",
        +      "description": "Représentation texte compacte de la forme (ex: 'V-V-D-V-V').",
        +      "title": "Forme Str",
        +      "type": "string"
        +    },
        +    "matchs": {
        +      "description": "Détail des matchs récents analysés.",
        +      "items": {
        +        "$ref": "#/$defs/MatchForme"
        +      },
        +      "title": "Matchs",
        +      "type": "array"
        +    },
        +    "meilleure_victoire": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Plus large victoire récente (ex: '+24 vs ASPTT (84-60)').",
        +      "title": "Meilleure Victoire"
        +    },
        +    "nuls_5_derniers": {
        +      "default": 0,
        +      "description": "Nombre de nuls sur les 5 derniers matchs.",
        +      "title": "Nuls 5 Derniers",
        +      "type": "integer"
        +    },
        +    "pire_defaite": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Plus lourde défaite récente (ex: '-12 vs US Chauriat (62-74)').",
        +      "title": "Pire Defaite"
        +    },
        +    "pts_encaisses_moyenne_5": {
        +      "default": 0,
        +      "description": "Moyenne de points encaissés par match sur les 5 derniers matchs.",
        +      "title": "Pts Encaisses Moyenne 5",
        +      "type": "number"
        +    },
        +    "pts_marques_moyenne_5": {
        +      "default": 0,
        +      "description": "Moyenne de points marqués par match sur les 5 derniers matchs.",
        +      "title": "Pts Marques Moyenne 5",
        +      "type": "number"
        +    },
        +    "ratio_victoires_5_derniers": {
        +      "default": 0,
        +      "description": "Pourcentage de victoires sur les 5 derniers matchs (0-100%).",
        +      "title": "Ratio Victoires 5 Derniers",
        +      "type": "number"
        +    },
        +    "serie_actuelle": {
        +      "$ref": "#/$defs/SerieEnCours",
        +      "description": "Série globale en cours toutes compétitions."
        +    },
        +    "serie_domicile": {
        +      "$ref": "#/$defs/SerieEnCours",
        +      "description": "Série en cours pour les matchs à domicile."
        +    },
        +    "serie_exterieur": {
        +      "$ref": "#/$defs/SerieEnCours",
        +      "description": "Série en cours pour les matchs à l'extérieur."
        +    },
        +    "tendance": {
        +      "default": "Stable ➡️",
        +      "description": "Tendance de la forme ('En hausse ↗️', 'Stable ➡️', 'En baisse ↘️').",
        +      "title": "Tendance",
        +      "type": "string"
        +    },
        +    "victoires_5_derniers": {
        +      "default": 0,
        +      "description": "Nombre de victoires sur les 5 derniers matchs.",
        +      "title": "Victoires 5 Derniers",
        +      "type": "integer"
        +    }
        +  },
        +  "title": "FormeRecente",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / MatchForme
        Added value: +{
        +  "description": "Détail d'un match pris en compte dans la forme récente.",
        +  "properties": {
        +    "adversaire": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Nom de l'adversaire.",
        +      "title": "Adversaire"
        +    },
        +    "date": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Date et heure du match.",
        +      "title": "Date"
        +    },
        +    "domicile": {
        +      "default": true,
        +      "description": "True si domicile, False si déplacement.",
        +      "title": "Domicile",
        +      "type": "boolean"
        +    },
        +    "ecart": {
        +      "default": 0,
        +      "description": "Différence de points (+13 ou -8).",
        +      "title": "Ecart",
        +      "type": "integer"
        +    },
        +    "journee": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Nom ou numéro de journée.",
        +      "title": "Journee"
        +    },
        +    "resultat": {
        +      "description": "'V' (Victoire), 'D' (Défaite) ou 'N' (Nul).",
        +      "title": "Resultat",
        +      "type": "string"
        +    },
        +    "salle": {
        +      "anyOf": [
        +        {
        +          "type": "string"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Nom de la salle.",
        +      "title": "Salle"
        +    },
        +    "score": {
        +      "description": "Score du match (ex: '78 - 65').",
        +      "title": "Score",
        +      "type": "string"
        +    },
        +    "score_contre": {
        +      "anyOf": [
        +        {
        +          "type": "integer"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Points encaissés.",
        +      "title": "Score Contre"
        +    },
        +    "score_pour": {
        +      "anyOf": [
        +        {
        +          "type": "integer"
        +        },
        +        {
        +          "type": "null"
        +        }
        +      ],
        +      "default": null,
        +      "description": "Points marqués.",
        +      "title": "Score Pour"
        +    }
        +  },
        +  "required": [
        +    "resultat",
        +    "score"
        +  ],
        +  "title": "MatchForme",
        +  "type": "object"
        +}
      • addedOutput schema / $defs / SerieEnCours
        Added value: +{
        +  "description": "Série actuelle de victoires, défaites ou invincibilité.",
        +  "properties": {
        +    "count": {
        +      "default": 0,
        +      "description": "Nombre de matchs consécutifs dans la série.",
        +      "title": "Count",
        +      "type": "integer"
        +    },
        +    "label": {
        +      "default": "",
        +      "description": "Description lisible (ex: '3 victoires consécutives').",
        +      "title": "Label",
        +      "type": "string"
        +    },
        +    "type": {
        +      "default": "aucune",
        +      "description": "'victoires', 'defaites', 'nuls' ou 'aucune'.",
        +      "title": "Type",
        +      "type": "string"
        +    }
        +  },
        +  "title": "SerieEnCours",
        +  "type": "object"
        +}
    • Changedffbb_bilan_saison13 fields changed
      • addedInput schema / properties / categorie / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / categorie / default
        Added value: +null
      • changedInput schema / properties / categorie / description
        Previous value: -"Catégorie + genre (ex: 'U11M', 'U13F', 'SeniorM'). Cette valeur sert à filtrer les engagements et les poules."New value: +"Catégorie + genre + numéro d'équipe facultatif (ex: 'U11M', 'U11M1', 'U13F2', 'SeniorM'). Cette valeur sert à filtrer les engagements et les poules."
      • removedInput schema / properties / categorie / type
        Removed value: -"string"
      • addedInput schema / properties / club_name
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Nom du club (ex: 'Stade Clermontois', 'ASVEL').",
        +  "title": "Club Name"
        +}
      • addedInput schema / properties / numero_equipe / anyOf
        Added value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / numero_equipe / default
        Added value: +1
      • changedInput schema / properties / numero_equipe / description
        Previous value: -"Numéro d'équipe (1, 2, ...) pour identifier l'équipe précise dans la catégorie."New value: +"Numéro d'équipe (1, 2, ...) pour identifier l'équipe précise dans la catégorie (défaut: 1)."
      • removedInput schema / properties / numero_equipe / type
        Removed value: -"integer"
      • changedInput schema / properties / organisme_id / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / organisme_id / default
        Added value: +null
      • changedInput schema / properties / organisme_id / description
        Previous value: -"ID FFBB du club (organisme) concerné."New value: +"ID FFBB du club (alternative plus rapide à club_name)."
      • removedInput schema / required
        Removed value: -[
        -  "organisme_id",
        -  "categorie",
        -  "numero_equipe"
        -]
    • Addedffbb_head_to_head
    • Changedffbb_resolve_team1 field changed
      • addedInput schema / properties / numero_equipe
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Numéro d'équipe facultatif (ex: 1, 2).",
        +  "title": "Numero Equipe"
        +}
    • Changedffbb_team_summary2 fields changed
      • addedInput schema / properties / force_refresh
        Added value: +{
        +  "default": false,
        +  "description": "Si True, force un rafraichissement des donnees",
        +  "title": "Force Refresh",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / numero_equipe
        Added value: +{
        +  "default": 1,
        +  "description": "Numéro d'équipe dans la catégorie (ex: 1, 2).",
        +  "title": "Numero Equipe",
        +  "type": "integer"
        +}
  9. 4 tool updatesv1.5.1
    • Changedffbb_bilan3 fields changed
      • addedOutput schema / $defs / BilanResponse / properties / competitions_incluses
        Added value: +{
        +  "description": "Liste des noms de compétitions incluses dans le bilan.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "title": "Competitions Incluses",
        +  "type": "array"
        +}
      • addedOutput schema / $defs / BilanResponse / properties / saison_terminee
        Added value: +{
        +  "default": true,
        +  "description": "Indique si la saison est terminée pour cette équipe (toutes les phases jouées).",
        +  "title": "Saison Terminee",
        +  "type": "boolean"
        +}
      • addedOutput schema / $defs / PhaseBilan / properties / total_equipes
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Nombre total d'équipes dans la poule.",
        +  "title": "Total Equipes"
        +}
    • Changedffbb_club6 fields changed
      • addedInput schema / properties / adversaire
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Nom de l'équipe adversaire pour filtrer uniquement les confrontations directes (ex: 'Royat Orcines', 'Stade Clermontois'). Utilisé avec action='calendrier'. Insensible à la casse et aux accents.",
        +  "title": "Adversaire"
        +}
      • changedInput schema / properties / organisme_id / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / organisme_id / description
        Previous value: -"Identifiant FFBB du club. Si absent, `club_name` est utilise pour effectuer une recherche."New value: +"Identifiant FFBB du club (ex: 1234 ou 'ARA0063058'). Si absent, `club_name` est utilise pour effectuer une recherche."
      • addedOutput schema / $defs / CalendrierMatch / properties / competition_type
        Added value: +{
        +  "default": "poule",
        +  "description": "Type de phase (poule ou élimination).",
        +  "title": "Competition Type",
        +  "type": "string"
        +}
      • addedOutput schema / $defs / CalendrierMatch / properties / lieu_complet
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Adresse formatée complète : 'Nom Salle - Adresse, CP Ville'.",
        +  "title": "Lieu Complet"
        +}
      • addedOutput schema / $defs / CalendrierMatch / properties / nom_salle
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Nom de la salle (libelle).",
        +  "title": "Nom Salle"
        +}
    • Changedffbb_last_result2 fields changed
      • changedInput schema / properties / organisme_id / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / organisme_id / description
        Previous value: -"Identifiant FFBB du club (organisme_id)"New value: +"Identifiant FFBB du club (organisme_id, ex: 1234 ou 'ARA0063058')"
    • Changedffbb_next_match2 fields changed
      • changedInput schema / properties / organisme_id / anyOf
        Previous value: -[
        -  {
        -    "type": "integer"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]New value: +[
        +  {
        +    "type": "integer"
        +  },
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / organisme_id / description
        Previous value: -"Identifiant FFBB du club (organisme_id)"New value: +"Identifiant FFBB du club (organisme_id, ex: 1234 ou 'ARA0063058')"
  10. 2 tool updatesv1.4.0
    • Changedffbb_bilan5 fields changed
      • addedOutput schema / $defs
        Added value: +{
        +  "BilanResponse": {
        +    "description": "Réponse structurée et typée pour le bilan d'une équipe.",
        +    "properties": {
        +      "_meta": {
        +        "additionalProperties": true,
        +        "description": "Métadonnées de fraîcheur et de cache.",
        +        "title": "Meta",
        +        "type": "object"
        +      },
        +      "bilan_total": {
        +        "$ref": "#/$defs/BilanTotal",
        +        "description": "Totaux cumulés toutes phases."
        +      },
        +      "categorie": {
        +        "description": "Catégorie d'âge/genre.",
        +        "title": "Categorie",
        +        "type": "string"
        +      },
        +      "club": {
        +        "description": "Nom officiel du club.",
        +        "title": "Club",
        +        "type": "string"
        +      },
        +      "equipes_bilan": {
        +        "additionalProperties": true,
        +        "description": "Bilans ventilés par numéro d'équipe.",
        +        "title": "Equipes Bilan",
        +        "type": "object"
        +      },
        +      "phase_courante": {
        +        "anyOf": [
        +          {
        +            "$ref": "#/$defs/PhaseBilan"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Détails de la dernière phase en cours."
        +      },
        +      "phases": {
        +        "description": "Liste de toutes les phases jouées.",
        +        "items": {
        +          "$ref": "#/$defs/PhaseBilan"
        +        },
        +        "title": "Phases",
        +        "type": "array"
        +      }
        +    },
        +    "required": [
        +      "club",
        +      "categorie",
        +      "bilan_total"
        +    ],
        +    "title": "BilanResponse",
        +    "type": "object"
        +  },
        +  "BilanTotal": {
        +    "description": "Statistiques cumulées d'une équipe (victoires, défaites, paniers).",
        +    "properties": {
        +      "difference": {
        +        "default": 0,
        +        "description": "Différence de paniers (marqués - encaissés).",
        +        "title": "Difference",
        +        "type": "integer"
        +      },
        +      "gagnes": {
        +        "default": 0,
        +        "description": "Nombre de matchs gagnés.",
        +        "title": "Gagnes",
        +        "type": "integer"
        +      },
        +      "match_joues": {
        +        "default": 0,
        +        "description": "Nombre de matchs joués.",
        +        "title": "Match Joues",
        +        "type": "integer"
        +      },
        +      "nuls": {
        +        "default": 0,
        +        "description": "Nombre de matchs nuls.",
        +        "title": "Nuls",
        +        "type": "integer"
        +      },
        +      "paniers_encaisses": {
        +        "default": 0,
        +        "description": "Total des paniers encaissés.",
        +        "title": "Paniers Encaisses",
        +        "type": "integer"
        +      },
        +      "paniers_marques": {
        +        "default": 0,
        +        "description": "Total des paniers marqués.",
        +        "title": "Paniers Marques",
        +        "type": "integer"
        +      },
        +      "perdus": {
        +        "default": 0,
        +        "description": "Nombre de matchs perdus.",
        +        "title": "Perdus",
        +        "type": "integer"
        +      }
        +    },
        +    "title": "BilanTotal",
        +    "type": "object"
        +  },
        +  "PhaseBilan": {
        +    "description": "Bilan détaillé pour une phase de compétition spécifique.",
        +    "properties": {
        +      "competition": {
        +        "description": "Nom de la compétition.",
        +        "title": "Competition",
        +        "type": "string"
        +      },
        +      "difference": {
        +        "default": 0,
        +        "description": "Différence de paniers.",
        +        "title": "Difference",
        +        "type": "integer"
        +      },
        +      "gagnes": {
        +        "default": 0,
        +        "description": "Matchs gagnés.",
        +        "title": "Gagnes",
        +        "type": "integer"
        +      },
        +      "match_joues": {
        +        "default": 0,
        +        "description": "Matchs joués dans cette phase.",
        +        "title": "Match Joues",
        +        "type": "integer"
        +      },
        +      "nuls": {
        +        "default": 0,
        +        "description": "Matchs nuls.",
        +        "title": "Nuls",
        +        "type": "integer"
        +      },
        +      "numero_equipe": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Numéro de l'équipe (ex: '1', '2').",
        +        "title": "Numero Equipe"
        +      },
        +      "paniers_encaisses": {
        +        "default": 0,
        +        "description": "Paniers encaissés.",
        +        "title": "Paniers Encaisses",
        +        "type": "integer"
        +      },
        +      "paniers_marques": {
        +        "default": 0,
        +        "description": "Paniers marqués.",
        +        "title": "Paniers Marques",
        +        "type": "integer"
        +      },
        +      "perdus": {
        +        "default": 0,
        +        "description": "Matchs perdus.",
        +        "title": "Perdus",
        +        "type": "integer"
        +      },
        +      "phase_terminee": {
        +        "default": false,
        +        "description": "Indique si la phase est terminée.",
        +        "title": "Phase Terminee",
        +        "type": "boolean"
        +      },
        +      "phase_type": {
        +        "default": "poule",
        +        "description": "Type de phase (poule ou élimination).",
        +        "title": "Phase Type",
        +        "type": "string"
        +      },
        +      "position": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Position actuelle au classement.",
        +        "title": "Position"
        +      },
        +      "poule_id": {
        +        "description": "ID de la poule.",
        +        "title": "Poule Id",
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "competition",
        +      "poule_id"
        +    ],
        +    "title": "PhaseBilan",
        +    "type": "object"
        +  }
        +}
      • removedOutput schema / additionalProperties
        Removed value: -true
      • addedOutput schema / properties
        Added value: +{
        +  "result": {
        +    "anyOf": [
        +      {
        +        "additionalProperties": true,
        +        "type": "object"
        +      },
        +      {
        +        "$ref": "#/$defs/BilanResponse"
        +      }
        +    ],
        +    "title": "Result"
        +  }
        +}
      • addedOutput schema / required
        Added value: +[
        +  "result"
        +]
      • changedOutput schema / title
        Previous value: -"ffbb_bilanDictOutput"New value: +"ffbb_bilanOutput"
    • Changedffbb_club7 fields changed
      • addedInput schema / properties / date_debut
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Date de début de filtrage au format YYYY-MM-DD (ex: '2026-05-01').",
        +  "title": "Date Debut"
        +}
      • addedInput schema / properties / date_fin
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Date de fin de filtrage au format YYYY-MM-DD (ex: '2026-05-31').",
        +  "title": "Date Fin"
        +}
      • addedInput schema / properties / limit
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Nombre maximum de matchs de calendrier à retourner (pagination/limite).",
        +  "title": "Limit"
        +}
      • addedOutput schema / $defs
        Added value: +{
        +  "CalendrierMatch": {
        +    "description": "Structure de données typée représentant un match de calendrier.",
        +    "properties": {
        +      "adresse": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Adresse complète de la salle.",
        +        "title": "Adresse"
        +      },
        +      "adresse_salle": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Adresse de la salle.",
        +        "title": "Adresse Salle"
        +      },
        +      "competition_nom": {
        +        "default": "",
        +        "description": "Nom de la compétition associée.",
        +        "title": "Competition Nom",
        +        "type": "string"
        +      },
        +      "date": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Date et heure du match en ISO format.",
        +        "title": "Date"
        +      },
        +      "equipe1": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Nom de l'équipe 1 (domicile).",
        +        "title": "Equipe1"
        +      },
        +      "equipe2": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Nom de l'équipe 2 (extérieur).",
        +        "title": "Equipe2"
        +      },
        +      "id": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "string"
        +          }
        +        ],
        +        "description": "ID unique de la rencontre.",
        +        "title": "Id"
        +      },
        +      "is_last_match": {
        +        "default": false,
        +        "description": "Indique s'il s'agit du dernier match joué.",
        +        "title": "Is Last Match",
        +        "type": "boolean"
        +      },
        +      "is_next_match": {
        +        "default": false,
        +        "description": "Indique s'il s'agit du prochain match à venir.",
        +        "title": "Is Next Match",
        +        "type": "boolean"
        +      },
        +      "joue": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "boolean"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Indique si le match a été joué (1 ou True) ou non (0 ou False).",
        +        "title": "Joue"
        +      },
        +      "num_journee": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "string"
        +          }
        +        ],
        +        "default": "",
        +        "description": "Numéro de la journée de championnat.",
        +        "title": "Num Journee"
        +      },
        +      "played": {
        +        "default": false,
        +        "description": "Indique si le match est déjà joué.",
        +        "title": "Played",
        +        "type": "boolean"
        +      },
        +      "salle": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "additionalProperties": true,
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Nom de la salle de sport ou dictionnaire d'informations.",
        +        "title": "Salle"
        +      },
        +      "salle_details": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": true,
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Détails enrichis de la salle de sport.",
        +        "title": "Salle Details"
        +      },
        +      "score_equipe1": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Score de l'équipe 1.",
        +        "title": "Score Equipe1"
        +      },
        +      "score_equipe2": {
        +        "anyOf": [
        +          {
        +            "type": "integer"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Score de l'équipe 2.",
        +        "title": "Score Equipe2"
        +      },
        +      "ville": {
        +        "anyOf": [
        +          {
        +            "type": "string"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ],
        +        "default": null,
        +        "description": "Ville où se situe la salle.",
        +        "title": "Ville"
        +      }
        +    },
        +    "required": [
        +      "id"
        +    ],
        +    "title": "CalendrierMatch",
        +    "type": "object"
        +  }
        +}
      • addedOutput schema / properties / result / anyOf
        Added value: +[
        +  {
        +    "items": {
        +      "additionalProperties": true,
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  {
        +    "items": {
        +      "$ref": "#/$defs/CalendrierMatch"
        +    },
        +    "type": "array"
        +  }
        +]
      • removedOutput schema / properties / result / items
        Removed value: -{
        -  "additionalProperties": true,
        -  "type": "object"
        -}
      • removedOutput schema / properties / result / type
        Removed value: -"array"
  11. 12 tool updatesv1.3.2
    • Addedffbb_bilan
    • Addedffbb_bilan_saison
    • Addedffbb_club
    • Addedffbb_get
    • Addedffbb_last_result
    • Addedffbb_lives
    • Addedffbb_next_match
    • Addedffbb_resolve_team
    • Addedffbb_saisons
    • Addedffbb_search
    • Addedffbb_team_summary
    • Addedffbb_version
  12. 12 tool updatesv1.3.1
    • Removedffbb_bilan
    • Removedffbb_bilan_saison
    • Removedffbb_club
    • Removedffbb_get
    • Removedffbb_last_result
    • Removedffbb_lives
    • Removedffbb_next_match
    • Removedffbb_resolve_team
    • Removedffbb_saisons
    • Removedffbb_search
    • Removedffbb_team_summary
    • Removedffbb_version
  13. 22 tool updatesv1.2.0
    • Addedffbb_bilan
    • Addedffbb_bilan_saison
    • Addedffbb_club
    • Addedffbb_get
    • Removedffbb_get_competition
    • Removedffbb_get_lives
    • Removedffbb_get_organisme
    • Removedffbb_get_poule
    • Removedffbb_get_saisons
    • Addedffbb_last_result
    • Addedffbb_lives
    • Removedffbb_multi_search
    • Addedffbb_next_match
    • Addedffbb_resolve_team
    • Addedffbb_saisons
    • Addedffbb_search
    • Removedffbb_search_competitions
    • Removedffbb_search_organismes
    • Removedffbb_search_rencontres
    • Removedffbb_search_salles
    • Addedffbb_team_summary
    • Addedffbb_version
  14. 10 tool updatesv0.1.0
    • First observedffbb_get_competition
    • First observedffbb_get_lives
    • First observedffbb_get_organisme
    • First observedffbb_get_poule
    • First observedffbb_get_saisons
    • First observedffbb_multi_search
    • First observedffbb_search_competitions
    • First observedffbb_search_organismes
    • First observedffbb_search_rencontres
    • First observedffbb_search_salles

TDQS

A3.5/5.0

Scored across 19 tools

Disambiguation3/5

Several clusters overlap: ffbb_bilan / ffbb_team_summary / ffbb_bilan_saison all summarize team performance, ffbb_resolve_team / ffbb_find_team_candidates both resolve team identity, and ffbb_next_match / ffbb_last_result / ffbb_club(calendrier) / ffbb_match_lookup all answer match queries. The descriptions try hard to disambiguate with cross-references and warnings, but the need for such heavy coaching reveals genuine boundary confusion.

Naming Consistency4/5

All 19 tools share the ffbb_ prefix and snake_case, giving a predictable, readable surface. There is some mixing of noun-only names (ffbb_version, ffbb_saisons, ffbb_bilan) with verb_noun names (ffbb_search_regulations, ffbb_resolve_team), but the convention stays consistent enough to be navigable.

Tool Count4/5

19 tools is slightly heavy but justified for a domain spanning teams, matches, clubs, standings, regulations, live feeds, and seasons. Only the regulation sub-domain (4 tools) and the team-resolution pair push toward redundancy, so the count is reasonable overall.

Completeness4/5

The surface covers the full lifecycle of the stated domain: discovery/search, retrieval by id, team resolution, match lookup, results, upcoming matches, standings, multi-phase season summaries, head-to-head, and regulation lookup. Minor gaps like player-level or competition-wide aggregation exist but core workflows appear complete.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides access to comprehensive sports data from 5 major leagues (NBA, NFL, MLB, EPL, NHL) including teams, players, games, statistics, standings, injuries, and betting odds through 67+ endpoints. Enables users to query sports information and analytics through natural language.
    12
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Gives your MCP host (Claude Desktop, Cursor, Continue, Zed) access to live scores, match details, standings, top scorers, knockout brackets and player stats across football, basketball, cricket and tennis. Backed by the free public SportScore API — no key, no signup, CORS-open.
    8
    60 npm
    14
    MIT
  • A
    license
    B
    quality
    D
    maintenance
    Provides comprehensive NBA statistics via Model Context Protocol, enabling queries for player stats, game scores, team info, and advanced analytics through natural language.
    21
    10
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to access comprehensive sports data including football, basketball, American football, and hockey leagues via 11 tools, with no API key required.
    MIT