Skip to content

feat: réécriture Go du serveur MCP (client de l'API /v1) — reads - #2

Open
t0m-car wants to merge 1 commit into
mainfrom
feat/go-rewrite
Open

feat: réécriture Go du serveur MCP (client de l'API /v1) — reads#2
t0m-car wants to merge 1 commit into
mainfrom
feat/go-rewrite

Conversation

@t0m-car

@t0m-car t0m-car commented Jul 4, 2026

Copy link
Copy Markdown
Member

Réécriture Go du serveur MCP Footics en client HTTP mince de footics-api /v1 (PRD 15). Livrable de staging à valider — pas une bascule prod. Le MCP live (mcp.footics.app sur Vercel) et tout le code TS restent intacts.

Ne pas merger. Le retrait du TS et la bascule = décision de Tom.

Ce qui est livré (go/)

  • Serveur Go : cmd/mcp + internal/{config,auth,apiclient,tools}.
    • Auth = vérif JWT Supabase locale, double-mode JWKS/HS256 (AUTH_JWKS_URL|AUTH_JWT_SECRET, aud), même logique que footics-api/internal/auth (cache JWKS + cooldown copiés). Zéro accès DB.
    • apiclient relaie le Bearer de l'appelant vers FOOTICS_API_URL + ?competition= ; footics-api re-vérifie (frontière de confiance).
    • SDK officiel github.com/modelcontextprotocol/go-sdk@v1.6.1 : Streamable HTTP stateless, auth.RequireBearerToken, auth.ProtectedResourceMetadataHandler (RFC 9728) sur les 2 chemins well-known + défi WWW-Authenticate. Routage = stdlib net/http.ServeMux (5 routes ; chi n'apporterait rien).
  • 9 outils de lecture, formes de sortie gelées (identiques à lib/tools.ts), inputSchema fixés explicitement (internal/tools/schemas.go).
  • submit_prediction = stub gated OFF (voir plus bas).
  • Tests : unit (auth double-mode ; mapping de forme de chaque outil vs le contrat TS, JSON byte-à-byte) + intégration contre l'API staging (127.0.0.1:8099, JWT alice minté, assert la forme de chaque outil ; skip propre si injoignable).
  • README (go/) + .env.example.

Mapping outil → endpoint /v1

Outil Endpoint
whoami — (JWT sub/email)
list_matches GET /v1/matches?competition=&status=&limit=
get_match GET /v1/matches/{id} (+ events[], 404 → « Match introuvable. »)
get_my_standing GET /v1/me?competition= (404 → « Profil introuvable. »)
get_my_predictions GET /v1/predictions?competition=&when=&limit=
get_leaderboard GET /v1/leaderboard?competition=&group=&limit=
list_my_groups GET /v1/groups?competition=
get_joker_status GET /v1/jokers?competition=
search GET /v1/search?q=
submit_prediction POST /v1/predictions (M4)

Projections pour rester byte-identique au TS : kickoffAt normalisé au format toISOString() (.000Z/v1/predictions et /v1/search l'émettent sans millis) ; venue vide → null ; score = Score (fini) / LiveScore (live) ; prediction sans winnerTeamCode ; result/points présents-null.

Ce qui attend M4 (writes)

footics-api POST /v1/predictions n'est pas livré (M4). submit_prediction est enregistré (la prod tourne writes ON) mais reste un stub : MCP_ENABLE_WRITES=false → « écriture pas encore disponible sur cette instance » ; writes ON → « arrivera avec l'API /v1 POST (M4) ». Câblage réel = un appel à ajouter dans apiclient + le handler une fois M4 mergé.

Structure de repo choisie : go/

Livré sous go/ → branche purement additive : aucun fichier TS de la racine n'est déplacé/supprimé, Vercel intact. PRD 15 §9 prévoit à terme une réécriture en place (TS → historique + tag v0-nextjs) ; promouvoir go/ à la racine et archiver le TS = décision séparée de Tom.

Non inclus (arrivent au cutover N4) : Dockerfile/GHCR, CI Go, service compose + route tunnel.

Gate

go build ./... && go vet ./... && gofmt -l . (vide) + go test ./...vert. Validé à la main contre l'API staging (sorties d'outils réelles dans le rapport de session).

Porte le serveur MCP de Next.js/TS vers Go dans go/ (le TS reste intact
à la racine). Le serveur devient un client HTTP mince de footics-api /v1 :
il vérifie le JWT Supabase localement (double-mode JWKS/HS256, même logique
que footics-api internal/auth) puis relaie le Bearer vers /v1. Zéro accès DB.

- SDK officiel github.com/modelcontextprotocol/go-sdk v1.6.1 (Streamable HTTP
  stateless + auth.RequireBearerToken + PRM RFC 9728 sur les 2 chemins well-known)
- 9 outils de lecture mappés sur /v1, formes de sortie GELÉES (identiques au
  TS lib/tools.ts) ; inputSchema fixés explicitement
- submit_prediction = stub gated OFF (POST /v1/predictions = M4, non livré)
- Tests : unit (auth double-mode, mapping de forme par outil vs contrat TS) +
  intégration contre l'API staging (skip propre si injoignable)

Gate vert : go build && go vet && gofmt -l (vide) && go test ./...
Validé à la main contre l'API staging (127.0.0.1:8099).

Claude-Session: https://claude.ai/code/session_01CsRaJpQmoPyXRqH7g29mwN
@vercel

vercel Bot commented Jul 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
footics-mcp-server Ready Ready Preview, Comment Jul 4, 2026 12:54am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant