footballcharts-mcp
Server Details
Tables, results, fixtures, goal timing, season projections: 93 football leagues incl. lower tiers
- Status
- Healthy
- Uptime
- 100.0% over 23 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
- Repository
- ddevetak/footballcharts-mcp
- GitHub Stars
- 2
- Server Listing
- footballcharts-mcp
TDQS
Scored across 10 tools
Each tool has a clear primary purpose (fixtures vs results vs match detail vs table), and descriptions repeatedly point to the right tool for a given question. The main soft spot is get_team, which deliberately re-includes table rows, match logs and goal timing from get_league_table/get_results/get_goal_timing, so an agent could occasionally pick the broader tool instead of the narrower one.
The surface is overwhelmingly get_<noun> (get_fixtures, get_results, get_team, etc.), with list_leagues and about_football_charts as sensible exceptions for enumeration and orientation. This makes tool selection predictable once the agent knows the resource it wants.
Ten tools is well-scoped for a read-only football data/modeling source: meta/orientation, league enumeration, match/standings/team/timing retrieval, projections, and model calibration. Every tool addresses a distinct need without the surface feeling bloated.
The surface covers the source's stated domain well: fixtures, results, tables, team detail, goal timing, season projections, and an honest model track record, plus clear notes on what is not held. Minor gaps exist, like no cross-league match search or direct head-to-head tool, but agents can work around them with get_results team filters.
Available Tools
10 toolsabout_football_chartsAbout this sourceARead-onlyIdempotentInspect
What football-charts.com covers (93 leagues incl. lower divisions), what it does NOT hold (live scores, players, odds), how league keys and season strings work, how to phrase model probabilities honestly, and which tool answers what. Call when unsure whether this source fits a question, or once before the first call in a session. No parameters. Example: "Can you get me Estonian league data?" → about_football_charts, then list_leagues.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| what | Yes | |
| tools | Yes | |
| free_tier | Yes | |
| get_a_key | Yes | |
| do_not_use_for | Yes | |
| how_to_answer_well | Yes | |
| use_this_source_when | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that the tool is read-only, open-world, idempotent, and non-destructive. The description adds meaningful context beyond that: the source lacks live scores, players, and odds, and the tool itself serves as a routing/orientation layer rather than a data endpoint. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but efficient: coverage, exclusions, conventions, routing guidance, call timing, and a concrete example are packed into a compact paragraph. Every clause adds useful orientation information with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter informational tool with an output schema, the description leaves no ambiguity about when or why to call it. It also addresses the likely decision an agent faces—whether this source fits a query—and provides a clear example.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and an empty input schema, so there is no parameter-semantic burden. The description explicitly notes 'No parameters,' matching the schema exactly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that this tool is a source orientation guide: it covers what football-charts.com includes, what it excludes, key/season-string conventions, probability phrasing, and which sibling tool to use. This is a specific verb+resource description that differentiates it from the data-retrieval sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage conditions: call when unsure whether the source fits a question, or once before the first call in a session. The Estonia example further demonstrates the intended call flow, ending with list_leagues.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_fixturesUpcoming fixturesARead-onlyIdempotentInspect
Upcoming matches of one league, earliest first: kick-off date and time, teams, a slug, and the model's calibrated probabilities (home/away, over/under ladders, both teams to score, half-time lines; draw = 1 − home − away) with team attack/defence ratings. Use for "who plays this weekend", kick-off times, or the chances in an upcoming match. The slug on each row is the input to get_match, which returns one fixture in full — call this first when you need one match in depth. Use get_results for matches already played. Probabilities are a baseline model from match history alone (no injuries, motivation or weather) and are not market prices or advice — say so. Example: "What are the chances of goals in Brentford v Sunderland?" → get_fixtures premier, read model_predictions.dc_v2.calibrated["over_2.5"].
| Name | Required | Description | Default |
|---|---|---|---|
| league | Yes | League key from list_leagues, e.g. 'premier' (England), 'spain1', 'brazil1', 'sweden1', 'wgermany1' (women). Not the display name. |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | No | |
| league | No | |
| matches | No | |
| attribution | No | Cite as "Data by football-charts.com" |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond read-only/idempotent annotations, the description discloses ordering, exact output contents, the source of probabilities, and limitations (no injuries/motivation/weather, not market prices). It even instructs the agent to communicate the caveat to the user.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and output, then efficiently covers usage, alternatives, limitations, and a concrete example. Every sentence adds value; there is no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With one well-documented parameter, an output schema present, and rich annotations, the description still adds necessary usage context, sibling-routing, and model caveats. Nothing essential for selecting or invoking the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents the single league parameter thoroughly with examples and a note not to use display names, so schema coverage is complete. The description adds only a reinforcing example ('get_fixtures premier') rather than new parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Upcoming matches of one league, earliest first' with details of returned fields. It differentiates from siblings by explicitly contrasting with get_match (one match in full) and get_results (matches already played).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit use cases: 'who plays this weekend', kick-off times, and chances in an upcoming match. It also tells the agent when to use get_results instead and instructs calling get_fixtures first before get_match for in-depth match data.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_goal_timingGoal timingARead-onlyIdempotentInspect
Goals per 15-minute bin (0-15 … 90+) for every team in a league season, each with peak_bins (the bin or bins with most goals — ties are listed; report a tie as a tie), late_share_pct and first_half_pct, plus league totals and the most active period. Use for "when does X score", late goals, fast starters, who concedes early, or which period a league's goals fall in. Pass team (name substring) for one team only. For one team's timing next to its match log get_team is more direct. Answer from peak_bins, never by eyeballing the bins. Example: "When does Flamengo score most?" → get_goal_timing brazil1, team="Flamengo".
| Name | Required | Description | Default |
|---|---|---|---|
| team | No | Team name substring, e.g. 'Flamengo' — returns that team's row only | |
| league | Yes | League key from list_leagues, e.g. 'premier' (England), 'spain1', 'brazil1', 'sweden1', 'wgermany1' (women). Not the display name. | |
| season | No | Season string exactly as list_leagues returns it: winter-calendar leagues look like '2026-2027', summer-calendar leagues (Brazil, Sweden, Norway, Japan…) like '2026'. Omit for the current season. The free tier serves the current and previous season only. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | No | |
| note | No | |
| stats | No | |
| league | No | |
| season | No | |
| time_bins | No | |
| attribution | No | Cite as "Data by football-charts.com" |
| team_filter | No | |
| team_not_found | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only and idempotent safety, so no contradiction exists. The description adds real behavioral context beyond annotations: ties in peak_bins are listed and must be reported as ties, the tool returns league totals and the most active period, and the agent is explicitly warned not to eyeball bins. This materially changes how the agent should interpret and use the result.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description front-loads the output shape and purpose, then gives use cases, parameter guidance, an alternative tool, and an example in a compact, ordered flow. Every sentence contributes: none repeats the name or annotations, and the example concretizes invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description does not need to enumerate return fields exhaustively, and it provides the essential invocation context: output semantics, tie handling, use cases, one-team vs. league-wide behavior, alternative routing, and a worked example. It is complete for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 that team is a substring and can be used to return one team's row, and it gives a concrete example mapping league='brazil1' and team='Flamengo'. It adds modest practical color but does not uncover semantics absent from the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: it computes goals per 15-minute bin for every team in a league season, with named derived fields (peak_bins, late_share_pct, first_half_pct) plus league totals. It also names the exact sibling alternative (get_team) for the one-team-plus-match-log case, removing ambiguity. The title and name align with a clear goal-timing analysis tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is explicitly scoped: it says to use this tool for 'when does X score', late goals, fast starters, early conceders, or league scoring periods. It also gives an exclusion by noting that get_team is more direct when one team's timing is needed next to its match log, and it instructs the agent to answer from peak_bins rather than raw bins.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_league_tableLeague tableARead-onlyIdempotentInspect
Standings for one league season: one row per team with position, played, W/D/L, goals, points, last-five form, plus expected points and a luck category (how far results run ahead of or behind the underlying numbers). Use for "who is top", "how many points", "what is the form", or any question about the table as ranked by points. view="luck" re-orders the same rows by over/under-performance (who is lucky, unlucky, flattered by the table); view="goals" by scoring. For one team in depth use get_team; for how the season is projected to END use get_season_projection. Omit season for the current one. Example: "Is Hull really a top-four side?" → get_league_table premier, view=luck, compare points with expected_points.
| Name | Required | Description | Default |
|---|---|---|---|
| view | No | Row order; default 'classic' (by points) | |
| league | Yes | League key from list_leagues, e.g. 'premier' (England), 'spain1', 'brazil1', 'sweden1', 'wgermany1' (women). Not the display name. | |
| season | No | Season string exactly as list_leagues returns it: winter-calendar leagues look like '2026-2027', summer-calendar leagues (Brazil, Sweden, Norway, Japan…) like '2026'. Omit for the current season. The free tier serves the current and previous season only. |
Output Schema
| Name | Required | Description |
|---|---|---|
| view | No | |
| table | No | |
| league | No | |
| season | No | |
| attribution | No | Cite as "Data by football-charts.com" |
| season_state | No | 'in_season' or 'finished' |
| current_season | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool read-only, idempotent, and non-destructive, so the description doesn't need to repeat that. It adds genuinely useful behavioral detail beyond the annotations: rows are one per team, view='luck' re-orders the same rows by over/under-performance rather than filtering, and the free tier only serves current and previous seasons. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but each sentence carries weight: definition, use cases, view behavior, sibling routing, season hint, and example. It only loses a point for slight redundancy, such as restating 'Omit for the current season' which is already in the season parameter's schema description. Still, it is well-structured and front-loaded with the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the description doesn't need to explain return values. It covers the essential operational context: row semantics, column contents, view variants, season behavior, and the free-tier limitation. With the annotations covering safety, an agent has everything needed to select this tool and invoke it correctly without ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is already 3. The description adds meaning beyond the schema by explaining what each view does in behavioral terms ('view="luck" re-orders the same rows by over/under-performance... view="goals" by scoring') and by providing a concrete example query. This goes beyond the schema's terse 'Row order; default classic' label, though it doesn't independently document parameter syntax.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear definition: 'Standings for one league season: one row per team with position, played, W/D/L, goals, points, last-five form, plus expected points and a luck category.' This specifies both the resource (league table) and the content of each row. It also proactively distinguishes itself from siblings by naming get_team for in-depth team data and get_season_projection for projected final standings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit usage guidance is provided: 'Use for "who is top", "how many points", "what is the form", or any question about the table as ranked by points.' It also names alternatives and when to choose them: 'For one team in depth use get_team; for how the season is projected to END use get_season_projection.' This is exactly the kind of when-to-use vs. when-not-to guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_matchMatch detailARead-onlyIdempotentInspect
One match in full: the complete model probability block (calibrated and raw, all markets), team ratings, first-goal-time histograms for both sides (fgt_h, fgt_a), recent form, and — once played — the score, half-time score and status. Use for one named fixture. slug has the form 'country/league-slug/YYYY-MM-DD-home-vs-away'; take it from a get_fixtures row rather than assembling it, because team spellings must match exactly. Use get_fixtures for a league's whole upcoming slate, get_results for scores of many matches. Probabilities are model output, not advice. Example: slug 'england/premier-league/2026-09-05-brentford-vs-sunderland'.
| Name | Required | Description | Default |
|---|---|---|---|
| slug | Yes | Match slug from get_fixtures, e.g. 'england/premier-league/2026-09-05-brentford-vs-sunderland' |
Output Schema
| Name | Required | Description |
|---|---|---|
| match | Yes | |
| attribution | No | Cite as "Data by football-charts.com" |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint false. The description adds meaningful behavioral context on top: what data is included, the conditional nature of score/status fields (only once played), and that probabilities are model output and not advice. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then enumerates contents, gives routing guidance, adds a caveat, and provides a concrete example. Every sentence earns its place; there is no filler or redundant restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, the description does not need to spell out return values. It covers what the tool returns, how to construct the slug, when to use it versus siblings, and a critical caveat about model probabilities. This is complete for correct selection and invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 specifying the slug format explicitly, providing a complete example, and warning against constructing the slug manually because team spellings must match exactly. This is more than the schema alone provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: retrieving one full match record with probability data, team ratings, histograms, form, and score/status once played. It clearly distinguishes itself from siblings like get_fixtures and get_results by emphasizing that it covers one named fixture in full.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells the agent when to use it ('Use for one named fixture'), when to use alternatives ('Use get_fixtures for a league's whole upcoming slate, get_results for scores of many matches'), and even instructs the agent to derive the slug from get_fixtures rather than assembling it manually due to exact spelling requirements.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_resultsMatch resultsARead-onlyIdempotentInspect
Finished matches of one league season, one row per match: date, teams, full-time and half-time score, first-goal minute, goalless flag. Rows are in chronological order, earliest first. last=N keeps only the N latest matches and still returns them earliest-first. team filters on a case-insensitive substring of either side's name. Use for scores, "how did X do lately", head-to-head within a season, half-time scores or first-goal minutes. Use get_fixtures for matches not yet played, get_match for one match's probability detail, get_team for one team's season in full. No odds. Example: "Last five Liverpool results" → get_results premier, team="Liverpool", last=5.
| Name | Required | Description | Default |
|---|---|---|---|
| last | No | Keep only the N latest matches of the season, e.g. 5 for recent form (default: all) | |
| team | No | Team name substring, e.g. 'Liverpool' | |
| league | Yes | League key from list_leagues, e.g. 'premier' (England), 'spain1', 'brazil1', 'sweden1', 'wgermany1' (women). Not the display name. | |
| season | No | Season string exactly as list_leagues returns it: winter-calendar leagues look like '2026-2027', summer-calendar leagues (Brazil, Sweden, Norway, Japan…) like '2026'. Omit for the current season. The free tier serves the current and previous season only. |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | No | |
| count | No | |
| league | No | |
| season | No | |
| matches | No | |
| attribution | No | Cite as "Data by football-charts.com" |
| season_state | No | 'in_season' or 'finished' |
| current_season | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description clearly discloses behavioral details beyond the annotations: rows are chronological, last=N returns the N latest still ordered earliest-first, team filters case-insensitively on either side's name, and odds are not included. The readOnly/idempotent annotations already cover safety, and this description adds meaningful operation semantics without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but every sentence earns its place: purpose, output rows, ordering, filter semantics, usage scenarios, sibling alternatives, limitation, and a worked example. Information is front-loaded with the core purpose before details, and nothing feels redundant or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that an output schema exists, annotations cover safety, and the schema documents all parameters, the description is complete for an agent to select and invoke the tool correctly. It covers selection criteria, parameter behavior, exclusions, and gives a realistic example, leaving no important operational gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already covers all parameters at 100%, so the baseline is 3. The description adds value beyond the schema by explaining that last preserves chronological order, team matches a case-insensitive substring of either side, and providing example league keys and season format nuances. This is more than repetition, though not all of it is required given the rich schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies a specific resource ('Finished matches of one league season') and output granularity (one row per match with listed fields). It also explicitly distinguishes itself from siblings by naming get_fixtures, get_match, and get_team, so an agent can tell exactly what this tool returns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: scores, recent form, head-to-head, half-time scores, and first-goal minutes. It also names alternatives with their conditions: get_fixtures for unplayed matches, get_match for probability detail, and get_team for full season team view, plus a concrete example mapping the query 'Last five Liverpool results' to parameters.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_season_projectionSeason projectionARead-onlyIdempotentInspect
How one league's CURRENT season is projected to finish: 10,000 Monte Carlo simulations refreshed daily, per team the title, top-four and relegation (bottom3) probabilities, points now, mean final points, a 10th–90th percentile points range and a full finishing-position matrix, plus the change since the previous run. Use for forward-looking questions — who wins the league, who goes down, how safe a position is, likely final points. Use get_league_table for where things stand NOW and get_fixtures for individual match probabilities. Always the current season; there is no season parameter. Example: "Can Hull stay up?" → get_season_projection premier, read projection.teams.Hull.bottom3.
| Name | Required | Description | Default |
|---|---|---|---|
| league | Yes | League key from list_leagues, e.g. 'premier' (England), 'spain1', 'brazil1', 'sweden1', 'wgermany1' (women). Not the display name. |
Output Schema
| Name | Required | Description |
|---|---|---|
| projection | Yes | |
| attribution | No | Cite as "Data by football-charts.com" |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnly, openWorld, idempotent, and non-destructive hints, so the bar is lower. The description adds useful behavioral context: 10,000 Monte Carlo simulations refreshed daily and the 'change since the previous run' output. It also discloses the current-season-only behavior, which is not obvious from the schema. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but well-structured: it front-loads the core purpose, then usage, then alternatives, then a concrete example. Every sentence contributes either capabilities, routing, or a limitation. It is slightly long, but the complexity of the tool justifies it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with an output schema, the description goes beyond the minimum by summarizing the key output fields and giving a path-style example ('projection.teams.Hull.bottom3'). It also explains the current-season constraint and points to sibling tools for adjacent questions. The agent has everything needed to select and call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds a concrete example call ('get_season_projection premier') and explains the league parameter convention via examples. It also clarifies there is no season parameter, which prevents the agent from inventing one. This is a meaningful addition over the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb+resource: 'How one league's CURRENT season is projected to finish' and enumerates the exact outputs (title, top-four, relegation probabilities, points ranges, finishing-position matrix). It also distinguishes itself from siblings by explicitly naming get_league_table and get_fixtures and their different purposes. This makes the tool's role unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: 'forward-looking questions — who wins the league, who goes down, how safe a position is, likely final points.' It clearly says to use get_league_table for current standings and get_fixtures for individual match probabilities, and it states the limitation 'Always the current season; there is no season parameter.' This fully routes the agent to the correct tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_teamTeam pageARead-onlyIdempotentInspect
Everything held on one team in one league season: its table row (with luck and expected points), the full match log (date, opponent, venue H/A, score, half-time score, first-goal minute, outcome), goals per 15-minute bin, first-goal distribution, season match-stat averages where the league is covered (shots, shots on target, shots against, possession, corners, xG for/against — null when not held), and the seasons available. team is a slug: lower-case, spaces as hyphens, e.g. 'arsenal', 'manchester-city'. Take the exact name from get_league_table first when unsure. Use for one team in depth ("tell me about Arsenal's season"). Use get_league_table for every team shallowly, get_results with a team filter for just the scores, get_goal_timing to compare timing across the whole league. Example: "How is Arsenal doing?" → get_team premier, team="arsenal".
| Name | Required | Description | Default |
|---|---|---|---|
| team | Yes | Team slug, e.g. 'arsenal', 'manchester-city' (from the table's team names, lower-case, spaces as hyphens) | |
| league | Yes | League key from list_leagues, e.g. 'premier' (England), 'spain1', 'brazil1', 'sweden1', 'wgermany1' (women). Not the display name. | |
| season | No | Season string exactly as list_leagues returns it: winter-calendar leagues look like '2026-2027', summer-calendar leagues (Brazil, Sweden, Norway, Japan…) like '2026'. Omit for the current season. The free tier serves the current and previous season only. |
Output Schema
| Name | Required | Description |
|---|---|---|
| slug | No | |
| team | No | |
| stats | No | Per-match averages over this season, computed from stored match statistics; null where the league has none |
| league | No | |
| season | No | |
| matches | No | |
| ranking | No | The team's table row |
| seasons | No | |
| attribution | No | Cite as "Data by football-charts.com" |
| first_goal_bins | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds value beyond that: it discloses that stats are null when not held, explains the slug format ('take the exact name from get_league_table first when unsure'), and notes the free-tier limitation (current and previous season only). All of this contextualizes behavior without contradicting any annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a bit long but everything earns its place: the opening sentence lists the output scope, then it covers slug format, season mechanics, usage alternatives, and a working example. It is front-loaded with the core purpose and the alternatives appear early in the flow. Slight redundancy ('Everything held on one team' followed by specifics) but not wasteful enough to drop below a 4.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool returns a rich payload and has an output schema (so return values need not be restated), the description is comprehensive: it covers edge cases (null stats), input derivation (exact team name), season format nuances, and free-tier availability. It also routes to alternatives so an agent can choose correctly. Nothing critical is missing for safe, accurate invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description enriches parameter understanding materially. For 'team' it specifies the slug format (lower-case, spaces as hyphens) and tells the agent to pull the exact name from get_league_table. For 'season' it explains winter vs summer calendar formats, when to omit it, and the free-tier restriction. These are not in the schema and prevent mis-invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific resource ('one team in one league season') and enumerates the data fields returned (table row, match log, goals per bin, etc.), which is far beyond a tautology. It also explicitly distinguishes itself from siblings by naming get_league_table, get_results, and get_goal_timing, so an agent can tell exactly what this tool covers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use guidance ('Use for one team in depth') and names the alternatives with their exact purposes ('get_league_table for every team shallowly', 'get_results with a team filter for just the scores', 'get_goal_timing to compare timing across the whole league'). A concrete example ('How is Arsenal doing?' → get_team premier, team='arsenal') ties it together.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_track_recordModel track recordARead-onlyIdempotentInspect
The public calibration ledger: every model prediction published before kick-off and graded after the result — count, hit rate and profit/loss at flat 1-unit stakes, overall and by market (1x2, ft_ou_25, ft_ou_35, ht_ou_15, bts), a daily cumulative series, the 50 most recent graded predictions, and calibration (Brier score, probability buckets vs actual hit rate). days sets the lookback window, default 90. Losing periods are included; nothing is filtered. Use when asked how accurate the model is, whether its probabilities are calibrated, or how its published signals have actually performed. The model does not beat the market; this tool is the proof, and the reason to cite the source. Example: "Is this model any good?" → get_track_record, quote summary.hit_rate, summary.pl and accuracy.brier.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | Lookback window in days (default 90) |
Output Schema
| Name | Required | Description |
|---|---|---|
| attribution | No | Cite as "Data by football-charts.com" |
| track_record | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false. The description adds valuable context beyond these: 'Losing periods are included; nothing is filtered' and 'The model does not beat the market; this tool is the proof.' These disclose the honest, unfiltered nature of the data and the model's performance expectation, which is not derivable from annotations. It does not contradict any annotation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but densely packed with essential information: core purpose, contents, parameter, usage context, and an example. It front-loads the primary purpose and lists the data items clearly. The example at the end is useful and the structure is logical. It could be slightly trimmed, but every sentence contributes to the agent's understanding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is complex with many output components, but the description covers the main data types (hit rate, P/L, by market, calibration, recent predictions) and provides usage context. The output schema is present (signal indicates true), so return value details are not required. The description is complete enough for an agent to decide when to call and what to expect, though it does not mention rate limits or performance constraints, which are not critical for this read-only tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema fully documents the only parameter 'days' (integer, 1-365, default 90, optional). The description repeats the default and function ('days sets the lookback window'), but adds no new semantic information beyond the schema. With 100% schema coverage, the baseline of 3 is appropriate; the description adds minimal value for this parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the tool returns a public calibration ledger with specific performance metrics (count, hit rate, P/L, by market, calibration) and names the exact markets. It is clearly distinct from siblings like get_results or get_team, which do not cover model track record or calibration. The verb 'get' plus resource 'track record' is precise and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'Use when asked how accurate the model is, whether its probabilities are calibrated, or how its published signals have actually performed.' It also gives a concrete example with a query and which output fields to quote. No overlapping siblings exist, so no exclusion is needed, but the guidance is direct and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_leaguesList leaguesARead-onlyIdempotentInspect
Every league this source covers — 93 across 42 countries — with country, league key, display name and the seasons available, newest first. No parameters. Call first in any workflow: every other tool takes a league key and most take a season string, and both must match these values exactly. Season format differs by competition (winter leagues '2026-2027', summer leagues '2026'), so read the season here rather than constructing it. ("list" rather than "get": it enumerates everything, it does not fetch one thing.) Example: "Which Polish league do you have?" → list_leagues, filter by country.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| count | No | |
| leagues | Yes | |
| attribution | No | Cite as "Data by football-charts.com" |
| season_window | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool read-only, idempotent, and non-destructive. The description adds useful behavioral context beyond that: no parameters, output ordered newest first, season availability included, and season format varying by competition ('2026-2027' vs '2026'). It does not discuss pagination or stability of the 93-league set, but those are minor given the available output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Every sentence earns its place: the first states the output inventory, followed by no-parameters, workflow precedence, season-format caveat, list-vs-get disambiguation, and an example. It is front-loaded with the core purpose and remains readable despite covering several important nuances.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless, read-only list tool with a rich output schema and strong annotations, the description is complete: it names return fields, ordering, scope, and downstream matching requirements. An agent has everything needed to call this tool correctly and understand its role in a broader workflow.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With zero parameters, the input schema carries no information beyond an empty object. The description explicitly states 'No parameters' and explains that league keys and season strings are output values that must match exactly when used in other tools, preventing the model from inventing or constructing parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource, stating it lists every league the source covers, with country, league key, display name, and seasons available. It also explicitly distinguishes "list" from "get": 'it enumerates everything, it does not fetch one thing,' which separates it from sibling tools like get_match and get_team.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit workflow precedence: 'Call first in any workflow: every other tool takes a league key and most take a season string.' It also advises reading season strings from this tool rather than constructing them and provides a concrete example query, leaving no doubt about when to invoke it.
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.
2 tool updates
- Changed
get_team1 field changed- added
Output schema / properties / statsAdded value: +{ + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "corners_avg": { + "$ref": "#/properties/ranking/anyOf/0/properties/avg_goals_scored" + }, + "matches_with_stats": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "possession_avg": { + "$ref": "#/properties/ranking/anyOf/0/properties/avg_goals_scored" + }, + "shots_against_avg": { + "$ref": "#/properties/ranking/anyOf/0/properties/avg_goals_scored" + }, + "shots_avg": { + "$ref": "#/properties/ranking/anyOf/0/properties/avg_goals_scored" + }, + "shots_on_target_avg": { + "$ref": "#/properties/ranking/anyOf/0/properties/avg_goals_scored" + }, + "xg_against_avg": { + "$ref": "#/properties/ranking/anyOf/0/properties/avg_goals_scored" + }, + "xg_avg": { + "$ref": "#/properties/ranking/anyOf/0/properties/avg_goals_scored" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Per-match averages over this season, computed from stored match statistics; null where the league has none" +}
- Changed
get_track_record1 field changed- changed
Output schema / properties / track_record / properties / recent / descriptionPrevious value: -"The 50 most recent graded leans"New value: +"The 50 most recent graded predictions"
10 tool updates
- Changed
about_football_charts1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "do_not_use_for": { + "items": { + "type": "string" + }, + "type": "array" + }, + "free_tier": { + "type": "string" + }, + "get_a_key": { + "type": "string" + }, + "how_to_answer_well": { + "items": { + "type": "string" + }, + "type": "array" + }, + "tools": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "use_this_source_when": { + "items": { + "type": "string" + }, + "type": "array" + }, + "what": { + "type": "string" + } + }, + "required": [ + "what", + "use_this_source_when", + "do_not_use_for", + "how_to_answer_well", + "free_tier", + "get_a_key", + "tools" + ], + "type": "object" +}
- Changed
get_fixtures1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "attribution": { + "description": "Cite as \"Data by football-charts.com\"", + "type": [ + "string", + "null" + ] + }, + "count": {}, + "league": {}, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "properties": { + "away_team": { + "type": "string" + }, + "country": { + "$ref": "#/properties/league" + }, + "home_team": { + "type": "string" + }, + "league": { + "$ref": "#/properties/league" + }, + "match_date": { + "$ref": "#/properties/league" + }, + "model_predictions": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "dc_v2": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "calibrated": { + "anyOf": [ + { + "additionalProperties": true, + "description": "Probabilities 0–1. The draw is NOT a field: draw = 1 − home − away.", + "properties": { + "away": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "btts_yes": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "expected_away_goals": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "expected_home_goals": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "expected_ht_goals": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "home": {}, + "ht_over_0.5": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "ht_over_1.5": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "over_0.5": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "over_1.5": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "over_2.5": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "over_3.5": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "over_4.5": { + "$ref": "#/properties/matches/anyOf/0/items/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Use these. Calibrated on settled matches." + }, + "computed_at": { + "$ref": "#/properties/league" + }, + "data_through": { + "$ref": "#/properties/league", + "description": "Last match date the model has seen" + }, + "model": { + "$ref": "#/properties/league" + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "real_league_name": { + "$ref": "#/properties/league" + }, + "slug": { + "description": "Input to get_match", + "type": "string" + }, + "status": { + "$ref": "#/properties/league" + }, + "time": { + "$ref": "#/properties/league" + } + }, + "required": [ + "slug", + "home_team", + "away_team" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" +}
- Changed
get_goal_timing2 fields changed- changed
Input schema / properties / team / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "attribution": { + "description": "Cite as \"Data by football-charts.com\"", + "type": [ + "string", + "null" + ] + }, + "data": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "properties": { + "bins": { + "anyOf": [ + { + "additionalProperties": { + "type": "number" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Goals per bin: '0-15','15-30','30-45','45+','46-60','60-75','75-90','90+'" + }, + "first_half_pct": { + "$ref": "#/properties/data/anyOf/0/items/properties/late_share_pct" + }, + "late_share_pct": { + "description": "% of goals from 75′ on" + }, + "peak_bins": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Bin(s) with most goals — ties are listed; report a tie as a tie" + }, + "peak_goals": { + "$ref": "#/properties/stats/anyOf/0/properties/total_goals" + }, + "team": { + "type": "string" + }, + "total": { + "$ref": "#/properties/stats/anyOf/0/properties/total_goals" + } + }, + "required": [ + "team" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "league": {}, + "note": { + "$ref": "#/properties/league" + }, + "season": { + "$ref": "#/properties/league" + }, + "stats": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "late_goals": { + "$ref": "#/properties/stats/anyOf/0/properties/total_goals" + }, + "match_count": { + "$ref": "#/properties/stats/anyOf/0/properties/total_goals" + }, + "most_active_period": { + "$ref": "#/properties/league" + }, + "total_goals": {} + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "team_filter": { + "$ref": "#/properties/league" + }, + "team_not_found": { + "$ref": "#/properties/league" + }, + "time_bins": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" +}
- Changed
get_league_table5 fields changed- added
Input schema / properties / view / anyOfAdded value: +[ + { + "enum": [ + "classic", + "luck", + "goals" + ], + "type": "string" + }, + { + "type": "null" + } +] - changed
Input schema / properties / view / descriptionPrevious value: -"Ranking view; default 'classic'"New value: +"Row order; default 'classic' (by points)" - removed
Input schema / properties / view / enumRemoved value: -[ - "classic", - "luck", - "goals" -] - removed
Input schema / properties / view / typeRemoved value: -"string" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "attribution": { + "description": "Cite as \"Data by football-charts.com\"", + "type": [ + "string", + "null" + ] + }, + "current_season": { + "$ref": "#/properties/league" + }, + "league": {}, + "season": { + "$ref": "#/properties/league" + }, + "season_state": { + "$ref": "#/properties/league", + "description": "'in_season' or 'finished'" + }, + "table": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "properties": { + "avg_goals_conceded": { + "$ref": "#/properties/table/anyOf/0/items/properties/avg_goals_scored" + }, + "avg_goals_scored": { + "$ref": "#/properties/table/anyOf/0/items/properties/expected_points" + }, + "clean_sheets": { + "$ref": "#/properties/table/anyOf/0/items/properties/position" + }, + "drawn": { + "$ref": "#/properties/table/anyOf/0/items/properties/position" + }, + "expected_points": { + "description": "Points the underlying numbers say the team should have" + }, + "expected_position": { + "$ref": "#/properties/table/anyOf/0/items/properties/position" + }, + "goal_difference": { + "$ref": "#/properties/table/anyOf/0/items/properties/position" + }, + "goals_against": { + "$ref": "#/properties/table/anyOf/0/items/properties/position" + }, + "goals_for": { + "$ref": "#/properties/table/anyOf/0/items/properties/position" + }, + "last_5_form": { + "$ref": "#/properties/league", + "description": "Latest results as letters, e.g. 'WWDLW'" + }, + "last_5_points": { + "$ref": "#/properties/table/anyOf/0/items/properties/position" + }, + "lost": { + "$ref": "#/properties/table/anyOf/0/items/properties/position" + }, + "luck_category": { + "$ref": "#/properties/league", + "description": "'lucky' | 'fair' | 'unlucky'" + }, + "luck_difference": { + "$ref": "#/properties/table/anyOf/0/items/properties/expected_points", + "description": "points − expected_points; positive = ahead of the numbers" + }, + "over_25_percentage": { + "$ref": "#/properties/table/anyOf/0/items/properties/avg_goals_scored" + }, + "played": { + "$ref": "#/properties/table/anyOf/0/items/properties/position" + }, + "points": { + "$ref": "#/properties/table/anyOf/0/items/properties/position" + }, + "position": {}, + "team": { + "type": "string" + }, + "won": { + "$ref": "#/properties/table/anyOf/0/items/properties/position" + } + }, + "required": [ + "team" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "view": { + "$ref": "#/properties/league" + } + }, + "type": "object" +}
- Changed
get_match1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "attribution": { + "description": "Cite as \"Data by football-charts.com\"", + "type": [ + "string", + "null" + ] + }, + "match": { + "additionalProperties": true, + "properties": { + "away_score": { + "$ref": "#/properties/match/properties/home_score" + }, + "away_team": { + "$ref": "#/properties/match/properties/slug" + }, + "country": { + "$ref": "#/properties/match/properties/slug" + }, + "fgt_a": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Away side first-goal-time histogram" + }, + "fgt_h": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Home side first-goal-time histogram" + }, + "home_score": {}, + "home_team": { + "$ref": "#/properties/match/properties/slug" + }, + "ht_result": { + "$ref": "#/properties/match/properties/slug" + }, + "label": { + "$ref": "#/properties/match/properties/slug" + }, + "league": { + "$ref": "#/properties/match/properties/slug" + }, + "match_date": { + "$ref": "#/properties/match/properties/slug" + }, + "match_status": { + "$ref": "#/properties/match/properties/slug", + "description": "'scheduled' before kick-off; 'ft' when finished" + }, + "model_predictions": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "dc_v2": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "calibrated": { + "anyOf": [ + { + "additionalProperties": true, + "description": "Probabilities 0–1. The draw is NOT a field: draw = 1 − home − away.", + "properties": { + "away": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "btts_yes": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "expected_away_goals": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "expected_home_goals": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "expected_ht_goals": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "home": {}, + "ht_over_0.5": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "ht_over_1.5": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "over_0.5": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "over_1.5": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "over_2.5": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "over_3.5": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + }, + "over_4.5": { + "$ref": "#/properties/match/properties/model_predictions/anyOf/0/properties/dc_v2/anyOf/0/properties/calibrated/anyOf/0/properties/home" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Use these. Calibrated on settled matches." + }, + "computed_at": { + "$ref": "#/properties/match/properties/slug" + }, + "data_through": { + "$ref": "#/properties/match/properties/slug", + "description": "Last match date the model has seen" + }, + "model": { + "$ref": "#/properties/match/properties/slug" + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "real_league_name": { + "$ref": "#/properties/match/properties/slug" + }, + "season": { + "$ref": "#/properties/match/properties/slug" + }, + "slug": {}, + "time": { + "$ref": "#/properties/match/properties/slug" + } + }, + "type": "object" + } + }, + "required": [ + "match" + ], + "type": "object" +}
- Changed
get_results7 fields changed- added
Input schema / properties / last / anyOfAdded value: +[ + { + "maximum": 500, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } +] - changed
Input schema / properties / last / descriptionPrevious value: -"Return only the N most recent matches (default: all)"New value: +"Keep only the N latest matches of the season, e.g. 5 for recent form (default: all)" - removed
Input schema / properties / last / maximumRemoved value: -500 - removed
Input schema / properties / last / minimumRemoved value: -1 - removed
Input schema / properties / last / typeRemoved value: -"integer" - changed
Input schema / properties / team / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "attribution": { + "description": "Cite as \"Data by football-charts.com\"", + "type": [ + "string", + "null" + ] + }, + "count": {}, + "current_season": { + "$ref": "#/properties/league" + }, + "league": {}, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "properties": { + "awayTeam": { + "type": "string" + }, + "date": { + "$ref": "#/properties/league" + }, + "first_goal_time": { + "$ref": "#/properties/count", + "description": "Minute of the first goal; null when goalless" + }, + "first_goal_time_extra": { + "$ref": "#/properties/count", + "description": "Stoppage-time minutes added to first_goal_time" + }, + "goalless": { + "type": [ + "boolean", + "null" + ] + }, + "homeTeam": { + "type": "string" + }, + "ht_result": { + "$ref": "#/properties/league", + "description": "Half-time 'home:away'" + }, + "score": { + "$ref": "#/properties/league", + "description": "Full-time 'home:away', e.g. '3:0'" + }, + "time": { + "$ref": "#/properties/league" + } + }, + "required": [ + "homeTeam", + "awayTeam" + ], + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "note": { + "$ref": "#/properties/league" + }, + "season": { + "$ref": "#/properties/league" + }, + "season_state": { + "$ref": "#/properties/league", + "description": "'in_season' or 'finished'" + } + }, + "type": "object" +}
- Changed
get_season_projection1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "attribution": { + "description": "Cite as \"Data by football-charts.com\"", + "type": [ + "string", + "null" + ] + }, + "projection": { + "additionalProperties": true, + "properties": { + "deltas_vs_prev": { + "anyOf": [ + { + "additionalProperties": { + "additionalProperties": true, + "properties": { + "bottom3": { + "$ref": "#/properties/projection/properties/teams/additionalProperties/properties/title" + }, + "title": { + "$ref": "#/properties/projection/properties/teams/additionalProperties/properties/title" + }, + "top4": { + "$ref": "#/properties/projection/properties/teams/additionalProperties/properties/title" + } + }, + "type": "object" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Change since the previous run" + }, + "expected_remaining": { + "$ref": "#/properties/projection/properties/n_sims" + }, + "league": {}, + "n_sims": {}, + "partial_schedule": { + "type": [ + "boolean", + "null" + ] + }, + "run_date": { + "$ref": "#/properties/projection/properties/league" + }, + "scheduled_remaining": { + "$ref": "#/properties/projection/properties/n_sims" + }, + "season": { + "$ref": "#/properties/projection/properties/league" + }, + "teams": { + "additionalProperties": { + "additionalProperties": true, + "properties": { + "bottom1": { + "$ref": "#/properties/projection/properties/teams/additionalProperties/properties/title" + }, + "bottom2": { + "$ref": "#/properties/projection/properties/teams/additionalProperties/properties/title" + }, + "bottom3": { + "$ref": "#/properties/projection/properties/teams/additionalProperties/properties/title", + "description": "Relegation-zone probability (bottom three)" + }, + "gd_now": { + "$ref": "#/properties/projection/properties/n_sims" + }, + "mean_pts": { + "$ref": "#/properties/projection/properties/teams/additionalProperties/properties/title" + }, + "p10_pts": { + "$ref": "#/properties/projection/properties/n_sims" + }, + "p90_pts": { + "$ref": "#/properties/projection/properties/n_sims" + }, + "played": { + "$ref": "#/properties/projection/properties/n_sims" + }, + "position_matrix": { + "anyOf": [ + { + "items": { + "type": "number" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "Probability of finishing 1st…last" + }, + "pts_now": { + "$ref": "#/properties/projection/properties/n_sims" + }, + "title": {}, + "top4": { + "$ref": "#/properties/projection/properties/teams/additionalProperties/properties/title" + } + }, + "type": "object" + }, + "description": "Keyed by team name", + "type": "object" + } + }, + "required": [ + "teams" + ], + "type": "object" + } + }, + "required": [ + "projection" + ], + "type": "object" +}
- Changed
get_team1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "attribution": { + "description": "Cite as \"Data by football-charts.com\"", + "type": [ + "string", + "null" + ] + }, + "first_goal_bins": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "properties": { + "count": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "time": { + "$ref": "#/properties/team" + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "league": { + "$ref": "#/properties/team" + }, + "matches": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "properties": { + "away": { + "$ref": "#/properties/team" + }, + "date": { + "$ref": "#/properties/team" + }, + "first_goal_time": { + "$ref": "#/properties/team" + }, + "home": { + "$ref": "#/properties/team" + }, + "ht": { + "$ref": "#/properties/team" + }, + "outcome": { + "$ref": "#/properties/team", + "description": "'W' | 'D' | 'L'" + }, + "score": { + "$ref": "#/properties/team" + }, + "time": { + "$ref": "#/properties/team" + }, + "venue": { + "$ref": "#/properties/team", + "description": "'H' or 'A'" + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "ranking": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "avg_goals_conceded": { + "$ref": "#/properties/ranking/anyOf/0/properties/avg_goals_scored" + }, + "avg_goals_scored": { + "$ref": "#/properties/ranking/anyOf/0/properties/expected_points" + }, + "clean_sheets": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "drawn": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "expected_points": { + "description": "Points the underlying numbers say the team should have" + }, + "expected_position": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "goal_difference": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "goals_against": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "goals_for": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "last_5_form": { + "$ref": "#/properties/team", + "description": "Latest results as letters, e.g. 'WWDLW'" + }, + "last_5_points": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "lost": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "luck_category": { + "$ref": "#/properties/team", + "description": "'lucky' | 'fair' | 'unlucky'" + }, + "luck_difference": { + "$ref": "#/properties/ranking/anyOf/0/properties/expected_points", + "description": "points − expected_points; positive = ahead of the numbers" + }, + "over_25_percentage": { + "$ref": "#/properties/ranking/anyOf/0/properties/avg_goals_scored" + }, + "played": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "points": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + }, + "position": {}, + "team": { + "type": "string" + }, + "won": { + "$ref": "#/properties/ranking/anyOf/0/properties/position" + } + }, + "required": [ + "team" + ], + "type": "object" + }, + { + "type": "null" + } + ], + "description": "The team's table row" + }, + "season": { + "$ref": "#/properties/team" + }, + "seasons": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "slug": { + "$ref": "#/properties/team" + }, + "team": {} + }, + "type": "object" +}
- Changed
get_track_record5 fields changed- added
Input schema / properties / days / anyOfAdded value: +[ + { + "maximum": 365, + "minimum": 1, + "type": "integer" + }, + { + "type": "null" + } +] - removed
Input schema / properties / days / maximumRemoved value: -365 - removed
Input schema / properties / days / minimumRemoved value: -1 - removed
Input schema / properties / days / typeRemoved value: -"integer" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "attribution": { + "description": "Cite as \"Data by football-charts.com\"", + "type": [ + "string", + "null" + ] + }, + "track_record": { + "additionalProperties": true, + "properties": { + "accuracy": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "brier": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/pl", + "description": "Brier score over settled probabilities; lower is better, 0.25 = coin flip" + }, + "buckets": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "properties": { + "avg_prob": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/hit_rate" + }, + "hi": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/hit_rate" + }, + "hit_rate": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/hit_rate" + }, + "lo": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/hit_rate" + }, + "n": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/n" + } + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "n": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/n" + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "by_market": { + "anyOf": [ + { + "additionalProperties": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0" + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "pending": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/n", + "description": "Leans published but not yet settled" + }, + "recent": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "properties": { + "market": { + "$ref": "#/properties/track_record/properties/recent/anyOf/0/items/properties/slug" + }, + "model_prob": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/hit_rate" + }, + "outcome": { + "$ref": "#/properties/track_record/properties/recent/anyOf/0/items/properties/slug", + "description": "'won' | 'lost' | 'void'" + }, + "pl": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/hit_rate" + }, + "result_score": { + "$ref": "#/properties/track_record/properties/recent/anyOf/0/items/properties/slug" + }, + "side": { + "$ref": "#/properties/track_record/properties/recent/anyOf/0/items/properties/slug" + }, + "slug": {} + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "The 50 most recent graded leans" + }, + "signals_only": { + "type": [ + "boolean", + "null" + ] + }, + "summary": { + "anyOf": [ + { + "additionalProperties": true, + "properties": { + "hit_rate": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/pl" + }, + "lost": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/n" + }, + "n": {}, + "pl": { + "description": "Profit/loss in units at flat 1-unit stakes" + }, + "void": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/n" + }, + "won": { + "$ref": "#/properties/track_record/properties/summary/anyOf/0/properties/n" + } + }, + "type": "object" + }, + { + "type": "null" + } + ], + "description": "Whole window" + } + }, + "type": "object" + } + }, + "required": [ + "track_record" + ], + "type": "object" +}
- Changed
list_leagues1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": true, + "properties": { + "attribution": { + "description": "Cite as \"Data by football-charts.com\"", + "type": [ + "string", + "null" + ] + }, + "count": {}, + "leagues": { + "items": { + "additionalProperties": true, + "properties": { + "country": { + "type": "string" + }, + "league": { + "description": "The key to pass as `league`", + "type": "string" + }, + "name": { + "type": "string" + }, + "seasons": { + "description": "Newest first; exact strings for `season`", + "items": { + "type": "string" + }, + "type": "array" + }, + "url": {} + }, + "required": [ + "league", + "name", + "country", + "seasons" + ], + "type": "object" + }, + "type": "array" + }, + "season_window": { + "$ref": "#/properties/leagues/items/properties/url" + } + }, + "required": [ + "leagues" + ], + "type": "object" +}
10 tool updates
- First observed
about_football_charts - First observed
get_fixtures - First observed
get_goal_timing - First observed
get_league_table - First observed
get_match - First observed
get_results - First observed
get_season_projection - First observed
get_team - First observed
get_track_record - First observed
list_leagues
Related MCP Connectors
Calibrated, sourced football predictions: odds, tournament sims, standings, brackets, model card.
Football-Data.org MCP — soccer competitions, matches, standings
Football fixtures, standings, and odds intelligence for AI agents.
Probability-calibrated NBA, EuroLeague, football and ATP/WTA tennis predictions, full distributions
Related MCP Servers
- AlicenseAqualityDmaintenanceProvides soccer match predictions and league statistics using xG data and Poisson distribution models. It enables users to forecast outcomes, analyze team performance, and view league tables across major European football leagues.3GPL 2.0
- AlicenseAqualityCmaintenanceLive football/soccer data from top European leagues, enabling queries for standings, fixtures, scorers, and team comparisons via natural language.610 npmMIT
- AlicenseNot gradedqualityDmaintenanceProvides football analytics tools including player scouting, comparisons, market-value filters, expected-goals tables, match-by-match form, team attacking profiles, match search, shot maps, and more for 10 leagues.6GPL 3.0
- AlicenseAqualityBmaintenanceProvides football fixtures, real results, and bet settlement with odds arithmetic, enabling AI agents to devig markets, evaluate prices, and settle picks without an API key.7MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.