Football Intelligence MCP
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Football Intelligence MCPPredict the winner of Barcelona vs Real Madrid"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Football Intelligence MCP
A local Model Context Protocol server that gives any MCP host — Claude Desktop, Claude Code, or a custom chatbot — access to a curated historical football database covering 36,982 matches across Europe's seven top competitions from 2010 to 2025.
The protocol is implemented directly over JSON-RPC 2.0, without using any MCP SDK: every message is built and parsed by hand following the 2025-06-18 specification.
What's in the database
Data originally extracted from API-Football, normalized into PostgreSQL.
Competition | League id | Seasons |
Premier League | 39 | 2010–2025 |
La Liga | 140 | 2010–2025 |
Serie A | 135 | 2010–2025 |
Bundesliga | 78 | 2010–2025 |
Ligue 1 | 61 | 2010–2025 |
Primeira Liga | 94 | 2010–2025 |
UEFA Champions League | 2 | 2011–2025 |
Table | Rows |
| 36,982 |
| 476,186 |
| 881,739 |
| 1,436,165 |
| 51,822 |
| 26,996 |
| 2,329 |
Known coverage limits
The server reports these instead of guessing, and so should you:
Match statistics start in 2015. Seasons 2010–2014 contain results, goals, events and lineups, but no shots, possession or passing data.
Expected goals (xG) only exists from 2023 onward, and never for the Champions League.
Formation and coach data starts in 2015.
58 matches (0.16%) have a goal missing from their event list — an upstream gap in API-Football. Scorelines are unaffected; they come from the fixture record, not from summing events.
Call the data_coverage tool to check what exists for any league and season.
Installation
Requires Python 3.10+ and PostgreSQL 14+.
git clone https://github.com/jaq23369/football-intelligence-mcp.git
cd football-intelligence-mcp
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
createdb football
pg_restore -d football data/football.dump
cp .env.example .env # edit DATABASE_URL if your setup differsVerify the restore:
psql -d football -c "SELECT count(*) FROM fixtures;"
# count
# -------
# 36982Running the server
python server.pyThe server speaks JSON-RPC over stdio. It is normally launched by an MCP host rather than by hand, but you can drive it directly:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"manual","version":"1.0"}}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
| python server.pyClaude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"football": {
"command": "/absolute/path/to/football-intelligence-mcp/.venv/bin/python",
"args": ["/absolute/path/to/football-intelligence-mcp/server.py"]
}
}
}Claude Code
claude mcp add football -- /absolute/path/to/.venv/bin/python /absolute/path/to/server.pyProtocol
Transport: stdio, newline-delimited JSON. Protocol version 2025-06-18.
Method | Notes |
| Handshake. Returns |
| Client notification. No |
| Liveness check. Returns |
| Returns the eleven tool definitions. |
| Executes a tool. |
Errors follow JSON-RPC 2.0: -32700 parse error, -32600 invalid request,
-32601 method not found, -32602 invalid params, -32603 internal error.
Tool-level failures are not JSON-RPC errors — they return a normal result
with isError: true, so the model can read the message and recover.
stdout carries only JSON-RPC. All diagnostics go to stderr.
Tools
search_team
Finds teams by partial name, ranked by how many matches they have on record.
Call this first — every other team tool needs a team_id.
Parameter | Type | Required | Default |
| string | yes | — |
| integer | no | 10 |
{"name": "search_team", "arguments": {"query": "Liverpool", "limit": 1}}[{"team_id": 40, "name": "Liverpool", "country": "England",
"founded": 1892, "partidos": 762,
"primera_temporada": 2010, "ultima_temporada": 2025}]search_player
Finds players by name, ranked by minutes played.
Parameter | Type | Required | Default |
| string | yes | — |
| integer | no | 10 |
get_match
Full match record: score, venue, referee, per-team statistics and every goal with minute and assist. Matches before 2015 return an explicit note instead of empty statistics.
Parameter | Type | Required |
| integer | yes |
get_team_form
Recent form: streak, points, goals for and against.
before restricts the calculation to matches strictly earlier than that date,
which lets you reconstruct a team's state at any past moment. This is the
guard against look-ahead bias when building predictive features.
Parameter | Type | Required | Default |
| integer | yes | — |
| integer | no | 5 |
| string ( | no | — |
{"name": "get_team_form",
"arguments": {"team_id": 40, "last": 5, "before": "2020-01-01"}}get_head_to_head
Win/draw/loss balance between two teams, their most recent meetings, and per-team averages (goals per match, yellow/red cards, fouls, corners) across their full history — useful context for deciding a bet, not just a prediction number. Cards/fouls/corners are only available for matches from 2015 onward; matches without statistics are excluded from those averages, not counted as zero.
Parameter | Type | Required | Default |
| integer | yes | — |
| integer | yes | — |
| integer | no | 10 |
get_team_season
Final league position, points and goals, alongside per-match averages for shots, possession, corners and passing accuracy.
Parameter | Type | Required |
| integer | yes |
| integer | yes |
| integer | yes |
Seasons are named by their starting year: 2024 means the 2024-25 season.
get_player_season
Per-season player totals aggregated from match-level records: goals, assists, minutes, shots, key passes, cards and average rating.
Parameter | Type | Required |
| integer | yes |
| integer | yes |
compare_teams
Recent form for two teams plus their head-to-head record, in one call.
Parameter | Type | Required | Default |
| integer | yes | — |
| integer | yes | — |
| integer | no | 10 |
compare_players
Two players' totals for the same season, side by side.
Parameter | Type | Required |
| integer | yes |
| integer | yes |
| integer | yes |
data_coverage
What actually exists in the database, per league and season. Use it before claiming a data point is missing.
Parameter | Type | Required |
| integer | no |
| integer | no |
predict_match
Win/draw/loss probability for a match, from a model trained on 23,168 matches
(2015–2025, six domestic leagues — Champions League excluded, its knockout
format isn't comparable to a round-robin table). Two candidates were compared
head to head on a held-out validation season (logistic regression vs. a
gradient-boosted trees classifier); the one with the better validation log
loss was kept. See model.metricas_prueba_2025 in the tool's own response
for the honest, never-touched-during-selection test score.
The match does not need to already exist in the database. Each team's
current Elo, recent form and rest days are kept in a team_current_form
snapshot, refreshed independently of any single fixture — so this works for
a match scheduled for next week just as well as one played five years ago.
Parameter | Type | Required |
| integer | yes |
| integer | yes |
{"name": "predict_match", "arguments": {"home_team_id": 529, "away_team_id": 531}}{
"local": "Barcelona", "visitante": "Athletic Club",
"probabilidad_local": 0.779, "probabilidad_empate": 0.145, "probabilidad_visitante": 0.076,
"modelo": "logistic_regression",
"advertencia": "Probabilidad estadistica basada en historial, no una garantia..."
}The trained model ships in data/predict_model.joblib (a few KB — a fitted
scikit-learn pipeline, not raw weights). Retraining requires the full feature
pipeline (conocimiento/ml/), which lives in the private project repository,
not here — same relationship as data/football.dump to the extraction
pipeline that built it.
Example session
Which team won the Premier League in 2015?
→ search_team {"query": "Leicester"}
→ get_team_season {"team_id": 46, "league_id": 39, "season": 2015}Leicester City, with 81 points from 23 wins, 12 draws and 3 losses — and only 42.7% average possession, unusual for a champion.
Architecture
MCP host ──JSON-RPC/stdio──> server.py ──> knowledge/engine.py ──> PostgreSQLserver.py owns the protocol and nothing else. All query logic lives in
knowledge/engine.py, which returns plain dictionaries and has no knowledge of
MCP — so it can be tested, or reused, entirely on its own.
License
MIT. Football data originates from API-Football and is redistributed here for academic use.
Built for CC3067 Redes, Universidad del Valle de Guatemala.
This server cannot be installed
Maintenance
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
API-Football MCP — comprehensive soccer/football data
Grounded sports predictions plus European soccer and tennis arbitrage data for AI agents.
Football-Data.org MCP — soccer competitions, matches, standings
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/jjaquezito/MCP_local'
If you have feedback or need assistance with the MCP directory API, please join our Discord server