Football Database and Results
Server Details
Historical football results, draws and no-draw streaks. 11 read-only tools, 6 need no API key.
- Status
- Healthy
- Uptime
- 42.1% over 40 days
- Last Tested
- Transport
- Streamable HTTP · MCP 2025-11-25
- URL
TDQS
Scored across 11 tools
The tools are largely distinct: get_draw_model handles match-level probabilities, head_to_head and search_results cover matches, and the list_* tools are lookups. However, get_team, get_team_prediction, and get_team_streaks all surface overlapping draw statistics for a single team, which could cause misselection despite the descriptions trying to differentiate them.
Nine of eleven tools follow a clear verb_noun pattern (get_team, list_tournaments, predict_draws, etc.). The exceptions head_to_head and top_streaks are domain-conventional noun phrases, so consistency is strong but not perfect.
11 tools is well-scoped for a read-only football database focused on draw analysis. Each tool earns its place by covering a distinct facet (teams, competitions, matches, predictions, streaks).
The surface covers team profiles, predictions, streaks, head-to-head records, match search, tournament listings, and draw models for individual matches. A minor gap is the lack of a direct get_match by ID, but agents can work around it via search_results with team and date filters.
Available Tools
11 toolsget_draw_modelDraw probability for one matchARead-onlyIdempotentInspect
[PAID] Every draw reading FDB4 holds for ONE match — use it when someone asks how likely a
specific fixture is to end level, rather than which teams are overdue a draw
(predict_draws answers that).
Five readings come back side by side, because they are not interchangeable: the Dixon-Coles goals model's own probability with the expected goals behind it; the historical draw rate at this fixture's Elo rating gap; the one-parameter blend of those two the site has published since September 2026; the five-feature logistic model that now sits beside it with a 95% band around it; and the bookmaker's draw price where one is recorded. Also returned: when the logistic model was last fitted, over how many matches, and its coefficients — so an answer can explain itself.
Identify the match by match_id, or by team (id or slug) plus an optional date;
with no date you get that team's next fixture. is_forecast says whether the
logistic figure is a real forecast (a fixture) or an in-sample description of a
match the model was fitted on. Historical pattern, not a betting tip.
Costs 1 point per call (1 point = 1 cent); paginated calls cost 1 point per page.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | With `team`, the match date as YYYY-MM-DD. Omit for that team's next fixture. | |
| team | No | A team id or slug (431, arsenal), from list_teams. Give this or `match_id`. | |
| match_id | No | The match id, from search_results or a fixture list. Give this or `team`. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnly/idempotent, and the description goes well beyond them: it discloses a per-call cost and per-page pagination charge, the forecast-vs-in-sample caveat via `is_forecast`, model vintage/coefficient return metadata, and an anti-misuse note ('historical pattern, not a betting tip').
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?
Front-loaded with the [PAID] tag and the single most important routing distinction. It is long, and the five-model enumeration partly restates what the output schema presumably contains, but each clause carries either routing, cost, or interpretation value.
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 paid, multi-model read tool this is complete: cost model, input identification paths, output interpretation and caveats are all present, and return-value structure is properly left to the output schema rather than duplicated.
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?
At 100% schema coverage the schema already documents all three params, so the description only needs to add meaning. It does: it explains that team-without-date yields the next fixture, that team accepts id or slug, and pairs `is_forecast` with the returned logistic figure, clarifying how inputs shape the answer.
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?
States a specific verb+resource+scope: draw probability readings for ONE match. It explicitly contrasts itself with the sibling `predict_draws` ('which teams are overdue a draw'), so an agent can route correctly without opening either schema.
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?
Gives an explicit when-to-use trigger ('when someone asks how likely a specific fixture is to end level') and names the alternative that answers a different question (`predict_draws`). Identification modes (match_id vs team+date) are also spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_teamTeam profile and draw statisticsARead-onlyIdempotentInspect
[FREE] One team's profile and its all-time draw statistics.
Returns the team's name, country and type alongside the numbers this database is built on: matches played, draws, draw percentage, the no-draw streak currently running, the longest one ever, the average of its longest runs, its draw debt and its rank in the draw-likelihood field. Use it to answer "how often does this team draw?" or "how long since they last drew?".
Takes a numeric id or a slug, whichever you already hold; both come from list_teams.
Free: no key needed, and it costs a key holder nothing either.
| Name | Required | Description | Default |
|---|---|---|---|
| team | Yes | Numeric team id or slug — 431 or "arsenal". Find either with list_teams. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool readOnly and idempotent. The description adds useful non-schema context: it is free, requires no key, and costs key holders nothing. It also discloses the scope of returned data beyond a simple profile, such as draw statistics and rankings. 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 well-organized and front-loaded with the core purpose, followed by return details, usage examples, parameter guidance, and access notes. Some phrasing like 'the numbers this database is built on' is slightly verbose, but every sentence adds useful information.
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?
This is a simple single-parameter lookup tool with complete schema coverage, a readOnly/idempotent annotation pair, and an output schema present. The description covers what the tool does, when to use it, how to pass the parameter, and access/auth implications. Nothing essential 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 thoroughly documents the single 'team' parameter with a concrete example ('431 or "arsenal"') and how to find it. The description adds 'whichever you already hold' and repeats the list_teams source, but provides no meaningful additional semantic detail. Baseline 3 is appropriate.
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 the tool returns 'One team's profile and its all-time draw statistics' with a specific resource (team) and content focus. It is distinct enough from siblings like get_draw_model or get_team_prediction, though it does not explicitly call out those differences.
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 use cases: 'how often does this team draw?' and 'how long since they last drew?'. It also explains how to provide the input via list_teams. It does not name alternative tools or exclusions, but the usage context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_team_predictionDraw prediction for one teamARead-onlyIdempotentInspect
[PAID] How overdue a draw one named team is, plus the results that made it so.
Returns the team's draw-likelihood rank and score among all ranked teams, the signals behind it (draw rate, current no-draw streak, longest ever, draw debt), and its recent form — every match in the current no-draw run, with opponent, score and side. Use this when the question is about a specific team ("is Brazil due a draw?"); use predict_draws when the question is about the field.
The prediction comes back null when the team exists but is not currently ranked (no
played matches, or excluded by the recent filter). Historical pattern, not a betting tip.
Costs 1 point per call (1 point = 1 cent); paginated calls cost 1 point per page.
| Name | Required | Description | Default |
|---|---|---|---|
| team | Yes | Numeric team id or slug — 431 or "arsenal". Both come from list_teams. | |
| recent | No | Rank within teams that have played recently, matching predict_draws. Default true. | |
| wc2026 | No | Rank within the 2026 World Cup team group. Default false. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly, idempotent), and the description adds genuinely non-structured context: it is a paid tool costing 1 point per call and 1 point per page, the result is a historical pattern rather than a betting tip, and the prediction can return null under stated conditions. It does not describe caching or rate limiting beyond cost, but the added behavioral detail is substantial.
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?
Front-loads the [PAID] marker and the core purpose, then adds breadth-of-return, routing, edge case, and cost in that order. Dense and mostly waste-free; the enumerated signal list is long but each item maps to returned data, so it earns its place.
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 does not need to explain return values — yet it still tells the agent what the payload contains and when it is null. Combined with cost disclosure and sibling routing, nothing needed to call this 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?
Schema coverage is 100%, so the baseline is 3. The description goes beyond the schema by explaining the consequence of `recent` — it determines ranking scope and can cause a null prediction — and by framing both filters as ranking groups ('matching predict_draws', 'the 2026 World Cup team group').
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?
States a specific verb+resource — 'how overdue a draw one named team is, plus the results that made it so' — and enumerates the returned signals (rank, draw rate, no-draw streak, longest ever, draw debt, recent form). It explicitly separates itself from predict_draws, so an agent can pick between them without opening a schema.
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?
Gives an explicit routing rule: 'use this when the question is about a specific team...; use predict_draws when the question is about the field.' It also documents the null-return condition (team exists but unranked, or excluded by `recent`), which is exactly the kind of when-not guidance agents need.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_team_streaksNo-draw runs of one teamARead-onlyIdempotentInspect
[FREE] Every no-draw run one team has ever had, plus the one it is on now.
A no-draw run is a sequence of matches that ended in a win or a loss. This returns the run currently in progress with each match in it — date, competition, opponent, score — so you can say exactly when the team last drew and what has happened since, together with every recorded run in the team's history, longest first, each with its start and end dates.
Runs span all competitions; per-competition runs are not split out.
Free: no key needed, and it costs a key holder nothing either.
| Name | Required | Description | Default |
|---|---|---|---|
| team | Yes | Numeric team id or slug — 431 or "arsenal". Find either with list_teams. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, so the safety profile is covered; the description adds real value beyond that with licensing terms (free, no key needed), scope disclosure (all competitions, not split), and return ordering (longest first, with start/end dates). It does not state result limits or pagination, which is the only notable gap.
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?
Front-loaded with the core capability in the first line, then definitions and scope. Three compact paragraphs with little waste; the closing '[FREE]... costs a key holder nothing either' is slightly redundant with the '[FREE]' tag but still informative.
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?
Single required parameter, 100% schema coverage, output schema present, and annotations covering the read-only/idempotent profile. The description rounds this out with run definition, competition scope, and ordering semantics, leaving nothing an agent needs in order to call it 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% and the schema already explains that 'team' accepts a numeric id or slug and points to list_teams. The description adds no format or constraint detail about the parameter, so baseline 3 is appropriate.
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?
States a specific verb+resource: every no-draw run a team has ever had plus the current one, with 'no-draw run' explicitly defined. This is clearly distinguishable from siblings like top_streaks (which ranks across teams) and search_results (which returns individual matches).
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?
Gives a concrete use case ('say exactly when the team last drew and what has happened since') and a scope constraint (runs span all competitions, per-competition runs are not split out), which implicitly steers away from expecting filtered results. It does not name an alternative tool for per-competition or cross-team views, so it stops short of explicit when-to-use/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
head_to_headHead-to-head recordARead-onlyIdempotentInspect
[PAID] The complete record between two teams, and every match they have ever played.
Answers "who wins more between these two, and how often do they draw?" — matches played, wins each way, draws, goals each way and the draw percentage, all from team A's perspective, followed by every meeting with its date, competition and score. Optionally narrow to one competition type or a single edition to compare only their league games, or only one season.
Both teams are given as numeric ids, which list_teams returns.
Costs 1 point per call (1 point = 1 cent); paginated calls cost 1 point per page.
| Name | Required | Description | Default |
|---|---|---|---|
| a | Yes | Team A, as a numeric id from list_teams. The record is reported from this team's point of view. | |
| b | Yes | Team B, as a numeric id from list_teams. Must differ from a. | |
| item | No | Restrict to a single edition or season id, from list_tournaments with a `tournament` argument. | |
| type | No | Restrict to one competition type, such as league or cup. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations already covering read-only and idempotent behavior, the description adds important operational context: paid access at 1 point per call, paginated calls costing 1 point per page, and that results are reported from team A's perspective. It also describes the returned aggregate stats and match list, which is valuable behavioral detail beyond the 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 cost notice and core purpose are front-loaded, and the description moves logically into outputs and optional filters. It is slightly verbose and repeats some schema details, but the length is reasonable for a paid, multi-filter historical analysis tool.
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 definition covers pricing, pagination cost, required team IDs and their source, optional filters, result perspective, and expected output content. Given the output schema and annotations already handle return structure and safety, this is complete enough for an agent to invoke 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 input schema already fully documents all four parameters, including team A perspective and id validation. The description mostly repeats that information and does not add significant parameter semantics beyond what the schema 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 resource and scope: the complete historical record between two teams, including every match ever played. It is clearly distinct from sibling tools like get_team, get_team_streaks, and search_results by focusing on head-to-head meetings and aggregate outcomes.
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 clear context for optional narrowing: use item or type to compare only league games, a single edition, or a single season. It does not explicitly state when not to use this tool or name alternative sibling tools for similar needs, so it falls just short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_countriesCountriesARead-onlyIdempotentInspect
[FREE] Every country in the database, with its FIFA code and id.
Use it to turn a country name into the id and FIFA code the rest of the data is keyed
by, or to check which countries are covered at all. Search with q, which matches a
name prefix or an exact FIFA code ("ENG"). Countries that no longer exist are included
and flagged, because the match archive still holds their games.
Free: no key needed, and it costs a key holder nothing either.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Country name prefix, or an exact FIFA code such as ENG or BRA. | |
| limit | No | How many countries to return. Default 25; the total is always reported. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | Countries matching the search. |
| hint | No | Present only when rows were left out: how to narrow the call. |
| total | Yes | How many rows matched before the limit. |
| returned | Yes | How many rows are in data. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint and idempotentHint, so the safety profile is covered. The description adds valuable behavioral context: it is free/no key needed, includes and flags defunct countries because the match archive still holds their games, and mentions that the total is always reported. 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 compact and front-loaded with the core result and use cases. The free-tier note is slightly redundant with the opening '[FREE]', but it is brief and does not hurt clarity.
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 a simple two-parameter tool with an output schema and safety annotations, the description covers everything needed: purpose, keyed id usage, q search behavior, defunct-country handling, and free access. Nothing critical 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?
Schema description coverage is 100%: q and limit are both fully described, including the exact FIFA code example and limit bounds/default. The description restates q's prefix/exact-match behavior but does not add materially new parameter meaning beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Every country in the database, with its FIFA code and id.' This makes the tool's scope and output immediately clear. It is also distinct enough from sibling list tools like list_teams and list_tournaments because it explicitly names countries as the resource.
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 concrete use cases: 'turn a country name into the id and FIFA code the rest of the data is keyed by' or 'check which countries are covered at all.' It also explains the q matching behavior. It does not explicitly name alternatives or when-not-to-use scenarios, but the guidance is clear and sufficient for this simple list tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_teamsFind a teamARead-onlyIdempotentInspect
[FREE] Find a team and its id — the lookup every other team tool depends on.
Search by name prefix with q ("arse" finds Arsenal), or browse by first letter, or
list one kind of team. Each row carries the numeric id and the slug that get_team,
get_team_streaks, get_team_prediction, head_to_head and search_results take.
The database holds thousands of teams, so an unfiltered call returns the first 25 with
the full total beside them. Always pass q when you know the name.
Free: no key needed, and it costs a key holder nothing either.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Name prefix, matched against both the short and the full name. The fastest way to find one team. | |
| type | No | Restrict to national teams or to clubs. | |
| limit | No | How many teams to return. Default 25; the total number of matches is always reported. | |
| letter | No | First letter A-Z to browse by, or "#" for names starting with a non-letter. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | Teams matching the search. |
| hint | No | Present only when rows were left out: how to narrow the call. |
| total | Yes | How many rows matched before the limit. |
| returned | Yes | How many rows are in data. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this as read-only and idempotent. The description adds useful behavioral context beyond that: unfiltered calls return only the first 25 with a total count, rows carry the id and slug, and the tool is free with no key needed. This is meaningful additional transparency without contradicting the 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 and immediately gives a concrete example. It is mostly efficient, though the free/no-key point is stated twice, adding mild redundancy. Overall it earns its length with useful routing and behavioral details.
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 lookup tool with a rich input schema and an output schema present, the description covers what an agent needs: how to search, what each result row contains, the default limit behavior, and the relationship to downstream team tools. No critical invocation information 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?
Schema description coverage is 100%, so the schema already documents all four parameters clearly. The description adds a helpful example ('arse' finds Arsenal) and notes the default limit behavior, but these are marginal enrichments over the schema rather than necessary compensations.
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: 'Find a team and its id'. It also explicitly positions itself as 'the lookup every other team tool depends on', which clearly distinguishes it from the sibling team tools like get_team and head_to_head.
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 clear usage context: search by prefix with q, browse by first letter, or filter by team type. It also gives an explicit rule—'Always pass q when you know the name'—which is actionable. It does not explicitly name alternatives or state when not to use this tool, but the role as a dependency lookup makes the intended use clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tournamentsCompetitions and seasonsARead-onlyIdempotentInspect
[FREE] Every competition covered — leagues, domestic cups, continental cups, World Cups — with how many matches and how many draws each one holds.
Two uses. Without tournament it answers "what is in this database, and how draw-heavy
is each competition?", returning each competition's id, slug, country, match count, draw
count and draw percentage. With tournament (an id or slug) it returns that one
competition in full: the years it covers, every edition newest first with its champion
where one was decided, and the all-time winners ranking with title counts and years.
The competition ids here are what search_results and head_to_head filter by.
Free: no key needed, and it costs a key holder nothing either.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | How many competitions to list. Default 25; the total is always reported. | |
| tournament | No | One competition, by numeric id or slug (53 or "norway-cup"). Returns its editions, champions and all-time winners instead of the list. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | Competitions, or one competition's editions. |
| hint | No | Present only when rows were left out: how to narrow the call. |
| total | Yes | How many rows matched before the limit. |
| returned | Yes | How many rows are in data. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the read-only and idempotent annotations, the description adds substantial behavioral detail: it reports draw percentage, orders editions newest first, includes champions only where decided, reports the total even when limited, and states the tool is free and costs a key holder nothing. No contradiction with annotations exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and free status, then organized into two clear usage modes, then the cross-tool linkage. Every sentence adds useful information, and the structure makes it easy for an agent to extract the behavior without wading through 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?
With a rich input schema and an output schema present, the description covers what an agent needs: the two modes, exactly what each returns, how limits behave, and how the ids relate to sibling tools. No major operational or selection detail 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?
Schema coverage is 100%, so the baseline is 3, but the description adds meaningful semantics: `tournament` toggles between a list and a single-competition detail view, and `limit` controls only the competitions list while the total is always reported. This goes beyond the schema's already informative parameter descriptions.
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: listing every competition covered, with league, cup, and World Cup scoping, plus per-competition match and draw counts. It also differentiates the two modes (with and without `tournament`) and explicitly ties competition ids to `search_results` and `head_to_head`, distinguishing it from 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 clearly tells an agent when to use it: to discover what competitions are in the database and how draw-heavy they are, or to pull a single competition's full season/champion history. It also explains that ids from this tool are what `search_results` and `head_to_head` filter by, giving practical routing guidance, though it does not explicitly state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
predict_drawsTeams most overdue a drawARead-onlyIdempotentInspect
[PAID] Rank teams by how overdue a draw is — the question this database exists to answer.
Every team has a historical draw rate and a run of matches since its last draw. When the run is long relative to how often that team normally draws, the team is carrying "draw debt", and this tool ranks the whole field by it, most overdue first. Ask it "which national teams are most due a draw?" or "who is overdue a draw in the World Cup 2026 field?" and it answers directly; nothing else here needs to be queried first.
Each entry returns the rank, the score, and the signals behind it: matches played, draws, draw percentage, the current no-draw streak, the longest ever, and the debt figure. Filters subset which teams are listed — a team's score and rank are global and never change with them. Historical pattern, not a betting tip.
Costs 1 point per call (1 point = 1 cent); paginated calls cost 1 point per page.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Restrict the ranking to national teams or to clubs. Omit to rank both together. | |
| limit | No | How many ranked teams to return. Default 25, max 500. One call, one point, whatever the limit. | |
| recent | No | Only teams with a recent match, so the answer is about teams currently playing. Default true. | |
| wc2026 | No | Restrict to the 2026 World Cup team group. Default false. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | Teams ranked by how overdue a draw is, most overdue first. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and idempotentHint annotations, the description discloses the paid cost (1 point per call, per page), the global nature of scores and ranks regardless of filters, the returned signal fields, and the caveat that it is a historical pattern, not a betting tip. This is rich behavioral context that annotations alone do not provide.
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 builds the concept, examples, return fields, filter caveat, and cost in a logical order. Every sentence earns its place, including the non-betting disclaimer and pagination cost note, with no filler or redundancy.
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 paid read-only tool with an output schema, the description is complete: it explains the ranking logic, what each result contains, how filters behave, cost implications, and example usage. An agent has everything needed to select and invoke this tool correctly without consulting siblings or external docs.
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 meaningful semantics by explaining that filters subset which teams are listed while a team's score and rank remain global and unchanged, which is not obvious from the schema alone. It also reiterates the cost behavior tied to limit/pagination, adding value beyond the parameter descriptions.
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 specific verb and resource: 'Rank teams by how overdue a draw is' and then explains the draw-debt concept in concrete terms. It is clear and distinct from the title, but it does not explicitly name sibling tools or differentiate itself from them, so it falls just short of the highest bar.
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 example queries ('which national teams are most due a draw?') and states that nothing else needs to be queried first, providing clear context for when to use it. It does not state when not to use it or mention alternatives, so it lacks explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_resultsMatch results archiveARead-onlyIdempotentInspect
[FREE for the last 7 days · PAID for the archive] Search the match archive: finished matches, newest first, with scores.
This is the raw history behind every other tool — decades of results across national team football, domestic leagues and cups. Filter by team, competition, single season, outcome (home win, away win or draw) and date range, in any combination: "Arsenal's draws since 2020", "every match in the 2025/26 Premier League", "all draws in the World Cup". Each match returns its date, competition and edition, both teams, the score and whether it was a draw.
Results are paginated, 50 per page by default; page walks through them and
meta.total tells you how many matches matched before you start.
Free, no key needed, for recent results: the first page of 50, and any from date
inside the last 7 days. Reaching further back — an older from, a bigger limit, or
page 2 onward — is the archive and costs 1 point per call (1 point = 1 cent), one point
per page.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Latest match date, inclusive, as YYYY-MM-DD. | |
| from | No | Earliest match date, inclusive, as YYYY-MM-DD. Inside the last 7 days the call is free and needs no key; earlier than that it costs 1 point. | |
| page | No | Page number, from 1. Page 1 can be free; every page after it is a separate call and costs its own point. | |
| type | No | Restrict to national-team or club football. | |
| limit | No | Page size: 50, 100, 250 or 500. Default 50, which is also the largest free page. Anything else is treated as 100. | |
| outcome | No | H for a home win, A for an away win, D for a draw. | |
| team_id | No | Matches involving this team, home or away. Numeric id from list_teams. | |
| competition_id | No | Restrict to one competition. Id from list_tournaments. | |
| competition_item_id | No | Restrict to a single edition or season. Edition ids come from list_tournaments with a `tournament` argument. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | Matches, newest first. |
| meta | No | Pagination: which page this is and how many rows exist. |
| links | No | first/last/prev/next page URLs on the REST API. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnly/idempotent; the description adds substantial behavior the annotations cannot: the pricing model (free first page/last 7 days, 1 point per archive page), pagination default of 50, and how `meta.total` works. This is exactly the cost/auth context the annotation bar leaves open.
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?
Front-loads the free/paid summary in brackets, then elaborates filtering, returns, and pagination in tight paragraphs. Slightly long but every section carries distinct information; no 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?
With 9 optional params and an output schema present, the description still covers filtering combinations, pagination, return shape, and the full free/paid boundary. An agent has everything needed to scope a call and predict its cost.
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. The description adds cross-parameter semantics the schema only partially captures — that going beyond the last 7 days, raising `limit` past 50, or moving past page 1 each trigger a charge — tying individual params to the cost model.
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?
States a specific verb and resource ('Search the match archive') with scope ('finished matches, newest first, with scores') and positions itself as 'the raw history behind every other tool.' An agent can distinguish this history-search tool from siblings like head_to_head or get_team_streaks without opening a schema.
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?
Gives concrete usage context and worked filter examples ('Arsenal's draws since 2020'), plus explicit when-free vs when-paid conditions. It does not name which sibling to use for narrower questions, so it stops short of full alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
top_streaksLongest no-draw runs of all timeARead-onlyIdempotentInspect
[PAID] The all-time leaderboard of no-draw runs — the longest any team has gone without drawing.
Answers "what is the longest run of matches without a draw on record?" and "who else has done it?". Each entry is one run: its length, the dates it started and ended, and the team. A team can appear more than once, since a great side may have several long runs. Filter to one team, to national teams or clubs, or to runs above a minimum length.
Paginated, 25 per page by default; page walks the leaderboard and each page costs its
own point.
Costs 1 point per call (1 point = 1 cent); paginated calls cost 1 point per page.
| Name | Required | Description | Default |
|---|---|---|---|
| min | No | Minimum run length to list. Default 5. | |
| page | No | Page number, from 1. Each page is a separate call and costs its own point. | |
| type | No | Restrict to national teams or to clubs. | |
| limit | No | Page size. Default 25, max 500. | |
| team_id | No | Restrict to one team. Numeric id from list_teams. |
Output Schema
| Name | Required | Description |
|---|---|---|
| data | Yes | The longest no-draw runs, longest first. |
| meta | No | Pagination: which page this is and how many rows exist. |
| links | No | first/last/prev/next page URLs on the REST API. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint and idempotentHint. The description adds meaningful behavioral context beyond that: paid cost per call, pagination walk behavior, and per-page cost. 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 well-structured and front-loaded with the paid marker and primary purpose. Each sentence adds value, covering answers, entry structure, filters, pagination, and cost without excessive verbosity.
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 description covers purpose, entry fields, filters, pagination, and cost. An output schema exists, so return-value details are not needed in the description. It is complete enough for an agent to call 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 coverage is 100% with descriptions for all five parameters. The description adds some semantic context by summarizing filter dimensions (team, type, minimum length) and pagination, but does not go beyond what the schema already documents.
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 a specific resource (all-time leaderboard of no-draw runs) and answers concrete questions. It does not explicitly differentiate from sibling get_team_streaks, but the 'all-time leaderboard' framing makes the global scope evident.
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 implied through the questions it answers and the mention of filters (team, type, minimum length). However, there is no explicit when-not guidance or routing to alternatives like get_team_streaks, leaving the choice partly to inference.
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.
5 tool updates
- Changed
get_draw_model1 field changed- changed
Output schema / properties / data / properties / match / properties / score / descriptionPrevious value: -"Final score; both null until the match is played."New value: +"Ninety-minute score; both values null before play or when the exact score is unknown, including played extra-time draws."
- Changed
get_team_prediction1 field changed- changed
Output schema / properties / data / properties / recent_form / items / properties / score / descriptionPrevious value: -"Final score; both null until the match is played."New value: +"Ninety-minute score; both values null before play or when the exact score is unknown, including played extra-time draws."
- Changed
get_team_streaks3 fields changed- added
Output schema / properties / data / properties / active_streak / properties / matches / items / properties / ninety_score_unknownAdded value: +{ + "description": "Played extra-time match known to be level at ninety minutes, with the exact ninety-minute score unavailable.", + "type": "boolean" +} - changed
Output schema / properties / data / properties / active_streak / properties / matches / items / properties / score / descriptionPrevious value: -"Final score; both null until the match is played."New value: +"Ninety-minute score; both values null before play or when the exact score is unknown, including played extra-time draws." - added
Output schema / properties / data / properties / active_streak / properties / matches / items / properties / score_120Added value: +{ + "description": "Score after extra time; both values null when unavailable or no extra time was played.", + "properties": { + "away": { + "type": [ + "integer", + "null" + ] + }, + "home": { + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" +}
- Changed
head_to_head3 fields changed- added
Output schema / properties / data / properties / meetings / items / properties / ninety_score_unknownAdded value: +{ + "description": "Played extra-time match known to be level at ninety minutes, with the exact ninety-minute score unavailable.", + "type": "boolean" +} - changed
Output schema / properties / data / properties / meetings / items / properties / score / descriptionPrevious value: -"Final score; both null until the match is played."New value: +"Ninety-minute score; both values null before play or when the exact score is unknown, including played extra-time draws." - added
Output schema / properties / data / properties / meetings / items / properties / score_120Added value: +{ + "description": "Score after extra time; both values null when unavailable or no extra time was played.", + "properties": { + "away": { + "type": [ + "integer", + "null" + ] + }, + "home": { + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" +}
- Changed
search_results3 fields changed- added
Output schema / properties / data / items / properties / ninety_score_unknownAdded value: +{ + "description": "Played extra-time match known to be level at ninety minutes, with the exact ninety-minute score unavailable.", + "type": "boolean" +} - changed
Output schema / properties / data / items / properties / score / descriptionPrevious value: -"Final score; both null until the match is played."New value: +"Ninety-minute score; both values null before play or when the exact score is unknown, including played extra-time draws." - added
Output schema / properties / data / items / properties / score_120Added value: +{ + "description": "Score after extra time; both values null when unavailable or no extra time was played.", + "properties": { + "away": { + "type": [ + "integer", + "null" + ] + }, + "home": { + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" +}
11 tool updates
- Changed
get_draw_model1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "properties": { + "blend": { + "description": "Goals model and Elo gap combined.", + "properties": { + "p_draw": { + "description": "The blended draw probability, 0 to 1.", + "type": [ + "number", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "caveats": { + "description": "What these numbers do not claim.", + "items": { + "type": "string" + }, + "type": "array" + }, + "elo": { + "description": "Elo ratings and the historical draw rate at this rating gap.", + "properties": { + "away_rating": { + "type": [ + "number", + "null" + ] + }, + "gap": { + "type": [ + "number", + "null" + ] + }, + "historical_draw_rate": { + "description": "Draw rate of past matches with a similar rating gap, 0 to 1.", + "type": [ + "number", + "null" + ] + }, + "home_rating": { + "type": [ + "number", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "fit": { + "description": "When and on what the logistic model was trained.", + "type": [ + "object", + "null" + ] + }, + "goals_model": { + "description": "Dixon-Coles goals model; null when it has no fit for these teams.", + "properties": { + "p_away": { + "description": "Away win probability, 0 to 1.", + "type": [ + "number", + "null" + ] + }, + "p_draw": { + "description": "Draw probability from the goals model, 0 to 1.", + "type": [ + "number", + "null" + ] + }, + "p_home": { + "description": "Home win probability, 0 to 1.", + "type": [ + "number", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "logistic": { + "description": "The calibrated logistic draw model.", + "properties": { + "confidence_95": { + "description": "low/high bounds of the 95% interval.", + "type": [ + "object", + "null" + ] + }, + "p_draw": { + "description": "Calibrated draw probability from the logistic model, 0 to 1.", + "type": [ + "number", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "market": { + "description": "Bookmaker-implied draw probability, when odds are held.", + "type": [ + "object", + "null" + ] + }, + "match": { + "description": "The fixture the readings are for.", + "properties": { + "away_team": { + "description": "A team reference.", + "properties": { + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + }, + "competition": { + "type": [ + "object", + "null" + ] + }, + "date": { + "type": "string" + }, + "home_team": { + "description": "A team reference.", + "properties": { + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + }, + "id": { + "type": "integer" + }, + "score": { + "description": "Final score; both null until the match is played.", + "properties": { + "away": { + "type": [ + "integer", + "null" + ] + }, + "home": { + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "status": { + "type": "string" + } + }, + "required": [ + "id", + "date" + ], + "type": "object" + } + }, + "required": [ + "match" + ], + "type": "object" + } + }, + "required": [ + "data" + ], + "type": "object" +}
- Changed
get_team1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "properties": { + "country": { + "description": "The country a team or competition belongs to.", + "properties": { + "fifa_code": { + "description": "Three-letter FIFA code.", + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id" + ], + "type": [ + "object", + "null" + ] + }, + "exists_now": { + "type": "boolean" + }, + "full_name": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "stats": { + "description": "All-time draw statistics.", + "properties": { + "current_no_draw_streak": { + "description": "Matches since the last draw.", + "type": [ + "integer", + "null" + ] + }, + "draw_debt": { + "type": [ + "number", + "null" + ] + }, + "draw_pct": { + "description": "Share of matches drawn, in percent.", + "type": [ + "number", + "null" + ] + }, + "draw_rank": { + "type": [ + "integer", + "null" + ] + }, + "draw_score": { + "type": [ + "number", + "null" + ] + }, + "draws": { + "type": "integer" + }, + "last_match_date": { + "type": [ + "string", + "null" + ] + }, + "max_no_draw_streak": { + "description": "Longest run without a draw, ever.", + "type": [ + "integer", + "null" + ] + }, + "played": { + "type": "integer" + } + }, + "type": [ + "object", + "null" + ] + }, + "type": { + "description": "\"national_team\" or \"club\".", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + } + }, + "required": [ + "data" + ], + "type": "object" +}
- Changed
get_team_prediction1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "properties": { + "prediction": { + "description": "The team's place in the ranking; null when it is not ranked (too few recent matches).", + "properties": { + "last_match_date": { + "description": "Date of the team's most recent match.", + "type": [ + "string", + "null" + ] + }, + "rank": { + "description": "Position in the ranking; 1 is the most overdue.", + "type": "integer" + }, + "score": { + "description": "The draw-likelihood score the ranking sorts on.", + "type": "number" + }, + "signals": { + "description": "The figures the score is built from.", + "properties": { + "current_no_draw_streak": { + "description": "Matches since the last draw.", + "type": [ + "integer", + "null" + ] + }, + "draw_debt": { + "description": "Draws expected from the draw rate minus draws that came.", + "type": [ + "number", + "null" + ] + }, + "draw_pct": { + "description": "Share of matches drawn, in percent.", + "type": [ + "number", + "null" + ] + }, + "draws": { + "type": "integer" + }, + "max_no_draw_streak": { + "description": "Longest run without a draw, ever.", + "type": [ + "integer", + "null" + ] + }, + "played": { + "type": "integer" + } + }, + "type": "object" + }, + "team": { + "description": "A team.", + "properties": { + "country": { + "description": "The country a team or competition belongs to.", + "properties": { + "fifa_code": { + "description": "Three-letter FIFA code.", + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id" + ], + "type": [ + "object", + "null" + ] + }, + "exists_now": { + "description": "False for a team that no longer exists.", + "type": "boolean" + }, + "full_name": { + "description": "Official or long name, when known.", + "type": [ + "string", + "null" + ] + }, + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + }, + "type": { + "description": "\"national_team\" or \"club\".", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + } + }, + "required": [ + "rank", + "score" + ], + "type": [ + "object", + "null" + ] + }, + "recent_form": { + "description": "The team's latest results, newest first.", + "items": { + "properties": { + "date": { + "type": "string" + }, + "is_draw": { + "type": "boolean" + }, + "match_id": { + "type": "integer" + }, + "opponent": { + "description": "A team reference.", + "properties": { + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + }, + "score": { + "description": "Final score; both null until the match is played.", + "properties": { + "away": { + "type": [ + "integer", + "null" + ] + }, + "home": { + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "side": { + "description": "\"home\" or \"away\".", + "type": "string" + }, + "won": { + "type": "boolean" + } + }, + "type": "object" + }, + "type": "array" + }, + "team": { + "description": "A team.", + "properties": { + "country": { + "description": "The country a team or competition belongs to.", + "properties": { + "fifa_code": { + "description": "Three-letter FIFA code.", + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id" + ], + "type": [ + "object", + "null" + ] + }, + "exists_now": { + "description": "False for a team that no longer exists.", + "type": "boolean" + }, + "full_name": { + "description": "Official or long name, when known.", + "type": [ + "string", + "null" + ] + }, + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + }, + "type": { + "description": "\"national_team\" or \"club\".", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "data" + ], + "type": "object" +}
- Changed
get_team_streaks1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "properties": { + "active_streak": { + "description": "The run the team is on now; null if its last match was a draw.", + "properties": { + "end": { + "type": [ + "string", + "null" + ] + }, + "length": { + "description": "Matches since the team last drew.", + "type": "integer" + }, + "matches": { + "items": { + "description": "A match.", + "properties": { + "away_team": { + "description": "A team reference.", + "properties": { + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + }, + "competition": { + "description": "The competition and edition the match belongs to.", + "properties": { + "edition": { + "type": [ + "string", + "null" + ] + }, + "edition_id": { + "description": "The season or edition id, from list_tournaments.", + "type": [ + "integer", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "year": { + "type": [ + "integer", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "date": { + "description": "Match date, YYYY-MM-DD.", + "type": "string" + }, + "home_team": { + "description": "A team reference.", + "properties": { + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + }, + "id": { + "description": "Match id, as get_draw_model takes it.", + "type": "integer" + }, + "is_draw": { + "description": "Whether the match ended level.", + "type": "boolean" + }, + "result": { + "description": "H home win, A away win, D draw; empty until played.", + "type": [ + "string", + "null" + ] + }, + "score": { + "description": "Final score; both null until the match is played.", + "properties": { + "away": { + "type": [ + "integer", + "null" + ] + }, + "home": { + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "status": { + "description": "PLAYED, SCHEDULED, POSTPONED and so on.", + "type": "string" + } + }, + "required": [ + "id", + "date" + ], + "type": "object" + }, + "type": "array" + }, + "start": { + "type": [ + "string", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "runs": { + "description": "Every no-draw run the team has had.", + "items": { + "description": "A run of matches without a draw.", + "properties": { + "end": { + "description": "Date of the last match in the run.", + "type": [ + "string", + "null" + ] + }, + "end_match_id": { + "type": [ + "integer", + "null" + ] + }, + "id": { + "type": "integer" + }, + "length": { + "description": "Matches in the run without a draw.", + "type": "integer" + }, + "start": { + "description": "Date of the first match in the run.", + "type": [ + "string", + "null" + ] + }, + "start_match_id": { + "type": [ + "integer", + "null" + ] + } + }, + "required": [ + "id", + "length" + ], + "type": "object" + }, + "type": "array" + }, + "team": { + "description": "A team.", + "properties": { + "country": { + "description": "The country a team or competition belongs to.", + "properties": { + "fifa_code": { + "description": "Three-letter FIFA code.", + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id" + ], + "type": [ + "object", + "null" + ] + }, + "exists_now": { + "description": "False for a team that no longer exists.", + "type": "boolean" + }, + "full_name": { + "description": "Official or long name, when known.", + "type": [ + "string", + "null" + ] + }, + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + }, + "type": { + "description": "\"national_team\" or \"club\".", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "data" + ], + "type": "object" +}
- Changed
head_to_head1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "properties": { + "meetings": { + "description": "Every match between them.", + "items": { + "description": "A match.", + "properties": { + "away_team": { + "description": "A team reference.", + "properties": { + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + }, + "competition": { + "description": "The competition and edition the match belongs to.", + "properties": { + "edition": { + "type": [ + "string", + "null" + ] + }, + "edition_id": { + "description": "The season or edition id, from list_tournaments.", + "type": [ + "integer", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "year": { + "type": [ + "integer", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "date": { + "description": "Match date, YYYY-MM-DD.", + "type": "string" + }, + "home_team": { + "description": "A team reference.", + "properties": { + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + }, + "id": { + "description": "Match id, as get_draw_model takes it.", + "type": "integer" + }, + "is_draw": { + "description": "Whether the match ended level.", + "type": "boolean" + }, + "result": { + "description": "H home win, A away win, D draw; empty until played.", + "type": [ + "string", + "null" + ] + }, + "score": { + "description": "Final score; both null until the match is played.", + "properties": { + "away": { + "type": [ + "integer", + "null" + ] + }, + "home": { + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "status": { + "description": "PLAYED, SCHEDULED, POSTPONED and so on.", + "type": "string" + } + }, + "required": [ + "id", + "date" + ], + "type": "object" + }, + "type": "array" + }, + "record": { + "description": "The overall record between the two.", + "properties": { + "draw_percent": { + "type": [ + "number", + "null" + ] + }, + "draws": { + "type": "integer" + }, + "goals_team_a": { + "type": "integer" + }, + "goals_team_b": { + "type": "integer" + }, + "played": { + "type": "integer" + }, + "team_a_wins": { + "type": "integer" + }, + "team_b_wins": { + "type": "integer" + } + }, + "type": "object" + }, + "team_a": { + "description": "A team.", + "properties": { + "country": { + "description": "The country a team or competition belongs to.", + "properties": { + "fifa_code": { + "description": "Three-letter FIFA code.", + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id" + ], + "type": [ + "object", + "null" + ] + }, + "exists_now": { + "description": "False for a team that no longer exists.", + "type": "boolean" + }, + "full_name": { + "description": "Official or long name, when known.", + "type": [ + "string", + "null" + ] + }, + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + }, + "type": { + "description": "\"national_team\" or \"club\".", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + }, + "team_b": { + "description": "A team.", + "properties": { + "country": { + "description": "The country a team or competition belongs to.", + "properties": { + "fifa_code": { + "description": "Three-letter FIFA code.", + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id" + ], + "type": [ + "object", + "null" + ] + }, + "exists_now": { + "description": "False for a team that no longer exists.", + "type": "boolean" + }, + "full_name": { + "description": "Official or long name, when known.", + "type": [ + "string", + "null" + ] + }, + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + }, + "type": { + "description": "\"national_team\" or \"club\".", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + } + }, + "type": "object" + } + }, + "required": [ + "data" + ], + "type": "object" +}
- Changed
list_countries1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Countries matching the search.", + "items": { + "description": "A country.", + "properties": { + "exists_now": { + "type": "boolean" + }, + "fifa_code": { + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "is_international": { + "type": "boolean" + }, + "iso2": { + "type": [ + "string", + "null" + ] + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ], + "type": "object" + }, + "type": "array" + }, + "hint": { + "description": "Present only when rows were left out: how to narrow the call.", + "type": "string" + }, + "returned": { + "description": "How many rows are in data.", + "type": "integer" + }, + "total": { + "description": "How many rows matched before the limit.", + "type": "integer" + } + }, + "required": [ + "data", + "total", + "returned" + ], + "type": "object" +}
- Changed
list_teams1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Teams matching the search.", + "items": { + "description": "A team.", + "properties": { + "country": { + "description": "The country a team or competition belongs to.", + "properties": { + "fifa_code": { + "description": "Three-letter FIFA code.", + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id" + ], + "type": [ + "object", + "null" + ] + }, + "exists_now": { + "description": "False for a team that no longer exists.", + "type": "boolean" + }, + "full_name": { + "description": "Official or long name, when known.", + "type": [ + "string", + "null" + ] + }, + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + }, + "type": { + "description": "\"national_team\" or \"club\".", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + }, + "type": "array" + }, + "hint": { + "description": "Present only when rows were left out: how to narrow the call.", + "type": "string" + }, + "returned": { + "description": "How many rows are in data.", + "type": "integer" + }, + "total": { + "description": "How many rows matched before the limit.", + "type": "integer" + } + }, + "required": [ + "data", + "total", + "returned" + ], + "type": "object" +}
- Changed
list_tournaments1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Competitions, or one competition's editions.", + "items": { + "description": "A competition, or with `tournament` given, one of its editions.", + "properties": { + "country": { + "description": "The country a team or competition belongs to.", + "properties": { + "fifa_code": { + "description": "Three-letter FIFA code.", + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id" + ], + "type": [ + "object", + "null" + ] + }, + "draw_percent": { + "type": [ + "number", + "null" + ] + }, + "draws_count": { + "type": [ + "integer", + "null" + ] + }, + "id": { + "type": "integer" + }, + "matches_count": { + "type": [ + "integer", + "null" + ] + }, + "name": { + "type": "string" + }, + "slug": { + "type": [ + "string", + "null" + ] + }, + "type": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "name" + ], + "type": "object" + }, + "type": "array" + }, + "hint": { + "description": "Present only when rows were left out: how to narrow the call.", + "type": "string" + }, + "returned": { + "description": "How many rows are in data.", + "type": "integer" + }, + "total": { + "description": "How many rows matched before the limit.", + "type": "integer" + } + }, + "required": [ + "data", + "total", + "returned" + ], + "type": "object" +}
- Changed
predict_draws1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Teams ranked by how overdue a draw is, most overdue first.", + "items": { + "description": "A ranked team.", + "properties": { + "last_match_date": { + "description": "Date of the team's most recent match.", + "type": [ + "string", + "null" + ] + }, + "rank": { + "description": "Position in the ranking; 1 is the most overdue.", + "type": "integer" + }, + "score": { + "description": "The draw-likelihood score the ranking sorts on.", + "type": "number" + }, + "signals": { + "description": "The figures the score is built from.", + "properties": { + "current_no_draw_streak": { + "description": "Matches since the last draw.", + "type": [ + "integer", + "null" + ] + }, + "draw_debt": { + "description": "Draws expected from the draw rate minus draws that came.", + "type": [ + "number", + "null" + ] + }, + "draw_pct": { + "description": "Share of matches drawn, in percent.", + "type": [ + "number", + "null" + ] + }, + "draws": { + "type": "integer" + }, + "max_no_draw_streak": { + "description": "Longest run without a draw, ever.", + "type": [ + "integer", + "null" + ] + }, + "played": { + "type": "integer" + } + }, + "type": "object" + }, + "team": { + "description": "A team.", + "properties": { + "country": { + "description": "The country a team or competition belongs to.", + "properties": { + "fifa_code": { + "description": "Three-letter FIFA code.", + "type": [ + "string", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id" + ], + "type": [ + "object", + "null" + ] + }, + "exists_now": { + "description": "False for a team that no longer exists.", + "type": "boolean" + }, + "full_name": { + "description": "Official or long name, when known.", + "type": [ + "string", + "null" + ] + }, + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + }, + "type": { + "description": "\"national_team\" or \"club\".", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + } + }, + "required": [ + "rank", + "score" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "data" + ], + "type": "object" +}
- Changed
search_results1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "Matches, newest first.", + "items": { + "description": "A match.", + "properties": { + "away_team": { + "description": "A team reference.", + "properties": { + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + }, + "competition": { + "description": "The competition and edition the match belongs to.", + "properties": { + "edition": { + "type": [ + "string", + "null" + ] + }, + "edition_id": { + "description": "The season or edition id, from list_tournaments.", + "type": [ + "integer", + "null" + ] + }, + "id": { + "type": "integer" + }, + "name": { + "type": [ + "string", + "null" + ] + }, + "year": { + "type": [ + "integer", + "null" + ] + } + }, + "type": [ + "object", + "null" + ] + }, + "date": { + "description": "Match date, YYYY-MM-DD.", + "type": "string" + }, + "home_team": { + "description": "A team reference.", + "properties": { + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + }, + "id": { + "description": "Match id, as get_draw_model takes it.", + "type": "integer" + }, + "is_draw": { + "description": "Whether the match ended level.", + "type": "boolean" + }, + "result": { + "description": "H home win, A away win, D draw; empty until played.", + "type": [ + "string", + "null" + ] + }, + "score": { + "description": "Final score; both null until the match is played.", + "properties": { + "away": { + "type": [ + "integer", + "null" + ] + }, + "home": { + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "status": { + "description": "PLAYED, SCHEDULED, POSTPONED and so on.", + "type": "string" + } + }, + "required": [ + "id", + "date" + ], + "type": "object" + }, + "type": "array" + }, + "links": { + "description": "first/last/prev/next page URLs on the REST API.", + "type": "object" + }, + "meta": { + "description": "Pagination: which page this is and how many rows exist.", + "properties": { + "current_page": { + "type": "integer" + }, + "last_page": { + "type": "integer" + }, + "per_page": { + "type": "integer" + }, + "total": { + "description": "Rows across every page.", + "type": "integer" + } + }, + "type": "object" + } + }, + "required": [ + "data" + ], + "type": "object" +}
- Changed
top_streaks1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "data": { + "description": "The longest no-draw runs, longest first.", + "items": { + "description": "A run of matches without a draw, and whose it was.", + "properties": { + "end": { + "type": [ + "string", + "null" + ] + }, + "end_match_id": { + "type": [ + "integer", + "null" + ] + }, + "id": { + "type": "integer" + }, + "length": { + "description": "Matches in the run without a draw.", + "type": "integer" + }, + "start": { + "type": [ + "string", + "null" + ] + }, + "start_match_id": { + "type": [ + "integer", + "null" + ] + }, + "team": { + "description": "A team reference.", + "properties": { + "id": { + "description": "Team id — the argument every team tool takes.", + "type": "integer" + }, + "name": { + "description": "Short display name.", + "type": "string" + }, + "slug": { + "description": "URL slug; accepted anywhere an id is.", + "type": "string" + } + }, + "required": [ + "id", + "slug", + "name" + ], + "type": "object" + } + }, + "required": [ + "id", + "length" + ], + "type": "object" + }, + "type": "array" + }, + "links": { + "description": "first/last/prev/next page URLs on the REST API.", + "type": "object" + }, + "meta": { + "description": "Pagination: which page this is and how many rows exist.", + "properties": { + "current_page": { + "type": "integer" + }, + "last_page": { + "type": "integer" + }, + "per_page": { + "type": "integer" + }, + "total": { + "description": "Rows across every page.", + "type": "integer" + } + }, + "type": "object" + } + }, + "required": [ + "data" + ], + "type": "object" +}
11 tool updates
- First observed
get_draw_model - First observed
get_team - First observed
get_team_prediction - First observed
get_team_streaks - First observed
head_to_head - First observed
list_countries - First observed
list_teams - First observed
list_tournaments - First observed
predict_draws - First observed
search_results - First observed
top_streaks
Related MCP Connectors
Football fixtures, standings, and odds intelligence for AI agents.
NFL/NBA/MLB/NHL/PGA + DFS and prediction-market data. Browse free; query with a free API key.
Live X/Twitter data: profiles, tweets, search, followers, lists and trends. 29 read-only tools.
API-Football MCP — comprehensive soccer/football data
Related MCP Servers
- 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
- AlicenseAqualityBmaintenanceProvides read-only access to pre-kick-off football match outcome probabilities and the open record of how those predictions turned out, including match listings, per-match analysis, and aggregate hit rates with baselines. It requires no account or API key and lets users query results by date, week, language, and time zone.3MIT
- AlicenseAqualityBmaintenanceEnables AI assistants to query live football data, including fixtures, live scores, standings, statistics, betting odds, and full odds movement history for corner and card lines.1135 npmMIT
- FlicenseNot gradedqualityBmaintenanceEnables access to and analysis of a curated historical football database covering 37,000 matches across European competitions, with tools for team/player search, match details, form, head-to-head, comparisons, and match prediction.-
Glama MCP Gateway
Add one secure layer between your agents and this server.