@claudinho/mcp 0.11.0 → 0.11.1
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 +5 -4
- package/dist/index.js +43 -18
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**An MCP server with live football scores, fixtures, standings and paste-ready match cards for
|
|
4
4
|
the competition you follow: the World Cup, the Premier League, LALIGA, the Champions League and
|
|
5
|
-
|
|
5
|
+
12 more.** Ask your agent in Claude Code, Cursor, Codex, Claude Desktop, Windsurf, Zed, VS Code,
|
|
6
6
|
or any MCP client (stdio). No API key, no signup. The World Cup's 104 fixtures ship bundled; the
|
|
7
7
|
other competitions' schedules are read from the feed, and live scores (and the optional,
|
|
8
8
|
read-only Polymarket signals for the World Cup) hit the network. It ran the 2026 World Cup from
|
|
@@ -86,9 +86,10 @@ match's `stage` is the written one (`REGULAR` for a league's season, `LEAGUE` fo
|
|
|
86
86
|
league phase, `PO` for play-offs), or `OTHER` with the provider's own words in `stageLabel`.
|
|
87
87
|
|
|
88
88
|
Resources: `standings://{group}` (its text starts with the competition it is for, like a tool's), `fixtures://{date}` (the bundled World Cup schedule, named first, whatever the competition). Prompts: `tournament_today`,
|
|
89
|
-
and `my_team` (the
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
and `my_team` (the competition you follow: give it a club's or a nation's code or name, or
|
|
90
|
+
none for your team (the server's `CLAUDINHO_TEAM`, else the one pinned with `claudinho follow --team`);
|
|
91
|
+
it asks for the next fixture with its date and state and the team's standing, and on the World Cup
|
|
92
|
+
for the prediction-market read of that fixture).
|
|
92
93
|
|
|
93
94
|
## Market signals
|
|
94
95
|
|
package/dist/index.js
CHANGED
|
@@ -4074,6 +4074,7 @@ var SUPPORTED = Object.freeze(
|
|
|
4074
4074
|
{ slug: "ita.1", alias: "serie-a", name: "Serie A", teams: "club", kind: "league", seasonSlug: "italian-serie-a", standings: "league", bracket: "not-offered-yet", markets: "not-offered-yet", cadenceYears: 1 },
|
|
4075
4075
|
{ slug: "ger.1", alias: "bundesliga", name: "Bundesliga", teams: "club", kind: "league", seasonSlug: "german-bundesliga", standings: "league", bracket: "not-offered-yet", markets: "not-offered-yet", cadenceYears: 1 },
|
|
4076
4076
|
{ slug: "mex.1", alias: "liga-mx", name: "Liga MX", teams: "club", kind: "league", standings: "league", bracket: "not-offered-yet", markets: "not-offered-yet", cadenceYears: 1 },
|
|
4077
|
+
{ slug: "uru.1", alias: "liga-auf", name: "Liga AUF Uruguaya", teams: "club", kind: "league", standings: "league", bracket: "not-offered-yet", markets: "not-offered-yet", cadenceYears: 1 },
|
|
4077
4078
|
{ slug: "uefa.champions", alias: "champions-league", name: "Champions League", teams: "club", kind: "cup", standings: "league", bracket: "not-offered-yet", markets: "not-offered-yet", cadenceYears: 1 },
|
|
4078
4079
|
{ slug: "conmebol.libertadores", alias: "libertadores", name: "Libertadores", teams: "club", kind: "cup", standings: "groups", bracket: "not-offered-yet", markets: "not-offered-yet", cadenceYears: 1 },
|
|
4079
4080
|
{ slug: "concacaf.champions", alias: "concacaf-champions-cup", name: "Concacaf Champions Cup", teams: "club", kind: "cup", standings: "none", bracket: "not-offered-yet", markets: "not-offered-yet", cadenceYears: 1 },
|
|
@@ -4727,7 +4728,7 @@ function fetchMeta(result) {
|
|
|
4727
4728
|
}
|
|
4728
4729
|
var ESPN_SOCCER = "https://site.api.espn.com/apis/site/v2/sports/soccer";
|
|
4729
4730
|
var DEFAULT_COMPETITION = BUNDLED_SLUG;
|
|
4730
|
-
var USER_AGENT = `claudinho/${"0.11.
|
|
4731
|
+
var USER_AGENT = `claudinho/${"0.11.1"} (+https://github.com/arturogarrido/claudinho)`;
|
|
4731
4732
|
var MAX_RESPONSE_BYTES = 5 * 1024 * 1024;
|
|
4732
4733
|
var DEFAULT_COOLDOWN_MS = 5 * 6e4;
|
|
4733
4734
|
var MAX_COOLDOWN_MS = 15 * 6e4;
|
|
@@ -8149,7 +8150,7 @@ function capSignals(signals, kept) {
|
|
|
8149
8150
|
// src/tools.ts
|
|
8150
8151
|
import { homedir } from "os";
|
|
8151
8152
|
var adapters = /* @__PURE__ */ new Map();
|
|
8152
|
-
var KEPT_ADAPTERS_MAX =
|
|
8153
|
+
var KEPT_ADAPTERS_MAX = 2 * SUPPORTED.length;
|
|
8153
8154
|
var sourceWindows = /* @__PURE__ */ new Map();
|
|
8154
8155
|
function throttleable(adapter) {
|
|
8155
8156
|
const t2 = adapter;
|
|
@@ -9054,7 +9055,7 @@ async function shareAnswer(args) {
|
|
|
9054
9055
|
|
|
9055
9056
|
// src/server.ts
|
|
9056
9057
|
var SERVER_NAME = "claudinho";
|
|
9057
|
-
var SERVER_VERSION = "0.11.
|
|
9058
|
+
var SERVER_VERSION = "0.11.1";
|
|
9058
9059
|
var VOICE = asFlavorLevel(process.env.CLAUDINHO_FLAVOR) === "off" ? "" : `
|
|
9059
9060
|
Voice: when relaying scores, narrate with lively, regionally-appropriate football-commentary energy in the user's language. Each match line may end with a short exclamation ("\u2014 \xA1GOOOOL!"): use it as a tone cue. Keep every fact exact; never invent details and never impersonate or name a real commentator.`;
|
|
9060
9061
|
var INSTRUCTIONS = `Claudinho serves live scores, fixtures, and standings for one football competition per request, chosen by the tool call's competition argument (an alias such as premier-league, or an ESPN slug such as eng.1), else the server's CLAUDINHO_COMPETITION, else the user's saved choice (set with claudinho follow <alias>). With none of the three, every competition-answering tool answers noCompetition with a sentence saying what to do: pass competition, or ask the user to run claudinho follow <alias>. list_competitions lists the supported competitions, their aliases and what each offers, offline. Every tool's text but get_team's, get_share_snippet's and list_competitions' starts with the competition it is for, and its structured data carries it as competition (get_share_snippet's card names it in its title; list_competitions says it last, as Current, and in data.current; get_team is the World Cup's roster). An unknown competition is a tool error that lists the aliases.
|
|
@@ -9696,28 +9697,52 @@ ${matchList(fixturesByDate(date, void 0, "UTC"), `No matches on ${date}.`)}`;
|
|
|
9696
9697
|
]
|
|
9697
9698
|
})
|
|
9698
9699
|
);
|
|
9699
|
-
|
|
9700
|
+
const myTeamArgs = {
|
|
9701
|
+
team: clubArg.optional().describe(
|
|
9702
|
+
"A club's or a nation's code or name in the competition you follow, e.g. Arsenal, ARS, Mexico or MEX. Omit it for your team: the server's CLAUDINHO_TEAM when it is set, else the one pinned with claudinho follow --team"
|
|
9703
|
+
)
|
|
9704
|
+
};
|
|
9705
|
+
const myTeam = server.registerPrompt(
|
|
9700
9706
|
"my_team",
|
|
9701
9707
|
{
|
|
9702
9708
|
title: "My team",
|
|
9703
|
-
description: "Focus on one
|
|
9704
|
-
argsSchema:
|
|
9709
|
+
description: "Focus on one team's next match in the competition you follow: its date and state, the team's standing in the table, and, on the World Cup, the prediction-market read.",
|
|
9710
|
+
argsSchema: myTeamArgs
|
|
9705
9711
|
},
|
|
9706
9712
|
({ team: asked }) => {
|
|
9707
|
-
const team = humanLabel(asked, 40);
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9713
|
+
const team = asked === void 0 ? "" : humanLabel(asked, 40);
|
|
9714
|
+
const text = [
|
|
9715
|
+
team ? `Tell me about ${team}'s next match and ${team}'s current standing.` : "Tell me about my team's next match and its current standing.",
|
|
9716
|
+
"Call each tool for the competition I follow: pass no competition argument (the server's competition applies, else my saved choice).",
|
|
9717
|
+
"If a tool answers noCompetition, tell me to run claudinho follow <alias> and stop.",
|
|
9718
|
+
"If a tool answers an error naming the competitions, relay it and stop.",
|
|
9719
|
+
...team ? [
|
|
9720
|
+
`Call get_next_fixture with ${team} as team (a team's code or name).`,
|
|
9721
|
+
"If it answers unknownTeam, relay that answer as it is, then ask me which team and stop."
|
|
9722
|
+
] : [
|
|
9723
|
+
"Call get_next_fixture with no team: it answers for my team, the server's CLAUDINHO_TEAM when it is set, else the team I pinned for this competition with claudinho follow --team.",
|
|
9724
|
+
"It answers an error when no team was given, the server's CLAUDINHO_TEAM is unset and none is pinned for this competition, or when CLAUDINHO_TEAM holds nothing readable: then ask me which team and stop.",
|
|
9725
|
+
"If it answers unknownTeam, relay that answer as it is, then ask me which team and stop."
|
|
9726
|
+
],
|
|
9727
|
+
"Always state the fixture's date and its state (scheduled, in play or finished), and call it in play only when the state says so: a next fixture is not a match happening now.",
|
|
9728
|
+
"If get_next_fixture answers no fixture, relay that answer as it is, with its horizon or its verdict when it carries one, and never invent a fixture.",
|
|
9729
|
+
"Name the competition the answer names.",
|
|
9730
|
+
`For the standing, call get_standings and read ${team ? `${team}'s` : "that team's"} row of its table (its group, or the league table).`,
|
|
9731
|
+
"When the competition has no table, or the answer says tables could not be read, say so.",
|
|
9732
|
+
"Only when the competition is the World Cup and get_next_fixture returned a fixture, also call get_market_signal with matchId set to that fixture's id (fixture.id in its data), never with the team's code, and relay what prediction markets say about that match.",
|
|
9733
|
+
"In any other competition, do not call get_market_signal and say nothing about markets.",
|
|
9734
|
+
"When you relay market percentages, treat them as informational context only: relay them factually, never as betting or trading advice."
|
|
9735
|
+
].join(" ");
|
|
9736
|
+
return { messages: [{ role: "user", content: { type: "text", text } }] };
|
|
9719
9737
|
}
|
|
9720
9738
|
);
|
|
9739
|
+
const blankTeamIsNone = (v) => {
|
|
9740
|
+
if (v === void 0 || v === null) return {};
|
|
9741
|
+
if (typeof v !== "object") return v;
|
|
9742
|
+
const { team, ...rest } = v;
|
|
9743
|
+
return typeof team === "string" && /^ *$/.test(team) ? rest : v;
|
|
9744
|
+
};
|
|
9745
|
+
myTeam.argsSchema = Object.assign(z.preprocess(blankTeamIsNone, z.object(myTeamArgs)), { shape: myTeamArgs });
|
|
9721
9746
|
return server;
|
|
9722
9747
|
}
|
|
9723
9748
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claudinho/mcp",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"mcpName": "io.github.arturogarrido/claudinho",
|
|
5
|
-
"description": "An MCP server with live football scores, fixtures, standings and paste-ready match cards for the competition you follow: the World Cup, the Premier League, LALIGA, the Champions League and
|
|
5
|
+
"description": "An MCP server with live football scores, fixtures, standings and paste-ready match cards for the competition you follow: the World Cup, the Premier League, LALIGA, the Champions League and 12 more. Works with Claude Code, Cursor, Codex, Claude Desktop, Windsurf, Zed and any MCP client. No API key. Independent fan project. Not affiliated with FIFA, any confederation, league or club, or Anthropic.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"author": "Arturo Garrido",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"serie-a",
|
|
58
58
|
"bundesliga",
|
|
59
59
|
"liga-mx",
|
|
60
|
+
"liga-auf",
|
|
60
61
|
"champions-league",
|
|
61
62
|
"libertadores",
|
|
62
63
|
"concacaf-champions-cup",
|
|
@@ -72,7 +73,7 @@
|
|
|
72
73
|
"tsup": "^8.0.0",
|
|
73
74
|
"typescript": "^5.7.0",
|
|
74
75
|
"vitest": "^5.0.3",
|
|
75
|
-
"@claudinho/core": "0.11.
|
|
76
|
+
"@claudinho/core": "0.11.1"
|
|
76
77
|
},
|
|
77
78
|
"scripts": {
|
|
78
79
|
"build": "tsup",
|