Skip to main content
Glama
livetennisapi

livetennisapi-mcp

livetennisapi-mcp

MCP server for the Live Tennis API.

Give Claude, Cursor, Zed or any MCP client live tennis scores, players and fixtures — for ATP, WTA, Challenger, ITF and juniors. Odds, rankings, match statistics, charting and model win-probability tools are included, and require the PRO and ULTRA plans.

CI npm license

Documentation · Get a free API key


Setup

Claude Code

claude mcp add livetennis -e LIVETENNISAPI_KEY=twjp_… -- npx -y livetennisapi-mcp

Claude Desktop — add to claude_desktop_config.json:

{
  "mcpServers": {
    "livetennis": {
      "command": "npx",
      "args": ["-y", "livetennisapi-mcp"],
      "env": { "LIVETENNISAPI_KEY": "twjp_…" }
    }
  }
}

Cursor / Zed / others — same command, same env var. No install step; npx fetches it on demand.

Get a free key (no card) at livetennisapi.com, or a paid plan at pricing.

Related MCP server: SportScore

Try it

"What tennis matches are live right now?" "Who's winning the Alcaraz match, and what does the model give him?" "Show me Sinner's ranking and recent results." "What are the current odds on match 18953?" "What's the all-time head-to-head between Borg and McEnroe?" "List Navratilova's Grand Slam finals from the archive." "Who was ATP #1 the week Alcaraz first entered the top 10?" "How is Sabalenka serving in her live match — aces, hold rate, break points?"

Tools

Tool

Does

Plan

get_live_matches

Matches in progress, with live scores

FREE

get_upcoming_matches

Matches starting soon

FREE

get_match

Full detail for one match

FREE

get_match_score

Current score only — the smallest payload

FREE

search_players

Find players by name

FREE

get_player

Profile, ranking, country, handedness

FREE

get_fixtures

Forward schedule

FREE

search_tournaments

Tournament catalogue — surface, location, category

FREE

get_tournament

One tournament by its stable id

FREE

get_recent_results

Completed matches and winners

BASIC

search_archive_matches

Results archive (1968–2022) — historical results with ranks and seeds at the time

BASIC

get_archive_match

One archive result, with serve stats where the era recorded them

BASIC

search_archive_players

Archive bios — hand, DOB, career-high rank

BASIC

get_archive_career

Career W-L, titles and serve aggregates over the archive

BASIC

get_h2h

Cross-era head-to-head — archive + current, one record

BASIC

get_match_events

Breaks, games, sets, momentum runs

PRO

get_match_odds

Match-winner prices — bid / ask / mid

PRO

get_rankings

Full published ranking table per system (ATP, WTA, ITF circuits), any week

PRO

get_player_rankings

Point-in-time ranking records for specific players, as of any date

ULTRA

get_match_statistics

In-play statistics — aces, serve split, hold/break %, break points

ULTRA

get_charting_player

Career shot-level profile from the Match Charting Project

ULTRA

get_charting_match

One charted match, every stat family, per-set split

ULTRA

get_match_analysis

Model thesis, win probability, key factors

ULTRA

check_api_status

Reachability + which plan your key is on

The six BASIC history tools are also unlocked by any History plan, which works on top of a free key. The results archive (1968–2022) — ATP and WTA, main draws, qualifying and the ITF/futures tiers — ends exactly where our own results begin (2023), so search_archive_matches answers "Borg's Wimbledon finals" and get_recent_results answers "yesterday's scores"; get_h2h spans both in one call.

Tier awareness

The API gates endpoints by plan and returns a bare 403 {"error":"upgrade_required"}. Handed that, a model will usually invent a reason or retry pointlessly.

So every tool that can hit a tier wall returns a plain-English explanation — as a normal result, not an error — naming the tier required and where to upgrade. The assistant can then tell you something true and actionable:

This data requires the ULTRA plan, and the configured API key is on a lower tier. Nothing is wrong with the key — the endpoint is simply not included in the current plan. Upgrade in place at https://livetennisapi.com/subscribe/upgrade

check_api_status probes upward to report which plan your key is actually on, so you can diagnose that without guessing.

Plans

FREE

BASIC

PRO

ULTRA

Matches, scores, players, fixtures, tournaments

Completed-match listings (results)¹

Results archive (1968–2022) + head-to-head¹

Match events, odds + rankings listing

Model analysis, as-of rankings, match statistics + charting

$0 — no card

$9.99/mo

$29.99/mo

$99.99/mo

¹ Also unlocked by any History plan, which works on top of a free key.

Request quotas

FREE

BASIC

PRO

ULTRA

Requests per minute

30

60

300

600

Requests per day

100

1,000

10,000

500,000

FREE is 100 requests/day, so poll no faster than every 15 minutes on a free key; for an always-on dashboard, BASIC is the plan to recommend. Every response carries X-RateLimit-Limit / -Remaining / -Reset headers, and the tools relay the three distinct 429 shapes honestly — per-minute (retry shortly), daily cap (the error names the exact reset instant), and the abuse block (don't retry; fix the loop).

Hosted endpoint

Most people should use the stdio server above — your key never leaves your machine. For clients that can only speak HTTP, there is also a hosted Streamable-HTTP endpoint:

https://mcp.livetennisapi.com/mcp

Send your key as Authorization: Bearer twjp_…, X-API-Key: twjp_…, or ?token= if your client cannot set headers. Tools are listable without a key, so directories can introspect the server; calling one needs a key.

It is multi-tenant and holds no key of its own: every request builds its own server bound to the key that request presented, and there is deliberately no fallback to the host's environment. The endpoint applies its own transport-level limit per caller — 60 req/min anonymous, 300 keyed. That limit only protects this host process; it is not your API quota, which is enforced upstream per key and tier (see the quota table above).

Self-hosting it: deploy/install-http.sh and deploy/TUNNEL.md.

Use with Claude

As a connector. In Claude, add a custom connector and paste the endpoint with your key as a query parameter — no OAuth, nothing to install:

https://mcp.livetennisapi.com/mcp?token=twjp_…

?token= exists for clients that cannot set request headers. The tradeoff, stated plainly: a key in a URL is not written to our logs, but it is visible to the CDN in front of the endpoint and is stored in the connector's configuration. Prefer Authorization: Bearer twjp_… wherever your client lets you set a header.

From the Messages API. Claude can call the endpoint directly. Both halves are required — the server and a matching toolset entry; sending mcp_servers alone is rejected as a validation error:

client.beta.messages.create(
    model="claude-opus-4-8",
    max_tokens=4096,
    betas=["mcp-client-2025-11-20"],
    mcp_servers=[{
        "type": "url",
        "name": "livetennisapi",
        "url": "https://mcp.livetennisapi.com/mcp",
        "authorization_token": os.environ["LIVETENNISAPI_KEY"],
    }],
    tools=[{"type": "mcp_toolset", "mcp_server_name": "livetennisapi"}],
    messages=[{"role": "user", "content": "What tennis is live right now?"}],
)

The authorization_token is sent as a bearer token, which is exactly what this server already accepts — no separate credential to obtain.

Use with Codex

One command:

codex mcp add livetennisapi \
  --url https://mcp.livetennisapi.com/mcp \
  --bearer-token-env-var LIVETENNISAPI_KEY

Or write it to ~/.codex/config.toml yourself — Codex shares that file across the CLI, the IDE extension and the desktop app:

[mcp_servers.livetennisapi]
url = "https://mcp.livetennisapi.com/mcp"
bearer_token_env_var = "LIVETENNISAPI_KEY"

Use bearer_token_env_var, not bearer_token: it keeps the key in your environment rather than committing it to a config file.

There is also a Codex plugin, on its own marketplace:

codex plugin marketplace add livetennisapi/livetennisapi-codex-plugin

That registers the marketplace; install the plugin from Codex's plugin picker. Source: livetennisapi-codex-plugin.

The stdio route works too, unchanged: npx -y livetennisapi-mcp.

Bundled skill: Polymarket / Kalshi tennis trading data

The Claude Code plugin (.claude-plugin/plugin.json) also ships the polymarket-tennis Agent Skill under skills/polymarket-tennis/. It teaches Claude the observe-only polymarket-tennis Python package (market discovery, market-to-match matching, joined price/live-score view), the free-tier budget (30 req/min, 100 requests/day), and the verbatim retirement/walkover settlement rules for Polymarket, Polymarket US and Kalshi. Canonical copy lives in the polymarket-tennis repo; this one is mirrored for plugin installs. No order execution, ever.

Notes

  • Read-only. Every tool is a GET; nothing here can modify anything.

  • Your key stays local with the stdio server. It is read from the environment by the server process on your machine and sent only to api.livetennisapi.com.

  • Requires Node 20+.

Development

npm install
npm run build
LIVETENNISAPI_KEY=twjp_… node dist/index.js   # speaks MCP over stdio
node dist/http.js                             # speaks MCP over HTTP, port 8081

npm test               # protocol + transport isolation + rate limiting
npm run test:mutation  # proves those tests fail when the code breaks

test:mutation is worth understanding before changing src/http.ts. It reintroduces each bug the tests claim to catch and asserts the suite goes red. It is not ceremony: the first version of the rate-limit test passed while the limiter was bucketing every caller together.

Built on the official livetennisapi client.

Everything in the Live Tennis API developer surface:

Install

Source

Package

Python client

pip install livetennisapi

repo

package

JavaScript / TypeScript client

npm install livetennisapi

repo

package

MCP server for LLM agents (this repo)

npx livetennisapi-mcp

package

Vercel AI SDK tools

npm install livetennisapi-ai

repo

Break-point starter — Python

repo

Break-point starter — Node

repo

Break-point starter — Go

repo

Affiliate program

Know developers who need tennis data? The affiliate program pays 51% recurring commission for the life of every referred subscription — 30-day cookie, and the people you refer get 10% off.

Licence

MIT — see LICENSE. Use of the API service is governed by the Terms of Service.

Available Tools

24 tools
check_api_statusAPI status and planA
Read-onlyIdempotent
Inspect

Check whether the Live Tennis API is reachable and which plan the configured key is on. Useful for diagnosing why other tools are refusing data.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
tierNoDetected plan: FREE, BASIC, PRO or ULTRA. Null when no key is configured.
has_keyNoWhether a key was supplied with this call.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
reachableNoTrue when the API answered its health check.
api_versionNoAPI version reported by the health check.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate the tool is read-only, idempotent, and non-destructive. The description adds behavioral detail by specifying it checks both reachability and plan, providing valuable context 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences: the first states the core action, the second provides usage context. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple diagnostic tool with no parameters and an output schema available, the description fully covers purpose and usage context, making it complete for selecting and invoking the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has no parameters, and schema coverage is 100%. Per guidelines, baseline is 4; the description does not add parameter semantics but none are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool checks API reachability and plan. This distinguishes it from sibling data-retrieval tools like get_fixtures or get_live_matches, which focus on specific data rather than API status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states the tool is 'useful for diagnosing why other tools are refusing data', providing clear context for when to use it and implying alternatives (sibling tools) for normal data retrieval.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_archive_careerArchive career aggregatesA
Read-onlyIdempotent
Inspect

One player's whole career over the results archive (1968–2022): W-L record overall and by surface/level/year, titles, and summed serve statistics with honest coverage — the corpus records serve stats from 1991 only, so matches_with_stats states how many matches the serve block covers. The name must resolve to one person; an ambiguous fragment returns the candidate list to choose from. Requires the BASIC plan or any History plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesPlayer name fragment, min 3 chars — must resolve to exactly one person.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
spanNoCareer span inside the archive.
serveNoSummed serve stats + derived ratios. matches_with_stats states the coverage; ratios are null where the denominator is zero.
recordNoThe W-L record.
by_yearNoPer-season W-L.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
player_nameNoThe resolved player.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnly, openWorld, idempotent), the description discloses an important data caveat: serve stats are only recorded from 1991 and matches_with_stats indicates coverage. It also explains the ambiguity resolution behavior. This is valuable added context, though not exhaustive in terms of pagination or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured, with a clear front-loaded purpose followed by necessary caveats and requirements. Every clause contributes useful information with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a single parameter, rich annotations, and an output schema, the description fully covers key usage rules, data limitations, and disambiguation behavior. It does not need to explain return values because the output schema is present. No significant gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already fully documents the 'name' parameter with type, minLength, and a description. The tool description reinforces the resolution requirement and explains that an ambiguous fragment returns a candidate list, providing context beyond the schema. This justifies a score above the baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns a single player's entire career over the results archive (1968–2022), including W-L record, titles, and serve statistics. This scope distinguishes it from sibling tools like get_archive_match or get_player, making the purpose highly specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides clear context on when to use the tool (for full career archive aggregates) and includes explicit requirements: the name must resolve to exactly one person, and a plan is required. However, it does not explicitly name alternative tools or state when not to use this tool, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_archive_matchArchive result detailA
Read-onlyIdempotent
Inspect

One result from the results archive (1968–2022), with per-match serve statistics where the era recorded them — stats are null for most rows before 1991, honestly, never synthesised. Requires the BASIC plan or any History plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
archive_match_idYesArchive match id, as returned by search_archive_matches.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
statsNoPer-match serve statistics (aces, double_faults, serve_points, first_in, first_won, second_won, serve_games, bp_saved, bp_faced). Null for most pre-1991 rows.
resultNoThe archive result.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes beyond annotations by disclosing that serve stats are null for most pre-1991 rows and that data is never synthesized. Also states the access plan requirement. Annotations already indicate read-only/idempotent, so the description adds honest data-quality context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core purpose, and each clause adds value (time range, stats caveat, plan). No fluff, despite the informal 'honestly' which conveys transparency rather than redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter retrieval tool, the description covers the key caveat (null stats before 1991) and access requirement. Output schema exists and handles return format, so no further detail is needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description does not add meaning beyond the input schema, which already fully describes archive_match_id including its source. With 100% schema coverage, baseline 3 is appropriate; no additional parameter nuance is provided.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the tool retrieves a single archived result (1968–2022) with serve statistics, distinguishing it from siblings like get_match (likely live) and search_archive_matches (search). The verb 'get' and specific resource 'archive result' are explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies use for archive results and specifies plan requirements, but does not explicitly contrast with siblings or state when not to use. The archive context and plan condition provide practical guidance, though exclusions are absent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_charting_matchCharting: one match, every stat familyA
Read-onlyIdempotent
Inspect

Every Match Charting Project stat family for ONE charted match, both players, with the per-set split (set 1, set 2, …, Total) exactly as charted. Charting ids are their own id space (1960–2026), mostly matches with no counterpart in the live tables. Requires the ULTRA plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
charting_match_idYesCharting match id — its own id space, not a match_id.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
genderNo
mcp_idNoThe Match Charting Project's own row identifier.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
playersNoBoth players as charted.
familiesNoEvery stat family, per player, with the per-set split.
charting_match_idNoThe charted match.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the tool as read-only and idempotent. The description adds valuable context: the per-set split is 'exactly as charted' (no processing), and the ULTRA plan requirement is disclosed. This supplements the annotations 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with the core function first, followed by two important clarifications. Every sentence earns its place, with no redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter retrieval tool with an output schema, the description covers scope, ID semantics, and access requirements. The output schema handles return-value details, so no further elaboration is needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents charting_match_id well, and the description reinforces its meaning by clarifying that charting IDs are a separate ID space from match_id. This adds practical guidance beyond the field description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: it returns every Match Charting Project stat family for one charted match, including both players and per-set splits. It distinguishes from sibling tools by explicitly noting charting IDs are their own ID space with no live-table counterpart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The context is clear: use this when you need charting data for a single match, especially when the match has no live-table equivalent. It does not explicitly name alternative tools, but the ID-space distinction and 'ULTRA plan' requirement effectively guide selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_charting_playerCharting: player career profileA
Read-onlyIdempotent
Inspect

Career shot-level profile from the Match Charting Project: serve placement (deuce/ad × wide/body/T), return depth and outcomes, net play, clutch break/game/set-point serving, winners and errors by wing, rally-length tendencies — summed over the player's charted matches. COVERAGE IS CURATED (11,646 charted matches back to the 1960s, concentrated on the majors), not full-slate. An ambiguous name returns the candidates to choose from. Requires the ULTRA plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesPlayer name fragment, min 3 chars — must resolve to one charted person.
genderNoDisambiguates a name charted on both tours.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
playerNoThe resolved charted player.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
coverageNoA reminder that charting coverage is curated, not full-slate.
familiesNoPer-family summed numeric columns — raw sums over the player's charted Total rows.
matches_chartedNoThe sample every summed field covers.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations, the description discloses that coverage is curated (11,646 matches, concentrated on majors) and that ambiguous names return candidate choices. It also notes the ULTRA plan requirement. These are non-obvious behavioral traits that help set expectations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is information-dense but well-organized, front-loaded with the core purpose. The metric list is exhaustive yet each item adds value, and the coverage and plan notes are clearly highlighted. No fluff or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity and that an output schema exists, the description covers the data source, coverage scope, ambiguity handling, and plan requirement. It gives enough context for an agent to know when to expect partial data and what inputs are needed. No significant gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema descriptions already cover both parameters well (100% coverage). The description adds the behavior that an ambiguous name returns candidates, clarifying how the name parameter resolution works beyond the schema's 'must resolve to one charted person'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it provides a 'career shot-level profile from the Match Charting Project' listing specific metrics (serve placement, return depth, net play, etc.), which distinguishes it from siblings like get_charting_match (match-level) and get_player (general profile). The scope is explicit: summed over charted matches.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use this tool (for aggregated career charting stats) and notes prerequisites like 'Requires the ULTRA plan' and the ambiguous-name behavior. However, it does not explicitly mention alternatives or exclusions, such as 'for a single match use get_charting_match'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_fixturesFixture scheduleB
Read-onlyIdempotent
Inspect

Upcoming scheduled tennis fixtures, earliest first — the forward schedule, filterable by tour, player and date. Use this for "what is on this week". Works on the FREE plan (no card needed).

ParametersJSON Schema
NameRequiredDescriptionDefault
tourNoTour filter; each name covers its doubles variants. Exhibition/team events carry no tour and are excluded whenever the filter is used.
limitNoMaximum fixtures to return (1-200).

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
fixturesNoScheduled fixtures, earliest first.

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds behavioral context beyond the annotations by stating the ordering (earliest first), the forward-looking scope, and the free-plan availability, complementing the read-only, idempotent, non-destructive hints. However, it falsely claims filterability by player and date when the schema only accepts tour and limit, which undermines accurate behavior disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the core purpose, with the use case and access note following efficiently. Minor redundancy ('the forward schedule' restates 'upcoming') and the inaccurate filter phrase prevent a perfect score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The input schema fully documents the two parameters and an output schema exists, so parameter semantics and return format are covered. The description supplies ordering and access context but lacks differentiation from the overlapping sibling get_upcoming_matches and includes an unsupported filter claim, leaving an agent with a notable gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline would be 3 even without additional parameter info in the description. But the description actively misrepresents the parameter surface by claiming player and date filters that do not exist in the schema; only tour and limit are supported. This misleading information makes the description counterproductive for parameter understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the tool returns upcoming scheduled tennis fixtures in chronological order ('earliest first'), clearly identifying a forward-looking read operation. However, it claims filtering by player and date, which the schema does not support, and it does not differentiate from the similarly named sibling get_upcoming_matches.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives an explicit use case ('what is on this week') and notes that it works on the free plan with no card needed, which is useful access guidance. It does not mention alternatives or exclusion conditions, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_h2hHead-to-headA
Read-onlyIdempotent
Inspect

The all-time record between two players, across BOTH halves of the product: the results archive (1968–2022) plus our own completed matches (2023 onward). Names are the keys — an ambiguous fragment returns the candidate list to choose from rather than guessing. Totals count only meetings with a known winner; walkovers and retirements are part of the record and each meeting carries its outcome. Requires the BASIC plan or any History plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
player1YesFirst player name (fragment, min 3 chars), e.g. "federer".
player2YesSecond player name (fragment, min 3 chars), e.g. "nadal".

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
totalsNoThe headline record.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
playersNoThe resolved names; null when no player matches the fragments.
meetingsNoIndividual meetings, newest first, capped at 200.
by_surfaceNoDecided wins per surface; keys are surface names plus "unknown".

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly/idempotent annotations, the description discloses critical behavioral details: ambiguous fragments return a candidate list, totals exclude matches without a known winner, walkovers/retirements are included, and each meeting carries an outcome. Also states plan requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each conveying essential information with no redundancy. The main purpose is front-loaded, followed by input behavior, counting rules, and access requirements. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has only two parameters, an output schema, and strong annotations. The description covers purpose, scope, edge cases, counting semantics, and access requirements, making it complete for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already fully documents both parameters with examples. The description adds value by explaining that names are keys and that ambiguous fragments trigger a candidate list, enriching the semantic understanding beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: retrieving the all-time head-to-head record between two players across both the archive (1968–2022) and completed matches (2023 onward). This specific verb+resource+scope distinguishes it from sibling tools like get_archive_career or get_match.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear context on when to use (for head-to-head records) and how input works (fragments, ambiguity handling). It doesn't explicitly name exclusions or alternatives, but no sibling tool serves the same purpose, so the guidance is strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_live_matchesLive matchesA
Read-onlyIdempotent
Inspect

List tennis matches currently in progress, with live scores. Covers ATP, WTA, Challenger, ITF and juniors. Use this for "what tennis is on right now". Works on the FREE plan (no card needed).

ParametersJSON Schema
NameRequiredDescriptionDefault
tourNoTour filter; each name covers its doubles variants. Exhibition/team events carry no tour and are excluded whenever the filter is used.
limitNoMaximum matches to return (1-200).
playerNoPlayer ids (from search_players), max 50 — keeps matches where ANY listed player is either participant.
countryNoEither participant's country — the lowercase 3-letter IOC-style code the Player object returns (e.g. ned, sui, gre), NOT ISO-3166. Players with no recorded country never match.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
matchesNoThe live matches, most relevant first.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry the safety profile (readOnlyHint, idempotentHint, destructiveHint, openWorldHint), and the description adds genuinely useful context beyond them: coverage scope, live-score return content, and notably the FREE-plan access constraint ('no card needed'), which is a real-world entitlement signal annotations do not express. The statement 'currently in progress' aligns with and reinforces openWorldHint without contradicting it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, each earning its place: what it does, what it covers, when to use it, and cost-of-use. The core verb+resource is front-loaded, and there is zero filler or schema repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given rich annotations, a fully self-documenting input schema, and an existing output schema (so return values need no explanation), the description is near-complete: purpose, tour scope, use case, and pricing are all covered. The only minor omission is explicit routing to sibling tools for non-live needs, which is a usage-guidelines nicety rather than a blocking gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all four parameters including the tour enum, limit bounds, player id array, and the IOC-vs-ISO country-code nuance. Per baseline, the description need not repeat parameter detail, and it doesn't — no added param semantics, but none required.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

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 — 'List tennis matches currently in progress, with live scores' — and pins the scope to five named tour levels (ATP, WTA, Challenger, ITF, juniors). It clearly reads as the live variant next to siblings like get_upcoming_matches, get_recent_results, and get_archive_match, so an agent can distinguish it without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use this for "what tennis is on right now"' is an explicit use-case statement that tells the agent when to invoke the tool. It provides clear context, though it stops short of naming alternatives or stating when-not-to-use (e.g., upcoming fixtures or finished matches belong elsewhere).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_matchMatch detailA
Read-onlyIdempotent
Inspect

Full detail for one match by id: players, score, surface, round and status. Includes market prices on PRO and model analysis on ULTRA. Works on the FREE plan (no card needed).

ParametersJSON Schema
NameRequiredDescriptionDefault
match_idYesMatch id, as returned by get_live_matches, get_upcoming_matches or get_recent_results.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
matchNoThe match.
marketNoMatch-winner market. Requires the PRO plan; absent otherwise.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
analysisNoModel analysis. Requires the ULTRA plan; absent otherwise.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint false, so the description correctly avoids repeating that. It adds valuable context about plan tiers: market prices are only on PRO and model analysis on ULTRA, and it works on the FREE plan without a card. This goes beyond the annotations by disclosing access-level limitations and feature availability, which is helpful for an agent deciding whether this tool meets the user's needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences, with the core purpose and contents front-loaded in the first sentence. The second sentence adds plan-tier information without unnecessary detail. Every word earns its place, making it highly efficient and easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (one parameter) and the presence of an output schema, the description does not need to explain return format. It covers the core behavior and plan limitations. It could be slightly more complete by explicitly mentioning alternatives or edge cases, but overall it provides sufficient context for an agent to call the tool correctly and understand what it returns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema fully documents the single parameter match_id, including its type and source (from other match-listing endpoints). The description adds no additional parameter guidance, but with 100% schema coverage, that is acceptable per the baseline of 3. No extra semantics are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves full detail for one match by id, listing the specific fields included (players, score, surface, round, status). This differentiates it from sibling tools like get_match_score or get_match_events, which focus on narrower aspects, so an agent can easily identify this as the comprehensive match lookup.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when full match detail is needed, but it does not explicitly contrast with alternatives such as get_match_score or get_match_events, nor does it state when not to use this tool. There is no guidance on choosing between this and the many specific match-related siblings, leaving the agent to infer the appropriate context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_match_analysisModel analysisA
Read-onlyIdempotent
Inspect

Model analysis for a match: predicted win probability, the model's thesis and the key factors behind it. Requires the ULTRA plan. Match rows carry has_analysis — check it first; a match with no thesis or profile has nothing to return.

ParametersJSON Schema
NameRequiredDescriptionDefault
match_idYesMatch id, as returned by get_live_matches, get_upcoming_matches or get_recent_results.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
thesisNoNarrative view.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
profileNoQuantitative view.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only and idempotent behavior. The description adds meaningful behavioral context beyond the annotations: the ULTRA plan requirement and the empty-result condition when has_analysis is false. This helps the agent avoid unnecessary calls.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The core purpose is front-loaded, followed by access requirements and an actionable precondition. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only, single-parameter tool with a full input schema and an output schema, the description covers all non-obvious context: plan requirement, the has_analysis prerequisite, and the empty-result case. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the only parameter, match_id, is already fully described with source endpoints. The description adds no new parameter-level detail, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states a specific verb/resource ('Model analysis for a match') and lists concrete contents: predicted win probability, model's thesis, and key factors. This clearly distinguishes it from sibling tools like get_match_odds or get_match_statistics, even without naming them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context and a strong precondition: 'Requires the ULTRA plan' and 'Match rows carry has_analysis — check it first.' It also implies when not to call ('a match with no thesis or profile has nothing to return'). It does not explicitly name alternative tools, but the usage boundary is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_match_eventsMatch timelineA
Read-onlyIdempotent
Inspect

Timeline of events for a match — breaks, games won, sets won, momentum runs. Requires the PRO plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum events to return (1-200).
match_idYesMatch id, as returned by get_live_matches, get_upcoming_matches or get_recent_results.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
eventsNoEvents in chronological order.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark it as read-only, idempotent, and non-destructive. The description adds that it requires the PRO plan, an access constraint not covered by annotations. It also clarifies the event categories, but doesn't discuss ordering or pagination behavior beyond what the schema's limit parameter implies.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single concise sentence with an added access constraint, immediately front-loading the tool's purpose. No redundant words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be described. The description covers the event types and the PRO plan requirement; combined with parameter descriptions and annotations, the tool is fully contextualized for a straightforward read-only operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema contains descriptions for both parameters (100% coverage), so the description adds no additional semantic value for match_id or limit. The baseline score of 3 applies as the schema sufficiently documents parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool provides a timeline of events for a match, listing specific event types (breaks, games won, sets won, momentum runs). This differentiates it from sibling tools like get_match or get_match_score, which likely provide summary or score data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides context that this tool is for timeline events, but does not explicitly instruct when to use it over alternatives. There is no mention of when not to use it or which sibling tool to choose for other needs, so guidance is implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_match_oddsMatch market pricesA
Read-onlyIdempotent
Inspect

Match-winner market prices for a match — implied probability per player, with bid, ask and mid. Requires the PRO plan. Match rows carry has_market — check it first; a match with no market mapped has no prices to return.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum price points to return (1-200).
match_idYesMatch id, as returned by get_live_matches, get_upcoming_matches or get_recent_results.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
marketNoThe match-winner market.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive behavior, so the description correctly adds context beyond them: the PRO plan requirement and the empty-result behavior when no market is mapped. This gives the agent practical expectations 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two dense sentences with no filler. The core purpose is front-loaded, followed by the most important usage caveats, making every sentence valuable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only lookup with a rich output schema, the description covers prerequisites (PRO plan), preconditions (has_market), and empty-result behavior. Nothing essential is missing for an agent to call and interpret the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema covers both parameters fully (match_id and limit with bounds/default), so the description does not need to add parameter details. It contributes only indirectly by explaining the match-level has_market precondition, which is not a parameter semantic.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states exactly what the tool returns: match-winner market prices with implied probability per player and bid/ask/mid. This precise scope clearly distinguishes it from sibling tools like get_match_score or get_match_analysis, which cover different data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context for when to call the tool by requiring the PRO plan and instructing the agent to check has_market first. It does not explicitly name alternatives or exclusions, but the precondition guidance is enough to route correct usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_match_scoreMatch scoreA
Read-onlyIdempotent
Inspect

Current score for one match — the fastest, lowest-latency read. Use this when you only need the score and already know the match id. Works on the FREE plan (no card needed).

ParametersJSON Schema
NameRequiredDescriptionDefault
match_idYesMatch id, as returned by get_live_matches, get_upcoming_matches or get_recent_results.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
scoreNoThe current score.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, covering the safety profile. The description adds valuable behavioral context beyond that: it promises low latency ('fastest, lowest-latency read') and mentions the plan requirement (FREE plan, no card needed), which are not in annotations. This is meaningful addition without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences with no filler. The first sentence establishes the core purpose and a key differentiator (speed). The second provides the usage condition and a plan constraint. Everything earns its place, and the most critical info is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple single-parameter read with an output schema present, the description covers the essential context: what it does, when to use it, and a plan constraint. It doesn't mention edge cases (e.g., match not found, stale data), but these are typically not required for such a lightweight read and are likely handled by the API response schema. Slightly more detail about the response format could be added, but it's not critical given the output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides a thorough description for match_id, including valid sources. Schema description coverage is 100%, so the description adds no extra parameter semantics. It doesn't repeat or enhance the parameter documentation, which is acceptable given the schema's completeness. Baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb and resource: 'Current score for one match' – a specific read operation. It also distinguishes itself from siblings by highlighting 'fastest, lowest-latency read', implying it is the lightweight option compared to tools like get_match or get_match_events. This gives an agent a clear sense of what it does and how it differs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Use this when you only need the score and already know the match id', which provides a clear condition for selection. It also notes it works on the FREE plan, which is a practical constraint. It doesn't name alternative tools explicitly, but the 'only need the score' phrasing implicitly steers away from richer tools. This is strong guidance, though not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_match_statisticsMatch statisticsA
Read-onlyIdempotent
Inspect

In-play (or final) statistics for one match, in TWO families kept deliberately separate: DERIVED is rebuilt from the point-by-point record (holds/breaks, break points, service/return points); MEASURED is counted upstream and includes what no point record can yield — aces, double faults, the serve split, winners/unforced errors. Measured coverage varies by tour; absent fields are omitted, never zero-filled. Requires the ULTRA plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
match_idYesMatch id, as returned by get_live_matches, get_upcoming_matches or get_recent_results.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
statisticsNoThe statistics.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (read-only, open-world), the description discloses that measured statistics coverage varies by tour, absent fields are omitted rather than zero-filled, and the two families are deliberately kept separate. These are nuanced behavioral details not available from annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the core purpose. Each sentence contributes meaningful detail—families, coverage variance, omission behavior, and access requirement—with no redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

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 need not enumerate return fields. It covers the important contextual aspects: match scope, in-play/final status, data families, coverage variability, omission policy, and plan requirement, making it complete for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already fully documents the single match_id parameter with a description. The tool description adds no extra parameter semantics beyond confirming it applies to 'one match,' so it meets the baseline for full schema coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool provides statistics for one match and distinguishes the two data families (DERIVED vs MEASURED), making the resource and intent unambiguous relative to sibling tools like get_match_score or get_match_analysis.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use for retrieving match statistics and notes the ULTRA plan requirement, giving clear context. However, it doesn't explicitly state when not to use alternative tools, so it stops short of full alternatives guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_playerPlayer profileA
Read-onlyIdempotent
Inspect

One player's profile: ranking, country, handedness, date of birth and cached stats. Works on the FREE plan (no card needed).

ParametersJSON Schema
NameRequiredDescriptionDefault
player_idYesPlayer id, as returned by search_players.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
playerNoThe player.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the operation read-only, idempotent, and non-destructive. The description adds value beyond that by disclosing that stats are cached and that no payment card is needed on the FREE plan, which gives the agent useful behavioral and access context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences with no filler. The core purpose is front-loaded, and the additional FREE plan note is relevant and quickly actionable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple, single-parameter read-only tool with an output schema and rich annotations, the description is sufficient. It explains the profile contents, notes cached data, and clarifies plan availability, leaving no critical gap for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with player_id documented as returned by search_players. The tool description does not add extra parameter detail, so baseline 3 is appropriate since the schema carries the burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns one player's profile and lists specific fields (ranking, country, handedness, date of birth, cached stats). This distinguishes it from siblings like get_player_rankings or search_players, which serve different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for fetching a single player's profile and notes it works on the FREE plan, but it does not explicitly state when to use this over alternatives like search_players or get_player_rankings. The schema adds that player_id comes from search_players, providing some routing context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_player_rankingsPlayer rankings as of a dateA
Read-onlyIdempotent
Inspect

Point-in-time ranking records for SPECIFIC players: per system, the newest record in force ON OR BEFORE as_of — never one dated after it. Every other ranking field in this API is the CURRENT value joined at read time; this is the historical answer. Systems are never collapsed: ATP/WTA and the ITF circuits carry rank+points, UTR a rating. ITF and UTR history begins 2026-07-29. Requires the ULTRA plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
as_ofNoYYYY-MM-DD — the record in force on this date. Omit for the latest known.
systemNoRestrict to one system. Omit for every system held for the player.
player_idsYesRoster player ids, as returned by search_players. Max 50.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
coverageNoWhat resolved against what was asked (players_resolved, systems_resolved, oldest_available per system). Read before trusting an empty result.
rankingsNoOne record per player × system held.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint, idempotentHint), the description adds critical behavioral details: the 'never one dated after it' constraint, per-system semantics (rank+points vs rating), and the ITF/UTR history start date. This provides substantial context for expected behavior and data availability.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is four sentences, front-loaded with the core behavior, and every sentence provides unique value: historical nature, contrast with current data, system-specific behavior, and plan requirement. No redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the tool's purpose, key date logic, system variations, data history start, and access requirement. With an output schema present, the description does not need to explain return values, and it provides sufficient context for an agent to select and invoke this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

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 by clarifying the as_of semantics ('newest record in force ON OR BEFORE as_of — never one dated after it') and explaining system-specific differences, which enriches the parameter meaning beyond the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves point-in-time ranking records for specific players, scoped by system and as_of date. It explicitly contrasts with current rankings ('Every other ranking field in this API is the CURRENT value... this is the historical answer'), distinguishing it from sibling tools like get_rankings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies when to use this tool: when historical, point-in-time rankings for specific players are needed. It notes the historical nature and requirements (ULTRA plan), and implies alternatives for current data, but does not explicitly name alternative tools or state 'when not to use'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_rankingsRankings listingA
Read-onlyIdempotent
Inspect

The FULL published ranking table in rank order for one system — the newest week at or before as_of. Rows carry player_name as published and a null player_id for players outside our roster, so the table has no silent holes. ATP/WTA history runs deep; the ITF circuits begin 2026-07-29. For point-in-time records of SPECIFIC players use get_player_rankings. Requires the PRO plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
as_ofNoYYYY-MM-DD — serves the newest published week at or before this date. Omit for latest.
limitNoMaximum ranking rows to return (1-200).
systemYesRanking system to list. utr has no listing — it is a rating, not a ranking.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
rankingsNoThe table in rank order.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnly, openWorld, idempotent, non-destructive), the description reveals row-level behavior: 'player_name as published and a null player_id for players outside our roster, so the table has no silent holes.' It also discloses data depth (ATP/WTA deep history vs ITF start date) and PRO plan requirement. This is meaningful added context, though not every edge case is covered.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Five short sentences, each carrying distinct information: primary purpose, row behavior, data availability, alternative tool, access requirement. No filler or repetition. Front-loaded with the main action.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only listing tool with a well-described schema and output schema present, the description covers purpose, usage, alternatives, data caveats, row semantics, and access. Nothing critical is missing; the explicit alternative and PRO plan note make it fully contextual.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides 100% parameter descriptions, including the as_of semantics and system enum. The description doesn't add parameter details beyond what the schema contains, so baseline 3 is appropriate; no gaps to compensate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

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: 'The FULL published ranking table in rank order for one system' – clearly stating this tool lists complete rankings for a chosen system. It explicitly contrasts with get_player_rankings, distinguishing its scope as the full table rather than point-in-time records for specific players.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use guidance: 'For point-in-time records of SPECIFIC players use get_player_rankings' directly names the alternative. Also gives context on data availability (ITF circuits begin 2026-07-29) and access requirements ('Requires the PRO plan'), which helps the agent decide if the tool is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_recent_resultsRecent resultsA
Read-onlyIdempotent
Inspect

Recently completed tennis matches with final scores and winners. Filterable by tour, player, nationality and play date. Requires the BASIC plan or any History plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoLatest play date: YYYY-MM-DD or ISO-8601; must not precede from.
fromNoEarliest play date: YYYY-MM-DD (a whole UTC day) or ISO-8601 datetime.
tourNoTour filter; each name covers its doubles variants. Exhibition/team events carry no tour and are excluded whenever the filter is used.
limitNoMaximum matches to return (1-200).
playerNoPlayer ids (from search_players), max 50 — keeps matches where ANY listed player is either participant.
countryNoEither participant's country — the lowercase 3-letter IOC-style code the Player object returns (e.g. ned, sui, gre), NOT ISO-3166. Players with no recorded country never match.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
matchesNoCompleted matches, most recent first.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish the tool as read-only, open-world, idempotent, and non-destructive. The description adds useful behavioral context beyond annotations by disclosing the plan requirement and clarifying that results are final-score winners for completed matches. This gives agents a better sense of what to expect 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler. It front-loads the core purpose, then adds filter capability and the access requirement. Every sentence earns its place and the structure is easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is complete for this tool's complexity. The schema covers all parameter details, output schema exists so return structure need not be repeated, and annotations cover the safety profile. The description covers scope, result contents, filters, and plan requirement, leaving no critical gap for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already fully documents all six parameters, including formats, enum values, defaults, and limits. The description only restates high-level filter dimensions (tour, player, nationality, play date) without adding new parameter-level meaning. Baseline 3 is appropriate given the schema carries the detailed semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the resource as recently completed tennis matches with final scores and winners. Combined with the tool name, an agent immediately knows it returns a list of recent completed results. This naturally distinguishes it from live, upcoming, and archive match tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context: use this for recently completed matches that have final scores and winners, with optional filters. It also states the required BASIC or History plan, which is a useful access prerequisite. It does not explicitly name sibling alternatives like get_live_matches or get_upcoming_matches, but 'recently completed' strongly implies the boundary.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_tournamentTournament detailA
Read-onlyIdempotent
Inspect

One tournament by its stable id — the tournament_id carried on match objects. Name, tour, surface, indoor, plus host city/country and category where curated. Works on the FREE plan (no card needed).

ParametersJSON Schema
NameRequiredDescriptionDefault
tournament_idYesStable tournament id, as returned by search_tournaments or carried on a match as tournament_id.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
tournamentNoThe tournament.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, idempotent, and non-destructive behavior. The description adds useful context beyond that: 'Works on the FREE plan (no card needed)' and the data-quality nuance that some fields are included 'where curated.' This helps with access and expectations in a way annotations do not.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description uses three short sentences with the central purpose first, then return fields, then the plan note. It is efficient and front-loaded, though some of the field list could arguably be left to the output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With one well-specified parameter, clear source for the ID, plan info, and visible output schema, the description is complete enough for an agent to invoke the tool correctly. A small gap is that it does not describe the behavior when a tournament_id is missing or not found, but that is a minor omission.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% for the single parameter, so the description has no burden to document the parameter. It only repeats what the schema says ('stable tournament id', carried on match objects) without adding format, validation, or additional semantic detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description plainly states the verb ('stable id') and resource ('tournament'), explains where the ID comes from, and lists the fields returned, distinguishing it from sibling tools like search_tournaments. An agent can immediately understand this is a single-entity fetch, not a search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for when to use it: you have a stable tournament_id, e.g., from a match object. The input schema adds that the ID can also come from search_tournaments. It does not explicitly tell the agent to use search_tournaments instead when only a name is known, but the intended use is easily inferable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_upcoming_matchesUpcoming matchesA
Read-onlyIdempotent
Inspect

List tennis matches scheduled to start soon, with players, tournament and start time. Use this for "who plays next" or to find a match id before it starts. Works on the FREE plan (no card needed).

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoLatest play date: YYYY-MM-DD or ISO-8601; must not precede from.
fromNoEarliest play date: YYYY-MM-DD (a whole UTC day) or ISO-8601 datetime.
tourNoTour filter; each name covers its doubles variants. Exhibition/team events carry no tour and are excluded whenever the filter is used.
limitNoMaximum matches to return (1-200).
playerNoPlayer ids (from search_players), max 50 — keeps matches where ANY listed player is either participant.
countryNoEither participant's country — the lowercase 3-letter IOC-style code the Player object returns (e.g. ned, sui, gre), NOT ISO-3166. Players with no recorded country never match.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
matchesNoMatches due to start, soonest first.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish read-only, non-destructive, and idempotent behavior, so the description's burden is lighter. It adds useful context about the FREE plan eligibility and that results are 'soon'-based, but does not detail freshness, time-window defaults, or how 'soon' is bounded.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with no filler: the primary behavior is front-loaded, followed by concrete use cases and a plan-eligibility note. Every sentence contributes value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with a rich output schema and fully documented parameters, the description is near-complete. It could clarify the temporal meaning of 'soon' or the relationship to get_fixtures, but the available schema and annotations cover most operational needs.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all six parameters are already documented. The description does not add parameter-level semantics beyond what the schema provides, keeping it at the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List'), a clear resource ('tennis matches scheduled to start soon'), and the included information (players, tournament, start time). The stated use cases ('who plays next', 'find a match id before it starts') also situate it relative to the broader tool family, making its purpose distinct.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use this tool: for upcoming-match discovery and obtaining a match id before start. It does not name sibling alternatives or state when not to use it, so it stops short of full usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_archive_matchesResults archive (1968–2022)A
Read-onlyIdempotent
Inspect

Search the results archive — completed-match RESULTS from 1968 through 2022: ATP and WTA, main draws, qualifying and the ITF/futures tiers. Winner/loser-shaped records with final score, seeds and ranks AT THE TIME of the match. Use this for historical questions ("Borg's Wimbledon finals"); the archive ends 2022-12-31 where our own results (get_recent_results) begin. Requires the BASIC plan or any History plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoLatest tournament START date, YYYY-MM-DD.
fromNoEarliest tournament START date, YYYY-MM-DD.
tourNoatp or wta.
levelNoSource tier code: G=grand slam, M=masters, A=tour, F=finals, D=davis cup, C=challenger, O=olympics, or a futures category code (e.g. 15).
limitNoMaximum results to return (1-200).
roundNoRound code, e.g. F for finals.
player_nameNoCase-insensitive fragment of EITHER player's name, min 3 chars, e.g. "borg".

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
resultsNoArchive results, newest tournament first.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate a safe read-only operation, but the description adds valuable context: the archive ends on 2022-12-31, results are winner/loser-shaped with final score and seeds/ranks at match time, and a plan requirement is disclosed. This enriches the agent's understanding beyond the defaults.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with the core action ('Search the results archive'), followed by scope, example, transition to sibling, and plan requirement. No unnecessary words; every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a full output schema (noted as present), the description needn't explain return values. It covers purpose, scope, temporal boundary, usage example, plan requirement, and handoff to a sibling tool. This is complete for a search tool with seven optional, well-documented parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers all parameters with descriptions, so the baseline is 3. The description adds little specific parameter detail beyond the schema; the time-range context for 'from'/'to' is implicit in the archive's date range, but no explicit param-level guidance is given beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool as searching the results archive for completed matches from 1968–2022, covering ATP/WTA, main draws, qualifying, and ITF/futures tiers. It distinguishes itself from siblings like get_recent_results by explicitly naming the archive's end date and where the sibling takes over.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides an explicit use case ('historical questions ("Borg's Wimbledon finals")') and states the boundary between this tool and get_recent_results ('where our own results (get_recent_results) begin'). Also mentions the required plan (BASIC or History), giving clear guidance on when this tool is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_archive_playersArchive player biosA
Read-onlyIdempotent
Inspect

The people of the results archive (1968–2022): hand, date of birth, country, height, and career-high rank with the week it was first reached. Their ids are corpus person ids (the winner/loser player_id on archive results), not roster ids — for current players use search_players. Requires the BASIC plan or any History plan.

ParametersJSON Schema
NameRequiredDescriptionDefault
tourNoatp or wta.
limitNoMaximum players to return (1-200).
queryYesFull or partial player name, min 3 chars, e.g. "navratilova".

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
playersNoMatching archive people, ordered by name.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already convey read-only, idempotent, and non-destructive behavior. The description adds valuable context: the fields returned, the historical time range, and the distinction between corpus person ids and roster ids. However, it does not mention rate limits or pagination behavior beyond the schema's limit parameter, so a perfect score is not warranted.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no redundancy. The first sentence front-loads the core resource and attributes; the second adds id semantics and a sibling alternative. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

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 doesn't need to explain return values. It covers the essential context: time range, id type, and plan requirement. Minor omission: no mention of result ordering or that the query is a partial match (though the schema example implies it), which prevents a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema fully describes all three parameters with types, enums, defaults, and examples. The description adds no additional parameter-level detail beyond what the schema provides, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the resource ('the people of the results archive (1968–2022)') and the specific attributes returned (hand, date of birth, country, height, career-high rank). It distinguishes from sibling tool search_players by explicitly noting the archive scope and the difference between corpus person ids and roster ids.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance: 'for current players use search_players' and clarifies the id namespace. It also mentions the plan requirement as a precondition, which helps the agent decide when to invoke this tool. This is a strong alternative-identification.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_playersSearch playersA
Read-onlyIdempotent
Inspect

Search tennis players by name. Returns id, country, ranking and tour. Use the returned id with get_player. Works on the FREE plan (no card needed).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum players to return (1-200).
queryYesFull or partial player name, e.g. "alcaraz".

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
playersNoMatching players, best match first.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and non-destructive intent, so the description does not need to restate safety. It adds useful context beyond the annotations: the free-plan/no-card requirement and the get_player follow-up, and nothing contradicts 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.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with no filler: purpose, output fields, follow-up workflow, and access constraint are each given in one line. The key action and result are front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With full schema documentation, safe-read annotations, and an output schema, the description is mostly complete. It could slightly improve by noting whether it searches only current players vs archive players, given the sibling search_archive_players, but the core workflow is fully covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the query parameter is well described with an example ('alcaraz'), while limit has min/max and default. The description only restates 'by name' and adds no parameter semantics beyond the schema, so it lands at the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the action explicitly: 'Search tennis players by name' and lists the returned fields (id, country, ranking, tour), so an agent knows what the tool does. It is clear, but it does not explicitly distinguish this from search_archive_players, so it misses sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete workflow guidance: use the returned id with get_player, and it notes the tool works on the free plan, which sets expectations about access. It does not explicitly state when not to use it or name alternatives like search_archive_players, so it falls short of fully explicit routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_tournamentsTournament catalogueA
Read-onlyIdempotent
Inspect

Search the tournament catalogue — the stable id space that match objects carry as tournament_id. Returns surface, indoor, host city/country and category where curated. Works on the FREE plan (no card needed).

ParametersJSON Schema
NameRequiredDescriptionDefault
tourNoRestrict to one tour.
limitNoMaximum tournaments to return (1-200).
queryNoFull or partial tournament name, e.g. "wimbledon". Omit to list all.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.
messageYesHuman-readable summary. Identical to the text content, so either half can be used alone.
tournamentsNoMatching tournaments, name order.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already provide readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is well covered. The description adds genuinely useful behavioral context beyond annotations: the 'stable id space' relationship, the caveat that some fields are returned only 'where curated,' and the access note about working on the FREE plan.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler. The core action and resource are front-loaded, the return data is summarized in the second sentence, and the access note is a compact, useful addition. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a moderate 3-parameter tool, full schema coverage, a present output schema, and rich annotations, the description covers the essentials: purpose, stable ID semantics, return fields, data caveats, and access requirements. It could mention ordering or pagination behavior, but the output schema and parameter constraints already cover the return structure and limits, so little is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the parameters (tour, limit, query) are already fully documented with defaults and constraints. The description adds minimal parameter-level meaning beyond saying this is a search; it does not describe query syntax or how tour filtering interacts with the catalogue, but the schema carries the full semantic load, so a baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

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: 'Search the tournament catalogue.' It goes beyond a generic label by defining the catalogue as the stable id space carried by match objects as tournament_id, and it lists the returned attributes, making the tool's purpose concrete and distinguishing it from get_tournament and search_archive_matches.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: this is a catalogue search suitable for resolving/match tournament IDs, and it notes the FREE plan eligibility. It does not explicitly mention when to prefer get_tournament or another sibling, but the stable-id-space explanation strongly implies the intended use case, so the guidance is clear though not exhaustive.

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.

  1. 4 tool updatesv1.5.0
    • Changedget_live_matches4 fields changed
      • addedOutput schema / properties / matches / items / properties / event_status_updated_at
        Added value: +{
        +  "description": "The instant the current event_status was recorded, UTC ISO-8601 (added 2026-08-19). Null while the status has never changed since the field was introduced — never backfilled.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / has_analysis
        Added value: +{
        +  "description": "Whether a model thesis or profile exists for this match (added 2026-09-02, every tier). Filter on this before calling get_match_analysis, which reports the same absence. Null only when the server predates the field.",
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / has_market
        Added value: +{
        +  "description": "Whether a match-winner market is mapped to this match (added 2026-09-02, every tier). Filter on this before calling get_match_odds, which reports the same absence. Null only when the server predates the field.",
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / matches / items / required
        Previous value: -[
        -  "id",
        -  "tour",
        -  "tournament",
        -  "tournament_id",
        -  "round",
        -  "round_code",
        -  "player1",
        -  "player2",
        -  "score",
        -  "status",
        -  "surface",
        -  "indoor",
        -  "serving",
        -  "winner",
        -  "event_status",
        -  "withdrew",
        -  "win_probability_p1"
        -]New value: +[
        +  "id",
        +  "tour",
        +  "tournament",
        +  "tournament_id",
        +  "round",
        +  "round_code",
        +  "player1",
        +  "player2",
        +  "score",
        +  "status",
        +  "surface",
        +  "indoor",
        +  "serving",
        +  "winner",
        +  "event_status",
        +  "event_status_updated_at",
        +  "withdrew",
        +  "has_analysis",
        +  "has_market",
        +  "win_probability_p1"
        +]
    • Changedget_match4 fields changed
      • addedOutput schema / properties / match / properties / event_status_updated_at
        Added value: +{
        +  "description": "The instant the current event_status was recorded, UTC ISO-8601 (added 2026-08-19). Null while the status has never changed since the field was introduced — never backfilled.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / match / properties / has_analysis
        Added value: +{
        +  "description": "Whether a model thesis or profile exists for this match (added 2026-09-02, every tier). Filter on this before calling get_match_analysis, which reports the same absence. Null only when the server predates the field.",
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / match / properties / has_market
        Added value: +{
        +  "description": "Whether a match-winner market is mapped to this match (added 2026-09-02, every tier). Filter on this before calling get_match_odds, which reports the same absence. Null only when the server predates the field.",
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / match / required
        Previous value: -[
        -  "id",
        -  "tour",
        -  "tournament",
        -  "tournament_id",
        -  "round",
        -  "round_code",
        -  "player1",
        -  "player2",
        -  "score",
        -  "status",
        -  "surface",
        -  "indoor",
        -  "serving",
        -  "winner",
        -  "event_status",
        -  "withdrew",
        -  "win_probability_p1"
        -]New value: +[
        +  "id",
        +  "tour",
        +  "tournament",
        +  "tournament_id",
        +  "round",
        +  "round_code",
        +  "player1",
        +  "player2",
        +  "score",
        +  "status",
        +  "surface",
        +  "indoor",
        +  "serving",
        +  "winner",
        +  "event_status",
        +  "event_status_updated_at",
        +  "withdrew",
        +  "has_analysis",
        +  "has_market",
        +  "win_probability_p1"
        +]
    • Changedget_recent_results4 fields changed
      • addedOutput schema / properties / matches / items / properties / event_status_updated_at
        Added value: +{
        +  "description": "The instant the current event_status was recorded, UTC ISO-8601 (added 2026-08-19). Null while the status has never changed since the field was introduced — never backfilled.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / has_analysis
        Added value: +{
        +  "description": "Whether a model thesis or profile exists for this match (added 2026-09-02, every tier). Filter on this before calling get_match_analysis, which reports the same absence. Null only when the server predates the field.",
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / has_market
        Added value: +{
        +  "description": "Whether a match-winner market is mapped to this match (added 2026-09-02, every tier). Filter on this before calling get_match_odds, which reports the same absence. Null only when the server predates the field.",
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / matches / items / required
        Previous value: -[
        -  "id",
        -  "tour",
        -  "tournament",
        -  "tournament_id",
        -  "round",
        -  "round_code",
        -  "player1",
        -  "player2",
        -  "score",
        -  "status",
        -  "surface",
        -  "indoor",
        -  "serving",
        -  "winner",
        -  "event_status",
        -  "withdrew",
        -  "win_probability_p1"
        -]New value: +[
        +  "id",
        +  "tour",
        +  "tournament",
        +  "tournament_id",
        +  "round",
        +  "round_code",
        +  "player1",
        +  "player2",
        +  "score",
        +  "status",
        +  "surface",
        +  "indoor",
        +  "serving",
        +  "winner",
        +  "event_status",
        +  "event_status_updated_at",
        +  "withdrew",
        +  "has_analysis",
        +  "has_market",
        +  "win_probability_p1"
        +]
    • Changedget_upcoming_matches4 fields changed
      • addedOutput schema / properties / matches / items / properties / event_status_updated_at
        Added value: +{
        +  "description": "The instant the current event_status was recorded, UTC ISO-8601 (added 2026-08-19). Null while the status has never changed since the field was introduced — never backfilled.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / has_analysis
        Added value: +{
        +  "description": "Whether a model thesis or profile exists for this match (added 2026-09-02, every tier). Filter on this before calling get_match_analysis, which reports the same absence. Null only when the server predates the field.",
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / has_market
        Added value: +{
        +  "description": "Whether a match-winner market is mapped to this match (added 2026-09-02, every tier). Filter on this before calling get_match_odds, which reports the same absence. Null only when the server predates the field.",
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / matches / items / required
        Previous value: -[
        -  "id",
        -  "tour",
        -  "tournament",
        -  "tournament_id",
        -  "round",
        -  "round_code",
        -  "player1",
        -  "player2",
        -  "score",
        -  "status",
        -  "surface",
        -  "indoor",
        -  "serving",
        -  "winner",
        -  "event_status",
        -  "withdrew",
        -  "win_probability_p1"
        -]New value: +[
        +  "id",
        +  "tour",
        +  "tournament",
        +  "tournament_id",
        +  "round",
        +  "round_code",
        +  "player1",
        +  "player2",
        +  "score",
        +  "status",
        +  "surface",
        +  "indoor",
        +  "serving",
        +  "winner",
        +  "event_status",
        +  "event_status_updated_at",
        +  "withdrew",
        +  "has_analysis",
        +  "has_market",
        +  "win_probability_p1"
        +]
  2. 10 tool updatesv1.4.0
    • Addedget_charting_match
    • Addedget_charting_player
    • Changedget_fixtures1 field changed
      • addedInput schema / properties / tour
        Added value: +{
        +  "description": "Tour filter; each name covers its doubles variants. Exhibition/team events carry no tour and are excluded whenever the filter is used.",
        +  "enum": [
        +    "atp",
        +    "wta",
        +    "challenger",
        +    "itf",
        +    "juniors"
        +  ],
        +  "type": "string"
        +}
    • Changedget_live_matches9 fields changed
      • addedInput schema / properties / country
        Added value: +{
        +  "description": "Either participant's country — the lowercase 3-letter IOC-style code the Player object returns (e.g. ned, sui, gre), NOT ISO-3166. Players with no recorded country never match.",
        +  "maxLength": 3,
        +  "minLength": 3,
        +  "type": "string"
        +}
      • addedInput schema / properties / player
        Added value: +{
        +  "description": "Player ids (from search_players), max 50 — keeps matches where ANY listed player is either participant.",
        +  "items": {
        +    "type": "integer"
        +  },
        +  "maxItems": 50,
        +  "type": "array"
        +}
      • addedInput schema / properties / tour
        Added value: +{
        +  "description": "Tour filter; each name covers its doubles variants. Exhibition/team events carry no tour and are excluded whenever the filter is used.",
        +  "enum": [
        +    "atp",
        +    "wta",
        +    "challenger",
        +    "itf",
        +    "juniors"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / matches / items / properties / event_status
        Added value: +{
        +  "description": "How the match ended (or paused) when it did not run its course: Retired, Cancelled, Walk Over, Postponed or Interrupted. Null means completed normally OR never resolved. Branch settlement logic here.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / round_code
        Added value: +{
        +  "description": "Round in the normalized vocabulary (F, SF, QF, R16 … Q); null when the label is unrecognised, never guessed.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / tour
        Added value: +{
        +  "description": "atp, wta, challenger, itf or juniors. Null when the feed never stated one (exhibitions, team events).",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / tournament_id
        Added value: +{
        +  "description": "Stable tournament id — pass to get_tournament. Null where uncatalogued.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / withdrew
        Added value: +{
        +  "description": "Completed matches only: which player retired or conceded the walkover, 1 or 2. Null means \"not a withdrawal, or no evidence\", never a guess.",
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / matches / items / required
        Previous value: -[
        -  "id",
        -  "tournament",
        -  "round",
        -  "player1",
        -  "player2",
        -  "score",
        -  "status",
        -  "surface",
        -  "indoor",
        -  "serving",
        -  "winner",
        -  "win_probability_p1"
        -]New value: +[
        +  "id",
        +  "tour",
        +  "tournament",
        +  "tournament_id",
        +  "round",
        +  "round_code",
        +  "player1",
        +  "player2",
        +  "score",
        +  "status",
        +  "surface",
        +  "indoor",
        +  "serving",
        +  "winner",
        +  "event_status",
        +  "withdrew",
        +  "win_probability_p1"
        +]
    • Changedget_match6 fields changed
      • addedOutput schema / properties / match / properties / event_status
        Added value: +{
        +  "description": "How the match ended (or paused) when it did not run its course: Retired, Cancelled, Walk Over, Postponed or Interrupted. Null means completed normally OR never resolved. Branch settlement logic here.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / match / properties / round_code
        Added value: +{
        +  "description": "Round in the normalized vocabulary (F, SF, QF, R16 … Q); null when the label is unrecognised, never guessed.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / match / properties / tour
        Added value: +{
        +  "description": "atp, wta, challenger, itf or juniors. Null when the feed never stated one (exhibitions, team events).",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / match / properties / tournament_id
        Added value: +{
        +  "description": "Stable tournament id — pass to get_tournament. Null where uncatalogued.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / match / properties / withdrew
        Added value: +{
        +  "description": "Completed matches only: which player retired or conceded the walkover, 1 or 2. Null means \"not a withdrawal, or no evidence\", never a guess.",
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / match / required
        Previous value: -[
        -  "id",
        -  "tournament",
        -  "round",
        -  "player1",
        -  "player2",
        -  "score",
        -  "status",
        -  "surface",
        -  "indoor",
        -  "serving",
        -  "winner",
        -  "win_probability_p1"
        -]New value: +[
        +  "id",
        +  "tour",
        +  "tournament",
        +  "tournament_id",
        +  "round",
        +  "round_code",
        +  "player1",
        +  "player2",
        +  "score",
        +  "status",
        +  "surface",
        +  "indoor",
        +  "serving",
        +  "winner",
        +  "event_status",
        +  "withdrew",
        +  "win_probability_p1"
        +]
    • Addedget_match_statistics
    • Addedget_player_rankings
    • Addedget_rankings
    • Changedget_recent_results11 fields changed
      • addedInput schema / properties / country
        Added value: +{
        +  "description": "Either participant's country — the lowercase 3-letter IOC-style code the Player object returns (e.g. ned, sui, gre), NOT ISO-3166. Players with no recorded country never match.",
        +  "maxLength": 3,
        +  "minLength": 3,
        +  "type": "string"
        +}
      • addedInput schema / properties / from
        Added value: +{
        +  "description": "Earliest play date: YYYY-MM-DD (a whole UTC day) or ISO-8601 datetime.",
        +  "type": "string"
        +}
      • addedInput schema / properties / player
        Added value: +{
        +  "description": "Player ids (from search_players), max 50 — keeps matches where ANY listed player is either participant.",
        +  "items": {
        +    "type": "integer"
        +  },
        +  "maxItems": 50,
        +  "type": "array"
        +}
      • addedInput schema / properties / to
        Added value: +{
        +  "description": "Latest play date: YYYY-MM-DD or ISO-8601; must not precede from.",
        +  "type": "string"
        +}
      • addedInput schema / properties / tour
        Added value: +{
        +  "description": "Tour filter; each name covers its doubles variants. Exhibition/team events carry no tour and are excluded whenever the filter is used.",
        +  "enum": [
        +    "atp",
        +    "wta",
        +    "challenger",
        +    "itf",
        +    "juniors"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / matches / items / properties / event_status
        Added value: +{
        +  "description": "How the match ended (or paused) when it did not run its course: Retired, Cancelled, Walk Over, Postponed or Interrupted. Null means completed normally OR never resolved. Branch settlement logic here.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / round_code
        Added value: +{
        +  "description": "Round in the normalized vocabulary (F, SF, QF, R16 … Q); null when the label is unrecognised, never guessed.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / tour
        Added value: +{
        +  "description": "atp, wta, challenger, itf or juniors. Null when the feed never stated one (exhibitions, team events).",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / tournament_id
        Added value: +{
        +  "description": "Stable tournament id — pass to get_tournament. Null where uncatalogued.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / withdrew
        Added value: +{
        +  "description": "Completed matches only: which player retired or conceded the walkover, 1 or 2. Null means \"not a withdrawal, or no evidence\", never a guess.",
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / matches / items / required
        Previous value: -[
        -  "id",
        -  "tournament",
        -  "round",
        -  "player1",
        -  "player2",
        -  "score",
        -  "status",
        -  "surface",
        -  "indoor",
        -  "serving",
        -  "winner",
        -  "win_probability_p1"
        -]New value: +[
        +  "id",
        +  "tour",
        +  "tournament",
        +  "tournament_id",
        +  "round",
        +  "round_code",
        +  "player1",
        +  "player2",
        +  "score",
        +  "status",
        +  "surface",
        +  "indoor",
        +  "serving",
        +  "winner",
        +  "event_status",
        +  "withdrew",
        +  "win_probability_p1"
        +]
    • Changedget_upcoming_matches11 fields changed
      • addedInput schema / properties / country
        Added value: +{
        +  "description": "Either participant's country — the lowercase 3-letter IOC-style code the Player object returns (e.g. ned, sui, gre), NOT ISO-3166. Players with no recorded country never match.",
        +  "maxLength": 3,
        +  "minLength": 3,
        +  "type": "string"
        +}
      • addedInput schema / properties / from
        Added value: +{
        +  "description": "Earliest play date: YYYY-MM-DD (a whole UTC day) or ISO-8601 datetime.",
        +  "type": "string"
        +}
      • addedInput schema / properties / player
        Added value: +{
        +  "description": "Player ids (from search_players), max 50 — keeps matches where ANY listed player is either participant.",
        +  "items": {
        +    "type": "integer"
        +  },
        +  "maxItems": 50,
        +  "type": "array"
        +}
      • addedInput schema / properties / to
        Added value: +{
        +  "description": "Latest play date: YYYY-MM-DD or ISO-8601; must not precede from.",
        +  "type": "string"
        +}
      • addedInput schema / properties / tour
        Added value: +{
        +  "description": "Tour filter; each name covers its doubles variants. Exhibition/team events carry no tour and are excluded whenever the filter is used.",
        +  "enum": [
        +    "atp",
        +    "wta",
        +    "challenger",
        +    "itf",
        +    "juniors"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / matches / items / properties / event_status
        Added value: +{
        +  "description": "How the match ended (or paused) when it did not run its course: Retired, Cancelled, Walk Over, Postponed or Interrupted. Null means completed normally OR never resolved. Branch settlement logic here.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / round_code
        Added value: +{
        +  "description": "Round in the normalized vocabulary (F, SF, QF, R16 … Q); null when the label is unrecognised, never guessed.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / tour
        Added value: +{
        +  "description": "atp, wta, challenger, itf or juniors. Null when the feed never stated one (exhibitions, team events).",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / tournament_id
        Added value: +{
        +  "description": "Stable tournament id — pass to get_tournament. Null where uncatalogued.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matches / items / properties / withdrew
        Added value: +{
        +  "description": "Completed matches only: which player retired or conceded the walkover, 1 or 2. Null means \"not a withdrawal, or no evidence\", never a guess.",
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / matches / items / required
        Previous value: -[
        -  "id",
        -  "tournament",
        -  "round",
        -  "player1",
        -  "player2",
        -  "score",
        -  "status",
        -  "surface",
        -  "indoor",
        -  "serving",
        -  "winner",
        -  "win_probability_p1"
        -]New value: +[
        +  "id",
        +  "tour",
        +  "tournament",
        +  "tournament_id",
        +  "round",
        +  "round_code",
        +  "player1",
        +  "player2",
        +  "score",
        +  "status",
        +  "surface",
        +  "indoor",
        +  "serving",
        +  "winner",
        +  "event_status",
        +  "withdrew",
        +  "win_probability_p1"
        +]
  3. 15 tool updatesv1.3.0
    • Addedget_archive_career
    • Addedget_archive_match
    • Addedget_h2h
    • Addedget_live_matches
    • Addedget_match_analysis
    • Addedget_match_events
    • Addedget_match_odds
    • Addedget_match_score
    • Addedget_player
    • Addedget_recent_results
    • Addedget_tournament
    • Addedsearch_archive_matches
    • Addedsearch_archive_players
    • Addedsearch_players
    • Addedsearch_tournaments
  4. 7 tool updatesv1.2.1
    • Addedcheck_api_status
    • Removedget_live_matches
    • Addedget_match
    • Removedget_match_analysis
    • Removedget_match_events
    • Removedget_recent_results
    • Removedsearch_players
  5. 9 tool updatesv1.2.0
    • Changedget_fixtures2 fields changed
      • addedInput schema / properties / limit / description
        Added value: +"Maximum fixtures to return (1-200)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "fixtures": {
        +      "description": "Scheduled fixtures, earliest first.",
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "event_date": {
        +            "description": "Scheduled start, ISO timestamp.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "player1": {
        +            "description": "Name of player 1.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "player2": {
        +            "description": "Name of player 2.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "round": {
        +            "description": "Round within the event.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "tournament": {
        +            "description": "Event name.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          }
        +        },
        +        "required": [
        +          "event_date",
        +          "tournament",
        +          "round",
        +          "player1",
        +          "player2"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "message": {
        +      "description": "Human-readable summary. Identical to the text content, so either half can be used alone.",
        +      "type": "string"
        +    },
        +    "ok": {
        +      "description": "True when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "ok",
        +    "message"
        +  ],
        +  "type": "object"
        +}
    • Changedget_live_matches2 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"Maximum matches to return"New value: +"Maximum matches to return (1-200)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "matches": {
        +      "description": "The live matches, most relevant first.",
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "id": {
        +            "description": "Match id. Pass to get_match, get_match_score, get_match_events or get_match_odds.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "indoor": {
        +            "description": "True when played indoors.",
        +            "type": [
        +              "boolean",
        +              "null"
        +            ]
        +          },
        +          "player1": {
        +            "description": "Name of player 1.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "player2": {
        +            "description": "Name of player 2.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "round": {
        +            "description": "Round within the event, e.g. \"QF\".",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "score": {
        +            "description": "Formatted score line, e.g. \"6-4 3-6 2-1\".",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "serving": {
        +            "description": "1 or 2 while a point is in play, otherwise null.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "status": {
        +            "description": "One of live, upcoming or completed.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "surface": {
        +            "description": "Court surface, e.g. hard, clay, grass.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "tournament": {
        +            "description": "Event name, e.g. \"Wimbledon\".",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "win_probability_p1": {
        +            "description": "Model probability that player 1 wins, 0-1. Requires the ULTRA plan; null otherwise.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "winner": {
        +            "description": "1 or 2 once decided, otherwise null.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          }
        +        },
        +        "required": [
        +          "id",
        +          "tournament",
        +          "round",
        +          "player1",
        +          "player2",
        +          "score",
        +          "status",
        +          "surface",
        +          "indoor",
        +          "serving",
        +          "winner",
        +          "win_probability_p1"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "message": {
        +      "description": "Human-readable summary. Identical to the text content, so either half can be used alone.",
        +      "type": "string"
        +    },
        +    "ok": {
        +      "description": "True when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "ok",
        +    "message"
        +  ],
        +  "type": "object"
        +}
    • Changedget_match_analysis2 fields changed
      • addedInput schema / properties / match_id / description
        Added value: +"Match id, as returned by get_live_matches, get_upcoming_matches or get_recent_results."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "message": {
        +      "description": "Human-readable summary. Identical to the text content, so either half can be used alone.",
        +      "type": "string"
        +    },
        +    "ok": {
        +      "description": "True when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.",
        +      "type": "boolean"
        +    },
        +    "profile": {
        +      "additionalProperties": false,
        +      "description": "Quantitative view.",
        +      "properties": {
        +        "expected_closeness": {
        +          "description": "How close the model expects the match to be.",
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "key_factors": {
        +          "description": "Drivers behind the model view.",
        +          "items": {
        +            "type": "string"
        +          },
        +          "type": "array"
        +        },
        +        "volatility_rating": {
        +          "description": "Expected swing in the match state.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "win_probability_p1": {
        +          "description": "Model probability player 1 wins, 0-1.",
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "win_probability_p1",
        +        "expected_closeness",
        +        "volatility_rating",
        +        "key_factors"
        +      ],
        +      "type": "object"
        +    },
        +    "thesis": {
        +      "additionalProperties": false,
        +      "description": "Narrative view.",
        +      "properties": {
        +        "confidence": {
        +          "description": "Model confidence, 0-1.",
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "pick_side": {
        +          "description": "Player the model favours, 1 or 2.",
        +          "type": [
        +            "number",
        +            "null"
        +          ]
        +        },
        +        "reasoning": {
        +          "description": "Narrative reasoning.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "state": {
        +          "description": "Current state of the thesis.",
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        }
        +      },
        +      "required": [
        +        "pick_side",
        +        "confidence",
        +        "state",
        +        "reasoning"
        +      ],
        +      "type": "object"
        +    }
        +  },
        +  "required": [
        +    "ok",
        +    "message"
        +  ],
        +  "type": "object"
        +}
    • Addedget_match_events
    • Removedget_match_odds
    • Removedget_match_score
    • Changedget_recent_results2 fields changed
      • addedInput schema / properties / limit / description
        Added value: +"Maximum matches to return (1-200)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "matches": {
        +      "description": "Completed matches, most recent first.",
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "id": {
        +            "description": "Match id. Pass to get_match, get_match_score, get_match_events or get_match_odds.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "indoor": {
        +            "description": "True when played indoors.",
        +            "type": [
        +              "boolean",
        +              "null"
        +            ]
        +          },
        +          "player1": {
        +            "description": "Name of player 1.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "player2": {
        +            "description": "Name of player 2.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "round": {
        +            "description": "Round within the event, e.g. \"QF\".",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "score": {
        +            "description": "Formatted score line, e.g. \"6-4 3-6 2-1\".",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "serving": {
        +            "description": "1 or 2 while a point is in play, otherwise null.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "status": {
        +            "description": "One of live, upcoming or completed.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "surface": {
        +            "description": "Court surface, e.g. hard, clay, grass.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "tournament": {
        +            "description": "Event name, e.g. \"Wimbledon\".",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "win_probability_p1": {
        +            "description": "Model probability that player 1 wins, 0-1. Requires the ULTRA plan; null otherwise.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "winner": {
        +            "description": "1 or 2 once decided, otherwise null.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          }
        +        },
        +        "required": [
        +          "id",
        +          "tournament",
        +          "round",
        +          "player1",
        +          "player2",
        +          "score",
        +          "status",
        +          "surface",
        +          "indoor",
        +          "serving",
        +          "winner",
        +          "win_probability_p1"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "message": {
        +      "description": "Human-readable summary. Identical to the text content, so either half can be used alone.",
        +      "type": "string"
        +    },
        +    "ok": {
        +      "description": "True when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "ok",
        +    "message"
        +  ],
        +  "type": "object"
        +}
    • Changedget_upcoming_matches2 fields changed
      • addedInput schema / properties / limit / description
        Added value: +"Maximum matches to return (1-200)."
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "$schema": "http://json-schema.org/draft-07/schema#",
        +  "additionalProperties": false,
        +  "properties": {
        +    "matches": {
        +      "description": "Matches due to start, soonest first.",
        +      "items": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "id": {
        +            "description": "Match id. Pass to get_match, get_match_score, get_match_events or get_match_odds.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "indoor": {
        +            "description": "True when played indoors.",
        +            "type": [
        +              "boolean",
        +              "null"
        +            ]
        +          },
        +          "player1": {
        +            "description": "Name of player 1.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "player2": {
        +            "description": "Name of player 2.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "round": {
        +            "description": "Round within the event, e.g. \"QF\".",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "score": {
        +            "description": "Formatted score line, e.g. \"6-4 3-6 2-1\".",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "serving": {
        +            "description": "1 or 2 while a point is in play, otherwise null.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "status": {
        +            "description": "One of live, upcoming or completed.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "surface": {
        +            "description": "Court surface, e.g. hard, clay, grass.",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "tournament": {
        +            "description": "Event name, e.g. \"Wimbledon\".",
        +            "type": [
        +              "string",
        +              "null"
        +            ]
        +          },
        +          "win_probability_p1": {
        +            "description": "Model probability that player 1 wins, 0-1. Requires the ULTRA plan; null otherwise.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          },
        +          "winner": {
        +            "description": "1 or 2 once decided, otherwise null.",
        +            "type": [
        +              "number",
        +              "null"
        +            ]
        +          }
        +        },
        +        "required": [
        +          "id",
        +          "tournament",
        +          "round",
        +          "player1",
        +          "player2",
        +          "score",
        +          "status",
        +          "surface",
        +          "indoor",
        +          "serving",
        +          "winner",
        +          "win_probability_p1"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "message": {
        +      "description": "Human-readable summary. Identical to the text content, so either half can be used alone.",
        +      "type": "string"
        +    },
        +    "ok": {
        +      "description": "True when the call returned data. False for a tier wall, a missing or rejected key, or an empty result — all of which are normal states with a clear remedy, not failures.",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "ok",
        +    "message"
        +  ],
        +  "type": "object"
        +}
    • Addedsearch_players
  6. 7 tool updatesv1.0.4
    • First observedget_fixtures
    • First observedget_live_matches
    • First observedget_match_analysis
    • First observedget_match_odds
    • First observedget_match_score
    • First observedget_recent_results
    • First observedget_upcoming_matches

TDQS

A3.9/5.0

Scored across 24 tools

Disambiguation4/5

Most tools target distinct resource+action pairs, and the match-level variants are carefully scoped by data family (score, events, odds, analysis, statistics). However, get_upcoming_matches and get_fixtures both list future matches, and get_match already exposes market/analysis data that dedicated odds/analysis tools also cover, so a couple of boundaries require careful reading.

Naming Consistency5/5

All tools use lowercase snake_case with a consistent get_/search_/check_ prefix, and resources are named predictably (get_match, get_match_score, search_tournaments). The only mild deviations are get_h2h and check_api_status, but they still fit the overall pattern.

Tool Count3/5

24 tools is on the heavy side and exceeds the typical well-scoped range, with some near-duplicate listing endpoints (upcoming vs fixtures) and several niche data families (archive, charting, odds/analysis). At the same time, each tool maps to a distinct data family and none feels purely redundant, so the count is heavy but not bloated.

Completeness4/5

The surface covers live scores, fixtures/results, players, tournaments, rankings, archive history, charting, odds, and analysis, which is unusually broad for a read-only API. Gaps are minor workflow issues: there is no tournament-id-based match/results listing, and historical/charting searches return ids that the career and H2H tools cannot directly consume since they take names.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides access to comprehensive sports data from 5 major leagues (NBA, NFL, MLB, EPL, NHL) including teams, players, games, statistics, standings, injuries, and betting odds through 67+ endpoints. Enables users to query sports information and analytics through natural language.
    12
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Gives your MCP host (Claude Desktop, Cursor, Continue, Zed) access to live scores, match details, standings, top scorers, knockout brackets and player stats across football, basketball, cricket and tennis. Backed by the free public SportScore API — no key, no signup, CORS-open.
    8
    44 npm
    10
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    A unified MCP server that aggregates 32 sports API providers into a single service, providing 336 tools for scores, stats, odds, esports, and more across 70+ sports.
    100
    66 npm
    33
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to access comprehensive sports data including football, basketball, American football, and hockey leagues via 11 tools, with no API key required.
    MIT