agentleFS
nickdesinickdesi/FFBB-MCP-Server/AGENTS.md

FFBB-MCP-Server

AGENTS.md4 starsChanged 50 days agoApache-2.0View on GitHub

⚠️ Fichier auto-généré par tools/update_agents_md.py — ne pas modifier manuellement. Dernière mise à jour : FFBB MCP server | server.py: 434 lignes | services.py: 13020 lignes

  • Reads credentials
  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 31,774 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

  • In this repository4 other files it gives its agents.

The file

We split this AGENTS.md into the rules it gives an agent

1 rule. About 0 are common, 1 is distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Test manuel du service : status='ok'

    line 167

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

FFBB MCP Server

⚠️ Fichier auto-généré par tools/update_agents_md.py — ne pas modifier manuellement. Dernière mise à jour : FFBB MCP server | server.py: 434 lignes | services.py: 13020 lignes

Langue

Tous les documents de travail (walkthrough.md, implementation_plan.md) DOIVENT être en français.

Persona

Expert en basketball français. Accès au serveur MCP FFBB (ffbb.desimone.fr) connecté aux données officielles FFBB.

Workflow FFBB (Outils MCP)

Ressources MCP

  • ffbb://saisons → Liste des saisons FFBB au format JSON
  • ffbb://competition/{competition_id} → Détails d'une compétition au format JSON
  • ffbb://poule/{poule_id} → Détails d'une poule au format JSON
  • ffbb://organisme/{organisme_id} → Détails d'un organisme/club au format JSON
  • ffbb://rencontre/{rencontre_id} → Détails d'une rencontre au format JSON
  • ffbb://salle/{salle_id} → Détails d'une salle au format JSON
  • ffbb://officiel/{officiel_id} → Détails d'un officiel/arbitre au format JSON
  • ffbb://entraineur/{entraineur_id} → Détails d'un entraîneur/coach au format JSON

Règles de comportement

  • Appelle TOUJOURS un outil MCP avant de répondre
  • OBLIGATION ABSOLUE : Utiliser TOUJOURS le préfixe 'rtk' pour TOUTES les commandes shell exécutées dans le terminal (ex: 'rtk uv run ...', 'rtk git ...')
  • Si plusieurs résultats, liste et demande confirmation
  • Réponds toujours en français
  • Si API ne répond pas, dis-le clairement
  • Scores live : précise "données en temps réel, mises à jour toutes les 15s"
  • Réutilise les organisme_id résolus dans la conversation (ne pas re-rechercher)

Règles strictes (outils FFBB)

  • INTERDIT : ffbb_get(type='poule') pour chercher un score ou match
  • INTERDIT : Déduire un score depuis le classement
  • INTERDIT : Déclarer qu'un score "n'est pas disponible" sans avoir vérifié
  • OBLIGATOIRE : Présenter un résultat de match AVEC le classement complet (paniers_marqués, paniers_encaissés)
  • OBLIGATOIRE : Dans le classement, mettre TOUJOURS l'équipe cible en gras avec 🎯 (is_target: true)
  • SINGULIER vs PLURIEL : "prochain match" → ffbb_next_match · "prochains matchs" → ffbb_club(action='calendrier')
  • Catégorie ambiguë : Appeler ffbb_resolve_team AVANT ffbb_next_match/ffbb_last_result si pas de numéro d'équipe
  • Question combinant résultats/prochain match et classement :
    1. Appeler ffbb_team_summary.
    2. Si la réponse ne contient pas le tableau complet, appeler ffbb_club(action="classement", poule_id=<phase_courante.poule_id>, organisme_id=<resource_ids.organisme_id>) dans le même tour, sans le signaler à l'utilisateur comme une limite.
    3. Ne jamais écrire "je n'ai pas le détail" sans avoir tenté l'appel de classement.

Karpathy Guidelines (Règles de développement)

Ces directives inspirées d'Andrej Karpathy visent à éliminer les erreurs de codage courantes en privilégiant la simplicité et la rigueur :

1. Penser avant de coder (Think Before Coding)

  • Ne pas assumer, ne pas cacher la confusion, expliciter les compromis.
  • Avant d'implémenter :
    • Déclarez vos hypothèses de manière explicite. En cas d'incertitude, demandez.
    • S'il existe plusieurs interprétations, présentez-les — ne choisissez pas en silence.
    • Si une approche plus simple existe, proposez-la. Argumentez contre la complexité inutile si nécessaire.
    • Si quelque chose n'est pas clair, arrêtez-vous. Nommez ce qui vous perturbe et demandez confirmation.

2. La simplicité d'abord (Simplicity First)

  • Le minimum de code nécessaire pour résoudre le problème. Rien de spéculatif.
  • Pas de fonctionnalités au-delà de ce qui est explicitement demandé.
  • Pas d'abstractions pour du code à usage unique.
  • Pas de "flexibilité" ou de "configurabilité" non requise.
  • Pas de gestion d'erreurs pour des scénarios impossibles.
  • Si vous écrivez 200 lignes alors que 50 suffiraient, réécrivez-le.
  • Posez-vous toujours la question : "Est-ce qu'un développeur senior validerait cette implémentation comme simple et directe ?"

Phases éliminatoires vs poules

Détection automatique

Si le champ competition contient (insensible à la casse) l'un de ces termes : finale, 1/2, demi-finale, demi-fin, quart, play-off, playoff, coupe, barrage, promotion → Phase éliminatoire 🏆 Sinon (Phase 1, Phase 2, Phase 3…) → Phase de poule 📊

Règles de formulation

  • Phase éliminatoire : toujours mentionner explicitement le contexte (ex : "ce match est une demi-finale départementale")
  • Ne JAMAIS rattacher un match éliminatoire au bilan de phase de poule

État d'une phase (terminée vs en cours)

phase_courante dans ffbb_bilan = dernière phase connue, pas nécessairement une phase active.

Règle de temps verbal :

  • Si aucun match futur détectable dans la poule → utiliser le passé ("ont terminé", "ont fini", "se sont classés")
  • Si des matchs restent à jouer → utiliser le présent ("sont", "occupent", "se trouvent")

⚠️ INTERDIT : écrire "sont actuellement Xe" si la phase est terminée.

Format enrichi pour tout match affiché

  • 📍 Domicile / Extérieur
  • 🏆 Phase éliminatoire OU 📊 Phase de poule (numéro)
  • ⚠️ Si salle ou ville vides → écrire "Salle non encore renseignée"
  • 📍 Format d'adresse standardisé : [Nom de la Salle] - [Adresse Postale], [Ville] (gérer proprement les valeurs manquantes sans séparateurs orphelins)

Alignement Strict FFBB Data Client & MCP

  • Machine à états stricte (Zéro résolution d'équipe ambiguë silencieuse) : Ne JAMAIS renvoyer status="resolved" si plusieurs engagements actifs correspondent au club + catégorie (ex: Championnat [PLAT] vs Coupe [COUPE]). Renvoyer obligatoirement status="ambiguous", la liste exhaustive candidates, et un clarification_prompt prêt pour le LLM. Propager systématiquement les filtres competition_id, competition_type, poule_id, season_id, force_refresh sur tous les outils d'équipe et sur ffbb_club(action='calendrier').
  • Contrat de pagination _meta & enveloppe uniforme : Respect strict de 1 <= limit <= 100 et offset >= 0 sur ffbb_search. Tout outil retournant une collection paginée (ffbb_search, ffbb_club(action='calendrier')) doit renvoyer un objet {"items": list, "_meta": dict} avec total, returned, has_more et sort. Ne jamais insérer un objet sentinelle _meta en tête de liste.
  • Vérification d'identifiants numériques : Toujours vérifier id is None or id == "" (ne jamais utiliser if not id qui élimine silencieusement id: 0).
  • Résolution H2H & Fallback de poule : Si l'adversaire B n'est pas directement résolu par recherche globale d'organismes, inspecter la poule partagée de l'équipe A pour construire une résolution synthétique avec fallback_warning.
  • Dispatching dynamique des mocks inter-services : Dans l'architecture modulaire services/, utiliser systématiquement le pattern de résolution dynamique (getter = getattr(svc, 'func_name', func_local)) pour garantir l'herméticité et la compatibilité totale avec les mocks de tests unitaires.
  • Calcul objectif des statuts de saison : Évaluer enCours et within_date_range par comparaison temporelle stricte (debut <= today <= fin) pour pallier les états non mis à jour par l'amont Directus.
  • Parité des index Meilisearch : Le serveur MCP interroge exclusivement les 6 index Meilisearch réels et actifs (organismes, competitions, rencontres, salles, terrains, tournois).
  • Élévation de niveau / Fallback : Si Directus renvoie classements: [] (avant 1ère journée), le MCP reconstruit la liste des équipes engagées depuis les rencontres (status: non_commence).
  • Allègement des payloads : Préférer get_organisme_for_search_async() pour la résolution de club afin de minimiser le transfert réseau.
  • Polymorphisme des paramètres : Toujours supporter numero_equipe et force_refresh sur les outils d'équipe (ffbb_bilan, ffbb_team_summary, ffbb_next_match, ffbb_last_result).

Développement MCP (FastMCP)

  • Cycle de vie : mcp.run() ou mcp.run_streamable_http_async() — pas de montage manuel via app.mount()
  • Chemin personnalisé : configurer mcp.settings.streamable_http_path avant mcp.run()
  • Routes HTTP : définies dans routes.py via register_routes(mcp)
  • Tools MCP : définis dans server.py via @mcp.tool()

Architecture

src/ffbb_mcp/
├── __init__.py            # Version du package
├── __main__.py            # Point d'entrée CLI
├── _state.py              # State global (caches, inflight)
├── aliases.py             # Alias clubs + cache acronymes persistant
├── app_factory.py         # Starlette app + middlewares
├── benchmark.py           # Benchmark performance
├── cache_strategy.py      # TTL dynamique selon fenêtres de match
├── client.py              # FFBBDataClient factory + token refresh
├── dashboard.py           # Dashboard HTML
├── metrics.py             # Prometheus metrics + health snapshot
├── prompts.py             # Prompts MCP réutilisables
├── resources.py           # Resources MCP (ffbb://saisons, etc.)
├── routes.py              # Routes HTTP (health, metrics, dashboard, docs, etc.)
├── server.py              # Tools MCP + main() (≈434 lignes)
├── services/              # Logique métier modularisée (≈13020 lignes)
│   ├── __init__.py        # Point d'entrée et factory de services
│   ├── bilan.py           # Module de service
│   ├── calendar.py        # Module de service
│   ├── club.py            # Service de gestion des clubs
│   ├── common.py          # Helpers et base services partagés
│   ├── division.py        # Module de service
│   ├── http_api.py        # Module de service
│   ├── poule.py           # Service de gestion des poules
│   ├── poule_lives.py     # Module de service
│   ├── poule_opponent.py  # Module de service
│   ├── regulations.py     # Module de service
│   ├── salle.py           # Service de gestion des salles
│   ├── search.py          # Service de recherche multicritère
│   ├── team_resolver.py   # Module de service
│   └── warmup.py          # Service de préchauffage du cache
└── utils.py               # serialize_model, parse_categorie, normalize_query

Conventions de code

  • Services : ffbb_<nom>_service (dans services/)
  • Tools MCP : ffbb_<nom> (dans server.py, @mcp.tool())
  • Pas de suffixe _compact_ ou _impl_ exposé
  • Modifier une fonction à la fois, seulement si test/usage échoue
  • Nouvelle fonction → test manuel validé avant exposition MCP
  • Modularisation : Le package services/ (total ≈13020 lignes) remplace l'ancien fichier unique de 2915 lignes pour une meilleure cohésion.

Commandes

  • Démarrer le serveur MCP (stdio) : rtk uv run python -m ffbb_mcp (recommandé pour Claude Desktop)
  • Démarrer le serveur MCP (HTTP/SSE) : MCP_MODE=streamable-http rtk uv run python -m ffbb_mcp (port 9123 par défaut)
  • Inspecter/Tester localement : rtk npx -y @modelcontextprotocol/inspector uv run python -m ffbb_mcp
  • Tests unitaires : .venv/bin/python -m pytest -q (pas pytest seul)
  • Pre-merge :
    1. pytest -q → 0 failed
    2. Test manuel du service : status='ok'
    3. grep "compact\|fantôme" src/ffbb_mcp/*.py → 0 résultat

Codebase Knowledge Graph (codebase-memory-mcp)

Ce projet utilise codebase-memory-mcp pour maintenir un graphe de connaissances AST/Cypher précis de la codebase. Outils disponibles : search_graph, trace_path, get_code_snippet, query_graph, get_architecture.

Push / Tag / Release Gate

⚠️ OBLIGATION STRICTE : Toutes ces commandes DOIVENT être préfixées par 'rtk' dans le terminal (ex: 'rtk uv run pytest'). Ne jamais exécuter de commande nue sans 'rtk'. Avant push/tag/release :

  • rtk uv run python tools/check_version_alignment.py
  • rtk uv run ruff format --check .
  • rtk uv run ruff check .
  • rtk uv run mypy src
  • rtk uv run pyright src
  • rtk uv run pytest
  • Si version files modifiés : rtk uv run tools/sync_version.py + vérifier diff docs/website
  • Vérifier cache (src/ffbb_mcp/acronyms_cache.json) — revert impératif de toute modification non liée à votre tâche
  • Après push : inspecter les GitHub Actions

Variables d'environnement

VariableDéfautUsage
XDG_CACHE_HOME``Dossier racine pour stocker les fichiers de cache persistants (ex: acronymes, benchmark)
FFBB_DATA_DIR/app/dataRépertoire racine contenant les données statiques (ex: regulations, cache)
MCP_MODEstdioMode de transport (stdio / streamable-http)
MCP_STATELESS_HTTPtrueActiver le mode stateless HTTP MCP spec 2026-07-28 sans session (défaut : true)
ENABLE_DNS_PROTECTION``Activer/désactiver explicitement la protection contre le DNS rebinding
TRUSTED_PROXY_HOSTS127.0.0.1Proxies de confiance
FFBB_LIVES_REFRESH_INTERVAL60Intervalle de rafraîchissement proactif des lives en secondes, mode HTTP (défaut : 10)
FFBB_ENABLE_DIRECTUS0Forcer l'activation des appels Directus (défaut : 0, Directus désactivé en faveur de Meilisearch)
FFBB_DISABLE_DIRECTUS1Désactiver les appels réseau Directus vers bo/api.ffbb.com bloqués par BunnyCDN (défaut : 1)
API_FFBB_APP_BEARER_TOKEN``Jeton d'authentification Bearer pour l'API Directus FFBB
MEILISEARCH_BEARER_TOKEN``Jeton d'authentification Bearer pour le cluster Meilisearch FFBB
FFBB_CACHE_BACKENDsqliteChoix du backend de cache HTTP (sqlite ou redis)
API_FFBB_BASE_URLhttps://api.ffbb.com/URL de base de l'API FFBB (défaut : https://api.ffbb.com/)
FFBB_SERVICE_CACHE_PERSIST1Activer la persistance des caches service sur disque (SQLite) entre redémarrages
FFBB_KNOWN_CLUB_IDS``Override JSON de la liste d'organisme_id connus pour les prompts MCP (fallback : _DEFAULT_KNOWN_CLUB_IDS)
FFBB_REGULATIONS_MANIFEST``Chemin explicite vers le fichier manifest.yaml des règlements sportifs
FFBB_WARMUP_API_KEY``Clé d'API secrète requise pour déclencher le warmup via l'endpoint HTTP /warmup
FFBB_WARMUP_MAX_ORGANISMES50Nombre maximum d'organismes à charger lors d'un cycle de warmup
PUBLIC_URLhttps://ffbb.desimone.frURL publique pour liens/sitemap
ALLOWED_HOSTS*Hosts autorisés (DNS rebinding protection)
ALLOWED_ORIGINS*Origins CORS
FFBB_LOG_LEVELINFONiveau de log
HOST0.0.0.0Interface d'écoute
PORT9123Port d'écoute HTTP
FFBB_SWR_ENABLED1Activer le Stale-While-Revalidate : servir le cache et rafraîchir en arrière-plan (défaut : 1)
FFBB_SWR_STALE_FRACTION0.75Fraction du TTL au-delà de laquelle une entrée est rafraîchie en arrière-plan (défaut : 0.75)
FFBB_API_TIMEOUT_SECONDS3.0Timeout en secondes pour les requêtes vers l'API FFBB / Meilisearch
MAX_CONCURRENT_FFBB4Concurrence max appels API FFBB
FFBB_MAX_CALENDAR_MATCHES300Max rencontres retournées
FFBB_SWR_MAX_TASKS32Nombre max de tâches SWR concurrentes (défaut : 32)
FFBB_WARMUP_ORGANISMES``Liste d'organisme_id séparés par des virgules à préchauffer au démarrage
FFBB_WARMUP_CONCURRENCY5Concurrence maximale lors du préchauffage du cache
GIT_SHA``Commit SHA Git déployé exposé dans ffbb_version et /health
BUILD_SHA``Build SHA de l'image conteneurisée
COMMIT_SHA``Alias de commit SHA pour les déploiements CI/CD
BUILD_DATE``Date de compilation/build de l'image ou du package exposé dans ffbb_version
DEPLOY_DATE``Date de déploiement en production (alternative à BUILD_DATE)
FFBB_ENABLE_BENCHMARK—Activer endpoint /benchmark/run (sécurité)
FFBB_POULE_FETCH_CONCURRENCY—Concurrence max fetch poules
FFBB_CACHE_TTL_*—TTL par type de cache (voir cache_strategy.py)
FFBB_REDIS_URL—URL de connexion à l'instance Redis si backend=redis
FFBB_CACHE_EXPIRE_AFTER—TTL en secondes pour le cache HTTP court de session (défaut : 30)

Notes workflow / outils

PR Comments pour Jules (Google)

  • NE PAS utiliser gh pr review --comment — Jules ne le détecte pas
  • Utiliser gh pr comment <number> --body "..." ou commenter via l'UI GitHub
  • Jules écoute les issue_comment events, pas les pull_request_review events

Journal Bolt (.jules/bolt.md)

  • OBLIGATION : chaque nouvelle entrée ajoutée à .jules/bolt.md DOIT être datée de la date du jour (format ## YYYY-MM-DD - Titre)
  • INTERDIT : copier une date existante (d'une entrée précédente, d'une autre branche, d'un commit ou d'une issue) — les dates antérieures au jour d'écriture signalent une entrée non datée
  • Vérifier la date courante avant d'écrire, ex : date +%F

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.