cito-mcp 0.4.5 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/client.js +39 -0
- package/dist/instructions.js +76 -76
- package/dist/scrub.js +44 -0
- package/dist/tools/insight.js +39 -39
- package/dist/tools/live.js +32 -32
- package/dist/tools/match.js +29 -29
- package/dist/tools/meta.js +1 -1
- package/dist/tools/player.js +44 -44
- package/dist/tools/standings.js +20 -20
- package/dist/tools/team.js +37 -37
- package/package.json +22 -2
package/README.md
CHANGED
|
@@ -535,7 +535,7 @@ claude mcp add cito -e CITO_API_KEY=cito_… "--" npx -y cito-mcp
|
|
|
535
535
|
### Semver expectations
|
|
536
536
|
|
|
537
537
|
- **0.2.4** is a **major surface break** vs 0.1 (tool rename + removal of OpenAPI mass-generation).
|
|
538
|
-
- Further 0.2.x patches may refine envelopes and composite quality without renaming the 15 tools.
|
|
538
|
+
- Further 0.2.x patches may refine envelopes and composite quality without renaming the shipped tools. (This line previously said "15 tools" while the catalog shipped 42 — the count here is intentionally not restated, because a number duplicated in prose drifts the moment the catalog changes.)
|
|
539
539
|
- Promoting Fortnite (or other titles) into the primary `game` enum would be a minor feature bump with catalog/docs updates.
|
|
540
540
|
|
|
541
541
|
---
|
package/dist/client.js
CHANGED
|
@@ -102,6 +102,8 @@ export async function fetchJson(ctx, path, opts) {
|
|
|
102
102
|
catch {
|
|
103
103
|
data = text;
|
|
104
104
|
}
|
|
105
|
+
if (!opts?.raw && response.ok && isTennisPath(path))
|
|
106
|
+
data = flattenTennisEnvelope(data);
|
|
105
107
|
return {
|
|
106
108
|
ok: response.ok,
|
|
107
109
|
status: response.status,
|
|
@@ -158,6 +160,43 @@ export function asRecord(value) {
|
|
|
158
160
|
}
|
|
159
161
|
return null;
|
|
160
162
|
}
|
|
163
|
+
const TENNIS_LIST_META_KEYS = new Set(['count', 'limit', 'total', 'page', 'totalPages', 'hasNext', 'hasPrev']);
|
|
164
|
+
function isTennisPath(path) {
|
|
165
|
+
return /^(\/api\/v1)?\/tennis(\/|\?|$)/.test(path);
|
|
166
|
+
}
|
|
167
|
+
function snakeKey(key) {
|
|
168
|
+
return key.replace(/[A-Z]/g, (ch) => `_${ch.toLowerCase()}`);
|
|
169
|
+
}
|
|
170
|
+
export function flattenTennisEnvelope(body) {
|
|
171
|
+
const env = asRecord(body);
|
|
172
|
+
if (!env || !('data' in env) || 'items' in env)
|
|
173
|
+
return body;
|
|
174
|
+
const meta = asRecord(env.meta);
|
|
175
|
+
if (!meta)
|
|
176
|
+
return body;
|
|
177
|
+
const success = env.success ?? true;
|
|
178
|
+
if (Array.isArray(env.data)) {
|
|
179
|
+
const out = { success, items: env.data };
|
|
180
|
+
for (const [key, value] of Object.entries(meta)) {
|
|
181
|
+
if (!TENNIS_LIST_META_KEYS.has(key))
|
|
182
|
+
out[snakeKey(key)] = value;
|
|
183
|
+
}
|
|
184
|
+
out.total = typeof meta.total === 'number' ? meta.total : env.data.length;
|
|
185
|
+
out.page = typeof meta.page === 'number' ? meta.page : 1;
|
|
186
|
+
out.page_size = typeof meta.limit === 'number' ? meta.limit : env.data.length;
|
|
187
|
+
if (typeof meta.totalPages === 'number')
|
|
188
|
+
out.total_pages = meta.totalPages;
|
|
189
|
+
if (typeof meta.hasNext === 'boolean')
|
|
190
|
+
out.has_next = meta.hasNext;
|
|
191
|
+
if (typeof meta.hasPrev === 'boolean')
|
|
192
|
+
out.has_prev = meta.hasPrev;
|
|
193
|
+
return out;
|
|
194
|
+
}
|
|
195
|
+
const resource = asRecord(env.data);
|
|
196
|
+
if (resource)
|
|
197
|
+
return { success, ...resource };
|
|
198
|
+
return body;
|
|
199
|
+
}
|
|
161
200
|
export function unwrapPayload(value) {
|
|
162
201
|
let cur = value;
|
|
163
202
|
for (let depth = 0; depth < 3; depth += 1) {
|
package/dist/instructions.js
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
export const SERVER_INSTRUCTIONS = `# Cito MCP — agent operating manual
|
|
2
|
-
|
|
3
|
-
You are connected to Cito esports data (read-only). Prefer curated outcome tools over raw REST. Production apps must call Cito REST with the user's API key; use this MCP to design, prototype, and resolve IDs — not as a multi-tenant runtime bus.
|
|
4
|
-
|
|
5
|
-
## Hard rules
|
|
6
|
-
|
|
7
|
-
1. **Never invent IDs.** Do not guess matchId, gameId, playerId, team slug, eventId, or boutId. Always obtain IDs from a prior tool result (resolve, live, schedule, search, or list). If the user gives a name ("T1", "s1mple", "UFC 300"), call resolve_entity/search_entities first.
|
|
8
|
-
2. **Resolve before deep.** Name → ID/slug → summary/page → deep stats. Skip resolve only when the user already provided a Cito ID/slug.
|
|
9
|
-
3. **One screen, one composite.** Prefer a page/summary tool over stitching 4–6 thin GETs.
|
|
10
|
-
4. **Honor the envelope.** Parse ok, data, pagination, partial, error, meta.rateLimit, meta.entities. Partial section failures are not total failures — use successful sections.
|
|
11
|
-
5. **Read-only.** All curated tools are safe to retry except where error.retryable is false for bad args / entitlement.
|
|
12
|
-
|
|
13
|
-
## Game parameter
|
|
14
|
-
|
|
15
|
-
game enum (unless a tool documents otherwise): lol | cs2 | dota2 | ufc | cod | tennis | all
|
|
16
|
-
|
|
17
|
-
- Default when the user named one title: that game. Default for "what's live?" / multi-title: omit game or all on tools that accept it.
|
|
18
|
-
- On UNSUPPORTED_GAME / 403 for a title: stop retrying that game; call api_health; report plan gaps.
|
|
19
|
-
- Fortnite and other titles may appear via call_api/resources; do not assume they are in the curated enum until list_capabilities says so.
|
|
20
|
-
|
|
21
|
-
## Preferred tool order
|
|
22
|
-
|
|
23
|
-
1. Unsure → list_capabilities (filter by game or job). Optional: api_health for key/tier/included games.
|
|
24
|
-
2. Name without ID → resolve_entity (best match) or search_entities (browse). Reuse returned id/slug.
|
|
25
|
-
3. Live / upcoming → live_matches; upcoming_schedule.
|
|
26
|
-
4. Match UI / recap → match_summary first. match_details only for timelines, full maps, demos, live state.
|
|
27
|
-
5. Team page → team_profile. Player form → player_profile. Tables/ranks → standings.
|
|
28
|
-
6. Pre-match → match_preview. Rivalry → head_to_head. Event / fight-night card → event_card.
|
|
29
|
-
7. Escape hatch → call_api (allowlisted path prefixes; prefer GET). Prefer curated tools.
|
|
30
|
-
|
|
31
|
-
Mnemonic: resolve → live/schedule → summary → deep.
|
|
32
|
-
|
|
33
|
-
## Parallel vs sequence
|
|
34
|
-
|
|
35
|
-
Parallel-safe: independent reads (team_profile A ∥ team_profile B; live_matches ∥ api_health). Cap ~3–5 concurrent agent tools; check meta.rateLimit.remaining.
|
|
36
|
-
|
|
37
|
-
Serial required: resolve → detail; pagination (cursor from page N only); live board → selected match deep-dive.
|
|
38
|
-
|
|
39
|
-
Prefer server-side fan-out inside composites (partial[] recovery) over agent N+1.
|
|
40
|
-
|
|
41
|
-
## Pagination
|
|
42
|
-
|
|
43
|
-
Lists use pagination: { limit, offset?, total?, hasMore, nextCursor, prevCursor }. Default limit 20, max 50. Loop with cursor: pagination.nextCursor and the same filters. Never invent cursors. Empty list is ok:true with items:[].
|
|
44
|
-
|
|
45
|
-
## Errors
|
|
46
|
-
|
|
47
|
-
ok:false → read error.code (VALIDATION, NOT_FOUND, UNSUPPORTED_GAME, RATE_LIMIT, UNAUTHORIZED, UPSTREAM, PATH_NOT_ALLOWED, NOT_IMPLEMENTED). Follow error.recover[]. Retry only when retryable.
|
|
48
|
-
|
|
49
|
-
ok:true with partial[] → use successful sections; do not treat partial as total fail.
|
|
50
|
-
ok:true with meta.warnings[] → filters or depth degraded; do not assume ignored filters applied.
|
|
51
|
-
resolve_entity ambiguity is soft: ok:true with data.needsDisambiguation and data.candidates — pick a candidate; do not wait for AMBIGUOUS_ENTITY.
|
|
52
|
-
|
|
53
|
-
## Recipes
|
|
54
|
-
|
|
55
|
-
Live board: api_health (optional) → live_matches → match_summary for selected matchId.
|
|
56
|
-
UFC empty live (count=0): read section.note / emptyReason / health (workerAlive, lag) / supervisor / nextCard — do not claim "API offline" without workerAlive/lag; never invent matchups from supervisor shells.
|
|
57
|
-
Team page: resolve_entity {type:team} → team_profile.
|
|
58
|
-
Player card: resolve_entity {type:player|fighter} → player_profile.
|
|
59
|
-
Fight night / event card: resolve_entity {type:event} → event_card {includeMatches:true} → match_preview for a featured bout.
|
|
60
|
-
Match preview (named sides): resolve_entity each side (optional) → match_preview {teamA, teamB}.
|
|
61
|
-
App scaffold: list_capabilities ∥ api_health ∥ live_matches, then one composite per screen.
|
|
62
|
-
|
|
63
|
-
## Resources
|
|
64
|
-
|
|
65
|
-
- cito://llms.txt — product context when available
|
|
66
|
-
- cito://capabilities — catalog summary
|
|
67
|
-
- cito://openapi.json — optional public OpenAPI fetch for typed clients
|
|
68
|
-
|
|
69
|
-
## What not to do
|
|
70
|
-
|
|
71
|
-
- Invent match/player/team IDs from memory.
|
|
72
|
-
- Parallel-paginate the same list with different cursors.
|
|
73
|
-
- N+1 match_details for every live row.
|
|
74
|
-
- Retry UNSUPPORTED_GAME or VALIDATION unchanged.
|
|
75
|
-
- Ship production traffic through MCP.
|
|
76
|
-
- Flood odds/timelines when a summary answers the question.
|
|
1
|
+
export const SERVER_INSTRUCTIONS = `# Cito MCP — agent operating manual
|
|
2
|
+
|
|
3
|
+
You are connected to Cito esports data (read-only). Prefer curated outcome tools over raw REST. Production apps must call Cito REST with the user's API key; use this MCP to design, prototype, and resolve IDs — not as a multi-tenant runtime bus.
|
|
4
|
+
|
|
5
|
+
## Hard rules
|
|
6
|
+
|
|
7
|
+
1. **Never invent IDs.** Do not guess matchId, gameId, playerId, team slug, eventId, or boutId. Always obtain IDs from a prior tool result (resolve, live, schedule, search, or list). If the user gives a name ("T1", "s1mple", "UFC 300"), call resolve_entity/search_entities first.
|
|
8
|
+
2. **Resolve before deep.** Name → ID/slug → summary/page → deep stats. Skip resolve only when the user already provided a Cito ID/slug.
|
|
9
|
+
3. **One screen, one composite.** Prefer a page/summary tool over stitching 4–6 thin GETs.
|
|
10
|
+
4. **Honor the envelope.** Parse ok, data, pagination, partial, error, meta.rateLimit, meta.entities. Partial section failures are not total failures — use successful sections.
|
|
11
|
+
5. **Read-only.** All curated tools are safe to retry except where error.retryable is false for bad args / entitlement.
|
|
12
|
+
|
|
13
|
+
## Game parameter
|
|
14
|
+
|
|
15
|
+
game enum (unless a tool documents otherwise): lol | cs2 | dota2 | ufc | cod | tennis | all
|
|
16
|
+
|
|
17
|
+
- Default when the user named one title: that game. Default for "what's live?" / multi-title: omit game or all on tools that accept it.
|
|
18
|
+
- On UNSUPPORTED_GAME / 403 for a title: stop retrying that game; call api_health; report plan gaps.
|
|
19
|
+
- Fortnite and other titles may appear via call_api/resources; do not assume they are in the curated enum until list_capabilities says so.
|
|
20
|
+
|
|
21
|
+
## Preferred tool order
|
|
22
|
+
|
|
23
|
+
1. Unsure → list_capabilities (filter by game or job). Optional: api_health for key/tier/included games.
|
|
24
|
+
2. Name without ID → resolve_entity (best match) or search_entities (browse). Reuse returned id/slug.
|
|
25
|
+
3. Live / upcoming → live_matches; upcoming_schedule.
|
|
26
|
+
4. Match UI / recap → match_summary first. match_details only for timelines, full maps, demos, live state.
|
|
27
|
+
5. Team page → team_profile. Player form → player_profile. Tables/ranks → standings.
|
|
28
|
+
6. Pre-match → match_preview. Rivalry → head_to_head. Event / fight-night card → event_card.
|
|
29
|
+
7. Escape hatch → call_api (allowlisted path prefixes; prefer GET). Prefer curated tools.
|
|
30
|
+
|
|
31
|
+
Mnemonic: resolve → live/schedule → summary → deep.
|
|
32
|
+
|
|
33
|
+
## Parallel vs sequence
|
|
34
|
+
|
|
35
|
+
Parallel-safe: independent reads (team_profile A ∥ team_profile B; live_matches ∥ api_health). Cap ~3–5 concurrent agent tools; check meta.rateLimit.remaining.
|
|
36
|
+
|
|
37
|
+
Serial required: resolve → detail; pagination (cursor from page N only); live board → selected match deep-dive.
|
|
38
|
+
|
|
39
|
+
Prefer server-side fan-out inside composites (partial[] recovery) over agent N+1.
|
|
40
|
+
|
|
41
|
+
## Pagination
|
|
42
|
+
|
|
43
|
+
Lists use pagination: { limit, offset?, total?, hasMore, nextCursor, prevCursor }. Default limit 20, max 50. Loop with cursor: pagination.nextCursor and the same filters. Never invent cursors. Empty list is ok:true with items:[].
|
|
44
|
+
|
|
45
|
+
## Errors
|
|
46
|
+
|
|
47
|
+
ok:false → read error.code (VALIDATION, NOT_FOUND, UNSUPPORTED_GAME, RATE_LIMIT, UNAUTHORIZED, UPSTREAM, PATH_NOT_ALLOWED, NOT_IMPLEMENTED). Follow error.recover[]. Retry only when retryable.
|
|
48
|
+
|
|
49
|
+
ok:true with partial[] → use successful sections; do not treat partial as total fail.
|
|
50
|
+
ok:true with meta.warnings[] → filters or depth degraded; do not assume ignored filters applied.
|
|
51
|
+
resolve_entity ambiguity is soft: ok:true with data.needsDisambiguation and data.candidates — pick a candidate; do not wait for AMBIGUOUS_ENTITY.
|
|
52
|
+
|
|
53
|
+
## Recipes
|
|
54
|
+
|
|
55
|
+
Live board: api_health (optional) → live_matches → match_summary for selected matchId.
|
|
56
|
+
UFC empty live (count=0): read section.note / emptyReason / health (workerAlive, lag) / supervisor / nextCard — do not claim "API offline" without workerAlive/lag; never invent matchups from supervisor shells.
|
|
57
|
+
Team page: resolve_entity {type:team} → team_profile.
|
|
58
|
+
Player card: resolve_entity {type:player|fighter} → player_profile.
|
|
59
|
+
Fight night / event card: resolve_entity {type:event} → event_card {includeMatches:true} → match_preview for a featured bout.
|
|
60
|
+
Match preview (named sides): resolve_entity each side (optional) → match_preview {teamA, teamB}.
|
|
61
|
+
App scaffold: list_capabilities ∥ api_health ∥ live_matches, then one composite per screen.
|
|
62
|
+
|
|
63
|
+
## Resources
|
|
64
|
+
|
|
65
|
+
- cito://llms.txt — product context when available
|
|
66
|
+
- cito://capabilities — catalog summary
|
|
67
|
+
- cito://openapi.json — optional public OpenAPI fetch for typed clients
|
|
68
|
+
|
|
69
|
+
## What not to do
|
|
70
|
+
|
|
71
|
+
- Invent match/player/team IDs from memory.
|
|
72
|
+
- Parallel-paginate the same list with different cursors.
|
|
73
|
+
- N+1 match_details for every live row.
|
|
74
|
+
- Retry UNSUPPORTED_GAME or VALIDATION unchanged.
|
|
75
|
+
- Ship production traffic through MCP.
|
|
76
|
+
- Flood odds/timelines when a summary answers the question.
|
|
77
77
|
`;
|
package/dist/scrub.js
CHANGED
|
@@ -15,6 +15,50 @@ const INTERNAL_KEYS = new Set([
|
|
|
15
15
|
'wikiUrl',
|
|
16
16
|
'wiki_url',
|
|
17
17
|
'jsonLd',
|
|
18
|
+
'_mergeSource',
|
|
19
|
+
'_provenance',
|
|
20
|
+
'duplicateOf',
|
|
21
|
+
'duplicate_of',
|
|
22
|
+
'identityConfidence',
|
|
23
|
+
'identity_confidence',
|
|
24
|
+
'roleSource',
|
|
25
|
+
'role_source',
|
|
26
|
+
'verifiedCompetitive',
|
|
27
|
+
'verified_competitive',
|
|
28
|
+
'profileAttemptedAt',
|
|
29
|
+
'profileFailureMessage',
|
|
30
|
+
'profileFailureReason',
|
|
31
|
+
'profileFetchStatus',
|
|
32
|
+
'profileImageAttemptedAt',
|
|
33
|
+
'profileImageAttempts',
|
|
34
|
+
'profileImageError',
|
|
35
|
+
'profileImageSteamAttemptedAt',
|
|
36
|
+
'profileImageWorker',
|
|
37
|
+
'ratingSource',
|
|
38
|
+
'requiredSourceData',
|
|
39
|
+
'rawText',
|
|
40
|
+
'raw_text',
|
|
41
|
+
'scrapedAt',
|
|
42
|
+
'scraped_at',
|
|
43
|
+
'sourceSummary',
|
|
44
|
+
'sourceNote',
|
|
45
|
+
'durableStatsTables',
|
|
46
|
+
'lineupSource',
|
|
47
|
+
'mapMediaSource',
|
|
48
|
+
'rosterSource',
|
|
49
|
+
'upstream',
|
|
50
|
+
'liveCandidateWindowMinutes',
|
|
51
|
+
'rowHash',
|
|
52
|
+
'row_hash',
|
|
53
|
+
'snapshotHash',
|
|
54
|
+
'snapshot_hash',
|
|
55
|
+
'syncRunId',
|
|
56
|
+
'sync_run_id',
|
|
57
|
+
'discoveredSources',
|
|
58
|
+
'sidecarAvailable',
|
|
59
|
+
'imageCandidates',
|
|
60
|
+
'image_candidates',
|
|
61
|
+
'source_url',
|
|
18
62
|
]);
|
|
19
63
|
const SCRAPE_PARENTS = new Set(['dataAvailability', 'health']);
|
|
20
64
|
const SCRAPE_KEYS = new Set(['strategy', 'samples']);
|
package/dist/tools/insight.js
CHANGED
|
@@ -260,20 +260,20 @@ export function composeH2H(game, sideA, sideB, rows, limit) {
|
|
|
260
260
|
}
|
|
261
261
|
export const matchPreview = {
|
|
262
262
|
name: 'match_preview',
|
|
263
|
-
description: `COMPOSITE pre-match briefing: sides, roster/form snippets, H2H stub, event context — for pick'ems, articles, and match-page before state.
|
|
264
|
-
|
|
265
|
-
When to use:
|
|
266
|
-
- Upcoming match deep link
|
|
267
|
-
- "Who should I watch before this game?"
|
|
268
|
-
- App scaffold for preview cards
|
|
269
|
-
|
|
270
|
-
Prefer over: manually chaining team_profile ×2 + head_to_head + schedule.
|
|
271
|
-
Prefer match_summary when match is completed; match_details for live in-game.
|
|
272
|
-
|
|
273
|
-
Do not use when: user wants final score/recap of a finished match.
|
|
274
|
-
|
|
275
|
-
Parallel-safe: yes. Upstream cost: 4–8.
|
|
276
|
-
Tennis H2H accepts an optional surface filter (Hard, Clay, Grass).
|
|
263
|
+
description: `COMPOSITE pre-match briefing: sides, roster/form snippets, H2H stub, event context — for pick'ems, articles, and match-page before state.
|
|
264
|
+
|
|
265
|
+
When to use:
|
|
266
|
+
- Upcoming match deep link
|
|
267
|
+
- "Who should I watch before this game?"
|
|
268
|
+
- App scaffold for preview cards
|
|
269
|
+
|
|
270
|
+
Prefer over: manually chaining team_profile ×2 + head_to_head + schedule.
|
|
271
|
+
Prefer match_summary when match is completed; match_details for live in-game.
|
|
272
|
+
|
|
273
|
+
Do not use when: user wants final score/recap of a finished match.
|
|
274
|
+
|
|
275
|
+
Parallel-safe: yes. Upstream cost: 4–8.
|
|
276
|
+
Tennis H2H accepts an optional surface filter (Hard, Clay, Grass).
|
|
277
277
|
Example: { "game": "lol", "teamA": "t1", "teamB": "gen-g", "includeH2H": true, "recentLimit": 5 }`,
|
|
278
278
|
inputSchema: {
|
|
279
279
|
type: 'object',
|
|
@@ -707,31 +707,31 @@ async function resolveEventKey(ctx, game, q) {
|
|
|
707
707
|
}
|
|
708
708
|
export const eventCard = {
|
|
709
709
|
name: 'event_card',
|
|
710
|
-
description: `COMPOSITE event / fight-night card: identity, bout or match list, optional standings snippet.
|
|
711
|
-
|
|
712
|
-
When to use:
|
|
713
|
-
- UFC fight night / numbered event page ("UFC 300 card", "Fight Night")
|
|
714
|
-
- CS2 event hub with match list
|
|
715
|
-
- Tournament/event overview before match_preview drill-down
|
|
716
|
-
|
|
717
|
-
Bouts come back in card order — main event first, then prelims, then early prelims.
|
|
718
|
-
Each bout carries weightClass, titleBout, card placement, and (once fought) result
|
|
719
|
-
{ method, round, time, referee, winnerSlug }. Each corner carries images
|
|
720
|
-
{ headshotUrl, bodyImageUrl, imageUrl, proxiedImageUrl }, record, nickname, rank,
|
|
721
|
-
championStatus, country and flag when upstream supplies them. Use proxiedImageUrl in
|
|
722
|
-
browsers — the image host sends no CORS header. You do not need call_api per fighter for faces.
|
|
723
|
-
|
|
724
|
-
Prefer over: agent-side resolve + call_api /ufc/events + bout expansion; N+1 match_summary for the card list only; per-fighter call_api just to fetch headshots.
|
|
725
|
-
|
|
726
|
-
Prefer match_preview for one bout/match briefing; match_summary for completed recaps; live_matches for live-only strips; standings alone for pure tables.
|
|
727
|
-
|
|
728
|
-
Do not use when: you only need live scores (live_matches); single finished match recap (match_summary); no event name/id yet and game unknown.
|
|
729
|
-
|
|
730
|
-
Tennis: pass a tournament id/slug to get the draw bracket — rounds carry a round
|
|
731
|
-
code (Q1..R128, QF, SF, F) with each match's players and score. Set is the
|
|
732
|
-
primary tennis path here; there is no separate draw tool.
|
|
733
|
-
|
|
734
|
-
Parallel-safe: yes. Upstream cost: 1–4.
|
|
710
|
+
description: `COMPOSITE event / fight-night card: identity, bout or match list, optional standings snippet.
|
|
711
|
+
|
|
712
|
+
When to use:
|
|
713
|
+
- UFC fight night / numbered event page ("UFC 300 card", "Fight Night")
|
|
714
|
+
- CS2 event hub with match list
|
|
715
|
+
- Tournament/event overview before match_preview drill-down
|
|
716
|
+
|
|
717
|
+
Bouts come back in card order — main event first, then prelims, then early prelims.
|
|
718
|
+
Each bout carries weightClass, titleBout, card placement, and (once fought) result
|
|
719
|
+
{ method, round, time, referee, winnerSlug }. Each corner carries images
|
|
720
|
+
{ headshotUrl, bodyImageUrl, imageUrl, proxiedImageUrl }, record, nickname, rank,
|
|
721
|
+
championStatus, country and flag when upstream supplies them. Use proxiedImageUrl in
|
|
722
|
+
browsers — the image host sends no CORS header. You do not need call_api per fighter for faces.
|
|
723
|
+
|
|
724
|
+
Prefer over: agent-side resolve + call_api /ufc/events + bout expansion; N+1 match_summary for the card list only; per-fighter call_api just to fetch headshots.
|
|
725
|
+
|
|
726
|
+
Prefer match_preview for one bout/match briefing; match_summary for completed recaps; live_matches for live-only strips; standings alone for pure tables.
|
|
727
|
+
|
|
728
|
+
Do not use when: you only need live scores (live_matches); single finished match recap (match_summary); no event name/id yet and game unknown.
|
|
729
|
+
|
|
730
|
+
Tennis: pass a tournament id/slug to get the draw bracket — rounds carry a round
|
|
731
|
+
code (Q1..R128, QF, SF, F) with each match's players and score. Set is the
|
|
732
|
+
primary tennis path here; there is no separate draw tool.
|
|
733
|
+
|
|
734
|
+
Parallel-safe: yes. Upstream cost: 1–4.
|
|
735
735
|
Example: { "game": "ufc", "eventIdOrSlug": "ufc-300", "includeMatches": true, "includeStandings": false }`,
|
|
736
736
|
inputSchema: {
|
|
737
737
|
type: 'object',
|
package/dist/tools/live.js
CHANGED
|
@@ -154,20 +154,20 @@ function slimUfcNextCard(payload) {
|
|
|
154
154
|
}
|
|
155
155
|
export const liveMatches = {
|
|
156
156
|
name: 'live_matches',
|
|
157
|
-
description: `Live matches board across primary games, or a single game filter. Normalized labels, scores, and matchIds.
|
|
158
|
-
|
|
159
|
-
When to use:
|
|
160
|
-
- "What's live right now?"
|
|
161
|
-
- Ops/dashboard live strip
|
|
162
|
-
|
|
163
|
-
Prefer over: sequential per-game call_api live probes.
|
|
164
|
-
|
|
165
|
-
Do not use when: user wants upcoming fixtures → upcoming_schedule; historical results → match_summary.
|
|
166
|
-
|
|
167
|
-
CS2 live path is /cs2/live; UFC is included in multi-game fan-out.
|
|
168
|
-
UFC empty board: section.note + emptyReason + health (workerAlive/lag) + optional supervisor/nextCard (non-live); never fake match items from events[].
|
|
169
|
-
|
|
170
|
-
Parallel-safe: yes. Upstream cost: 1–5 (allSettled).
|
|
157
|
+
description: `Live matches board across primary games, or a single game filter. Normalized labels, scores, and matchIds.
|
|
158
|
+
|
|
159
|
+
When to use:
|
|
160
|
+
- "What's live right now?"
|
|
161
|
+
- Ops/dashboard live strip
|
|
162
|
+
|
|
163
|
+
Prefer over: sequential per-game call_api live probes.
|
|
164
|
+
|
|
165
|
+
Do not use when: user wants upcoming fixtures → upcoming_schedule; historical results → match_summary.
|
|
166
|
+
|
|
167
|
+
CS2 live path is /cs2/live; UFC is included in multi-game fan-out.
|
|
168
|
+
UFC empty board: section.note + emptyReason + health (workerAlive/lag) + optional supervisor/nextCard (non-live); never fake match items from events[].
|
|
169
|
+
|
|
170
|
+
Parallel-safe: yes. Upstream cost: 1–5 (allSettled).
|
|
171
171
|
Example: { "game": "all", "limitPerGame": 10 }`,
|
|
172
172
|
inputSchema: {
|
|
173
173
|
type: 'object',
|
|
@@ -347,24 +347,24 @@ Example: { "game": "all", "limitPerGame": 10 }`,
|
|
|
347
347
|
};
|
|
348
348
|
export const upcomingSchedule = {
|
|
349
349
|
name: 'upcoming_schedule',
|
|
350
|
-
description: `Upcoming matches/events for one game, with game-specific filters.
|
|
351
|
-
|
|
352
|
-
When to use:
|
|
353
|
-
- "What's on this week?"
|
|
354
|
-
- Calendar UI; team next matches
|
|
355
|
-
|
|
356
|
-
Prefer over: live_matches for not-yet-started fixtures.
|
|
357
|
-
|
|
358
|
-
Do not use when: only in-progress matches needed → live_matches.
|
|
359
|
-
|
|
360
|
-
Filter support (unsupported params are ignored with meta.warnings — do not assume filtering worked):
|
|
361
|
-
- lol: hours, team (slug), league (slug)
|
|
362
|
-
- cs2: team, from, to (ISO); hours not applied upstream
|
|
363
|
-
- cod: team, tournamentId
|
|
364
|
-
- dota2: limit/cursor primarily; team may be client-filtered where data allows
|
|
365
|
-
- ufc: hours / from / to applied client-side after bout expansion (API has no hours); event shells labeled by event name; bouts use fighters[] corners
|
|
366
|
-
|
|
367
|
-
Parallel-safe: yes. Upstream cost: 1–2.
|
|
350
|
+
description: `Upcoming matches/events for one game, with game-specific filters.
|
|
351
|
+
|
|
352
|
+
When to use:
|
|
353
|
+
- "What's on this week?"
|
|
354
|
+
- Calendar UI; team next matches
|
|
355
|
+
|
|
356
|
+
Prefer over: live_matches for not-yet-started fixtures.
|
|
357
|
+
|
|
358
|
+
Do not use when: only in-progress matches needed → live_matches.
|
|
359
|
+
|
|
360
|
+
Filter support (unsupported params are ignored with meta.warnings — do not assume filtering worked):
|
|
361
|
+
- lol: hours, team (slug), league (slug)
|
|
362
|
+
- cs2: team, from, to (ISO); hours not applied upstream
|
|
363
|
+
- cod: team, tournamentId
|
|
364
|
+
- dota2: limit/cursor primarily; team may be client-filtered where data allows
|
|
365
|
+
- ufc: hours / from / to applied client-side after bout expansion (API has no hours); event shells labeled by event name; bouts use fighters[] corners
|
|
366
|
+
|
|
367
|
+
Parallel-safe: yes. Upstream cost: 1–2.
|
|
368
368
|
Example: { "game": "lol", "hours": 72, "team": "t1", "limit": 20 }`,
|
|
369
369
|
inputSchema: {
|
|
370
370
|
type: 'object',
|
package/dist/tools/match.js
CHANGED
|
@@ -163,18 +163,18 @@ function primaryPath(game, matchId) {
|
|
|
163
163
|
}
|
|
164
164
|
export const matchSummary = {
|
|
165
165
|
name: 'match_summary',
|
|
166
|
-
description: `COMPOSITE match card: scoreline, key context, player performances, and VOD/demo links when available.
|
|
167
|
-
|
|
168
|
-
When to use:
|
|
169
|
-
- Match recap / default match UI
|
|
170
|
-
- After user selects a live or completed matchId
|
|
171
|
-
|
|
172
|
-
Prefer over match_details for chat answers and default UIs.
|
|
173
|
-
Prefer match_details for timelines, full map trees, live state, advanced packages.
|
|
174
|
-
|
|
175
|
-
Do not use when: no matchId yet (resolve from live/schedule); pure pre-match → match_preview.
|
|
176
|
-
|
|
177
|
-
Parallel-safe: yes. Upstream cost: 2–5.
|
|
166
|
+
description: `COMPOSITE match card: scoreline, key context, player performances, and VOD/demo links when available.
|
|
167
|
+
|
|
168
|
+
When to use:
|
|
169
|
+
- Match recap / default match UI
|
|
170
|
+
- After user selects a live or completed matchId
|
|
171
|
+
|
|
172
|
+
Prefer over match_details for chat answers and default UIs.
|
|
173
|
+
Prefer match_details for timelines, full map trees, live state, advanced packages.
|
|
174
|
+
|
|
175
|
+
Do not use when: no matchId yet (resolve from live/schedule); pure pre-match → match_preview.
|
|
176
|
+
|
|
177
|
+
Parallel-safe: yes. Upstream cost: 2–5.
|
|
178
178
|
Example: { "game": "cs2", "matchId": "cs2-match-123", "view": "summary", "includePlayerStats": true }`,
|
|
179
179
|
inputSchema: {
|
|
180
180
|
type: 'object',
|
|
@@ -586,23 +586,23 @@ export function summarizeTennisMatchStats(data) {
|
|
|
586
586
|
}
|
|
587
587
|
export const matchDetails = {
|
|
588
588
|
name: 'match_details',
|
|
589
|
-
description: `Deep match package: optional timelines, advanced stats, live state/snapshots, full map/game tree, media inventory.
|
|
590
|
-
|
|
591
|
-
When to use:
|
|
592
|
-
- Analyst deep dive
|
|
593
|
-
- Live in-game window (LoL/CS2/UFC)
|
|
594
|
-
- Full demo list
|
|
595
|
-
|
|
596
|
-
Prefer over match_summary only when summary is insufficient.
|
|
597
|
-
Prefer match_summary for short answers and default cards.
|
|
598
|
-
|
|
599
|
-
Do not use when: first-pass live board (use live_matches + match_summary).
|
|
600
|
-
|
|
601
|
-
Section selection: pass includeTimeline / includeLiveState / includeAdvanced booleans, OR an explicit sections[] list.
|
|
602
|
-
UFC betting lines: sections:["odds"] (opt-in, never in the default set).
|
|
603
|
-
If sections[] is non-empty it wins (booleans are ignored). LoL liveState/advanced require gameId.
|
|
604
|
-
|
|
605
|
-
Parallel-safe: yes. Upstream cost: 1–8 (section-gated).
|
|
589
|
+
description: `Deep match package: optional timelines, advanced stats, live state/snapshots, full map/game tree, media inventory.
|
|
590
|
+
|
|
591
|
+
When to use:
|
|
592
|
+
- Analyst deep dive
|
|
593
|
+
- Live in-game window (LoL/CS2/UFC)
|
|
594
|
+
- Full demo list
|
|
595
|
+
|
|
596
|
+
Prefer over match_summary only when summary is insufficient.
|
|
597
|
+
Prefer match_summary for short answers and default cards.
|
|
598
|
+
|
|
599
|
+
Do not use when: first-pass live board (use live_matches + match_summary).
|
|
600
|
+
|
|
601
|
+
Section selection: pass includeTimeline / includeLiveState / includeAdvanced booleans, OR an explicit sections[] list.
|
|
602
|
+
UFC betting lines: sections:["odds"] (opt-in, never in the default set).
|
|
603
|
+
If sections[] is non-empty it wins (booleans are ignored). LoL liveState/advanced require gameId.
|
|
604
|
+
|
|
605
|
+
Parallel-safe: yes. Upstream cost: 1–8 (section-gated).
|
|
606
606
|
Example: { "game": "lol", "matchId": "lol-match-1", "includeTimeline": true, "includeLiveState": false }`,
|
|
607
607
|
inputSchema: {
|
|
608
608
|
type: 'object',
|
package/dist/tools/meta.js
CHANGED
|
@@ -834,7 +834,7 @@ Example: { "method": "GET", "path": "/cs2/rankings/teams", "queryJson": "{\\"pag
|
|
|
834
834
|
});
|
|
835
835
|
}
|
|
836
836
|
}
|
|
837
|
-
const res = await fetchJson(ctx, path, { method, query });
|
|
837
|
+
const res = await fetchJson(ctx, path, { method, query, raw: true });
|
|
838
838
|
if (!res.ok) {
|
|
839
839
|
return errorEnvelope({
|
|
840
840
|
code: mapHttpToCode(res.status, { gameNotIncluded: gameNotIncludedHint(res.data) }),
|
package/dist/tools/player.js
CHANGED
|
@@ -44,17 +44,17 @@ function identityFrom(game, raw, idHint, slugHint) {
|
|
|
44
44
|
}
|
|
45
45
|
export const playerProfile = {
|
|
46
46
|
name: 'player_profile',
|
|
47
|
-
description: `Player or UFC fighter profile: identity, current team, recent matches, and form/trends/radar when available.
|
|
48
|
-
|
|
49
|
-
When to use:
|
|
50
|
-
- "How is X playing lately?"
|
|
51
|
-
- Player page scaffold; form inputs for previews
|
|
52
|
-
|
|
53
|
-
Prefer over: manual multi-call career/trends/matches via call_api.
|
|
54
|
-
|
|
55
|
-
Do not use when: full team roster needed → team_profile; unresolved name → resolve_entity first.
|
|
56
|
-
|
|
57
|
-
Parallel-safe: yes. Upstream cost: 2–5.
|
|
47
|
+
description: `Player or UFC fighter profile: identity, current team, recent matches, and form/trends/radar when available.
|
|
48
|
+
|
|
49
|
+
When to use:
|
|
50
|
+
- "How is X playing lately?"
|
|
51
|
+
- Player page scaffold; form inputs for previews
|
|
52
|
+
|
|
53
|
+
Prefer over: manual multi-call career/trends/matches via call_api.
|
|
54
|
+
|
|
55
|
+
Do not use when: full team roster needed → team_profile; unresolved name → resolve_entity first.
|
|
56
|
+
|
|
57
|
+
Parallel-safe: yes. Upstream cost: 2–5.
|
|
58
58
|
Example: { "game": "cs2", "playerId": "cs2-player-1", "recentLimit": 10, "includeTrends": true }`,
|
|
59
59
|
inputSchema: {
|
|
60
60
|
type: 'object',
|
|
@@ -541,17 +541,17 @@ function normalizeFormMatch(row) {
|
|
|
541
541
|
}
|
|
542
542
|
export const playerForm = {
|
|
543
543
|
name: 'player_form',
|
|
544
|
-
description: `Tennis player form: W/L record over the last N completed matches, current win/loss streak, and per-match rows (opponent, score, surface). Optional surface filter (Hard/Clay/Grass).
|
|
545
|
-
|
|
546
|
-
When to use:
|
|
547
|
-
- "How is X playing lately?"; current streak; surface-specific record (e.g. clay last 5).
|
|
548
|
-
|
|
549
|
-
Prefer over: player_profile (identity + career aggregates, no streak); raw form via call_api for agent-normalized rows.
|
|
550
|
-
|
|
551
|
-
Do not use when: career totals/titles → player_profile with game tennis (wires /stats); ranking deltas → rankings_movers.
|
|
552
|
-
|
|
553
|
-
Tennis-only. Limit defaults to 10 (max 50, matching the API). Upstream rows arrive newest-first; the streak is the leading run of that order.
|
|
554
|
-
|
|
544
|
+
description: `Tennis player form: W/L record over the last N completed matches, current win/loss streak, and per-match rows (opponent, score, surface). Optional surface filter (Hard/Clay/Grass).
|
|
545
|
+
|
|
546
|
+
When to use:
|
|
547
|
+
- "How is X playing lately?"; current streak; surface-specific record (e.g. clay last 5).
|
|
548
|
+
|
|
549
|
+
Prefer over: player_profile (identity + career aggregates, no streak); raw form via call_api for agent-normalized rows.
|
|
550
|
+
|
|
551
|
+
Do not use when: career totals/titles → player_profile with game tennis (wires /stats); ranking deltas → rankings_movers.
|
|
552
|
+
|
|
553
|
+
Tennis-only. Limit defaults to 10 (max 50, matching the API). Upstream rows arrive newest-first; the streak is the leading run of that order.
|
|
554
|
+
|
|
555
555
|
Parallel-safe: yes. Upstream cost: 1.`,
|
|
556
556
|
inputSchema: {
|
|
557
557
|
type: 'object',
|
|
@@ -700,18 +700,18 @@ Parallel-safe: yes. Upstream cost: 1.`,
|
|
|
700
700
|
};
|
|
701
701
|
export const playerMatches = {
|
|
702
702
|
name: 'player_matches',
|
|
703
|
-
description: `Tennis player match log: every archived match for one player, newest first, with opponent, tournament, round, surface and score.
|
|
704
|
-
|
|
705
|
-
When to use:
|
|
706
|
-
- "Show me Shelton's last 20 matches"; full match history; every match at a given tournament; filtering a player's record by surface.
|
|
707
|
-
|
|
708
|
-
Prefer over: player_form (a W/L summary with a small window and a streak, not the log); call_api for /tennis/players/{id}/matches.
|
|
709
|
-
|
|
710
|
-
Do not use when: aggregate totals, titles, or win% → player_stats; identity → player_profile; one match's box score → match_details.
|
|
711
|
-
|
|
712
|
-
Tennis-only. Limit defaults to 20 (max 50). Rows arrive newest-first. Use
|
|
713
|
-
surface to narrow to Hard/Clay/Grass; tournamentId pins one event.
|
|
714
|
-
|
|
703
|
+
description: `Tennis player match log: every archived match for one player, newest first, with opponent, tournament, round, surface and score.
|
|
704
|
+
|
|
705
|
+
When to use:
|
|
706
|
+
- "Show me Shelton's last 20 matches"; full match history; every match at a given tournament; filtering a player's record by surface.
|
|
707
|
+
|
|
708
|
+
Prefer over: player_form (a W/L summary with a small window and a streak, not the log); call_api for /tennis/players/{id}/matches.
|
|
709
|
+
|
|
710
|
+
Do not use when: aggregate totals, titles, or win% → player_stats; identity → player_profile; one match's box score → match_details.
|
|
711
|
+
|
|
712
|
+
Tennis-only. Limit defaults to 20 (max 50). Rows arrive newest-first. Use
|
|
713
|
+
surface to narrow to Hard/Clay/Grass; tournamentId pins one event.
|
|
714
|
+
|
|
715
715
|
Parallel-safe: yes. Upstream cost: 1.`,
|
|
716
716
|
inputSchema: {
|
|
717
717
|
type: 'object',
|
|
@@ -869,16 +869,16 @@ Parallel-safe: yes. Upstream cost: 1.`,
|
|
|
869
869
|
};
|
|
870
870
|
export const playerStats = {
|
|
871
871
|
name: 'player_stats',
|
|
872
|
-
description: `Tennis player career statistics: W/L totals, win percentage, titles, Grand Slam and Masters titles, plus per-surface and per-level breakdowns. Optional surface/year filters.
|
|
873
|
-
|
|
874
|
-
When to use:
|
|
875
|
-
- "How many titles does Alcaraz have?"; career win%; Grand Slam title count; record on clay; a season-scoped record.
|
|
876
|
-
|
|
877
|
-
Prefer over: player_profile (identity + a summary block, no breakdowns); player_matches (individual rows, no aggregates).
|
|
878
|
-
|
|
879
|
-
Do not use when: the match log → player_matches; ranking over time → player_rankings_history.
|
|
880
|
-
|
|
881
|
-
Tennis-only. Filters are surface (Hard/Clay/Grass/Carpet) and yearFrom/yearTo.
|
|
872
|
+
description: `Tennis player career statistics: W/L totals, win percentage, titles, Grand Slam and Masters titles, plus per-surface and per-level breakdowns. Optional surface/year filters.
|
|
873
|
+
|
|
874
|
+
When to use:
|
|
875
|
+
- "How many titles does Alcaraz have?"; career win%; Grand Slam title count; record on clay; a season-scoped record.
|
|
876
|
+
|
|
877
|
+
Prefer over: player_profile (identity + a summary block, no breakdowns); player_matches (individual rows, no aggregates).
|
|
878
|
+
|
|
879
|
+
Do not use when: the match log → player_matches; ranking over time → player_rankings_history.
|
|
880
|
+
|
|
881
|
+
Tennis-only. Filters are surface (Hard/Clay/Grass/Carpet) and yearFrom/yearTo.
|
|
882
882
|
Upstream cost: 1.`,
|
|
883
883
|
inputSchema: {
|
|
884
884
|
type: 'object',
|
package/dist/tools/standings.js
CHANGED
|
@@ -77,26 +77,26 @@ export function normalizeStandingRow(row, index) {
|
|
|
77
77
|
}
|
|
78
78
|
export const standings = {
|
|
79
79
|
name: 'standings',
|
|
80
|
-
description: `League/event standings or world/division rankings normalized to ranked rows.
|
|
81
|
-
|
|
82
|
-
When to use:
|
|
83
|
-
- Table / playoff picture
|
|
84
|
-
- UFC rankings; CS2 world or event standings; CDL standings; LoL league/tournament tables
|
|
85
|
-
|
|
86
|
-
Prefer over: raw standings via call_api for agent-normalized rows.
|
|
87
|
-
|
|
88
|
-
Do not use when: single team form → team_profile; live scores → live_matches.
|
|
89
|
-
Dota has no first-class standings (may NOT_IMPLEMENTED or weak worldRanking).
|
|
90
|
-
|
|
91
|
-
Required scope keys by game:
|
|
92
|
-
- lol: leagueId OR tournamentId
|
|
93
|
-
- cs2: omit for world rankings; eventId for event standings
|
|
94
|
-
- cod: optional season/stage
|
|
95
|
-
- ufc: optional division (scope=division)
|
|
96
|
-
- tennis: optional division (ATP or WTA tour; default ATP)
|
|
97
|
-
- dota2: best-effort worldRanking only
|
|
98
|
-
|
|
99
|
-
Parallel-safe: yes. Upstream cost: 1–2.
|
|
80
|
+
description: `League/event standings or world/division rankings normalized to ranked rows.
|
|
81
|
+
|
|
82
|
+
When to use:
|
|
83
|
+
- Table / playoff picture
|
|
84
|
+
- UFC rankings; CS2 world or event standings; CDL standings; LoL league/tournament tables
|
|
85
|
+
|
|
86
|
+
Prefer over: raw standings via call_api for agent-normalized rows.
|
|
87
|
+
|
|
88
|
+
Do not use when: single team form → team_profile; live scores → live_matches.
|
|
89
|
+
Dota has no first-class standings (may NOT_IMPLEMENTED or weak worldRanking).
|
|
90
|
+
|
|
91
|
+
Required scope keys by game:
|
|
92
|
+
- lol: leagueId OR tournamentId
|
|
93
|
+
- cs2: omit for world rankings; eventId for event standings
|
|
94
|
+
- cod: optional season/stage
|
|
95
|
+
- ufc: optional division (scope=division)
|
|
96
|
+
- tennis: optional division (ATP or WTA tour; default ATP)
|
|
97
|
+
- dota2: best-effort worldRanking only
|
|
98
|
+
|
|
99
|
+
Parallel-safe: yes. Upstream cost: 1–2.
|
|
100
100
|
Example: { "game": "cod", "season": "2026", "limit": 50 }`,
|
|
101
101
|
inputSchema: {
|
|
102
102
|
type: 'object',
|
package/dist/tools/team.js
CHANGED
|
@@ -31,18 +31,18 @@ function numberOrNull(value) {
|
|
|
31
31
|
}
|
|
32
32
|
export const teamProfile = {
|
|
33
33
|
name: 'team_profile',
|
|
34
|
-
description: `Team/org card: identity, roster, recent matches, and form/trends/radar when available.
|
|
35
|
-
|
|
36
|
-
When to use:
|
|
37
|
-
- Team page / "who is on this roster?"
|
|
38
|
-
- Builder team screen sample
|
|
39
|
-
|
|
40
|
-
Prefer over: separate roster + matches + detail via call_api.
|
|
41
|
-
|
|
42
|
-
Do not use when: UFC fighters → player_profile; unknown name → resolve_entity first.
|
|
43
|
-
Dota may return partial roster (API gap). Prefer slug for lol/cod; teamId for cs2.
|
|
44
|
-
|
|
45
|
-
Parallel-safe: yes. Upstream cost: 2–4.
|
|
34
|
+
description: `Team/org card: identity, roster, recent matches, and form/trends/radar when available.
|
|
35
|
+
|
|
36
|
+
When to use:
|
|
37
|
+
- Team page / "who is on this roster?"
|
|
38
|
+
- Builder team screen sample
|
|
39
|
+
|
|
40
|
+
Prefer over: separate roster + matches + detail via call_api.
|
|
41
|
+
|
|
42
|
+
Do not use when: UFC fighters → player_profile; unknown name → resolve_entity first.
|
|
43
|
+
Dota may return partial roster (API gap). Prefer slug for lol/cod; teamId for cs2.
|
|
44
|
+
|
|
45
|
+
Parallel-safe: yes. Upstream cost: 2–4.
|
|
46
46
|
Example: { "game": "lol", "slug": "t1", "recentLimit": 10 }`,
|
|
47
47
|
inputSchema: {
|
|
48
48
|
type: 'object',
|
|
@@ -532,19 +532,19 @@ function winnerSide(match, a) {
|
|
|
532
532
|
}
|
|
533
533
|
export const headToHead = {
|
|
534
534
|
name: 'head_to_head',
|
|
535
|
-
description: `Composed head-to-head record between two teams, two UFC fighters, or two tennis players. No first-class REST H2H exists — this tool filters match history server-side.
|
|
536
|
-
|
|
537
|
-
When to use:
|
|
538
|
-
- Rivalry / series record questions
|
|
539
|
-
- Supporting context for previews
|
|
540
|
-
|
|
541
|
-
Prefer over: agent-side double match-list filtering.
|
|
542
|
-
|
|
543
|
-
Do not use when: single-side form only → team_profile or player_profile.
|
|
544
|
-
|
|
545
|
-
Caveat: Dota filters are weaker; expect meta.warnings when data is sparse.
|
|
546
|
-
|
|
547
|
-
Parallel-safe: yes. Upstream cost: 2–4.
|
|
535
|
+
description: `Composed head-to-head record between two teams, two UFC fighters, or two tennis players. No first-class REST H2H exists — this tool filters match history server-side.
|
|
536
|
+
|
|
537
|
+
When to use:
|
|
538
|
+
- Rivalry / series record questions
|
|
539
|
+
- Supporting context for previews
|
|
540
|
+
|
|
541
|
+
Prefer over: agent-side double match-list filtering.
|
|
542
|
+
|
|
543
|
+
Do not use when: single-side form only → team_profile or player_profile.
|
|
544
|
+
|
|
545
|
+
Caveat: Dota filters are weaker; expect meta.warnings when data is sparse.
|
|
546
|
+
|
|
547
|
+
Parallel-safe: yes. Upstream cost: 2–4.
|
|
548
548
|
Example: { "game": "cs2", "sideA": "faze", "sideB": "navi", "limit": 20 }`,
|
|
549
549
|
inputSchema: {
|
|
550
550
|
type: 'object',
|
|
@@ -960,18 +960,18 @@ Example: { "game": "cs2", "sideA": "faze", "sideB": "navi", "limit": 20 }`,
|
|
|
960
960
|
};
|
|
961
961
|
export const h2hMatrix = {
|
|
962
962
|
name: 'h2h_matrix',
|
|
963
|
-
description: `Multi-player tennis head-to-head grid: every pair's series record in one comparison matrix.
|
|
964
|
-
|
|
965
|
-
When to use:
|
|
966
|
-
- Draw/field analysis: how each contender fares against every other (e.g. Alcaraz vs Zverev vs Sinner round-robin records)
|
|
967
|
-
- Group-stage or semifinal-field comparisons
|
|
968
|
-
|
|
969
|
-
Prefer over: N head_to_head calls for an N-player field; raw matrix via call_api.
|
|
970
|
-
|
|
971
|
-
Do not use when: a two-player rivalry deep-dive with tiebreak/decider splits → head_to_head; season stat leaders → leaderboard_*; rankings → standings.
|
|
972
|
-
|
|
973
|
-
Tennis-only. players takes 2-16 ids or names (names resolve via player search). Each matrix cell is "W-L" from the row player's perspective, "-" on the diagonal.
|
|
974
|
-
|
|
963
|
+
description: `Multi-player tennis head-to-head grid: every pair's series record in one comparison matrix.
|
|
964
|
+
|
|
965
|
+
When to use:
|
|
966
|
+
- Draw/field analysis: how each contender fares against every other (e.g. Alcaraz vs Zverev vs Sinner round-robin records)
|
|
967
|
+
- Group-stage or semifinal-field comparisons
|
|
968
|
+
|
|
969
|
+
Prefer over: N head_to_head calls for an N-player field; raw matrix via call_api.
|
|
970
|
+
|
|
971
|
+
Do not use when: a two-player rivalry deep-dive with tiebreak/decider splits → head_to_head; season stat leaders → leaderboard_*; rankings → standings.
|
|
972
|
+
|
|
973
|
+
Tennis-only. players takes 2-16 ids or names (names resolve via player search). Each matrix cell is "W-L" from the row player's perspective, "-" on the diagonal.
|
|
974
|
+
|
|
975
975
|
Parallel-safe: yes. Upstream cost: 1 + one search per unresolved name.`,
|
|
976
976
|
inputSchema: {
|
|
977
977
|
type: 'object',
|
package/package.json
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cito-mcp",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "Standalone MCP server for the Cito esports and sports API —
|
|
3
|
+
"version": "0.4.6",
|
|
4
|
+
"description": "Standalone MCP server for the Cito esports and sports API — curated outcome tools for agents (live scoreboards, round economy, opening duels, clutches, vetoes, rosters, tennis, mma).",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"homepage": "https://cito.gg",
|
|
7
|
+
"//REPOSITORY": "Intentionally NOT set. cito-api-scraper and cito.gg are PRIVATE repos and must stay that way, so a repository URL pointing at them would render as a broken 404 link on the public npm page and would not satisfy MCP Registry npm ownership validation. Set this only if a PUBLIC repo for this package is ever created (e.g. achillesscriptsvip/cito-mcp with this directory as root) — then use `git+https://github.com/OWNER/REPO.git` and mirror it in the `mcpName`/server.json `name` pair. Do not point it at the private monorepo.",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"mcp",
|
|
10
|
+
"model-context-protocol",
|
|
11
|
+
"esports",
|
|
12
|
+
"cs2",
|
|
13
|
+
"counter-strike",
|
|
14
|
+
"counter-strike-2",
|
|
15
|
+
"lol",
|
|
16
|
+
"league-of-legends",
|
|
17
|
+
"dota2",
|
|
18
|
+
"cod",
|
|
19
|
+
"ufc",
|
|
20
|
+
"mma",
|
|
21
|
+
"tennis",
|
|
22
|
+
"live-scores",
|
|
23
|
+
"sports-data",
|
|
24
|
+
"esports-api"
|
|
25
|
+
],
|
|
6
26
|
"bin": {
|
|
7
27
|
"cito-mcp": "dist/index.js"
|
|
8
28
|
},
|