cfb-stats-mcp 0.1.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/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/cache.d.ts +4 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +17 -0
- package/dist/cache.js.map +1 -0
- package/dist/cfbd-client.d.ts +9 -0
- package/dist/cfbd-client.d.ts.map +1 -0
- package/dist/cfbd-client.js +49 -0
- package/dist/cfbd-client.js.map +1 -0
- package/dist/cfbd-client.test.d.ts +2 -0
- package/dist/cfbd-client.test.d.ts.map +1 -0
- package/dist/cfbd-client.test.js +37 -0
- package/dist/cfbd-client.test.js.map +1 -0
- package/dist/embedded-resources.d.ts +3 -0
- package/dist/embedded-resources.d.ts.map +1 -0
- package/dist/embedded-resources.js +300 -0
- package/dist/embedded-resources.js.map +1 -0
- package/dist/exports.d.ts +7 -0
- package/dist/exports.d.ts.map +1 -0
- package/dist/exports.js +33 -0
- package/dist/exports.js.map +1 -0
- package/dist/exports.test.d.ts +2 -0
- package/dist/exports.test.d.ts.map +1 -0
- package/dist/exports.test.js +80 -0
- package/dist/exports.test.js.map +1 -0
- package/dist/formatters/advanced-formatter.d.ts +3 -0
- package/dist/formatters/advanced-formatter.d.ts.map +1 -0
- package/dist/formatters/advanced-formatter.js +106 -0
- package/dist/formatters/advanced-formatter.js.map +1 -0
- package/dist/formatters/box-score-formatter.d.ts +3 -0
- package/dist/formatters/box-score-formatter.d.ts.map +1 -0
- package/dist/formatters/box-score-formatter.js +154 -0
- package/dist/formatters/box-score-formatter.js.map +1 -0
- package/dist/formatters/conference-ratings-formatter.d.ts +4 -0
- package/dist/formatters/conference-ratings-formatter.d.ts.map +1 -0
- package/dist/formatters/conference-ratings-formatter.js +62 -0
- package/dist/formatters/conference-ratings-formatter.js.map +1 -0
- package/dist/formatters/conference-ratings-formatter.test.d.ts +2 -0
- package/dist/formatters/conference-ratings-formatter.test.d.ts.map +1 -0
- package/dist/formatters/conference-ratings-formatter.test.js +153 -0
- package/dist/formatters/conference-ratings-formatter.test.js.map +1 -0
- package/dist/formatters/game-formatter.d.ts +3 -0
- package/dist/formatters/game-formatter.d.ts.map +1 -0
- package/dist/formatters/game-formatter.js +46 -0
- package/dist/formatters/game-formatter.js.map +1 -0
- package/dist/formatters/head-to-head-formatter.d.ts +3 -0
- package/dist/formatters/head-to-head-formatter.d.ts.map +1 -0
- package/dist/formatters/head-to-head-formatter.js +162 -0
- package/dist/formatters/head-to-head-formatter.js.map +1 -0
- package/dist/formatters/head-to-head-formatter.test.d.ts +2 -0
- package/dist/formatters/head-to-head-formatter.test.d.ts.map +1 -0
- package/dist/formatters/head-to-head-formatter.test.js +160 -0
- package/dist/formatters/head-to-head-formatter.test.js.map +1 -0
- package/dist/formatters/ratings-formatter.d.ts +3 -0
- package/dist/formatters/ratings-formatter.d.ts.map +1 -0
- package/dist/formatters/ratings-formatter.js +75 -0
- package/dist/formatters/ratings-formatter.js.map +1 -0
- package/dist/formatters/ratings-formatter.test.d.ts +2 -0
- package/dist/formatters/ratings-formatter.test.d.ts.map +1 -0
- package/dist/formatters/ratings-formatter.test.js +137 -0
- package/dist/formatters/ratings-formatter.test.js.map +1 -0
- package/dist/formatters/season-advanced-formatter.d.ts +3 -0
- package/dist/formatters/season-advanced-formatter.d.ts.map +1 -0
- package/dist/formatters/season-advanced-formatter.js +160 -0
- package/dist/formatters/season-advanced-formatter.js.map +1 -0
- package/dist/formatters/season-advanced-formatter.test.d.ts +2 -0
- package/dist/formatters/season-advanced-formatter.test.d.ts.map +1 -0
- package/dist/formatters/season-advanced-formatter.test.js +239 -0
- package/dist/formatters/season-advanced-formatter.test.js.map +1 -0
- package/dist/formatters/season-records-formatter.d.ts +3 -0
- package/dist/formatters/season-records-formatter.d.ts.map +1 -0
- package/dist/formatters/season-records-formatter.js +64 -0
- package/dist/formatters/season-records-formatter.js.map +1 -0
- package/dist/formatters/season-stats-formatter.d.ts +3 -0
- package/dist/formatters/season-stats-formatter.d.ts.map +1 -0
- package/dist/formatters/season-stats-formatter.js +156 -0
- package/dist/formatters/season-stats-formatter.js.map +1 -0
- package/dist/formatters/season-stats-formatter.test.d.ts +2 -0
- package/dist/formatters/season-stats-formatter.test.d.ts.map +1 -0
- package/dist/formatters/season-stats-formatter.test.js +76 -0
- package/dist/formatters/season-stats-formatter.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +16 -0
- package/dist/logger.js.map +1 -0
- package/dist/prompts.d.ts +3 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +242 -0
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +3 -0
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +12 -0
- package/dist/resources.js.map +1 -0
- package/dist/tools/advanced-stats.d.ts +3 -0
- package/dist/tools/advanced-stats.d.ts.map +1 -0
- package/dist/tools/advanced-stats.js +67 -0
- package/dist/tools/advanced-stats.js.map +1 -0
- package/dist/tools/box-score.d.ts +3 -0
- package/dist/tools/box-score.d.ts.map +1 -0
- package/dist/tools/box-score.js +50 -0
- package/dist/tools/box-score.js.map +1 -0
- package/dist/tools/build-glossary.d.ts +8 -0
- package/dist/tools/build-glossary.d.ts.map +1 -0
- package/dist/tools/build-glossary.js +125 -0
- package/dist/tools/build-glossary.js.map +1 -0
- package/dist/tools/build-glossary.test.d.ts +2 -0
- package/dist/tools/build-glossary.test.d.ts.map +1 -0
- package/dist/tools/build-glossary.test.js +182 -0
- package/dist/tools/build-glossary.test.js.map +1 -0
- package/dist/tools/conference-ratings.d.ts +3 -0
- package/dist/tools/conference-ratings.d.ts.map +1 -0
- package/dist/tools/conference-ratings.js +74 -0
- package/dist/tools/conference-ratings.js.map +1 -0
- package/dist/tools/export-subtitles.d.ts +23 -0
- package/dist/tools/export-subtitles.d.ts.map +1 -0
- package/dist/tools/export-subtitles.js +102 -0
- package/dist/tools/export-subtitles.js.map +1 -0
- package/dist/tools/export-subtitles.test.d.ts +2 -0
- package/dist/tools/export-subtitles.test.d.ts.map +1 -0
- package/dist/tools/export-subtitles.test.js +152 -0
- package/dist/tools/export-subtitles.test.js.map +1 -0
- package/dist/tools/games.d.ts +3 -0
- package/dist/tools/games.d.ts.map +1 -0
- package/dist/tools/games.js +64 -0
- package/dist/tools/games.js.map +1 -0
- package/dist/tools/head-to-head.d.ts +3 -0
- package/dist/tools/head-to-head.d.ts.map +1 -0
- package/dist/tools/head-to-head.js +74 -0
- package/dist/tools/head-to-head.js.map +1 -0
- package/dist/tools/ratings.d.ts +3 -0
- package/dist/tools/ratings.d.ts.map +1 -0
- package/dist/tools/ratings.js +63 -0
- package/dist/tools/ratings.js.map +1 -0
- package/dist/tools/read-transcript.d.ts +9 -0
- package/dist/tools/read-transcript.d.ts.map +1 -0
- package/dist/tools/read-transcript.js +72 -0
- package/dist/tools/read-transcript.js.map +1 -0
- package/dist/tools/read-transcript.test.d.ts +2 -0
- package/dist/tools/read-transcript.test.d.ts.map +1 -0
- package/dist/tools/read-transcript.test.js +94 -0
- package/dist/tools/read-transcript.test.js.map +1 -0
- package/dist/tools/season-advanced.d.ts +3 -0
- package/dist/tools/season-advanced.d.ts.map +1 -0
- package/dist/tools/season-advanced.js +103 -0
- package/dist/tools/season-advanced.js.map +1 -0
- package/dist/tools/season-records.d.ts +3 -0
- package/dist/tools/season-records.d.ts.map +1 -0
- package/dist/tools/season-records.js +51 -0
- package/dist/tools/season-records.js.map +1 -0
- package/dist/tools/season-stats.d.ts +3 -0
- package/dist/tools/season-stats.d.ts.map +1 -0
- package/dist/tools/season-stats.js +75 -0
- package/dist/tools/season-stats.js.map +1 -0
- package/dist/tools/status.d.ts +3 -0
- package/dist/tools/status.d.ts.map +1 -0
- package/dist/tools/status.js +19 -0
- package/dist/tools/status.js.map +1 -0
- package/dist/tools/transcript-types.d.ts +36 -0
- package/dist/tools/transcript-types.d.ts.map +1 -0
- package/dist/tools/transcript-types.js +2 -0
- package/dist/tools/transcript-types.js.map +1 -0
- package/dist/tools/write-chapters.d.ts +40 -0
- package/dist/tools/write-chapters.d.ts.map +1 -0
- package/dist/tools/write-chapters.js +143 -0
- package/dist/tools/write-chapters.js.map +1 -0
- package/dist/tools/write-chapters.test.d.ts +2 -0
- package/dist/tools/write-chapters.test.d.ts.map +1 -0
- package/dist/tools/write-chapters.test.js +167 -0
- package/dist/tools/write-chapters.test.js.map +1 -0
- package/dist/tools/write-clip-candidates.d.ts +30 -0
- package/dist/tools/write-clip-candidates.d.ts.map +1 -0
- package/dist/tools/write-clip-candidates.js +130 -0
- package/dist/tools/write-clip-candidates.js.map +1 -0
- package/dist/tools/write-clip-candidates.test.d.ts +2 -0
- package/dist/tools/write-clip-candidates.test.d.ts.map +1 -0
- package/dist/tools/write-clip-candidates.test.js +213 -0
- package/dist/tools/write-clip-candidates.test.js.map +1 -0
- package/dist/tools/write-description.d.ts +11 -0
- package/dist/tools/write-description.d.ts.map +1 -0
- package/dist/tools/write-description.js +71 -0
- package/dist/tools/write-description.js.map +1 -0
- package/dist/tools/write-description.test.d.ts +2 -0
- package/dist/tools/write-description.test.d.ts.map +1 -0
- package/dist/tools/write-description.test.js +42 -0
- package/dist/tools/write-description.test.js.map +1 -0
- package/dist/tools/write-transcript.d.ts +20 -0
- package/dist/tools/write-transcript.d.ts.map +1 -0
- package/dist/tools/write-transcript.js +133 -0
- package/dist/tools/write-transcript.js.map +1 -0
- package/dist/tools/write-transcript.test.d.ts +2 -0
- package/dist/tools/write-transcript.test.d.ts.map +1 -0
- package/dist/tools/write-transcript.test.js +133 -0
- package/dist/tools/write-transcript.test.js.map +1 -0
- package/package.json +59 -0
- package/resources/football-glossary.json +69 -0
- package/resources/workflow.md +228 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Teague
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# cfb-stats-mcp
|
|
2
|
+
|
|
3
|
+
MCP server for college football statistics -- scores, rankings, advanced analytics, and historical data from the CFBD API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Run directly with npx:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx cfb-stats-mcp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or install globally:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g cfb-stats-mcp
|
|
17
|
+
cfb-stats-mcp
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Configuration
|
|
21
|
+
|
|
22
|
+
Requires a CFBD API key. Get one (free tier available) at [collegefootballdata.com](https://collegefootballdata.com).
|
|
23
|
+
|
|
24
|
+
Set the `CFBD_API_KEY` environment variable:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
CFBD_API_KEY=your-key-here npx cfb-stats-mcp
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## MCP Client Setup
|
|
31
|
+
|
|
32
|
+
Add to your Claude Desktop configuration (`claude_desktop_config.json`):
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"mcpServers": {
|
|
37
|
+
"cfb-stats": {
|
|
38
|
+
"command": "npx",
|
|
39
|
+
"args": ["-y", "cfb-stats-mcp"],
|
|
40
|
+
"env": {
|
|
41
|
+
"CFBD_API_KEY": "your-key-here"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Available Tools
|
|
49
|
+
|
|
50
|
+
| Tool | Description |
|
|
51
|
+
|------|-------------|
|
|
52
|
+
| `cfbd_status` | Check CFBD API connectivity and authentication status |
|
|
53
|
+
| `cfbd_games` | Look up college football game results by team and season. Returns scores, dates, venues, and Elo ratings. |
|
|
54
|
+
| `cfbd_box_score` | Get traditional box score stats (yards, 3rd down efficiency, turnovers, time of possession) for a team's games |
|
|
55
|
+
| `cfbd_advanced_stats` | Get advanced analytics (PPA, success rate, explosiveness, havoc) for a team's games. Combines efficiency metrics with defensive disruption rates. |
|
|
56
|
+
| `cfbd_records` | Get a team's season record with overall, conference, home/away, and postseason splits plus expected wins |
|
|
57
|
+
| `cfbd_ratings` | Get multi-system ratings (SP+, SRS, Elo, FPI) for a team. Shows headline numbers: overall rating and ranking, offense/defense breakdowns where available. |
|
|
58
|
+
| `cfbd_conference_ratings` | Get SP+ ratings for a conference. 'teams' view ranks all conference teams by SP+ overall. 'conference' view shows aggregate conference-level rating. |
|
|
59
|
+
| `cfbd_head_to_head` | Get historical head-to-head series data between two teams. Shows all-time series record, last 10 and last 5 results, and venue breakdowns. |
|
|
60
|
+
| `cfbd_season_stats` | Get season-wide traditional stat aggregates (yards, turnovers, 3rd down, completions, etc.) for a team. Returns totals/averages organized by category. |
|
|
61
|
+
| `cfbd_season_advanced` | Get season-wide advanced analytics for a team: EPA (opponent-adjusted efficiency), PPA (raw predicted points), success rate, havoc, explosiveness, and PPA by down. |
|
|
62
|
+
| `build_glossary` | Assemble a proper noun correction glossary from the static football glossary and CFBD roster data for specified teams. Returns formatted correction pairs for transcript correction. |
|
|
63
|
+
|
|
64
|
+
## Resources
|
|
65
|
+
|
|
66
|
+
The server exposes a **Workflow Guide** resource (`resource:///workflow`) that describes the full tool inventory, parameter details, chaining patterns, and recommended workflows. Load this resource to understand how tools work together for analysis tasks.
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
|
|
70
|
+
MIT
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAOA,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAOR;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAGvD;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAEvD"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const cache = new Map();
|
|
2
|
+
export function cacheKey(endpoint, params) {
|
|
3
|
+
const sorted = Object.entries(params)
|
|
4
|
+
.filter(([, v]) => v !== undefined)
|
|
5
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
6
|
+
.map(([k, v]) => `${k}=${String(v)}`)
|
|
7
|
+
.join("&");
|
|
8
|
+
return `${endpoint}?${sorted}`;
|
|
9
|
+
}
|
|
10
|
+
export function getCached(key) {
|
|
11
|
+
const entry = cache.get(key);
|
|
12
|
+
return entry?.data;
|
|
13
|
+
}
|
|
14
|
+
export function setCached(key, data) {
|
|
15
|
+
cache.set(key, { data, cachedAt: Date.now() });
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAKA,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;AAErD,MAAM,UAAU,QAAQ,CACtB,QAAgB,EAChB,MAA+B;IAE/B,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;SAClC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC;SAClC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;SACpC,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,GAAG,QAAQ,IAAI,MAAM,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,SAAS,CAAI,GAAW;IACtC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,OAAO,KAAK,EAAE,IAAqB,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,SAAS,CAAI,GAAW,EAAE,IAAO;IAC/C,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function initCfbdClient(): void;
|
|
2
|
+
export declare function checkCfbdStatus(): Promise<{
|
|
3
|
+
ok: boolean;
|
|
4
|
+
message: string;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function cachedFetch<T>(endpoint: string, params: Record<string, unknown>, fetcher: () => Promise<{
|
|
7
|
+
data?: T;
|
|
8
|
+
}>): Promise<T>;
|
|
9
|
+
//# sourceMappingURL=cfbd-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cfbd-client.d.ts","sourceRoot":"","sources":["../src/cfbd-client.ts"],"names":[],"mappings":"AAIA,wBAAgB,cAAc,IAAI,IAAI,CAcrC;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC;IAC/C,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAeD;AAED,wBAAsB,WAAW,CAAC,CAAC,EACjC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,EAAE,MAAM,OAAO,CAAC;IAAE,IAAI,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC,GACnC,OAAO,CAAC,CAAC,CAAC,CAkBZ"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { client, getConferences } from "cfbd";
|
|
2
|
+
import { cacheKey, getCached, setCached } from "./cache.js";
|
|
3
|
+
import { logger } from "./logger.js";
|
|
4
|
+
export function initCfbdClient() {
|
|
5
|
+
const apiKey = process.env.CFBD_API_KEY;
|
|
6
|
+
if (!apiKey) {
|
|
7
|
+
logger.warn("CFBD_API_KEY not set -- cfb-stats tools will return errors on use");
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
client.setConfig({
|
|
11
|
+
headers: {
|
|
12
|
+
Authorization: `Bearer ${apiKey}`,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
logger.info("CFBD client initialized");
|
|
16
|
+
}
|
|
17
|
+
export async function checkCfbdStatus() {
|
|
18
|
+
try {
|
|
19
|
+
const result = await getConferences();
|
|
20
|
+
const count = result.data?.length ?? 0;
|
|
21
|
+
const status = {
|
|
22
|
+
ok: true,
|
|
23
|
+
message: `Connected. ${count} conferences returned.`,
|
|
24
|
+
};
|
|
25
|
+
logger.info("CFBD status check passed", { conferences: count });
|
|
26
|
+
return status;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
const message = `CFBD API error: ${error instanceof Error ? error.message : String(error)}`;
|
|
30
|
+
logger.error("CFBD status check failed", { error: message });
|
|
31
|
+
return { ok: false, message };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export async function cachedFetch(endpoint, params, fetcher) {
|
|
35
|
+
const key = cacheKey(endpoint, params);
|
|
36
|
+
const cached = getCached(key);
|
|
37
|
+
if (cached !== undefined) {
|
|
38
|
+
logger.debug("Cache hit", { endpoint, key });
|
|
39
|
+
return cached;
|
|
40
|
+
}
|
|
41
|
+
logger.debug("Cache miss, fetching from API", { endpoint, key });
|
|
42
|
+
const result = await fetcher();
|
|
43
|
+
if (result.data === undefined) {
|
|
44
|
+
throw new Error(`CFBD API returned no data for ${endpoint}`);
|
|
45
|
+
}
|
|
46
|
+
setCached(key, result.data);
|
|
47
|
+
return result.data;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=cfbd-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cfbd-client.js","sourceRoot":"","sources":["../src/cfbd-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,UAAU,cAAc;IAC5B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,CAAC,IAAI,CACT,mEAAmE,CACpE,CAAC;QACF,OAAO;IACT,CAAC;IACD,MAAM,CAAC,SAAS,CAAC;QACf,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,MAAM,EAAE;SAClC;KACF,CAAC,CAAC;IACH,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IAInC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG;YACb,EAAE,EAAE,IAAI;YACR,OAAO,EAAE,cAAc,KAAK,wBAAwB;SACrD,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,mBAAmB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5F,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC7D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAChC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,QAAgB,EAChB,MAA+B,EAC/B,OAAoC;IAEpC,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEvC,MAAM,MAAM,GAAG,SAAS,CAAI,GAAG,CAAC,CAAC;IACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,MAAM,OAAO,EAAE,CAAC;IAE/B,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cfbd-client.test.d.ts","sourceRoot":"","sources":["../src/cfbd-client.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
describe("initCfbdClient", () => {
|
|
3
|
+
const originalEnv = process.env.CFBD_API_KEY;
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
vi.resetModules();
|
|
6
|
+
delete process.env.CFBD_API_KEY;
|
|
7
|
+
});
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
if (originalEnv !== undefined) {
|
|
10
|
+
process.env.CFBD_API_KEY = originalEnv;
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
delete process.env.CFBD_API_KEY;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
it("does not throw when CFBD_API_KEY is missing", async () => {
|
|
17
|
+
delete process.env.CFBD_API_KEY;
|
|
18
|
+
const { initCfbdClient } = await import("./cfbd-client.js");
|
|
19
|
+
expect(() => initCfbdClient()).not.toThrow();
|
|
20
|
+
});
|
|
21
|
+
it("logs a warning when CFBD_API_KEY is missing", async () => {
|
|
22
|
+
delete process.env.CFBD_API_KEY;
|
|
23
|
+
const loggerModule = await import("./logger.js");
|
|
24
|
+
const warnSpy = vi.spyOn(loggerModule.logger, "warn");
|
|
25
|
+
const { initCfbdClient } = await import("./cfbd-client.js");
|
|
26
|
+
initCfbdClient();
|
|
27
|
+
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining("CFBD_API_KEY"));
|
|
28
|
+
warnSpy.mockRestore();
|
|
29
|
+
});
|
|
30
|
+
it("configures client when CFBD_API_KEY is present", async () => {
|
|
31
|
+
process.env.CFBD_API_KEY = "test-key-123";
|
|
32
|
+
const { initCfbdClient } = await import("./cfbd-client.js");
|
|
33
|
+
// Should not throw, should configure normally
|
|
34
|
+
expect(() => initCfbdClient()).not.toThrow();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=cfbd-client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cfbd-client.test.js","sourceRoot":"","sources":["../src/cfbd-client.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEzE,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAE7C,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,WAAW,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QAClC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QAChC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC5D,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QAChC,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACtD,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC5D,cAAc,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,CAAC,CAAC,oBAAoB,CAClC,MAAM,CAAC,gBAAgB,CAAC,cAAc,CAAC,CACxC,CAAC;QACF,OAAO,CAAC,WAAW,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,cAAc,CAAC;QAC1C,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAC5D,8CAA8C;QAC9C,MAAM,CAAC,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const workflow = "# Workflow Guide\n\nTool inventory and chaining patterns for the Press Box MCP servers. Two servers work together: **cfb-stats-mcp** pulls college football data from the CFBD API, and **thumbnail-gen** renders branded YouTube thumbnails.\n\n---\n\n## cfb-stats-mcp Tools\n\n### cfbd_status\n\nCheck CFBD API connectivity and authentication status.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| *(none)* | \u2014 | \u2014 | No parameters |\n\n---\n\n### cfbd_games\n\nLook up game results by team and season. Returns scores, dates, venues, and Elo ratings.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| team | string | yes | Team school name (e.g. \"Alabama\", \"Ohio State\") |\n| year | number | yes | Season year (e.g. 2024) |\n| week | number | no | Week number \u2014 omit for full season |\n| seasonType | enum: regular, postseason, both | no | Season type filter \u2014 defaults to \"both\" |\n\n---\n\n### cfbd_box_score\n\nGet traditional box score stats (yards, 3rd down efficiency, turnovers, time of possession) for a team's games.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| team | string | yes | Team school name |\n| year | number | yes | Season year |\n| week | number | no | Week number \u2014 narrows to specific game(s) |\n\n---\n\n### cfbd_advanced_stats\n\nGet advanced analytics (PPA, success rate, explosiveness, havoc) for a team's games. Combines efficiency metrics with defensive disruption rates.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| team | string | yes | Team school name |\n| year | number | yes | Season year |\n| week | number | no | Week number \u2014 narrows to specific game(s) |\n| excludeGarbageTime | boolean | no | Exclude garbage time plays (default: false) |\n\n---\n\n### cfbd_records\n\nGet a team's season record with overall, conference, home/away, and postseason splits plus expected wins.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| team | string | yes | Team school name |\n| year | number | no | Season year \u2014 defaults to current season |\n\n---\n\n### cfbd_ratings\n\nGet multi-system ratings (SP+, SRS, Elo, FPI) for a team. Shows headline numbers, offense/defense breakdowns where available.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| team | string | yes | Team school name |\n| year | number | no | Season year \u2014 defaults to current season |\n\n---\n\n### cfbd_conference_ratings\n\nGet SP+ ratings for a conference. Teams view ranks all conference teams by SP+ overall. Conference view shows aggregate rating.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| conference | string | yes | Conference name (e.g. \"SEC\", \"Big Ten\") |\n| year | number | no | Season year \u2014 defaults to current season |\n| view | enum: teams, conference | no | \"teams\" = individual team rankings (default), \"conference\" = aggregate |\n\n---\n\n### cfbd_head_to_head\n\nGet historical head-to-head series data between two teams. Shows all-time series record, last 10/5 results, and venue breakdowns.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| team1 | string | yes | First team school name |\n| team2 | string | yes | Second team school name |\n| startYear | number | no | Start of year range \u2014 omit for all-time series |\n| endYear | number | no | End of year range \u2014 omit for all-time series |\n\n---\n\n### cfbd_season_stats\n\nGet season-wide traditional stat aggregates (yards, turnovers, 3rd down, completions, etc.) for a team. Returns totals/averages organized by category.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| team | string | yes | Team school name |\n| year | number | no | Season year \u2014 defaults to current season |\n| startWeek | number | no | Start week for filtering \u2014 omit for full season |\n| endWeek | number | no | End week for filtering \u2014 omit for full season |\n\n---\n\n### cfbd_season_advanced\n\nGet season-wide advanced analytics: EPA (opponent-adjusted), PPA (raw predicted points), success rate, havoc, explosiveness, rushing detail, and PPA by down. Garbage time excluded by default.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| team | string | yes | Team school name |\n| year | number | no | Season year \u2014 defaults to current season |\n| startWeek | number | no | Start week for filtering (raw stats only \u2014 EPA and PPA-by-down are always full season) |\n| endWeek | number | no | End week for filtering (same caveat) |\n| includeGarbageTime | boolean | no | Include garbage time plays (default: false) |\n\n---\n\n## thumbnail-gen Tools\n\n### generate_thumbnail\n\nRender a branded YouTube thumbnail from hook text and a background image. Returns a base64 preview and saves the PNG to disk.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| hookText | string | yes | Bold text overlay for the thumbnail |\n| backgroundImagePath | string | yes | Absolute path to the background image file |\n| outputDir | string | yes | Directory where the PNG will be saved |\n| team1 | string | yes | First team name (e.g. \"Alabama\") |\n| team2 | string | yes | Second team name (e.g. \"Auburn\") |\n| textSide | enum: left, right | no | Side for text placement \u2014 defaults to \"right\" |\n| subtitle | string | no | Subtitle below hook text (e.g. \"WITH BO SCARBROUGH\") |\n| sponsorImagePath | string | no | Path to sponsor logo image |\n\n---\n\n## Chaining Patterns\n\nCommon tool sequences for show prep workflows.\n\n### Game Breakdown\n\nSingle-game deep dive. Start with game results, then pull box score and advanced stats in parallel.\n\n```\ncfbd_games(team, year, week)\n -> cfbd_box_score(team, year, week) + cfbd_advanced_stats(team, year, week) [parallel]\n -> surface angles from combined data\n```\n\n### Season Context\n\nBig-picture team assessment. Pull records and ratings in parallel, then season-level stats in parallel.\n\n```\ncfbd_records(team, year) + cfbd_ratings(team, year) [parallel]\n -> cfbd_season_stats(team, year) + cfbd_season_advanced(team, year) [parallel]\n```\n\n### Rivalry Prep\n\nHistorical matchup context flowing into recent game detail.\n\n```\ncfbd_head_to_head(team1, team2)\n -> cfbd_games(team1, year) [recent matchups]\n -> cfbd_box_score(team1, year, week)\n```\n\n### Full Show Prep\n\nCombines Game Breakdown and Season Context in parallel, then flows into content generation.\n\n```\n[Game Breakdown] + [Season Context] [parallel]\n -> identify angles from combined data\n -> generate-title-description prompt (notes with angles + stats)\n -> generate_thumbnail(hookText, backgroundImagePath, outputDir, team1, team2)\n```\n\n### Quick Publish\n\nCompressed pipeline for the Monday night scramble.\n\n```\ncfbd_games(team, year, week)\n -> cfbd_box_score(team, year, week) + cfbd_advanced_stats(team, year, week) [parallel]\n -> generate-title-description prompt (notes with key stats)\n -> generate_thumbnail(hookText, backgroundImagePath, outputDir, team1, team2)\n```\n\n---\n\n## Resources\n\n| Resource | URI | Description |\n|----------|-----|-------------|\n| Style Guide | `resource:///style-guide` | Title and description style conventions with voice guidelines |\n| Style Examples | `resource:///examples` | Annotated title/description samples with ratings and reasoning |\n| Workflow Guide | `resource:///workflow` | This document \u2014 tool inventory and chaining patterns |\n| Show Prep Playbook | `resource:///playbook` | Editorial voice, proactive behavior, and show prep conventions |\n\n---\n\n## Prompts\n\n### generate-title-description\n\nGenerate podcast-ready titles, YouTube descriptions, and thumbnail hook options from game notes, backed by the Teague's Take style guide.\n\n| Argument | Type | Required | Description |\n|----------|------|----------|-------------|\n| notes | string | yes | Rough game/episode notes |\n\nProduces 2-3 title options, a YouTube description with above-the-fold hook, and 3-5 thumbnail hook options. Auto-loads the style guide resource.\n";
|
|
2
|
+
export declare const footballGlossary = "{\n \"version\": \"1.0\",\n \"players\": {\n \"jalen milro\": \"Jalen Milroe\",\n \"jalen milroe\": \"Jalen Milroe\",\n \"caleb downs\": \"Caleb Downs\",\n \"ryan williams\": \"Ryan Williams\",\n \"tyler buchner\": \"Tyler Buchner\",\n \"jase mcclellan\": \"Jase McClellan\",\n \"dallas turner\": \"Dallas Turner\",\n \"qu'vonte hicks\": \"Qu'Vonte Hicks\",\n \"trevor lawrence\": \"Trevor Lawrence\",\n \"travis hunter\": \"Travis Hunter\",\n \"cam ward\": \"Cam Ward\",\n \"shedeur sanders\": \"Shedeur Sanders\",\n \"quinshon judkins\": \"Quinshon Judkins\"\n },\n \"coaches\": {\n \"kalen deboer\": \"Kalen DeBoer\",\n \"kirby smart\": \"Kirby Smart\",\n \"nick sabin\": \"Nick Saban\",\n \"nick saban\": \"Nick Saban\",\n \"brian kelly\": \"Brian Kelly\",\n \"lane kiffin\": \"Lane Kiffin\",\n \"josh heupel\": \"Josh Heupel\",\n \"eliah drinkwitz\": \"Eliah Drinkwitz\",\n \"mike elko\": \"Mike Elko\",\n \"sam pittman\": \"Sam Pittman\",\n \"shane beamer\": \"Shane Beamer\",\n \"clark lea\": \"Clark Lea\"\n },\n \"terms\": {\n \"rpo\": \"RPO\",\n \"tampa 2\": \"Tampa 2\",\n \"cover 3\": \"Cover 3\",\n \"cover 2\": \"Cover 2\",\n \"cover 4\": \"Cover 4\",\n \"cover 0\": \"Cover 0\",\n \"cover 1\": \"Cover 1\",\n \"cover 6\": \"Cover 6\",\n \"quarters coverage\": \"Quarters Coverage\",\n \"man coverage\": \"Man Coverage\",\n \"zone coverage\": \"Zone Coverage\",\n \"play action\": \"Play Action\",\n \"read option\": \"Read Option\",\n \"nickelback\": \"Nickelback\",\n \"will linebacker\": \"Will Linebacker\",\n \"mike linebacker\": \"Mike Linebacker\",\n \"sam linebacker\": \"Sam Linebacker\",\n \"epa\": \"EPA\",\n \"ppa\": \"PPA\",\n \"wpa\": \"WPA\",\n \"sp+\": \"SP+\",\n \"sp plus\": \"SP+\"\n },\n \"schools\": {\n \"ole miss\": \"Ole Miss\",\n \"texas a&m\": \"Texas A&M\",\n \"texas a and m\": \"Texas A&M\",\n \"lsu\": \"LSU\",\n \"usc\": \"USC\",\n \"ucf\": \"UCF\",\n \"smu\": \"SMU\",\n \"tcu\": \"TCU\",\n \"oklahoma state\": \"Oklahoma State\",\n \"mississippi state\": \"Mississippi State\",\n \"south carolina\": \"South Carolina\"\n }\n}";
|
|
3
|
+
//# sourceMappingURL=embedded-resources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded-resources.d.ts","sourceRoot":"","sources":["../src/embedded-resources.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,QAAQ,kyQAoOpB,CAAC;AAEF,eAAO,MAAM,gBAAgB,otEAoE3B,CAAC"}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
// Auto-generated by scripts/embed-resources.mjs — do not edit manually
|
|
2
|
+
export const workflow = `# Workflow Guide
|
|
3
|
+
|
|
4
|
+
Tool inventory and chaining patterns for the Press Box MCP servers. Two servers work together: **cfb-stats-mcp** pulls college football data from the CFBD API, and **thumbnail-gen** renders branded YouTube thumbnails.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## cfb-stats-mcp Tools
|
|
9
|
+
|
|
10
|
+
### cfbd_status
|
|
11
|
+
|
|
12
|
+
Check CFBD API connectivity and authentication status.
|
|
13
|
+
|
|
14
|
+
| Parameter | Type | Required | Description |
|
|
15
|
+
|-----------|------|----------|-------------|
|
|
16
|
+
| *(none)* | — | — | No parameters |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
### cfbd_games
|
|
21
|
+
|
|
22
|
+
Look up game results by team and season. Returns scores, dates, venues, and Elo ratings.
|
|
23
|
+
|
|
24
|
+
| Parameter | Type | Required | Description |
|
|
25
|
+
|-----------|------|----------|-------------|
|
|
26
|
+
| team | string | yes | Team school name (e.g. "Alabama", "Ohio State") |
|
|
27
|
+
| year | number | yes | Season year (e.g. 2024) |
|
|
28
|
+
| week | number | no | Week number — omit for full season |
|
|
29
|
+
| seasonType | enum: regular, postseason, both | no | Season type filter — defaults to "both" |
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
### cfbd_box_score
|
|
34
|
+
|
|
35
|
+
Get traditional box score stats (yards, 3rd down efficiency, turnovers, time of possession) for a team's games.
|
|
36
|
+
|
|
37
|
+
| Parameter | Type | Required | Description |
|
|
38
|
+
|-----------|------|----------|-------------|
|
|
39
|
+
| team | string | yes | Team school name |
|
|
40
|
+
| year | number | yes | Season year |
|
|
41
|
+
| week | number | no | Week number — narrows to specific game(s) |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### cfbd_advanced_stats
|
|
46
|
+
|
|
47
|
+
Get advanced analytics (PPA, success rate, explosiveness, havoc) for a team's games. Combines efficiency metrics with defensive disruption rates.
|
|
48
|
+
|
|
49
|
+
| Parameter | Type | Required | Description |
|
|
50
|
+
|-----------|------|----------|-------------|
|
|
51
|
+
| team | string | yes | Team school name |
|
|
52
|
+
| year | number | yes | Season year |
|
|
53
|
+
| week | number | no | Week number — narrows to specific game(s) |
|
|
54
|
+
| excludeGarbageTime | boolean | no | Exclude garbage time plays (default: false) |
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### cfbd_records
|
|
59
|
+
|
|
60
|
+
Get a team's season record with overall, conference, home/away, and postseason splits plus expected wins.
|
|
61
|
+
|
|
62
|
+
| Parameter | Type | Required | Description |
|
|
63
|
+
|-----------|------|----------|-------------|
|
|
64
|
+
| team | string | yes | Team school name |
|
|
65
|
+
| year | number | no | Season year — defaults to current season |
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### cfbd_ratings
|
|
70
|
+
|
|
71
|
+
Get multi-system ratings (SP+, SRS, Elo, FPI) for a team. Shows headline numbers, offense/defense breakdowns where available.
|
|
72
|
+
|
|
73
|
+
| Parameter | Type | Required | Description |
|
|
74
|
+
|-----------|------|----------|-------------|
|
|
75
|
+
| team | string | yes | Team school name |
|
|
76
|
+
| year | number | no | Season year — defaults to current season |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### cfbd_conference_ratings
|
|
81
|
+
|
|
82
|
+
Get SP+ ratings for a conference. Teams view ranks all conference teams by SP+ overall. Conference view shows aggregate rating.
|
|
83
|
+
|
|
84
|
+
| Parameter | Type | Required | Description |
|
|
85
|
+
|-----------|------|----------|-------------|
|
|
86
|
+
| conference | string | yes | Conference name (e.g. "SEC", "Big Ten") |
|
|
87
|
+
| year | number | no | Season year — defaults to current season |
|
|
88
|
+
| view | enum: teams, conference | no | "teams" = individual team rankings (default), "conference" = aggregate |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
### cfbd_head_to_head
|
|
93
|
+
|
|
94
|
+
Get historical head-to-head series data between two teams. Shows all-time series record, last 10/5 results, and venue breakdowns.
|
|
95
|
+
|
|
96
|
+
| Parameter | Type | Required | Description |
|
|
97
|
+
|-----------|------|----------|-------------|
|
|
98
|
+
| team1 | string | yes | First team school name |
|
|
99
|
+
| team2 | string | yes | Second team school name |
|
|
100
|
+
| startYear | number | no | Start of year range — omit for all-time series |
|
|
101
|
+
| endYear | number | no | End of year range — omit for all-time series |
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### cfbd_season_stats
|
|
106
|
+
|
|
107
|
+
Get season-wide traditional stat aggregates (yards, turnovers, 3rd down, completions, etc.) for a team. Returns totals/averages organized by category.
|
|
108
|
+
|
|
109
|
+
| Parameter | Type | Required | Description |
|
|
110
|
+
|-----------|------|----------|-------------|
|
|
111
|
+
| team | string | yes | Team school name |
|
|
112
|
+
| year | number | no | Season year — defaults to current season |
|
|
113
|
+
| startWeek | number | no | Start week for filtering — omit for full season |
|
|
114
|
+
| endWeek | number | no | End week for filtering — omit for full season |
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### cfbd_season_advanced
|
|
119
|
+
|
|
120
|
+
Get season-wide advanced analytics: EPA (opponent-adjusted), PPA (raw predicted points), success rate, havoc, explosiveness, rushing detail, and PPA by down. Garbage time excluded by default.
|
|
121
|
+
|
|
122
|
+
| Parameter | Type | Required | Description |
|
|
123
|
+
|-----------|------|----------|-------------|
|
|
124
|
+
| team | string | yes | Team school name |
|
|
125
|
+
| year | number | no | Season year — defaults to current season |
|
|
126
|
+
| startWeek | number | no | Start week for filtering (raw stats only — EPA and PPA-by-down are always full season) |
|
|
127
|
+
| endWeek | number | no | End week for filtering (same caveat) |
|
|
128
|
+
| includeGarbageTime | boolean | no | Include garbage time plays (default: false) |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## thumbnail-gen Tools
|
|
133
|
+
|
|
134
|
+
### generate_thumbnail
|
|
135
|
+
|
|
136
|
+
Render a branded YouTube thumbnail from hook text and a background image. Returns a base64 preview and saves the PNG to disk.
|
|
137
|
+
|
|
138
|
+
| Parameter | Type | Required | Description |
|
|
139
|
+
|-----------|------|----------|-------------|
|
|
140
|
+
| hookText | string | yes | Bold text overlay for the thumbnail |
|
|
141
|
+
| backgroundImagePath | string | yes | Absolute path to the background image file |
|
|
142
|
+
| outputDir | string | yes | Directory where the PNG will be saved |
|
|
143
|
+
| team1 | string | yes | First team name (e.g. "Alabama") |
|
|
144
|
+
| team2 | string | yes | Second team name (e.g. "Auburn") |
|
|
145
|
+
| textSide | enum: left, right | no | Side for text placement — defaults to "right" |
|
|
146
|
+
| subtitle | string | no | Subtitle below hook text (e.g. "WITH BO SCARBROUGH") |
|
|
147
|
+
| sponsorImagePath | string | no | Path to sponsor logo image |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Chaining Patterns
|
|
152
|
+
|
|
153
|
+
Common tool sequences for show prep workflows.
|
|
154
|
+
|
|
155
|
+
### Game Breakdown
|
|
156
|
+
|
|
157
|
+
Single-game deep dive. Start with game results, then pull box score and advanced stats in parallel.
|
|
158
|
+
|
|
159
|
+
\`\`\`
|
|
160
|
+
cfbd_games(team, year, week)
|
|
161
|
+
-> cfbd_box_score(team, year, week) + cfbd_advanced_stats(team, year, week) [parallel]
|
|
162
|
+
-> surface angles from combined data
|
|
163
|
+
\`\`\`
|
|
164
|
+
|
|
165
|
+
### Season Context
|
|
166
|
+
|
|
167
|
+
Big-picture team assessment. Pull records and ratings in parallel, then season-level stats in parallel.
|
|
168
|
+
|
|
169
|
+
\`\`\`
|
|
170
|
+
cfbd_records(team, year) + cfbd_ratings(team, year) [parallel]
|
|
171
|
+
-> cfbd_season_stats(team, year) + cfbd_season_advanced(team, year) [parallel]
|
|
172
|
+
\`\`\`
|
|
173
|
+
|
|
174
|
+
### Rivalry Prep
|
|
175
|
+
|
|
176
|
+
Historical matchup context flowing into recent game detail.
|
|
177
|
+
|
|
178
|
+
\`\`\`
|
|
179
|
+
cfbd_head_to_head(team1, team2)
|
|
180
|
+
-> cfbd_games(team1, year) [recent matchups]
|
|
181
|
+
-> cfbd_box_score(team1, year, week)
|
|
182
|
+
\`\`\`
|
|
183
|
+
|
|
184
|
+
### Full Show Prep
|
|
185
|
+
|
|
186
|
+
Combines Game Breakdown and Season Context in parallel, then flows into content generation.
|
|
187
|
+
|
|
188
|
+
\`\`\`
|
|
189
|
+
[Game Breakdown] + [Season Context] [parallel]
|
|
190
|
+
-> identify angles from combined data
|
|
191
|
+
-> generate-title-description prompt (notes with angles + stats)
|
|
192
|
+
-> generate_thumbnail(hookText, backgroundImagePath, outputDir, team1, team2)
|
|
193
|
+
\`\`\`
|
|
194
|
+
|
|
195
|
+
### Quick Publish
|
|
196
|
+
|
|
197
|
+
Compressed pipeline for the Monday night scramble.
|
|
198
|
+
|
|
199
|
+
\`\`\`
|
|
200
|
+
cfbd_games(team, year, week)
|
|
201
|
+
-> cfbd_box_score(team, year, week) + cfbd_advanced_stats(team, year, week) [parallel]
|
|
202
|
+
-> generate-title-description prompt (notes with key stats)
|
|
203
|
+
-> generate_thumbnail(hookText, backgroundImagePath, outputDir, team1, team2)
|
|
204
|
+
\`\`\`
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Resources
|
|
209
|
+
|
|
210
|
+
| Resource | URI | Description |
|
|
211
|
+
|----------|-----|-------------|
|
|
212
|
+
| Style Guide | \`resource:///style-guide\` | Title and description style conventions with voice guidelines |
|
|
213
|
+
| Style Examples | \`resource:///examples\` | Annotated title/description samples with ratings and reasoning |
|
|
214
|
+
| Workflow Guide | \`resource:///workflow\` | This document — tool inventory and chaining patterns |
|
|
215
|
+
| Show Prep Playbook | \`resource:///playbook\` | Editorial voice, proactive behavior, and show prep conventions |
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Prompts
|
|
220
|
+
|
|
221
|
+
### generate-title-description
|
|
222
|
+
|
|
223
|
+
Generate podcast-ready titles, YouTube descriptions, and thumbnail hook options from game notes, backed by the Teague's Take style guide.
|
|
224
|
+
|
|
225
|
+
| Argument | Type | Required | Description |
|
|
226
|
+
|----------|------|----------|-------------|
|
|
227
|
+
| notes | string | yes | Rough game/episode notes |
|
|
228
|
+
|
|
229
|
+
Produces 2-3 title options, a YouTube description with above-the-fold hook, and 3-5 thumbnail hook options. Auto-loads the style guide resource.
|
|
230
|
+
`;
|
|
231
|
+
export const footballGlossary = `{
|
|
232
|
+
"version": "1.0",
|
|
233
|
+
"players": {
|
|
234
|
+
"jalen milro": "Jalen Milroe",
|
|
235
|
+
"jalen milroe": "Jalen Milroe",
|
|
236
|
+
"caleb downs": "Caleb Downs",
|
|
237
|
+
"ryan williams": "Ryan Williams",
|
|
238
|
+
"tyler buchner": "Tyler Buchner",
|
|
239
|
+
"jase mcclellan": "Jase McClellan",
|
|
240
|
+
"dallas turner": "Dallas Turner",
|
|
241
|
+
"qu'vonte hicks": "Qu'Vonte Hicks",
|
|
242
|
+
"trevor lawrence": "Trevor Lawrence",
|
|
243
|
+
"travis hunter": "Travis Hunter",
|
|
244
|
+
"cam ward": "Cam Ward",
|
|
245
|
+
"shedeur sanders": "Shedeur Sanders",
|
|
246
|
+
"quinshon judkins": "Quinshon Judkins"
|
|
247
|
+
},
|
|
248
|
+
"coaches": {
|
|
249
|
+
"kalen deboer": "Kalen DeBoer",
|
|
250
|
+
"kirby smart": "Kirby Smart",
|
|
251
|
+
"nick sabin": "Nick Saban",
|
|
252
|
+
"nick saban": "Nick Saban",
|
|
253
|
+
"brian kelly": "Brian Kelly",
|
|
254
|
+
"lane kiffin": "Lane Kiffin",
|
|
255
|
+
"josh heupel": "Josh Heupel",
|
|
256
|
+
"eliah drinkwitz": "Eliah Drinkwitz",
|
|
257
|
+
"mike elko": "Mike Elko",
|
|
258
|
+
"sam pittman": "Sam Pittman",
|
|
259
|
+
"shane beamer": "Shane Beamer",
|
|
260
|
+
"clark lea": "Clark Lea"
|
|
261
|
+
},
|
|
262
|
+
"terms": {
|
|
263
|
+
"rpo": "RPO",
|
|
264
|
+
"tampa 2": "Tampa 2",
|
|
265
|
+
"cover 3": "Cover 3",
|
|
266
|
+
"cover 2": "Cover 2",
|
|
267
|
+
"cover 4": "Cover 4",
|
|
268
|
+
"cover 0": "Cover 0",
|
|
269
|
+
"cover 1": "Cover 1",
|
|
270
|
+
"cover 6": "Cover 6",
|
|
271
|
+
"quarters coverage": "Quarters Coverage",
|
|
272
|
+
"man coverage": "Man Coverage",
|
|
273
|
+
"zone coverage": "Zone Coverage",
|
|
274
|
+
"play action": "Play Action",
|
|
275
|
+
"read option": "Read Option",
|
|
276
|
+
"nickelback": "Nickelback",
|
|
277
|
+
"will linebacker": "Will Linebacker",
|
|
278
|
+
"mike linebacker": "Mike Linebacker",
|
|
279
|
+
"sam linebacker": "Sam Linebacker",
|
|
280
|
+
"epa": "EPA",
|
|
281
|
+
"ppa": "PPA",
|
|
282
|
+
"wpa": "WPA",
|
|
283
|
+
"sp+": "SP+",
|
|
284
|
+
"sp plus": "SP+"
|
|
285
|
+
},
|
|
286
|
+
"schools": {
|
|
287
|
+
"ole miss": "Ole Miss",
|
|
288
|
+
"texas a&m": "Texas A&M",
|
|
289
|
+
"texas a and m": "Texas A&M",
|
|
290
|
+
"lsu": "LSU",
|
|
291
|
+
"usc": "USC",
|
|
292
|
+
"ucf": "UCF",
|
|
293
|
+
"smu": "SMU",
|
|
294
|
+
"tcu": "TCU",
|
|
295
|
+
"oklahoma state": "Oklahoma State",
|
|
296
|
+
"mississippi state": "Mississippi State",
|
|
297
|
+
"south carolina": "South Carolina"
|
|
298
|
+
}
|
|
299
|
+
}`;
|
|
300
|
+
//# sourceMappingURL=embedded-resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded-resources.js","sourceRoot":"","sources":["../src/embedded-resources.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,MAAM,CAAC,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoOvB,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAoE9B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
/**
|
|
3
|
+
* Register all cfb-stats-mcp tools and resources on the given server.
|
|
4
|
+
* Calls initCfbdClient() first (non-fatal if CFBD_API_KEY is absent).
|
|
5
|
+
*/
|
|
6
|
+
export declare function registerAll(server: McpServer): void;
|
|
7
|
+
//# sourceMappingURL=exports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../src/exports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAezE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAcnD"}
|
package/dist/exports.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { initCfbdClient } from "./cfbd-client.js";
|
|
2
|
+
import { registerAdvancedStatsTool } from "./tools/advanced-stats.js";
|
|
3
|
+
import { registerBoxScoreTool } from "./tools/box-score.js";
|
|
4
|
+
import { registerBuildGlossaryTool } from "./tools/build-glossary.js";
|
|
5
|
+
import { registerConferenceRatingsTool } from "./tools/conference-ratings.js";
|
|
6
|
+
import { registerGamesTool } from "./tools/games.js";
|
|
7
|
+
import { registerHeadToHeadTool } from "./tools/head-to-head.js";
|
|
8
|
+
import { registerRatingsTool } from "./tools/ratings.js";
|
|
9
|
+
import { registerResources } from "./resources.js";
|
|
10
|
+
import { registerSeasonAdvancedTool } from "./tools/season-advanced.js";
|
|
11
|
+
import { registerSeasonRecordsTool } from "./tools/season-records.js";
|
|
12
|
+
import { registerSeasonStatsTool } from "./tools/season-stats.js";
|
|
13
|
+
import { registerStatusTool } from "./tools/status.js";
|
|
14
|
+
/**
|
|
15
|
+
* Register all cfb-stats-mcp tools and resources on the given server.
|
|
16
|
+
* Calls initCfbdClient() first (non-fatal if CFBD_API_KEY is absent).
|
|
17
|
+
*/
|
|
18
|
+
export function registerAll(server) {
|
|
19
|
+
initCfbdClient();
|
|
20
|
+
registerStatusTool(server);
|
|
21
|
+
registerGamesTool(server);
|
|
22
|
+
registerBoxScoreTool(server);
|
|
23
|
+
registerAdvancedStatsTool(server);
|
|
24
|
+
registerSeasonRecordsTool(server);
|
|
25
|
+
registerRatingsTool(server);
|
|
26
|
+
registerConferenceRatingsTool(server);
|
|
27
|
+
registerHeadToHeadTool(server);
|
|
28
|
+
registerSeasonStatsTool(server);
|
|
29
|
+
registerSeasonAdvancedTool(server);
|
|
30
|
+
registerBuildGlossaryTool(server);
|
|
31
|
+
registerResources(server);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=exports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exports.js","sourceRoot":"","sources":["../src/exports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAiB;IAC3C,cAAc,EAAE,CAAC;IACjB,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtC,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exports.test.d.ts","sourceRoot":"","sources":["../src/exports.test.ts"],"names":[],"mappings":""}
|