@claudinho/mcp 0.8.4 → 0.8.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/dist/index.js +37 -12
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -302,8 +302,8 @@ var ES = {
|
|
|
302
302
|
"bracket.invalidStage": "La fase debe ser una de: R32, R16, QF, SF, 3P, F",
|
|
303
303
|
"bracket.unknownStage": 'Fase desconocida "{stage}". Usa R32, R16, QF, SF, 3P o F.',
|
|
304
304
|
"bracket.slot.groupWinner": "Ganador del grupo {group}",
|
|
305
|
-
"bracket.slot.groupSecond": "2
|
|
306
|
-
"bracket.slot.third": "3
|
|
305
|
+
"bracket.slot.groupSecond": "2\xBA del grupo {group}",
|
|
306
|
+
"bracket.slot.third": "3\xBA ({groups})",
|
|
307
307
|
"bracket.slot.winner": "Ganador {stage} {n}",
|
|
308
308
|
"bracket.slot.loser": "Perdedor {stage} {n}",
|
|
309
309
|
"bracket.slot.tbd": "Por definir",
|
|
@@ -3047,6 +3047,18 @@ function hasGroupStarted(group, tables) {
|
|
|
3047
3047
|
if (!table?.rows.length) return false;
|
|
3048
3048
|
return table.rows.some((r) => r.played > 0);
|
|
3049
3049
|
}
|
|
3050
|
+
function matchesPerTeamInGroup(teamCount) {
|
|
3051
|
+
return Math.max(0, teamCount - 1);
|
|
3052
|
+
}
|
|
3053
|
+
function isGroupStandingsComplete(table) {
|
|
3054
|
+
const n = table?.rows.length ?? 0;
|
|
3055
|
+
if (n < 2) return false;
|
|
3056
|
+
const required = matchesPerTeamInGroup(n);
|
|
3057
|
+
return table.rows.every((r) => r.played >= required);
|
|
3058
|
+
}
|
|
3059
|
+
function isGroupComplete(group, tables) {
|
|
3060
|
+
return isGroupStandingsComplete(tables.find((t2) => t2.group === group));
|
|
3061
|
+
}
|
|
3050
3062
|
function resolveWinner(match) {
|
|
3051
3063
|
if (!isFinished(match.status)) return void 0;
|
|
3052
3064
|
if (match.winnerCode) {
|
|
@@ -3082,25 +3094,36 @@ function participant(team, status) {
|
|
|
3082
3094
|
function tbd(label) {
|
|
3083
3095
|
return { label, flag: "\u{1F3F3}\uFE0F", status: "tbd" };
|
|
3084
3096
|
}
|
|
3097
|
+
function confirmedLiveParticipant(team) {
|
|
3098
|
+
if (!team || team.flag === "\u{1F3F3}\uFE0F") return void 0;
|
|
3099
|
+
return participant(team, "confirmed");
|
|
3100
|
+
}
|
|
3085
3101
|
function winnerLabel(ctx, stage, index) {
|
|
3086
3102
|
return t(ctx.lang, "bracket.slot.winner", {
|
|
3087
3103
|
stage: stageLabelI18n(ctx.lang, stage),
|
|
3088
3104
|
n: String(index)
|
|
3089
3105
|
});
|
|
3090
3106
|
}
|
|
3091
|
-
function resolveSlot(ref, ctx) {
|
|
3107
|
+
function resolveSlot(ref, ctx, liveTeam) {
|
|
3108
|
+
const liveParticipant = confirmedLiveParticipant(liveTeam);
|
|
3092
3109
|
switch (ref.kind) {
|
|
3093
3110
|
case "seed":
|
|
3111
|
+
if (liveParticipant) return liveParticipant;
|
|
3094
3112
|
return tbd(ref.label);
|
|
3095
3113
|
case "group": {
|
|
3114
|
+
if (liveParticipant) return liveParticipant;
|
|
3096
3115
|
if (!ctx.standingsDegraded && hasGroupStarted(ref.group, ctx.tables)) {
|
|
3097
3116
|
const team = teamFromStandings(ref.group, ref.position, ctx.tables);
|
|
3098
|
-
if (team)
|
|
3117
|
+
if (team) {
|
|
3118
|
+
const status = isGroupComplete(ref.group, ctx.tables) ? "confirmed" : "projected";
|
|
3119
|
+
return participant(team, status);
|
|
3120
|
+
}
|
|
3099
3121
|
}
|
|
3100
3122
|
const label = ref.position === 1 ? t(ctx.lang, "bracket.slot.groupWinner", { group: ref.group }) : t(ctx.lang, "bracket.slot.groupSecond", { group: ref.group });
|
|
3101
3123
|
return tbd(label);
|
|
3102
3124
|
}
|
|
3103
3125
|
case "third":
|
|
3126
|
+
if (liveParticipant) return liveParticipant;
|
|
3104
3127
|
return tbd(t(ctx.lang, "bracket.slot.third", { groups: ref.groups.join("/") }));
|
|
3105
3128
|
case "winner": {
|
|
3106
3129
|
const node = ctx.nodesByKey.get(matchKey(ref.stage, ref.index));
|
|
@@ -3109,6 +3132,7 @@ function resolveSlot(ref, ctx) {
|
|
|
3109
3132
|
const winner = resolveWinner(match);
|
|
3110
3133
|
if (winner) return participant(winner, "confirmed");
|
|
3111
3134
|
}
|
|
3135
|
+
if (liveParticipant) return liveParticipant;
|
|
3112
3136
|
return tbd(winnerLabel(ctx, ref.stage, ref.index));
|
|
3113
3137
|
}
|
|
3114
3138
|
case "loser": {
|
|
@@ -3118,6 +3142,7 @@ function resolveSlot(ref, ctx) {
|
|
|
3118
3142
|
const loser = resolveLoser(match);
|
|
3119
3143
|
if (loser) return participant(loser, "confirmed");
|
|
3120
3144
|
}
|
|
3145
|
+
if (liveParticipant) return liveParticipant;
|
|
3121
3146
|
return tbd(
|
|
3122
3147
|
t(ctx.lang, "bracket.slot.loser", {
|
|
3123
3148
|
stage: stageLabelI18n(ctx.lang, ref.stage),
|
|
@@ -3155,8 +3180,8 @@ function buildBracketView(topology, matches, tables, standingsDegraded, liveDegr
|
|
|
3155
3180
|
stage: node.stage,
|
|
3156
3181
|
index: node.index,
|
|
3157
3182
|
kickoff: match.kickoff,
|
|
3158
|
-
home: resolveSlot(node.home, ctx),
|
|
3159
|
-
away: resolveSlot(node.away, ctx),
|
|
3183
|
+
home: resolveSlot(node.home, ctx, match.home),
|
|
3184
|
+
away: resolveSlot(node.away, ctx, match.away),
|
|
3160
3185
|
match
|
|
3161
3186
|
};
|
|
3162
3187
|
});
|
|
@@ -4650,7 +4675,7 @@ ${matchList(todays, "No matches scheduled.", opts)}`;
|
|
|
4650
4675
|
if (degraded) text += "\n\n(Live scores unavailable \u2014 showing the bundled schedule.)";
|
|
4651
4676
|
const marketSignals = await reliableMarketData(args, todays);
|
|
4652
4677
|
return {
|
|
4653
|
-
text: withDisclaimer(text, source),
|
|
4678
|
+
text: withDisclaimer(text, source, args.lang),
|
|
4654
4679
|
data: {
|
|
4655
4680
|
date,
|
|
4656
4681
|
degraded,
|
|
@@ -4668,7 +4693,7 @@ async function toolGetLive(args = {}) {
|
|
|
4668
4693
|
const text = degraded ? "Live scores unavailable right now \u2014 could not reach the data provider." : `Live now:
|
|
4669
4694
|
${matchList(matches, "No matches in play right now.", opts)}`;
|
|
4670
4695
|
return {
|
|
4671
|
-
text: withDisclaimer(text, source),
|
|
4696
|
+
text: withDisclaimer(text, source, args.lang),
|
|
4672
4697
|
data: { degraded, source: source ?? null, count: matches.length, matches }
|
|
4673
4698
|
};
|
|
4674
4699
|
}
|
|
@@ -4689,7 +4714,7 @@ async function toolGetMatch(args) {
|
|
|
4689
4714
|
${marketBlock(marketSignal, match).join("\n")}` : base;
|
|
4690
4715
|
if (degraded) text += "\n\n(Live state unavailable \u2014 showing the scheduled fixture.)";
|
|
4691
4716
|
return {
|
|
4692
|
-
text: withDisclaimer(text, liveSource),
|
|
4717
|
+
text: withDisclaimer(text, liveSource, args.lang),
|
|
4693
4718
|
data: {
|
|
4694
4719
|
degraded,
|
|
4695
4720
|
source: liveSource ?? null,
|
|
@@ -4705,14 +4730,14 @@ async function toolGetStandings(args) {
|
|
|
4705
4730
|
const g = args.group?.toUpperCase();
|
|
4706
4731
|
const msg = g ? `No group "${g}". Groups are A\u2013L.` : "No standings available.";
|
|
4707
4732
|
return {
|
|
4708
|
-
text: withDisclaimer(degraded ? `${msg} (Live standings unavailable.)` : msg, source),
|
|
4733
|
+
text: withDisclaimer(degraded ? `${msg} (Live standings unavailable.)` : msg, source, args.lang),
|
|
4709
4734
|
data: { degraded, source: source ?? null, tables: args.group ? null : [] }
|
|
4710
4735
|
};
|
|
4711
4736
|
}
|
|
4712
4737
|
let text = shaped.map((t2) => standingsTable(t2.group, t2.standings)).join("\n\n");
|
|
4713
4738
|
if (degraded) text += "\n\n(Live standings unavailable \u2014 showing the group roster.)";
|
|
4714
4739
|
return {
|
|
4715
|
-
text: withDisclaimer(text, source),
|
|
4740
|
+
text: withDisclaimer(text, source, args.lang),
|
|
4716
4741
|
data: { degraded, source: source ?? null, tables: args.group ? shaped[0] ?? null : shaped }
|
|
4717
4742
|
};
|
|
4718
4743
|
}
|
|
@@ -5031,7 +5056,7 @@ async function toolGetShareSnippet(args) {
|
|
|
5031
5056
|
|
|
5032
5057
|
// src/server.ts
|
|
5033
5058
|
var SERVER_NAME = "claudinho";
|
|
5034
|
-
var SERVER_VERSION = "0.8.
|
|
5059
|
+
var SERVER_VERSION = "0.8.6";
|
|
5035
5060
|
var VOICE = asFlavorLevel(process.env.CLAUDINHO_FLAVOR) === "off" ? "" : `
|
|
5036
5061
|
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!") \u2014 use it as a tone cue. Keep every fact exact; never invent details and never impersonate or name a real commentator.`;
|
|
5037
5062
|
var INSTRUCTIONS = `Claudinho serves live scores, fixtures, and group standings for the 2026 men's football tournament.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claudinho/mcp",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
4
|
"mcpName": "io.github.arturogarrido/claudinho",
|
|
5
5
|
"description": "MCP server for the 2026 men's football tournament — live scores, fixtures, standings, read-only prediction-market signals, and paste-ready match cards. Works with Claude Code, Cursor, Codex, Windsurf, Zed. Not affiliated with FIFA or Anthropic.",
|
|
6
6
|
"type": "module",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"tsup": "^8.0.0",
|
|
58
58
|
"typescript": "^5.7.0",
|
|
59
59
|
"vitest": "^4.1.9",
|
|
60
|
-
"@claudinho/core": "0.8.
|
|
60
|
+
"@claudinho/core": "0.8.6"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "tsup",
|