@semanticintent/semantic-chirp-intelligence-mcp 3.1.0 → 4.0.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 CHANGED
@@ -1,7 +1,8 @@
1
1
  # 🏒 Semantic CHIRP Intelligence MCP
2
2
 
3
- > **Fantasy hockey intelligence that chirps you into championships.**
4
- > A Model Context Protocol (MCP) server that turns your Yahoo Fantasy Hockey league into an AI advisor — not just a data pipe, but a **Semantic Intent** brain that reads the ice and tells you the cold truth.
3
+ > **Universal fantasy hockey intelligence.**
4
+ > A Model Context Protocol (MCP) server that turns any roster into an AI advisor —
5
+ > no account, no API key, no platform lock-in. Paste your team, get the cold truth.
5
6
 
6
7
  [![Docs](https://img.shields.io/badge/docs-chirp.semanticintent.dev-1f6feb)](https://chirp.semanticintent.dev)
7
8
  ![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)
@@ -15,18 +16,28 @@
15
16
 
16
17
  ## What this is
17
18
 
18
- Most fantasy MCP servers stop at "fetch my roster." This one is a **semantic intelligence layer**: every tool carries intent metadata, analyses run through a shared template, and results come back with a *point of view* — schedule edges, streaming opportunities, and savage roster truths.
19
+ CHIRP is a **players-and-teams intelligence layer**. You tell it who is on your
20
+ roster — by pasting it from anywhere — and it reasons about schedules, statistics,
21
+ lineups, trades and draft value using the NHL's public API.
19
22
 
20
- It's built on the same **Semantic Intent** philosophy as its sibling project, the temporal-intelligence brain [`@semanticintent/semantic-wake-intelligence-mcp`](https://github.com/semanticintent/semantic-wake-intelligence-mcp) — here applied to the domain of fantasy hockey.
23
+ It is not tied to a fantasy platform. Yahoo, ESPN, Sleeper, CBS, a spreadsheet or a
24
+ paper league all work the same way, because the only thing CHIRP needs from you is
25
+ a list of names.
26
+
27
+ Every tool carries intent metadata, analyses run through a shared template, and
28
+ results come back with a *point of view* — schedule edges, roster truths, and the
29
+ occasional chirp.
21
30
 
22
31
  ### Highlights
23
32
 
33
+ - 🚀 **Zero setup** — no OAuth, no API key, no application to any platform. Install, paste a roster, done.
34
+ - 📋 **Paste from anywhere** — names resolve against live NHL rosters, so team and position fill themselves in. Accents, `Lastname, Firstname` and punctuation all handled.
24
35
  - ❄️ **ICE — the Intent Chirp Engine** — championship-level roster analysis with brutal honesty
25
- - 🗓️ **Schedule intelligence** — games-in-hand edges and streaming windows (NHL public API for real schedules)
26
- - 🌊 **Weekend stream classifier** — tells desperation pickups apart from genuine multi-week opportunities
36
+ - 🎯 **Draft intelligence** — who to take at pick N, scored on real production and playoff-week schedule
37
+ - 🗓️ **Schedule intelligence** — every game count comes from the NHL's public club-schedule API, per club, per week
27
38
  - 🏛️ **Semantic Anchoring Governance** — every tool declares its intent; a dashboard surfaces the health metrics
28
39
  - 🧩 **Template Pattern architecture** — analyses are composable, consistent, and testable
29
- - 🔒 **Read-only & local** — OAuth 2.0, minimum permissions, no third-party data egress
40
+ - 🔒 **Read-only & local** — no credentials of any kind, no third-party data egress; your roster never leaves your machine
30
41
 
31
42
  ---
32
43
 
@@ -42,11 +53,15 @@ It's built on the same **Semantic Intent** philosophy as its sibling project, th
42
53
  ├─────────────────────────────────────────────────────────────┤
43
54
  │ Intelligence layer (src/analyses/ + src/template/) │
44
55
  │ • AnalysisTemplate — shared Template Pattern base │
45
- │ • Ice / Streaming / GamesInHand / WeekendStream / Lineup
56
+ │ • Ice / Lineup / GamesInHand / Streaming / WeekendStream
57
+ │ • Breakout / ScheduleValue / DraftPick │
46
58
  ├─────────────────────────────────────────────────────────────┤
47
59
  │ Services (src/services/) │
48
60
  │ • ChirpIntelligence — turns data into chirp │
49
- │ • YahooApiClient all Yahoo Fantasy API access
61
+ │ • NhlScheduleService schedules, standings (NHL public API)
62
+ │ • NhlStatsService — player identity + season statistics │
63
+ │ • RosterStore — parses and stores what you paste │
64
+ │ • LeagueDataService — league state, source-agnostic │
50
65
  ├─────────────────────────────────────────────────────────────┤
51
66
  │ Domain (src/domain/) — types + governance │
52
67
  └─────────────────────────────────────────────────────────────┘
@@ -59,90 +74,97 @@ It's built on the same **Semantic Intent** philosophy as its sibling project, th
59
74
 
60
75
  ## Available Tools
61
76
 
62
- ### Core data tools (read-only Yahoo Fantasy)
77
+ ### Setting up your league (paste-based)
63
78
 
64
79
  | Tool | Description |
65
80
  |------|-------------|
66
- | `get_team_roster` | Your current roster with players, positions, and status |
67
- | `get_league_standings` | League standings all teams and their records |
68
- | `get_current_matchup` | Your current week's matchup and status |
69
- | `search_players` | Search free agents by position (C, LW, RW, D, G) |
70
- | `get_player_stats` | Detailed stats for a player by ID |
71
- | `get_weekly_stats` | Your week's stats vs. your opponent |
72
- | `compare_matchup` | Category-by-category breakdown of your matchup |
73
- | `optimize_lineup` | Lineup recommendations based on health and positions |
74
- | `get_trending_players` | Most-added / most-owned players — hot pickups |
75
- | `debug_api_call` | Inspect raw Yahoo API responses for troubleshooting |
76
-
77
- ### CHIRP intelligence tools (Template Pattern + semantic analysis)
81
+ | `set_roster` | 📋 Paste your roster. Names resolve against live NHL rosters; team and position fill themselves in |
82
+ | `set_opponent_roster` | 📋 Paste your weekly opponent, enabling head-to-head analysis |
83
+ | `set_standings` | 📊 Paste league standings for league context |
84
+ | `show_stored_data` | 🗂️ Show (or clear) what CHIRP currently knows |
85
+
86
+ ### Core data tools
78
87
 
79
88
  | Tool | Description |
80
89
  |------|-------------|
81
- | `ice` | ❄️ **Intent Chirp Engine** the flagship multi-mode advisor; ice-cold, championship-level analysis combining all insights |
82
- | `get_roster_transaction_recommendations` | 🏒 ICE roster optimization — savage, brutally honest lineup/transaction calls |
83
- | `get_streaming_recommendations` | Schedule- and trend-aware waiver/streaming picks (weekly / weekend / daily strategies) |
84
- | `get_games_in_hand` | Schedule-advantage analysisremaining games, you vs. opponent |
85
- | `analyze_weekend_streams` | 🌊 Weekend stream classifier desperation filler vs. genuine multi-week upside (0–100 upside score) |
86
- | `governance_dashboard` | 🏛️ Semantic Anchoring Governance health, analysis metrics, and violations |
90
+ | `get_team_roster` | Your roster with live NHL club, position, season stats and games this week |
91
+ | `get_league_standings` | The standings you pasted |
92
+ | `search_players` | Search all 1,200+ NHL players by position, ranked by production |
93
+ | `get_player_stats` | Full stats for any player by name, not an internal id |
94
+ | `compare_matchup` | Category-by-category comparison of your roster against your opponent's |
87
95
 
88
- ---
96
+ ### CHIRP intelligence tools
89
97
 
90
- ## Prerequisites
98
+ | Tool | Description |
99
+ |------|-------------|
100
+ | `ice` | ❄️ **Intent Chirp Engine** — the flagship advisor; ice-cold, championship-level roster analysis |
101
+ | `get_roster_transaction_recommendations` | 🏒 ICE roster optimization — savage, brutally honest calls |
102
+ | `optimize_lineup` | Lineup recommendations from health, position and who actually plays tonight |
103
+ | `get_games_in_hand` | Schedule-advantage analysis, you vs. your opponent |
104
+ | `get_streaming_recommendations` | Schedule-aware pickup candidates |
105
+ | `analyze_weekend_streams` | 🌊 Weekend classifier — desperation filler vs. genuine upside |
106
+ | `analyze_breakout_players` | 📈 Breakout candidates scored on real production, opportunity and risk |
107
+ | `analyze_trade` | Category-by-category trade breakdown with an ACCEPT / DECLINE / PUSH verdict |
108
+ | `chirp_opponent` | Scouts your opponent's roster and chirps its weaknesses |
109
+ | `governance_dashboard` | 🏛️ Semantic Anchoring Governance health and analysis metrics |
110
+
111
+ ### Draft tools
91
112
 
92
- - **Node.js 20+**
93
- - A **Yahoo account** with a Fantasy Hockey team
94
- - An MCP client e.g. **Claude Desktop**
113
+ | Tool | Description |
114
+ |------|-------------|
115
+ | `chirp_draft_pick` | 🎯 **ICE at the draft table** — who to take at pick N, given who is gone, what you need, and playoff-week schedule |
116
+ | `schedule_value` | 🗓️ All 32 clubs rated — total games, four-game weeks, light weeks, back-to-backs, playoff-window volume |
95
117
 
96
- ## Setup
118
+ > **On availability:** CHIRP knows every NHL player, but it cannot know who is
119
+ > *unowned in your league* — ownership is league-private and no public source
120
+ > exposes it. Pool-based tools therefore return "players not on the rosters you
121
+ > provided", ranked by production, and say so. Check availability before adding.
97
122
 
98
- ### 1. Create a Yahoo app
123
+ ## Where the numbers come from
99
124
 
100
- Go to [developer.yahoo.com/apps/create](https://developer.yahoo.com/apps/create/) and create an app:
125
+ Every figure is fetched, not estimated — and none of it needs an account:
101
126
 
102
- - **OAuth Client Type:** `Confidential Client`
103
- - **Redirect URI:** `https://localhost:3000/callback` *(must match exactly)*
104
- - **API Permissions:** `Fantasy Sports Read`
127
+ | Signal | Source |
128
+ |--------|--------|
129
+ | Games per week, back-to-backs, playoff-window volume | NHL public API (`club-schedule-season`) all 32 clubs, cached per season |
130
+ | Player identity, club, position | NHL public API (`roster`) — 1,268 players |
131
+ | Season statistics (skaters and goalies) | NHL public API (`club-stats`) |
132
+ | Opponent difficulty | NHL standings, ranked by goals allowed per game |
133
+ | Your roster, opponent, standings | What you paste |
105
134
 
106
- Copy your **Client ID** and **Client Secret**.
135
+ When a source is unreachable, the tool says so in its output and drops that
136
+ component from its scoring — it does not substitute an estimate for a fact.
107
137
 
108
- > 🔒 Treat the Client Secret like a password. Never commit it. If it ever leaks, **rotate it** by creating a new app and deleting the old one — see [SECURITY.md](./SECURITY.md).
138
+ ---
109
139
 
110
- ### 2. Find your league and team IDs
140
+ ## Prerequisites
111
141
 
112
- From your team URL `https://hockey.fantasysports.yahoo.com/hockey/{LEAGUE_ID}/{TEAM_ID}` — the two numbers are your league and team IDs.
142
+ - **Node.js 20+**
143
+ - An MCP client — e.g. **Claude Desktop**
113
144
 
114
- ### 3. Install & configure
145
+ That is the whole list. There is no account to create, no application to file, and
146
+ no credential to store.
115
147
 
116
- ```bash
117
- git clone https://github.com/semanticintent/semantic-chirp-intelligence-mcp.git
118
- cd semantic-chirp-intelligence-mcp
119
- npm install
120
- cp .env.example .env # then fill in your credentials
121
- ```
148
+ > **Coming from v3?** v3 read your league through the Yahoo Fantasy API. In 2026
149
+ > Yahoo put that API behind a manual approval process that also revoked existing
150
+ > access, so a working install could stop working without any change to the code.
151
+ > v4 removes the dependency entirely: CHIRP now reasons about any roster you paste,
152
+ > on any platform. The Yahoo integration is preserved at the
153
+ > [v3.2.0 tag](https://github.com/semanticintent/semantic-chirp-intelligence-mcp/releases/tag/v3.2.0).
122
154
 
123
- `.env`:
124
- ```
125
- YAHOO_CLIENT_ID=your_client_id
126
- YAHOO_CLIENT_SECRET=your_client_secret
127
- YAHOO_LEAGUE_ID=your_league_id
128
- YAHOO_TEAM_ID=your_team_id
129
- ```
155
+ ---
130
156
 
131
- ### 4. Build
157
+ ## Setup
132
158
 
133
159
  ```bash
160
+ git clone https://github.com/semanticintent/semantic-chirp-intelligence-mcp.git
161
+ cd semantic-chirp-intelligence-mcp
162
+ npm install
134
163
  npm run build
164
+ npm run preflight # checks the build and the NHL API — no credentials involved
135
165
  ```
136
166
 
137
- ### 5. Authenticate with Yahoo (one time)
138
-
139
- ```bash
140
- node authenticate.js
141
- ```
142
-
143
- Open the printed URL, click through the self-signed-certificate warning (it's a local callback), sign in, and authorize. The token is saved to `.yahoo-oauth.json` (git-ignored). The server auto-refreshes it after that.
144
-
145
- ### 6. Add to Claude Desktop
167
+ ### Add to Claude Desktop
146
168
 
147
169
  Edit your Claude Desktop config:
148
170
  - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
@@ -153,14 +175,7 @@ Edit your Claude Desktop config:
153
175
  "mcpServers": {
154
176
  "semantic-chirp-intelligence-mcp": {
155
177
  "command": "node",
156
- "args": ["/absolute/path/to/semantic-chirp-intelligence-mcp/build/index.js"],
157
- "env": {
158
- "YAHOO_CLIENT_ID": "your_client_id",
159
- "YAHOO_CLIENT_SECRET": "your_client_secret",
160
- "YAHOO_LEAGUE_ID": "your_league_id",
161
- "YAHOO_TEAM_ID": "your_team_id",
162
- "DOTENV_CONFIG_QUIET": "true"
163
- }
178
+ "args": ["/absolute/path/to/semantic-chirp-intelligence-mcp/build/index.js"]
164
179
  }
165
180
  }
166
181
  }
@@ -168,17 +183,23 @@ Edit your Claude Desktop config:
168
183
 
169
184
  Use an **absolute path** to `build/index.js` (forward slashes, even on Windows). Restart Claude Desktop — the CHIRP tools will appear.
170
185
 
186
+ There is no `env` block, because there is nothing to configure. Your pasted
187
+ roster is stored in the project's git-ignored `.chirp-data/` and never leaves
188
+ your machine.
189
+
171
190
  ---
172
191
 
173
192
  ## Usage
174
193
 
175
194
  Once connected, just talk to Claude about your team:
176
195
 
196
+ - *"I'm on the clock at pick 47 — who should I take?"*
197
+ - *"Which teams have the best schedule during my league's playoff weeks?"*
177
198
  - *"Run ICE on my roster — what should I actually do this week?"*
178
199
  - *"Where do I have a games-in-hand edge over my opponent?"*
179
200
  - *"Find me streaming goalies for the weekend — real value, not desperation pickups."*
180
201
  - *"Am I winning my matchup? Which categories am I losing?"*
181
- - *"Who are the hottest waiver adds in my league?"*
202
+ - *"Who are the best players not on my roster right now?"*
182
203
  - *"Show me the governance dashboard."*
183
204
 
184
205
  ---
@@ -191,6 +212,8 @@ npm run type-check # tsc --noEmit
191
212
  npm test # run the vitest suite once
192
213
  npm run test:watch # watch mode
193
214
  npm run test:coverage
215
+ npm run preflight # build + NHL API reachability
216
+ npm run smoke # call every tool and flag crash-like responses
194
217
  ```
195
218
 
196
219
  ### Project structure
@@ -199,25 +222,48 @@ npm run test:coverage
199
222
  semantic-chirp-intelligence-mcp/
200
223
  ├── src/
201
224
  │ ├── index.ts # MCP server (stdio) + tool registration
202
- │ ├── analyses/ # Template-Pattern analyses (Ice, Streaming, GamesInHand, WeekendStream, Lineup, Breakout)
225
+ │ ├── analyses/ # Template-Pattern analyses (Ice, Streaming, GamesInHand,
226
+ │ │ # WeekendStream, Lineup, Breakout, ScheduleValue, DraftPick)
203
227
  │ ├── template/ # AnalysisTemplate base
204
- │ ├── services/ # ChirpIntelligence, YahooApiClient
228
+ │ ├── services/ # NhlScheduleService, NhlStatsService, RosterStore,
229
+ │ │ # LeagueDataService, ChirpIntelligence
205
230
  │ ├── config/ # tool-metadata, personality-modes, chirp-styles
206
- │ ├── domain/ # types, governance
207
- │ └── experimental/ # semantic-intent parser experiments
231
+ │ ├── domain/ # types, governance, nhl-teams
208
232
  ├── tests/ # vitest tests
209
- ├── authenticate.js # one-time Yahoo OAuth helper
233
+ ├── scripts/preflight.mjs # build + NHL API check
234
+ ├── scripts/smoke.mjs # calls every tool, flags crash-like responses
210
235
  ├── docs/ # documentation (architecture, setup, dev notes)
211
- └── .env.example
212
236
  ```
213
237
 
214
238
  ---
215
239
 
240
+ ## Troubleshooting
241
+
242
+ **A name did not resolve**
243
+ `set_roster` reports every line it could not match to exactly one NHL player,
244
+ under `needs_attention`. Ambiguous surnames come back with their candidates —
245
+ give a full name and re-run. Nothing is ever guessed onto your roster.
246
+
247
+ **Tools say no roster has been provided**
248
+ Paste one with `set_roster`. `show_stored_data` shows what is currently stored.
249
+
250
+ **Game counts are zero**
251
+ Check the dates. Outside the regular season there are genuinely no games to count;
252
+ `schedule_value` still works year-round because it reads the whole published season.
253
+
254
+ **Stats look like last season**
255
+ They are. Before opening night the current season has no statistics at all, so
256
+ CHIRP attaches the last completed season — which is the right basis at a draft.
257
+ Every response names the season it used.
258
+
259
+ ---
260
+
216
261
  ## Security
217
262
 
218
- - **Read-only** integration requests the minimum Yahoo `Read` permission; never modifies your roster or transactions.
219
- - **Local-only** — runs over stdio; the only network calls are to Yahoo's API (and the NHL public schedule API).
220
- - **Secrets never committed** — `.env` and `.yahoo-oauth.json` are git-ignored. See [SECURITY.md](./SECURITY.md) for the full policy and how to rotate a leaked credential.
263
+ - **No credentials at all** — v4 holds no API keys, tokens or account bindings. There is nothing to leak.
264
+ - **Read-only** — the only network calls are GETs to the NHL's public API. CHIRP cannot modify a roster anywhere.
265
+ - **Local-only** — runs over stdio. Your pasted roster stays in `.chirp-data/` on your machine and is git-ignored.
266
+ - See [SECURITY.md](./SECURITY.md) for the full policy.
221
267
 
222
268
  ## Part of Cormorant Foraging
223
269
 
@@ -242,7 +288,7 @@ Contributions welcome — see [CONTRIBUTING.md](./CONTRIBUTING.md) and the [Code
242
288
  ## Acknowledgments
243
289
 
244
290
  - [Model Context Protocol](https://modelcontextprotocol.io) by Anthropic
245
- - [Yahoo Fantasy Sports API](https://developer.yahoo.com/fantasysports/)
291
+ - [NHL public API](https://api-web.nhle.com) — schedules, rosters, statistics and standings, free and unauthenticated
246
292
  - Sibling project: [`semantic-wake-intelligence-mcp`](https://github.com/semanticintent/semantic-wake-intelligence-mcp)
247
293
 
248
294
  ---
@@ -12,42 +12,25 @@
12
12
  */
13
13
  import { AnalysisTemplate } from '../template/AnalysisTemplate.js';
14
14
  import { ChirpIntelligence } from '../services/ChirpIntelligence.js';
15
+ import { LEAGUE_DATA, LeagueDataService } from '../services/LeagueDataService.js';
16
+ import { NHL_STATS } from '../services/NhlStatsService.js';
17
+ import { NHL_SCHEDULE } from '../services/NhlScheduleService.js';
15
18
  export class BreakoutAnalysis extends AnalysisTemplate {
16
- yahooClient;
17
- leagueId;
18
- teamId;
19
- constructor(yahooClient, leagueId, teamId) {
19
+ constructor() {
20
20
  super('get_breakout_analysis', 'streaming_recommendations');
21
- this.yahooClient = yahooClient;
22
- this.leagueId = leagueId;
23
- this.teamId = teamId;
24
21
  }
25
22
  /**
26
23
  * Fetch raw data: free agents, trending players, roster
27
24
  */
28
25
  async fetchData(args) {
29
- const ownershipThreshold = args.ownership_threshold || 50;
30
- // Fetch free agents across all positions
31
- const positions = args.position_filter || ['C', 'LW', 'RW', 'D', 'G'];
32
- const freeAgentPromises = positions.map(pos => this.yahooClient.searchPlayers(pos, 50, this.leagueId));
33
- const [freeAgentResults, trendingAdds, roster] = await Promise.all([
34
- Promise.all(freeAgentPromises),
35
- this.yahooClient.getTrendingPlayers('add', 25, this.leagueId),
36
- this.yahooClient.getTeamRoster(this.leagueId, this.teamId)
37
- ]);
38
- // Combine and deduplicate free agents
39
- const allFreeAgents = [];
40
- for (const result of freeAgentResults) {
41
- if (result.players) {
42
- allFreeAgents.push(...result.players);
43
- }
44
- }
45
- // Remove duplicates and filter by ownership
46
- const uniqueFreeAgents = Array.from(new Map(allFreeAgents.map(p => [p.player_id, p])).values()).filter(p => (p.percent_owned || 0) < ownershipThreshold);
26
+ await Promise.all([NHL_STATS.load(), NHL_SCHEDULE.load()]);
27
+ // Breakout candidates are drawn from every NHL player not already on a
28
+ // roster you provided, scored on their real season line.
47
29
  return {
48
- freeAgents: uniqueFreeAgents,
49
- trendingAdds: trendingAdds.players || [],
50
- roster
30
+ freeAgents: LEAGUE_DATA.getPlayerPool({ limit: 200 }),
31
+ trendingAdds: [],
32
+ roster: LEAGUE_DATA.getRoster(),
33
+ pool_caveat: LeagueDataService.POOL_CAVEAT
51
34
  };
52
35
  }
53
36
  /**
@@ -228,17 +211,23 @@ export class BreakoutAnalysis extends AnalysisTemplate {
228
211
  return 'sleeper';
229
212
  }
230
213
  /**
231
- * Get player metrics (mock implementation)
214
+ * Real season stat line for a candidate, from Yahoo.
215
+ *
216
+ * Missing categories come back as 0 rather than absent so the scoring
217
+ * formula keeps its shape; `has_stats` distinguishes a genuine zero from a
218
+ * player Yahoo returned nothing for.
232
219
  */
233
220
  async getPlayerMetrics(player) {
234
- // In real implementation, fetch detailed stats
235
- // For now, return mock data
221
+ // v4: the pool carries NHL season statistics on each player already.
222
+ const stats = player.stats ?? null;
236
223
  return {
237
- G: Math.random() * 30,
238
- A: Math.random() * 40,
239
- GP: 50 + Math.random() * 30,
240
- PPP: Math.random() * 20,
241
- SOG: Math.random() * 150
224
+ G: stats?.goals ?? 0,
225
+ A: stats?.assists ?? 0,
226
+ GP: stats?.games_played ?? 0,
227
+ // The NHL feed publishes power-play goals, not power-play points.
228
+ PPP: stats?.power_play_goals ?? 0,
229
+ SOG: stats?.shots ?? 0,
230
+ has_stats: Boolean(stats)
242
231
  };
243
232
  }
244
233
  /**