Skip to main content
Glama
nickdesi

FFBB MCP Server

by nickdesi

🏀 FFBB MCP Server

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

Serveur MCP pour consulter calendriers, classements, bilans, résultats et scores live de la FFBB.

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

Version Python CI MCP Glama 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 ? » « Donne-moi le classement de la poule 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

Outil

Usage

ffbb_version

Informations de version et configuration runtime du serveur FFBB MCP.

ffbb_search

Recherche FFBB — clubs, compétitions, matchs, salles, tournois, etc.

ffbb_bilan

Bilan complet d'une équipe toutes phases confondues en UN seul appel (V/D/N, paniers, phases).

ffbb_get

Recupere une ressource FFBB par identifiant.

ffbb_club

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

ffbb_lives

Matchs en cours (scores live, cache 30s). Retourne [] si aucun match.

ffbb_saisons

Liste des saisons FFBB. active_only=True pour la saison en cours uniquement.

ffbb_resolve_team

Identifie une equipe unique (Pivot central).

ffbb_team_summary

Résumé complet et agent-friendly pour une équipe.

ffbb_last_result

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

ffbb_next_match

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

ffbb_bilan_saison

Bilan détaillé de la saison pour une équipe précise (toutes phases).

ffbb_head_to_head

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

NOTE

Référence complète des 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

flowchart LR
    A[Client MCP<br/>Claude · Cursor · Antigravity] -->|Streamable HTTP / Stdio| B[FFBB MCP Server<br/>FastMCP]
    B --> C[Services métier<br/>Cache SWR & Agrégation]
    C --> D[ffbb-data-client<br/>SDK Python]
    D --> E[(API Directus &<br/>Meilisearch FFBB)]

Points clés :

  • Double transport : Streamable HTTP distant (spec 2025-11-25) ou Stdio local (uvx) ;

  • SDK Python découplé : Requêtes réseau et parsing Pydantic v2 délégués à ffbb-data-client ;

  • Agrégation composite : 12 outils optimisés pour réduire les allers-retours et le contexte LLM ;

  • 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.


💻 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

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

13 tools
ffbb_bilanBilan complet toutes phasesA
Read-onlyIdempotent

Bilan complet d'une équipe toutes phases confondues en UN seul appel (V/D/N, paniers, phases).

Outil prioritaire pour 'quel est le bilan de X ?' ou 'résultats de U11M1'.

ParametersJSON Schema
NameRequiredDescriptionDefault
categorieNoCatégorie/genre/numéro (ex: 'U11M1', 'Senior').
club_nameNoNom du club (ex: 'Stade Clermontois', 'ASVEL').
organisme_idNoID FFBB du club (ex: 9326).
force_refreshNoSi True, contourne le cache.
numero_equipeNoNuméro d'équipe (ex: 1, 2).

TDQS

A4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful context about scope (all phases, one call, result contents) but does not disclose behaviors such as freshness, caching, or limits beyond what the annotation hints imply.

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?

The description is compact and front-loaded: the first sentence states exactly what the tool does, and the second gives concrete query examples. Every sentence earns its place with no wasted words.

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 moderate-complexity tool with 5 params, full schema coverage, and no output schema, the description provides enough high-level output expectation (V/D/N, paniers, phases) and example usage. It could be more complete with explicit mention of the required club_name/organisme_id identification, but the schema covers that.

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 parameters are already documented with examples in the input schema. The description does not add extra semantic value for parameters, which matches the baseline of 3 when the schema carries the burden.

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 action and resource: producing a complete bilan (record) for a team across all phases in a single call, and enumerates included data (V/D/N, paniers, phases). This clearly distinguishes it from siblings like ffbb_bilan_saison and ffbb_team_summary.

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 description explicitly positions the tool as the priority choice for queries like 'quel est le bilan de X ?' and 'résultats de U11M1', giving clear usage context. It does not explicitly name alternatives or exclusion conditions, so it stops short of full when-not guidance.

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 détaillé de la saison pour une équipe précise (toutes phases).

Cet outil est optimisé pour les questions du type "Quel est le bilan de la saison des U11M1 ?".

Il agrège toutes les phases (toutes poules) de la saison FFBB pour l'équipe identifiée par (organisme_id/club_name, categorie, numero_equipe).

Pour chaque phase, il retourne :

  • competition

  • poule_id

  • position

  • match_joues, gagnes, perdus, nuls

  • paniers_marques, paniers_encaissés, difference

Et fournit également un champ bilan_total qui cumule toutes les phases.

ParametersJSON Schema
NameRequiredDescriptionDefault
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').
organisme_idNoID FFBB du club (alternative plus rapide à club_name).
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).

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already mark the tool as readOnly, idempotent, and non-destructive. The description adds useful behavioral context by explaining that it 'agrège toutes les phases' and returns both per-phase details and a 'bilan_total' field. This goes beyond the annotations by showing the aggregation logic and exact 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?

The description is well-structured and front-loaded with the main purpose, followed by an example trigger and a clear bulleted list of returned fields. Each part adds value, especially given there is no output schema. It is slightly longer than strictly necessary but not repetitive or padded.

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 appropriately details the per-phase return fields and the cumulative bilan_total. It also specifies the team identification parameters. Minor gaps remain, such as cache behavior, handling of ambiguous club names, or disambiguation between categorie and numero_equipe, but these are largely covered by 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 baseline is 3. The description reinforces the team-identification tuple (organisme_id/club_name, categorie, numero_equipe), but does not add significant semantic detail beyond the schema. It does not explain force_refresh beyond what the schema already states.

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 and resource: 'Bilan détaillé de la saison pour une équipe précise (toutes phases)'. It clearly explains that the tool aggregates all phases and all pools for team identified by organisme_id/club_name, categorie, and numero_equipe. It distinguishes itself from siblings by emphasizing 'toutes phases' and the per-phase plus total output.

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 description gives a clear use case: 'Cet outil est optimisé pour les questions du type "Quel est le bilan de la saison des U11M1 ?"'. This provides strong contextual guidance on when to invoke the tool. However, it does not explicitly mention alternatives or when not to use it, so it stops short of a 5.

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.

Outil de référence pour toute demande au pluriel : matchs restants, calendrier complet. Utiliser adversaire avec action='calendrier' pour isoler les confrontations directes.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoNombre max de matchs retournés (pagination).
phaseNoNom ou numéro de phase (ex: 'Phase 2').
actionYesAction : 'calendrier' (matchs pluriels/restants), 'equipes' ou 'classement'.
filtreNoFiltre catégorie/genre (ex: 'U11M', 'Senior').
date_finNoDate fin YYYY-MM-DD (action='calendrier').
poule_idNoID poule (action='classement').
club_nameNoNom du club (ex: 'Stade Clermontois'). Requis si organisme_id absent.
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.
force_refreshNoSi True, contourne le cache.
numero_equipeNoNuméro d'équipe (ex: 1, 2) pour action='calendrier'.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds behavioral context beyond the annotations by clarifying that this tool returns plural/aggregated data (matchs pluriels, calendrier complet) and supports head-to-head filtering with the adversaire parameter.

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?

The description is compact and front-loaded: the first line states the resource and actions, the second gives the primary use case, and the third gives a specific parameter guidance. Every sentence earns its place with no redundant filler.

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 multi-action tool with 12 parameters, the description gives enough context to select it and understand its three main modes. The schema covers parameter-level details, and the annotations cover safety. A short note on expected return shape would improve it, but the current level is sufficient 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?

Schema description coverage is 100%, so the schema already documents every parameter. The description reinforces the usage of adversaire with action='calendrier' for direct confrontations, but this is also stated in the adversaire parameter description, so the added value is marginal.

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 resource (club) and the three concrete operations: calendrier, équipes, classement. It also defines a clear scope — 'toute demande au pluriel' (remaining matches, full calendar) — which distinguishes it from singular sibling tools like ffbb_next_match and ffbb_last_result.

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 description explicitly states when to use the tool: 'Outil de référence pour toute demande au pluriel : matchs restants, calendrier complet.' It also gives a specific usage pattern (adversaire avec action='calendrier') for direct confrontations. However, it does not explicitly name sibling alternatives or state when not to use this tool.

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 identifiantA
Read-onlyIdempotent

Recupere une ressource FFBB par identifiant.

  • type="competition" equivaut a get_competition.

  • type="poule" charge la poule (classements + rencontres).

  • type="organisme" charge les details d'un club.

  • type="rencontre" charge une rencontre précise.

⚠️ Attention: type="poule" peut être tronqué si la poule est grande. Pour un calendrier exhaustif, préférez ffbb_club(action="calendrier").

Avertissement: ne pas utiliser pour obtenir un score ou un prochain match. Utiliser ffbb_last_result et ffbb_next_match a la place.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesIdentifiant numérique FFBB exact. Ne pas passer un nom de club: utiliser d'abord ffbb_search pour résoudre l'id.
typeYesType de ressource a charger.
force_refreshNoSi True et type='poule', contourne le cache pour recuperer la poule en temps reel (scores live).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and openWorldHint=true, and the description adds meaningful behavioral nuance: 'type='poule' peut être tronqué si la poule est grande' and force_refresh 'contourne le cache... en temps réel (scores live)'. This explains side effects, caching, and truncaton beyond the annotation flags, with no contradiction.

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?

The description is compact and well structured: a leading one-line purpose, bulleted resource type meanings, and two focused warnings. Every sentence contributes either a direct behavior or a routing decision, with no fluff or redundancy.

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 multi-type getter with no output schema, the description covers the important behavioral and routing details: resource types, truncaton risk, cache behavior, and exclusions for score/next-match use. It does not describe the 'officiel' and 'entraineur' enum variants, but the essential guidance for correct selection and invocation is present.

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?

Input schema description coverage is 100%, so the baseline is 3; the description adds semantic meaning for the type enum by stating what each major type loads, e.g. competition, pocle, organisme, rencontre. It also reinforces the id resolution behavior indirectly by warning about using ffbb_search in the schema, and contextualises force_refresh for live scores.

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 concrete verb and object – 'Recupere une ressource FFBB par identifiant' – and then enumerates what each resource type returns, e.g. 'type='poule' charge la poule (classments + rencontres)' and 'type='organisme' charge les details d'un club'. This makes the tool's purpose and scope clear and distinguishes it from focused siblings like ffbb_last_result and ffbb_next_match.

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?

Gives explicit when-to-use guidance for the main resource types and provides direct alternatives: for an exhaustive schedule, 'préférez ffbb_club(action='calendrier')' and for a score or next match, use 'ffbb_last_result' and 'ffbb_next_match' instead. This is factual routing guidance, not a generic hint.

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).

Fournit :

  • Bilan historique des confrontations directes de la saison (victoires A vs B, scores, écarts)

  • Forme récente respective de chaque équipe (V-D-V-V...) et séries en cours

  • Duel statistique des styles : Attaque vs Défense, ratio de victoires domicile/extérieur

  • Points clés narratifs prêts pour la rédaction d'articles ou de synthèses d'avant-match

ParametersJSON Schema
NameRequiredDescriptionDefault
club_aNoNom du premier club (ex: 'Stade Clermontois').
club_bNoNom du second club (ex: 'Vichy', 'Roanne').
categorieNoCatégorie d'équipe commune à comparer (ex: 'SEM1', 'U18M', 'Senior').
force_refreshNoSi True, force le rafraîchissement des données
organisme_id_aNoID FFBB du premier club (ex: 9326).
organisme_id_bNoID FFBB du second club.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and non-destructive behavior. The description adds useful behavioral context by enumerating the analysis dimensions returned (historical H2H, form, attack/defense duel, narrative points). It does not disclose edge cases like missing H2H data, but the annotation coverage lowers the burden.

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?

The description front-loads the main purpose in one sentence and then organizes the additional value into four compact, semantically distinct bullets. Every bullet earns its place and there is no filler or repetition.

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 6-parameter tool with no output schema, the bullet list covers the major return contents well, and the annotations cover side effects. However, it does not state which parameters are needed to start (e.g., club_a/club_b vs organisme_id_a/b or categorie), though the input schema compensates. This gap keeps it just below a 5.

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?

Input schema coverage is 100% and every parameter (club_a, club_b, categorie, force_refresh, organisme_id_a/b) has its own description, so the baseline is 3. The tool description adds no parameter-specific guidance beyond the notion of comparing two teams; it does not explain the name-vs-ID alternatives or the need for a common categorie, but the schema already covers these.

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 action ('Compare deux équipes') and a specific resource ('confrontations directes (H2H)'). The bullets clearly define the output as a head-to-head analysis covering historical record, recent form, statistical duel, and narrative points, which differentiates it from single-team siblings like ffbb_team_summary or ffbb_bilan.

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 description gives clear use context: the output is 'prêtes pour la rédaction d'articles ou de synthèses d'avant-match', so an agent can infer it is for pre-match comparison articles. It does not, however, explicitly state when not to use it or name alternative tools, so it stops short of 5.

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
categorieYesCatégorie de l'équipe précise (ex: 'U11M1', 'U11M', 'U11F')
club_nameNoNom du club (ex: 'Stade Clermontois')
organisme_idNoIdentifiant FFBB du club (organisme_id, ex: 1234 ou 'ARA0063058')
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.

TDQS

A3.8/5.0
Behavior3/5

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

Annotations already convey read-only, idempotent, non-destructive behavior, so the bar for extra disclosure is lower. The description adds the singular-team constraint and the category-resolution recommendation, which are useful, but it does not describe output shape, error behavior, or what happens with unresolved categories. No contradiction with annotations 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?

The description is short, front-loaded with the core purpose, and uses a clear recommendation block. There is minor redundancy between the first sentence and the title, but the singular-only warning and LLM recommendation both earn their 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 tool with rich annotations and fully documented parameters, the description covers the essential selection and invocation logic: singular scope, category ambiguity, and the resolve-team prerequisite. It does not detail the return payload, but no output schema exists and the core return concept is stated.

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?

All five parameters have schema descriptions, so the baseline is 3. The description goes further by explaining how `categorie` and `numero_equipe` relate, and recommends calling `ffbb_resolve_team` when the category lacks a number. This adds practical parameter-level guidance beyond the schema.

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 clearly identifies the tool's purpose: it returns the last played match for a single team. The explicit 'SINGULIER UNIQUEMENT' warning and reference to a precise team make the scope unambiguous, though it does not explicitly contrast with sibling tools like ffbb_next_match.

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 description gives clear context for when to use the tool (single team only) and provides a concrete prerequisite workflow: resolve an imprecise category via ffbb_resolve_team before calling. It stops short of explaining when to choose this over alternatives such as ffbb_next_match or team summaries.

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

ffbb_livesScores en directA
Read-onlyIdempotent

Matchs en cours (scores live, cache 30s). Retourne [] si aucun match.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

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

The description adds useful behavior beyond the annotations by noting a 30-second cache and the empty-array return when no matches are ongoing. The annotations already establish read-only, idempotent, non-destructive behavior, so the description's extra details are meaningful and non-contradictory.

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?

The description is extremely compact, with every phrase earning its place: it states what is returned, adds the cache detail, and handles the no-match edge case. It is front-loaded and easy to parse.

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 read-only tool, the description covers the essential behavior: current matches, live scores, caching, and empty result. An output schema is absent, so the exact shape of each live score entry is not specified, but the simplicity of the tool makes this a minor gap.

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?

There are zero parameters, so the description is not required to explain any input schema. Schema description coverage is effectively 100%, and the description adds relevant output semantics (live scores, empty result) that help the agent understand what the tool returns.

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 clearly identifies the resource (ongoing/live matches) and the output (live scores, empty array if no match). It is clear and specific, though it does not explicitly distinguish itself from sibling tools such as ffbb_last_result or ffbb_next_match.

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?

The phrase 'Matchs en cours' implies the tool should be used when the agent needs current live scores, and the 30s cache hints at near-real-time data. However, there is no explicit guidance about when to choose this tool over alternatives or when not to use it.

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
categorieYesCatégorie de l'équipe précise (ex: 'U11M1', 'U11M', 'U11F')
club_nameNoNom du club (ex: 'Stade Clermontois')
organisme_idNoIdentifiant FFBB du club (organisme_id, ex: 1234 ou 'ARA0063058')
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.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already establish readOnly, idempotent, openWorld, and non-destructive behavior, so the bar is lower. The description adds important behavioral context: it returns exactly one match, is not suitable for plural queries, and may require team resolution when the category is ambiguous. It does not describe the response format, but the core behavioral constraints are well communicated.

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?

The description is front-loaded and structured with clear warning sections, but the singular-only message is repeated in multiple paragraphs with heavy capitalization and emoji. The plural-request guidance appears twice, so not every sentence earns its place despite the criticality of the warning.

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 tool with five parameters and no output schema, the description covers the critical context: strict singular behavior, which sibling to use for plurals, and how to resolve ambiguous categories. Parameter details are covered by the schema, and the safety profile is covered by annotations. The only notable gap is the lack of return-format description, which is mitigated by the simple 'next match' concept.

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 adds value by explaining that an imprecise category like 'U11M' should be resolved via ffbb_resolve_team to obtain the real numero_equipe. This goes beyond the schema by linking parameter disambiguation to a concrete workflow.

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 clearly states the tool's purpose: returning the next match to be played for a specific team. It explicitly says the tool returns strictly one unique match and distinguishes itself from the sibling ffbb_club, which handles plural/calendar requests. There is no ambiguity about what the tool does.

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?

The description gives explicit when-to-use and when-not-to-use guidance: singular requests only, and plural requests must use ffbb_club(action='calendrier') instead. It also recommends using ffbb_resolve_team when the category is imprecise, which is concrete and actionable routing advice.

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').

ParametersJSON Schema
NameRequiredDescriptionDefault
categorieNoCatégorie + genre + numéro d'équipe (ex: 'U11M1', 'U13F2', 'U15M'). Si le numéro manque, cet outil retourne la bonne équipe ou des candidats.
club_nameNoNom du club (ex: 'Stade Clermontois', 'ASVEL').
organisme_idNoID FFBB du club (alternative plus rapide à club_name).
numero_equipeNoNuméro d'équipe facultatif (ex: 1, 2).

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already disclose read-only, idempotent, non-destructive behavior. The description adds useful behavioral context beyond that: it resolves to a unique team, acts as a central pivot, and should be invoked before match/result tools when there is ambiguity. It does not detail return shape or error behavior, but given the annotations, this is acceptable.

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?

The description is short, front-loaded with the core purpose, and each sentence earns its place. The prerequisite usage guidance is delivered in a clear, direct way without redundant filler.

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?

Given the rich schema descriptions and strong annotations, the description adequately explains the tool's purpose and when to invoke it. A small gap is that it does not explicitly state what the return value should be used for, though 'identifie une equipe unique' and the prerequisite wording strongly imply it.

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 input schema already documents all parameters. The description adds no parameter-level detail beyond mentioning category ambiguity in the usage example. Therefore the baseline score of 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?

The description opens with a specific verb and resource: 'Identifie une equipe unique (Pivot central).' It clearly differentiates the tool from siblings by stating it is a prerequisite for `ffbb_next_match` and `ffbb_last_result`, so an agent can understand what this tool does and how it fits into a workflow.

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?

The description explicitly states when to use the tool: before `ffbb_next_match` or `ffbb_last_result` when the exact team number is unknown or the category is ambiguous. This gives concrete usage conditions and names the alternative workflow it supports, leaving little to inference.

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 FFBBA
Read-onlyIdempotent

Liste des saisons FFBB. active_only=True pour la saison en cours uniquement.

ParametersJSON Schema
NameRequiredDescriptionDefault
active_onlyNoTrue = saison active uniquement.

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, openWorldHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds the active_only filtering behavior, which is beyond annotations, but it does not disclose return format, pagination, or data source; the lowered bar for annotated tools makes this acceptable.

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?

Two short sentences, front-loaded with the core purpose, with the second sentence covering the only parameter. No filler or redundant explanation.

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 simple, optional-parameter, read-only list tool with rich annotations, the description is functionally complete. It could go further by describing the shape of the returned season list, since there is no output schema, but the name and verb make the expected return reasonably clear.

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 coverage is 100%: the sole boolean parameter already has a description ('True = saison active uniquement'). The description mostly restates this in prose, adding little semantic value 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.

Purpose4/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 ('saisons FFBB'), making the purpose immediately clear. It does not explicitly differentiate from related season-specific siblings like ffbb_bilan_saison, but no sibling appears to offer the same season-list functionality.

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?

The purpose implies when to use it: when a list of FFBB seasons is needed, optionally restricted to the current season. However, there is no explicit when-to-use vs alternatives guidance or exclusions, so the usage context is mainly implied.

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

Résumé complet et agent-friendly pour une équipe.

Combine en UN seul appel :

  • bilan global (toutes phases)

  • phase courante et son classement

  • dernier match joué

  • prochain match à venir

Recommandé pour une vue rapide d'une équipe précise. Si la catégorie est ambiguë ou sans numéro d'équipe, l'outil tente une résolution via ffbb_resolve_team. Pour une liste de matchs restants, utiliser plutôt ffbb_club(action="calendrier").

ParametersJSON Schema
NameRequiredDescriptionDefault
categorieNoCatégorie + genre + numéro d'équipe (ex: 'U11M1', 'U13F2', 'U15M', 'Senior').
club_nameNoNom du club (ex: 'Stade Clermontois', 'ASVEL').
organisme_idNoID FFBB du club (alternative plus rapide à club_name).
force_refreshNoSi True, force un rafraichissement des donnees
numero_equipeNoNuméro d'équipe dans la catégorie (ex: 1, 2).

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds meaningful behavioral context beyond annotations: it combines four data categories into one call and attempts team resolution via ffbb_resolve_team under ambiguous conditions. This is useful but does not fully describe response structure or edge-case behavior, hence not 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.

Conciseness5/5

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

The description is tightly structured: a one-line overview, a bulleted list of what the combined call contains, and two short sentences for usage guidance and alternatives. It is front-loaded with the core purpose and every sentence serves a clear role, with no redundant explanation.

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?

Given the tool's moderate complexity (5 parameters, no output schema), the description covers the key invocation decisions: what the summary includes, when to use it, the resolution fallback, and the alternative tool for remaining matches. A fully explicit response format is not specified, but the annotations and full schema coverage compensate enough that the agent can reliably select and invoke the tool.

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. The description adds value beyond the schema by explaining the resolution behavior tied to categorie/numero_equipe ('Si la catégorie est ambiguë ou sans numéro d'équipe, l'outil tente une résolution via ffbb_resolve_team'). This clarifies parameter semantics more than the schema descriptions alone.

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 clearly states a specific verb and resource: it produces a complete team summary in a single call, and explicitly lists the four combined components (global bilan, current phase/ranking, last match, next match). It also differentiates itself from sibling tools by naming ffbb_club for a different need and ffbb_resolve_team for resolution behavior.

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?

The description gives explicit usage context: 'Recommandé pour une vue rapide d'une équipe précise'. It also provides an alternative tool for a different use case ('Pour une liste de matchs restants, utiliser plutôt ffbb_club(action="calendrier")') and explains the resolution fallback when the category is ambiguous or no team number is provided.

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

Informations de version et configuration runtime du serveur FFBB MCP.

Retourne une structure compacte et strictement typée, pratique pour les agents et les outils de supervision.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds useful behavioral context about the return value ('structure compacte et strictement typée'), which helps agents parse the response, but it does not disclose additional runtime behaviors such as caching, latency, or what specific version fields are included.

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?

Two tight sentences with no filler. The first sentence states what the tool returns, and the second explains the return structure's shape and intended audience. Everything 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 zero-parameter version/diagnostics tool, the description covers the essentials: what is returned (version and runtime configuration) and the nature of the return structure (compact, strictly typed). With no output schema present, this is adequate for an agent to know what to expect and how it differs from the data-focused sibling tools.

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 has zero parameters and schema description coverage is 100%, so there is nothing for the description to clarify about arguments. The baseline of 4 for parameterless tools applies here, and the description appropriately focuses on the output rather than inputs.

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 clearly states a specific resource (the FFBB MCP server) and what it returns: 'Informations de version et configuration runtime du serveur FFBB MCP.' This aligns with the title 'Version et diagnostics serveur' and is easily distinguishable from the sibling tools (search, bilan, get), which serve different purposes.

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?

The description gives a use context—'pratique pour les agents et les outils de supervision'—indicating this is a diagnostics/monitoring tool. However, it does not explicitly state when to use it versus alternatives, nor does it name any sibling or exclusion condition. Usage is implied rather than explicit.

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. Dates show when Glama detected each change.

  1. 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
  2. 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"
        +}
  3. 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')"
  4. 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"
  5. 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
  6. 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
  7. 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
  8. 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.9/5.0
Disambiguation3/5

Most tools have clear distinct roles, and the descriptions contain helpful routing warnings (singular vs plural, resolve-before-lookup, prioritization notes). However, ffbb_bilan and ffbb_bilan_saison cover nearly the same all-phases season bilan, and ffbb_team_summary also overlaps with bilan/last/next, so some selection ambiguity remains.

Naming Consistency4/5

All tools share the ffbb_ prefix and consistently use lowercase snake_case, which makes the set feel cohesive. The grammatical pattern is slightly mixed (verbs like search/get/resolve_team vs noun phrases like bilan, team_summary, head_to_head), but nothing is erratic or inconsistent in style.

Tool Count5/5

13 tools is well within the ideal 3-15 range for a domain-specific read-only API. The count covers discovery, detail retrieval, club/team aggregations, live scores, seasons, and head-to-head analysis without feeling bloated.

Completeness4/5

The surface is quite complete for the FFBB basketball domain: search, resource retrieval, club schedules, team summaries, last/next matches, live scores, seasons, and head-to-head. Minor gaps remain, such as no non-truncated competition-wide calendar (ffbb_get type='poule' warns about truncation) and no roster/player tools, but agents can work around these.

Maintenance

ActivityActive
ResponsivenessResponsive

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    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
    D
    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
    131
    10
    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

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nickdesi/FFBB-MCP-Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server