@semanticintent/semantic-chirp-intelligence-mcp 3.1.0 → 4.0.0

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,15 +16,25 @@
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
40
  - 🔒 **Read-only & local** — OAuth 2.0, minimum permissions, no third-party data egress
@@ -46,7 +57,10 @@ It's built on the same **Semantic Intent** philosophy as its sibling project, th
46
57
  ├─────────────────────────────────────────────────────────────┤
47
58
  │ Services (src/services/) │
48
59
  │ • ChirpIntelligence — turns data into chirp │
49
- │ • YahooApiClient all Yahoo Fantasy API access
60
+ │ • NhlScheduleService schedules, standings (NHL public API)
61
+ │ • NhlStatsService — player identity + season statistics │
62
+ │ • RosterStore — parses and stores what you paste │
63
+ │ • LeagueDataService — league state, source-agnostic │
50
64
  ├─────────────────────────────────────────────────────────────┤
51
65
  │ Domain (src/domain/) — types + governance │
52
66
  └─────────────────────────────────────────────────────────────┘
@@ -59,90 +73,97 @@ It's built on the same **Semantic Intent** philosophy as its sibling project, th
59
73
 
60
74
  ## Available Tools
61
75
 
62
- ### Core data tools (read-only Yahoo Fantasy)
76
+ ### Setting up your league (paste-based)
63
77
 
64
78
  | Tool | Description |
65
79
  |------|-------------|
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)
80
+ | `set_roster` | 📋 Paste your roster. Names resolve against live NHL rosters; team and position fill themselves in |
81
+ | `set_opponent_roster` | 📋 Paste your weekly opponent, enabling head-to-head analysis |
82
+ | `set_standings` | 📊 Paste league standings for league context |
83
+ | `show_stored_data` | 🗂️ Show (or clear) what CHIRP currently knows |
84
+
85
+ ### Core data tools
78
86
 
79
87
  | Tool | Description |
80
88
  |------|-------------|
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 |
89
+ | `get_team_roster` | Your roster with live NHL club, position, season stats and games this week |
90
+ | `get_league_standings` | The standings you pasted |
91
+ | `search_players` | Search all 1,200+ NHL players by position, ranked by production |
92
+ | `get_player_stats` | Full stats for any player by name, not an internal id |
93
+ | `compare_matchup` | Category-by-category comparison of your roster against your opponent's |
87
94
 
88
- ---
95
+ ### CHIRP intelligence tools
89
96
 
90
- ## Prerequisites
97
+ | Tool | Description |
98
+ |------|-------------|
99
+ | `ice` | ❄️ **Intent Chirp Engine** — the flagship advisor; ice-cold, championship-level roster analysis |
100
+ | `get_roster_transaction_recommendations` | 🏒 ICE roster optimization — savage, brutally honest calls |
101
+ | `optimize_lineup` | Lineup recommendations from health, position and who actually plays tonight |
102
+ | `get_games_in_hand` | Schedule-advantage analysis, you vs. your opponent |
103
+ | `get_streaming_recommendations` | Schedule-aware pickup candidates |
104
+ | `analyze_weekend_streams` | 🌊 Weekend classifier — desperation filler vs. genuine upside |
105
+ | `analyze_breakout_players` | 📈 Breakout candidates scored on real production, opportunity and risk |
106
+ | `analyze_trade` | Category-by-category trade breakdown with an ACCEPT / DECLINE / PUSH verdict |
107
+ | `chirp_opponent` | Scouts your opponent's roster and chirps its weaknesses |
108
+ | `governance_dashboard` | 🏛️ Semantic Anchoring Governance health and analysis metrics |
109
+
110
+ ### Draft tools
91
111
 
92
- - **Node.js 20+**
93
- - A **Yahoo account** with a Fantasy Hockey team
94
- - An MCP client e.g. **Claude Desktop**
112
+ | Tool | Description |
113
+ |------|-------------|
114
+ | `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 |
115
+ | `schedule_value` | 🗓️ All 32 clubs rated — total games, four-game weeks, light weeks, back-to-backs, playoff-window volume |
95
116
 
96
- ## Setup
117
+ > **On availability:** CHIRP knows every NHL player, but it cannot know who is
118
+ > *unowned in your league* — ownership is league-private and no public source
119
+ > exposes it. Pool-based tools therefore return "players not on the rosters you
120
+ > provided", ranked by production, and say so. Check availability before adding.
97
121
 
98
- ### 1. Create a Yahoo app
122
+ ## Where the numbers come from
99
123
 
100
- Go to [developer.yahoo.com/apps/create](https://developer.yahoo.com/apps/create/) and create an app:
124
+ Every figure is fetched, not estimated — and none of it needs an account:
101
125
 
102
- - **OAuth Client Type:** `Confidential Client`
103
- - **Redirect URI:** `https://localhost:3000/callback` *(must match exactly)*
104
- - **API Permissions:** `Fantasy Sports Read`
126
+ | Signal | Source |
127
+ |--------|--------|
128
+ | Games per week, back-to-backs, playoff-window volume | NHL public API (`club-schedule-season`) all 32 clubs, cached per season |
129
+ | Player identity, club, position | NHL public API (`roster`) — 1,268 players |
130
+ | Season statistics (skaters and goalies) | NHL public API (`club-stats`) |
131
+ | Opponent difficulty | NHL standings, ranked by goals allowed per game |
132
+ | Your roster, opponent, standings | What you paste |
105
133
 
106
- Copy your **Client ID** and **Client Secret**.
134
+ When a source is unreachable, the tool says so in its output and drops that
135
+ component from its scoring — it does not substitute an estimate for a fact.
107
136
 
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).
137
+ ---
109
138
 
110
- ### 2. Find your league and team IDs
139
+ ## Prerequisites
111
140
 
112
- From your team URL `https://hockey.fantasysports.yahoo.com/hockey/{LEAGUE_ID}/{TEAM_ID}` — the two numbers are your league and team IDs.
141
+ - **Node.js 20+**
142
+ - An MCP client — e.g. **Claude Desktop**
113
143
 
114
- ### 3. Install & configure
144
+ That is the whole list. There is no account to create, no application to file, and
145
+ no credential to store.
115
146
 
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
- ```
147
+ > **Coming from v3?** v3 read your league through the Yahoo Fantasy API. In 2026
148
+ > Yahoo put that API behind a manual approval process that also revoked existing
149
+ > access, so a working install could stop working without any change to the code.
150
+ > v4 removes the dependency entirely: CHIRP now reasons about any roster you paste,
151
+ > on any platform. The Yahoo integration is preserved at the
152
+ > [v3.2.0 tag](https://github.com/semanticintent/semantic-chirp-intelligence-mcp/releases/tag/v3.2.0).
122
153
 
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
- ```
154
+ ---
130
155
 
131
- ### 4. Build
156
+ ## Setup
132
157
 
133
158
  ```bash
159
+ git clone https://github.com/semanticintent/semantic-chirp-intelligence-mcp.git
160
+ cd semantic-chirp-intelligence-mcp
161
+ npm install
134
162
  npm run build
163
+ npm run preflight # checks the build and the NHL API — no credentials involved
135
164
  ```
136
165
 
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
166
+ ### Add to Claude Desktop
146
167
 
147
168
  Edit your Claude Desktop config:
148
169
  - **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
@@ -155,10 +176,6 @@ Edit your Claude Desktop config:
155
176
  "command": "node",
156
177
  "args": ["/absolute/path/to/semantic-chirp-intelligence-mcp/build/index.js"],
157
178
  "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
179
  "DOTENV_CONFIG_QUIET": "true"
163
180
  }
164
181
  }
@@ -168,12 +185,20 @@ Edit your Claude Desktop config:
168
185
 
169
186
  Use an **absolute path** to `build/index.js` (forward slashes, even on Windows). Restart Claude Desktop — the CHIRP tools will appear.
170
187
 
188
+ Your credentials stay in the project's git-ignored `.env`; the server resolves
189
+ it from its own install directory, so it is found regardless of the working
190
+ directory the client launches it with. You do **not** need to copy secrets into
191
+ the client config. If you prefer to set them there anyway, a client `env` block
192
+ still overrides the file.
193
+
171
194
  ---
172
195
 
173
196
  ## Usage
174
197
 
175
198
  Once connected, just talk to Claude about your team:
176
199
 
200
+ - *"I'm on the clock at pick 47 — who should I take?"*
201
+ - *"Which teams have the best schedule during my league's playoff weeks?"*
177
202
  - *"Run ICE on my roster — what should I actually do this week?"*
178
203
  - *"Where do I have a games-in-hand edge over my opponent?"*
179
204
  - *"Find me streaming goalies for the weekend — real value, not desperation pickups."*
@@ -191,6 +216,8 @@ npm run type-check # tsc --noEmit
191
216
  npm test # run the vitest suite once
192
217
  npm run test:watch # watch mode
193
218
  npm run test:coverage
219
+ npm run preflight # build + NHL API reachability
220
+ npm run smoke # call every tool and flag crash-like responses
194
221
  ```
195
222
 
196
223
  ### Project structure
@@ -199,25 +226,48 @@ npm run test:coverage
199
226
  semantic-chirp-intelligence-mcp/
200
227
  ├── src/
201
228
  │ ├── index.ts # MCP server (stdio) + tool registration
202
- │ ├── analyses/ # Template-Pattern analyses (Ice, Streaming, GamesInHand, WeekendStream, Lineup, Breakout)
229
+ │ ├── analyses/ # Template-Pattern analyses (Ice, Streaming, GamesInHand,
230
+ │ │ # WeekendStream, Lineup, Breakout, ScheduleValue, DraftPick)
203
231
  │ ├── template/ # AnalysisTemplate base
204
- │ ├── services/ # ChirpIntelligence, YahooApiClient
232
+ │ ├── services/ # NhlScheduleService, NhlStatsService, RosterStore,
233
+ │ │ # LeagueDataService, ChirpIntelligence
205
234
  │ ├── config/ # tool-metadata, personality-modes, chirp-styles
206
- │ ├── domain/ # types, governance
207
- │ └── experimental/ # semantic-intent parser experiments
235
+ │ ├── domain/ # types, governance, nhl-teams, yahoo-stats
208
236
  ├── tests/ # vitest tests
209
- ├── authenticate.js # one-time Yahoo OAuth helper
237
+ ├── scripts/preflight.mjs # build + NHL API check
238
+ ├── scripts/smoke.mjs # calls every tool, flags crash-like responses
210
239
  ├── docs/ # documentation (architecture, setup, dev notes)
211
- └── .env.example
212
240
  ```
213
241
 
214
242
  ---
215
243
 
244
+ ## Troubleshooting
245
+
246
+ **A name did not resolve**
247
+ `set_roster` reports every line it could not match to exactly one NHL player,
248
+ under `needs_attention`. Ambiguous surnames come back with their candidates —
249
+ give a full name and re-run. Nothing is ever guessed onto your roster.
250
+
251
+ **Tools say no roster has been provided**
252
+ Paste one with `set_roster`. `show_stored_data` shows what is currently stored.
253
+
254
+ **Game counts are zero**
255
+ Check the dates. Outside the regular season there are genuinely no games to count;
256
+ `schedule_value` still works year-round because it reads the whole published season.
257
+
258
+ **Stats look like last season**
259
+ They are. Before opening night the current season has no statistics at all, so
260
+ CHIRP attaches the last completed season — which is the right basis at a draft.
261
+ Every response names the season it used.
262
+
263
+ ---
264
+
216
265
  ## Security
217
266
 
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.
267
+ - **No credentials at all** — v4 holds no API keys, tokens or account bindings. There is nothing to leak.
268
+ - **Read-only** — the only network calls are GETs to the NHL's public API. CHIRP cannot modify a roster anywhere.
269
+ - **Local-only** — runs over stdio. Your pasted roster stays in `.chirp-data/` on your machine and is git-ignored.
270
+ - See [SECURITY.md](./SECURITY.md) for the full policy.
221
271
 
222
272
  ## Part of Cormorant Foraging
223
273
 
@@ -242,7 +292,7 @@ Contributions welcome — see [CONTRIBUTING.md](./CONTRIBUTING.md) and the [Code
242
292
  ## Acknowledgments
243
293
 
244
294
  - [Model Context Protocol](https://modelcontextprotocol.io) by Anthropic
245
- - [Yahoo Fantasy Sports API](https://developer.yahoo.com/fantasysports/)
295
+ - [NHL public API](https://api-web.nhle.com) — schedules, rosters, statistics and standings, free and unauthenticated
246
296
  - Sibling project: [`semantic-wake-intelligence-mcp`](https://github.com/semanticintent/semantic-wake-intelligence-mcp)
247
297
 
248
298
  ---
@@ -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
  /**