@semanticintent/semantic-chirp-intelligence-mcp 4.0.1 → 4.0.2
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/.chirp-data/roster.json
CHANGED
|
@@ -81,7 +81,7 @@ export class DraftPickAnalysis extends AnalysisTemplate {
|
|
|
81
81
|
draftResultsAvailable: false,
|
|
82
82
|
manualDraftedCount: draftedNames.size,
|
|
83
83
|
rosterPositions,
|
|
84
|
-
playoffWindow: this.resolvePlayoffWindow(
|
|
84
|
+
playoffWindow: this.resolvePlayoffWindow(args),
|
|
85
85
|
poolCaveat: rawData.pool_caveat
|
|
86
86
|
};
|
|
87
87
|
}
|
|
@@ -127,26 +127,38 @@ export class DraftPickAnalysis extends AnalysisTemplate {
|
|
|
127
127
|
const contract = this.mergeContractWithDefaults(semanticContract);
|
|
128
128
|
const enhanced = ChirpIntelligence.enhance(this.toolName, analysisResults, contract);
|
|
129
129
|
const top = analysisResults.candidates[0];
|
|
130
|
+
// The playoff clause is only truthful when a window was actually resolved.
|
|
131
|
+
const windowResolved = analysisResults.playoff_window?.resolved === true;
|
|
132
|
+
const scheduleClause = top && windowResolved && top.playoff_games !== null
|
|
133
|
+
? `, and ${top.team} plays ${top.playoff_games} games in your playoff window`
|
|
134
|
+
: '';
|
|
130
135
|
let chirp;
|
|
131
136
|
if (!top) {
|
|
132
137
|
chirp = 'Nobody left worth chirping about. Either the pool is empty or everyone is drafted.';
|
|
133
138
|
}
|
|
134
139
|
else if (top.adp_delta !== null && top.adp_delta >= 12) {
|
|
140
|
+
// v4 has no market ADP. average_pick is this player's rank by production,
|
|
141
|
+
// so the claim is "better player than this slot", not "the room drafts
|
|
142
|
+
// him earlier" — nothing here knows what a room does.
|
|
135
143
|
chirp =
|
|
136
|
-
`${top.name} is
|
|
137
|
-
`
|
|
138
|
-
`
|
|
144
|
+
`${top.name} is the ${this.ordinal(top.average_pick ?? 0)} best producer left and you are ` +
|
|
145
|
+
`picking at ${analysisResults.pick_number}. That is ${Math.round(top.adp_delta)} slots of ` +
|
|
146
|
+
`talent above where you are sitting${scheduleClause}.`;
|
|
139
147
|
}
|
|
140
148
|
else if (top.fills_need) {
|
|
141
149
|
chirp =
|
|
142
|
-
`${top.name} fills the hole you actually have (${top.position})
|
|
143
|
-
`${top.team} plays ${top.playoff_games ?? '?'} games in your playoff window. ` +
|
|
150
|
+
`${top.name} fills the hole you actually have (${top.position})${scheduleClause}. ` +
|
|
144
151
|
`Best available is a luxury; a full lineup is not.`;
|
|
145
152
|
}
|
|
146
153
|
else {
|
|
147
154
|
chirp =
|
|
148
|
-
`${top.name} is the pick. No bargain, no drama — just the best
|
|
149
|
-
`
|
|
155
|
+
`${top.name} is the pick. No bargain, no drama — just the best producer left ` +
|
|
156
|
+
`at ${analysisResults.pick_number}${scheduleClause}.`;
|
|
157
|
+
}
|
|
158
|
+
if (!windowResolved) {
|
|
159
|
+
chirp +=
|
|
160
|
+
' I have not scored your playoff weeks — pass playoff_start_week and ' +
|
|
161
|
+
'playoff_end_week and the schedule becomes a tiebreaker.';
|
|
150
162
|
}
|
|
151
163
|
if (analysisResults.players_off_board === 0) {
|
|
152
164
|
chirp +=
|
|
@@ -249,6 +261,18 @@ export class DraftPickAnalysis extends AnalysisTemplate {
|
|
|
249
261
|
reasoning: this.reasoningFor(player, adpDelta, playoffGames, weekCount, fillsNeed)
|
|
250
262
|
};
|
|
251
263
|
}
|
|
264
|
+
/** 1 -> "1st", 2 -> "2nd", 23 -> "23rd". */
|
|
265
|
+
ordinal(n) {
|
|
266
|
+
const rem100 = n % 100;
|
|
267
|
+
if (rem100 >= 11 && rem100 <= 13)
|
|
268
|
+
return `${n}th`;
|
|
269
|
+
switch (n % 10) {
|
|
270
|
+
case 1: return `${n}st`;
|
|
271
|
+
case 2: return `${n}nd`;
|
|
272
|
+
case 3: return `${n}rd`;
|
|
273
|
+
default: return `${n}th`;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
252
276
|
verdictFor(adpDelta) {
|
|
253
277
|
if (adpDelta === null)
|
|
254
278
|
return 'FAIR';
|
|
@@ -391,25 +415,32 @@ export class DraftPickAnalysis extends AnalysisTemplate {
|
|
|
391
415
|
}
|
|
392
416
|
return counts;
|
|
393
417
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
418
|
+
/**
|
|
419
|
+
* Resolve the fantasy playoff weeks to calendar dates.
|
|
420
|
+
*
|
|
421
|
+
* v4 has no league settings to read, so the weeks come from the caller and
|
|
422
|
+
* week 1 is anchored to the NHL season's own opening night. Without stated
|
|
423
|
+
* weeks the window is unresolved, and the schedule component stays neutral
|
|
424
|
+
* rather than silently scoring the wrong three weeks.
|
|
425
|
+
*/
|
|
426
|
+
resolvePlayoffWindow(args) {
|
|
427
|
+
const startWeek = Number(args?.playoff_start_week ?? 0);
|
|
428
|
+
const endWeek = Number(args?.playoff_end_week ?? 0);
|
|
429
|
+
const seasonStart = NHL_SCHEDULE.getSeasonStartDate();
|
|
430
|
+
if (!startWeek || !endWeek || startWeek > endWeek || !seasonStart) {
|
|
401
431
|
return { resolved: false, start: null, end: null, weeks: [] };
|
|
402
432
|
}
|
|
403
|
-
const week1Monday = NhlScheduleService.weekStart(
|
|
433
|
+
const week1Monday = NhlScheduleService.weekStart(seasonStart);
|
|
404
434
|
const weeks = [];
|
|
405
|
-
for (let week =
|
|
435
|
+
for (let week = startWeek; week <= endWeek; week++) {
|
|
406
436
|
weeks.push(NhlScheduleService.addDays(week1Monday, (week - 1) * 7));
|
|
407
437
|
}
|
|
408
438
|
return {
|
|
409
439
|
resolved: true,
|
|
410
|
-
|
|
440
|
+
week_1_anchor: `${week1Monday} (NHL season opener)`,
|
|
441
|
+
playoff_start_week: startWeek,
|
|
411
442
|
end_week: endWeek,
|
|
412
|
-
start: NhlScheduleService.addDays(week1Monday, (
|
|
443
|
+
start: NhlScheduleService.addDays(week1Monday, (startWeek - 1) * 7),
|
|
413
444
|
end: NhlScheduleService.addDays(week1Monday, endWeek * 7 - 1),
|
|
414
445
|
weeks
|
|
415
446
|
};
|
package/build/index.js
CHANGED
|
@@ -1218,8 +1218,16 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
1218
1218
|
},
|
|
1219
1219
|
pool_size: {
|
|
1220
1220
|
type: "number",
|
|
1221
|
-
description: "How deep to pull the player pool (default
|
|
1222
|
-
default:
|
|
1221
|
+
description: "How deep to pull the player pool (default 250, max 400)",
|
|
1222
|
+
default: 250
|
|
1223
|
+
},
|
|
1224
|
+
playoff_start_week: {
|
|
1225
|
+
type: "number",
|
|
1226
|
+
description: "First week of your fantasy playoffs. Supply this with playoff_end_week and each club's playoff-window schedule becomes a tiebreaker between similar players."
|
|
1227
|
+
},
|
|
1228
|
+
playoff_end_week: {
|
|
1229
|
+
type: "number",
|
|
1230
|
+
description: "Final week of your fantasy playoffs (commonly your league's last week)."
|
|
1223
1231
|
},
|
|
1224
1232
|
...baseChirpSchema
|
|
1225
1233
|
}
|
|
@@ -1638,7 +1646,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1638
1646
|
already_drafted: args?.already_drafted,
|
|
1639
1647
|
roster_needs: args?.roster_needs,
|
|
1640
1648
|
max_results: args?.max_results,
|
|
1641
|
-
pool_size: args?.pool_size
|
|
1649
|
+
pool_size: args?.pool_size,
|
|
1650
|
+
playoff_start_week: args?.playoff_start_week,
|
|
1651
|
+
playoff_end_week: args?.playoff_end_week
|
|
1642
1652
|
}, semanticContract);
|
|
1643
1653
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1644
1654
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@semanticintent/semantic-chirp-intelligence-mcp",
|
|
3
|
-
"version": "4.0.
|
|
4
|
-
"description": "Universal fantasy hockey intelligence
|
|
3
|
+
"version": "4.0.2",
|
|
4
|
+
"description": "Universal fantasy hockey intelligence \u2014 a Model Context Protocol server that reads NHL schedule and player data and analyses any roster you paste. No account, no API key, no platform lock-in.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "build/index.js",
|
|
7
7
|
"scripts": {
|