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.
Files changed (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -0
  3. package/dist/cache.d.ts +4 -0
  4. package/dist/cache.d.ts.map +1 -0
  5. package/dist/cache.js +17 -0
  6. package/dist/cache.js.map +1 -0
  7. package/dist/cfbd-client.d.ts +9 -0
  8. package/dist/cfbd-client.d.ts.map +1 -0
  9. package/dist/cfbd-client.js +49 -0
  10. package/dist/cfbd-client.js.map +1 -0
  11. package/dist/cfbd-client.test.d.ts +2 -0
  12. package/dist/cfbd-client.test.d.ts.map +1 -0
  13. package/dist/cfbd-client.test.js +37 -0
  14. package/dist/cfbd-client.test.js.map +1 -0
  15. package/dist/embedded-resources.d.ts +3 -0
  16. package/dist/embedded-resources.d.ts.map +1 -0
  17. package/dist/embedded-resources.js +300 -0
  18. package/dist/embedded-resources.js.map +1 -0
  19. package/dist/exports.d.ts +7 -0
  20. package/dist/exports.d.ts.map +1 -0
  21. package/dist/exports.js +33 -0
  22. package/dist/exports.js.map +1 -0
  23. package/dist/exports.test.d.ts +2 -0
  24. package/dist/exports.test.d.ts.map +1 -0
  25. package/dist/exports.test.js +80 -0
  26. package/dist/exports.test.js.map +1 -0
  27. package/dist/formatters/advanced-formatter.d.ts +3 -0
  28. package/dist/formatters/advanced-formatter.d.ts.map +1 -0
  29. package/dist/formatters/advanced-formatter.js +106 -0
  30. package/dist/formatters/advanced-formatter.js.map +1 -0
  31. package/dist/formatters/box-score-formatter.d.ts +3 -0
  32. package/dist/formatters/box-score-formatter.d.ts.map +1 -0
  33. package/dist/formatters/box-score-formatter.js +154 -0
  34. package/dist/formatters/box-score-formatter.js.map +1 -0
  35. package/dist/formatters/conference-ratings-formatter.d.ts +4 -0
  36. package/dist/formatters/conference-ratings-formatter.d.ts.map +1 -0
  37. package/dist/formatters/conference-ratings-formatter.js +62 -0
  38. package/dist/formatters/conference-ratings-formatter.js.map +1 -0
  39. package/dist/formatters/conference-ratings-formatter.test.d.ts +2 -0
  40. package/dist/formatters/conference-ratings-formatter.test.d.ts.map +1 -0
  41. package/dist/formatters/conference-ratings-formatter.test.js +153 -0
  42. package/dist/formatters/conference-ratings-formatter.test.js.map +1 -0
  43. package/dist/formatters/game-formatter.d.ts +3 -0
  44. package/dist/formatters/game-formatter.d.ts.map +1 -0
  45. package/dist/formatters/game-formatter.js +46 -0
  46. package/dist/formatters/game-formatter.js.map +1 -0
  47. package/dist/formatters/head-to-head-formatter.d.ts +3 -0
  48. package/dist/formatters/head-to-head-formatter.d.ts.map +1 -0
  49. package/dist/formatters/head-to-head-formatter.js +162 -0
  50. package/dist/formatters/head-to-head-formatter.js.map +1 -0
  51. package/dist/formatters/head-to-head-formatter.test.d.ts +2 -0
  52. package/dist/formatters/head-to-head-formatter.test.d.ts.map +1 -0
  53. package/dist/formatters/head-to-head-formatter.test.js +160 -0
  54. package/dist/formatters/head-to-head-formatter.test.js.map +1 -0
  55. package/dist/formatters/ratings-formatter.d.ts +3 -0
  56. package/dist/formatters/ratings-formatter.d.ts.map +1 -0
  57. package/dist/formatters/ratings-formatter.js +75 -0
  58. package/dist/formatters/ratings-formatter.js.map +1 -0
  59. package/dist/formatters/ratings-formatter.test.d.ts +2 -0
  60. package/dist/formatters/ratings-formatter.test.d.ts.map +1 -0
  61. package/dist/formatters/ratings-formatter.test.js +137 -0
  62. package/dist/formatters/ratings-formatter.test.js.map +1 -0
  63. package/dist/formatters/season-advanced-formatter.d.ts +3 -0
  64. package/dist/formatters/season-advanced-formatter.d.ts.map +1 -0
  65. package/dist/formatters/season-advanced-formatter.js +160 -0
  66. package/dist/formatters/season-advanced-formatter.js.map +1 -0
  67. package/dist/formatters/season-advanced-formatter.test.d.ts +2 -0
  68. package/dist/formatters/season-advanced-formatter.test.d.ts.map +1 -0
  69. package/dist/formatters/season-advanced-formatter.test.js +239 -0
  70. package/dist/formatters/season-advanced-formatter.test.js.map +1 -0
  71. package/dist/formatters/season-records-formatter.d.ts +3 -0
  72. package/dist/formatters/season-records-formatter.d.ts.map +1 -0
  73. package/dist/formatters/season-records-formatter.js +64 -0
  74. package/dist/formatters/season-records-formatter.js.map +1 -0
  75. package/dist/formatters/season-stats-formatter.d.ts +3 -0
  76. package/dist/formatters/season-stats-formatter.d.ts.map +1 -0
  77. package/dist/formatters/season-stats-formatter.js +156 -0
  78. package/dist/formatters/season-stats-formatter.js.map +1 -0
  79. package/dist/formatters/season-stats-formatter.test.d.ts +2 -0
  80. package/dist/formatters/season-stats-formatter.test.d.ts.map +1 -0
  81. package/dist/formatters/season-stats-formatter.test.js +76 -0
  82. package/dist/formatters/season-stats-formatter.test.js.map +1 -0
  83. package/dist/index.d.ts +3 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +22 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/logger.d.ts +7 -0
  88. package/dist/logger.d.ts.map +1 -0
  89. package/dist/logger.js +16 -0
  90. package/dist/logger.js.map +1 -0
  91. package/dist/prompts.d.ts +3 -0
  92. package/dist/prompts.d.ts.map +1 -0
  93. package/dist/prompts.js +242 -0
  94. package/dist/prompts.js.map +1 -0
  95. package/dist/resources.d.ts +3 -0
  96. package/dist/resources.d.ts.map +1 -0
  97. package/dist/resources.js +12 -0
  98. package/dist/resources.js.map +1 -0
  99. package/dist/tools/advanced-stats.d.ts +3 -0
  100. package/dist/tools/advanced-stats.d.ts.map +1 -0
  101. package/dist/tools/advanced-stats.js +67 -0
  102. package/dist/tools/advanced-stats.js.map +1 -0
  103. package/dist/tools/box-score.d.ts +3 -0
  104. package/dist/tools/box-score.d.ts.map +1 -0
  105. package/dist/tools/box-score.js +50 -0
  106. package/dist/tools/box-score.js.map +1 -0
  107. package/dist/tools/build-glossary.d.ts +8 -0
  108. package/dist/tools/build-glossary.d.ts.map +1 -0
  109. package/dist/tools/build-glossary.js +125 -0
  110. package/dist/tools/build-glossary.js.map +1 -0
  111. package/dist/tools/build-glossary.test.d.ts +2 -0
  112. package/dist/tools/build-glossary.test.d.ts.map +1 -0
  113. package/dist/tools/build-glossary.test.js +182 -0
  114. package/dist/tools/build-glossary.test.js.map +1 -0
  115. package/dist/tools/conference-ratings.d.ts +3 -0
  116. package/dist/tools/conference-ratings.d.ts.map +1 -0
  117. package/dist/tools/conference-ratings.js +74 -0
  118. package/dist/tools/conference-ratings.js.map +1 -0
  119. package/dist/tools/export-subtitles.d.ts +23 -0
  120. package/dist/tools/export-subtitles.d.ts.map +1 -0
  121. package/dist/tools/export-subtitles.js +102 -0
  122. package/dist/tools/export-subtitles.js.map +1 -0
  123. package/dist/tools/export-subtitles.test.d.ts +2 -0
  124. package/dist/tools/export-subtitles.test.d.ts.map +1 -0
  125. package/dist/tools/export-subtitles.test.js +152 -0
  126. package/dist/tools/export-subtitles.test.js.map +1 -0
  127. package/dist/tools/games.d.ts +3 -0
  128. package/dist/tools/games.d.ts.map +1 -0
  129. package/dist/tools/games.js +64 -0
  130. package/dist/tools/games.js.map +1 -0
  131. package/dist/tools/head-to-head.d.ts +3 -0
  132. package/dist/tools/head-to-head.d.ts.map +1 -0
  133. package/dist/tools/head-to-head.js +74 -0
  134. package/dist/tools/head-to-head.js.map +1 -0
  135. package/dist/tools/ratings.d.ts +3 -0
  136. package/dist/tools/ratings.d.ts.map +1 -0
  137. package/dist/tools/ratings.js +63 -0
  138. package/dist/tools/ratings.js.map +1 -0
  139. package/dist/tools/read-transcript.d.ts +9 -0
  140. package/dist/tools/read-transcript.d.ts.map +1 -0
  141. package/dist/tools/read-transcript.js +72 -0
  142. package/dist/tools/read-transcript.js.map +1 -0
  143. package/dist/tools/read-transcript.test.d.ts +2 -0
  144. package/dist/tools/read-transcript.test.d.ts.map +1 -0
  145. package/dist/tools/read-transcript.test.js +94 -0
  146. package/dist/tools/read-transcript.test.js.map +1 -0
  147. package/dist/tools/season-advanced.d.ts +3 -0
  148. package/dist/tools/season-advanced.d.ts.map +1 -0
  149. package/dist/tools/season-advanced.js +103 -0
  150. package/dist/tools/season-advanced.js.map +1 -0
  151. package/dist/tools/season-records.d.ts +3 -0
  152. package/dist/tools/season-records.d.ts.map +1 -0
  153. package/dist/tools/season-records.js +51 -0
  154. package/dist/tools/season-records.js.map +1 -0
  155. package/dist/tools/season-stats.d.ts +3 -0
  156. package/dist/tools/season-stats.d.ts.map +1 -0
  157. package/dist/tools/season-stats.js +75 -0
  158. package/dist/tools/season-stats.js.map +1 -0
  159. package/dist/tools/status.d.ts +3 -0
  160. package/dist/tools/status.d.ts.map +1 -0
  161. package/dist/tools/status.js +19 -0
  162. package/dist/tools/status.js.map +1 -0
  163. package/dist/tools/transcript-types.d.ts +36 -0
  164. package/dist/tools/transcript-types.d.ts.map +1 -0
  165. package/dist/tools/transcript-types.js +2 -0
  166. package/dist/tools/transcript-types.js.map +1 -0
  167. package/dist/tools/write-chapters.d.ts +40 -0
  168. package/dist/tools/write-chapters.d.ts.map +1 -0
  169. package/dist/tools/write-chapters.js +143 -0
  170. package/dist/tools/write-chapters.js.map +1 -0
  171. package/dist/tools/write-chapters.test.d.ts +2 -0
  172. package/dist/tools/write-chapters.test.d.ts.map +1 -0
  173. package/dist/tools/write-chapters.test.js +167 -0
  174. package/dist/tools/write-chapters.test.js.map +1 -0
  175. package/dist/tools/write-clip-candidates.d.ts +30 -0
  176. package/dist/tools/write-clip-candidates.d.ts.map +1 -0
  177. package/dist/tools/write-clip-candidates.js +130 -0
  178. package/dist/tools/write-clip-candidates.js.map +1 -0
  179. package/dist/tools/write-clip-candidates.test.d.ts +2 -0
  180. package/dist/tools/write-clip-candidates.test.d.ts.map +1 -0
  181. package/dist/tools/write-clip-candidates.test.js +213 -0
  182. package/dist/tools/write-clip-candidates.test.js.map +1 -0
  183. package/dist/tools/write-description.d.ts +11 -0
  184. package/dist/tools/write-description.d.ts.map +1 -0
  185. package/dist/tools/write-description.js +71 -0
  186. package/dist/tools/write-description.js.map +1 -0
  187. package/dist/tools/write-description.test.d.ts +2 -0
  188. package/dist/tools/write-description.test.d.ts.map +1 -0
  189. package/dist/tools/write-description.test.js +42 -0
  190. package/dist/tools/write-description.test.js.map +1 -0
  191. package/dist/tools/write-transcript.d.ts +20 -0
  192. package/dist/tools/write-transcript.d.ts.map +1 -0
  193. package/dist/tools/write-transcript.js +133 -0
  194. package/dist/tools/write-transcript.js.map +1 -0
  195. package/dist/tools/write-transcript.test.d.ts +2 -0
  196. package/dist/tools/write-transcript.test.d.ts.map +1 -0
  197. package/dist/tools/write-transcript.test.js +133 -0
  198. package/dist/tools/write-transcript.test.js.map +1 -0
  199. package/package.json +59 -0
  200. package/resources/football-glossary.json +69 -0
  201. package/resources/workflow.md +228 -0
@@ -0,0 +1,102 @@
1
+ import { z } from "zod";
2
+ import { readFileSync, writeFileSync } from "node:fs";
3
+ import { logger } from "../logger.js";
4
+ /**
5
+ * Convert float seconds to SRT timestamp format "HH:MM:SS,mmm".
6
+ * Uses comma separator (not period) per SRT spec.
7
+ */
8
+ export function formatSrtTimestamp(seconds) {
9
+ const totalMs = Math.round(seconds * 1000);
10
+ const ms = totalMs % 1000;
11
+ const totalSecs = Math.floor(totalMs / 1000);
12
+ const s = totalSecs % 60;
13
+ const totalMins = Math.floor(totalSecs / 60);
14
+ const m = totalMins % 60;
15
+ const h = Math.floor(totalMins / 60);
16
+ return (`${String(h).padStart(2, "0")}:` +
17
+ `${String(m).padStart(2, "0")}:` +
18
+ `${String(s).padStart(2, "0")},` +
19
+ `${String(ms).padStart(3, "0")}`);
20
+ }
21
+ /**
22
+ * Generate SRT subtitle string from a transcript.
23
+ * Uses segment-level timing (not word-level) per D4 decision.
24
+ * Returns empty string for transcripts with no segments.
25
+ */
26
+ export function generateSrt(transcript) {
27
+ if (transcript.segments.length === 0) {
28
+ return "";
29
+ }
30
+ const entries = transcript.segments.map((segment, index) => {
31
+ const num = index + 1;
32
+ const start = formatSrtTimestamp(segment.start);
33
+ const end = formatSrtTimestamp(segment.end);
34
+ return `${num}\n${start} --> ${end}\n${segment.text}`;
35
+ });
36
+ return entries.join("\n\n") + "\n";
37
+ }
38
+ /**
39
+ * Read a corrected transcript JSON from disk, generate SRT, and write to file.
40
+ * Returns success/failure with descriptive message.
41
+ */
42
+ export function exportSubtitles(transcriptPath, outputPath) {
43
+ try {
44
+ const raw = readFileSync(transcriptPath, "utf-8");
45
+ const transcript = JSON.parse(raw);
46
+ const srt = generateSrt(transcript);
47
+ writeFileSync(outputPath, srt, "utf-8");
48
+ const count = transcript.segments.length;
49
+ return {
50
+ success: true,
51
+ message: `Exported ${count} subtitle segments to ${outputPath}`,
52
+ };
53
+ }
54
+ catch (error) {
55
+ return {
56
+ success: false,
57
+ message: `Failed to export subtitles: ${error instanceof Error ? error.message : String(error)}`,
58
+ };
59
+ }
60
+ }
61
+ const inputSchema = {
62
+ transcript_path: z
63
+ .string()
64
+ .describe("Path to the corrected transcript JSON file"),
65
+ output_path: z.string().describe("Output path for the SRT file"),
66
+ };
67
+ export function registerExportSubtitlesTool(server) {
68
+ server.registerTool("export_subtitles", {
69
+ title: "Export Subtitles",
70
+ description: "Exports a corrected transcript as an SRT subtitle file for YouTube upload. " +
71
+ "Reads the transcript JSON and writes a .srt file with segment-level timestamps.",
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
+ inputSchema: inputSchema,
74
+ }, (args) => {
75
+ try {
76
+ const result = exportSubtitles(args.transcript_path, args.output_path);
77
+ logger.info("export_subtitles tool invoked", {
78
+ transcript_path: args.transcript_path,
79
+ output_path: args.output_path,
80
+ success: result.success,
81
+ });
82
+ if (!result.success) {
83
+ return {
84
+ content: [{ type: "text", text: result.message }],
85
+ isError: true,
86
+ };
87
+ }
88
+ return {
89
+ content: [{ type: "text", text: result.message }],
90
+ };
91
+ }
92
+ catch (error) {
93
+ const message = `Failed to export subtitles: ${error instanceof Error ? error.message : String(error)}`;
94
+ logger.error("export_subtitles tool error", { error: message });
95
+ return {
96
+ content: [{ type: "text", text: message }],
97
+ isError: true,
98
+ };
99
+ }
100
+ });
101
+ }
102
+ //# sourceMappingURL=export-subtitles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-subtitles.js","sourceRoot":"","sources":["../../src/tools/export-subtitles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=export-subtitles.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-subtitles.test.d.ts","sourceRoot":"","sources":["../../src/tools/export-subtitles.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,152 @@
1
+ import { vi, describe, it, expect, beforeEach } from "vitest";
2
+ vi.mock("node:fs", () => ({
3
+ readFileSync: vi.fn(),
4
+ writeFileSync: vi.fn(),
5
+ }));
6
+ vi.mock("../logger.js", () => ({
7
+ logger: {
8
+ debug: vi.fn(),
9
+ info: vi.fn(),
10
+ warn: vi.fn(),
11
+ error: vi.fn(),
12
+ },
13
+ }));
14
+ import { formatSrtTimestamp, generateSrt, exportSubtitles, } from "./export-subtitles.js";
15
+ import { readFileSync, writeFileSync } from "node:fs";
16
+ const mockReadFileSync = vi.mocked(readFileSync);
17
+ const mockWriteFileSync = vi.mocked(writeFileSync);
18
+ function makeTranscript(overrides) {
19
+ const segments = overrides?.segments ?? [
20
+ {
21
+ start: 0.0,
22
+ end: 5.0,
23
+ text: "Hello world",
24
+ words: [
25
+ {
26
+ word: "Hello",
27
+ start: 0.0,
28
+ end: 0.5,
29
+ score: 0.95,
30
+ speaker: "SPEAKER_00",
31
+ },
32
+ {
33
+ word: "world",
34
+ start: 0.6,
35
+ end: 1.0,
36
+ score: 0.98,
37
+ speaker: "SPEAKER_00",
38
+ },
39
+ ],
40
+ speaker: "SPEAKER_00",
41
+ },
42
+ ];
43
+ // Ensure all segments have words array
44
+ const normalizedSegments = segments.map((s) => ({
45
+ start: s.start,
46
+ end: s.end,
47
+ text: s.text,
48
+ words: s.words ?? [],
49
+ speaker: s.speaker ?? null,
50
+ }));
51
+ return {
52
+ version: "1.0",
53
+ language: "en",
54
+ segments: normalizedSegments,
55
+ chapters: [],
56
+ metadata: null,
57
+ };
58
+ }
59
+ describe("formatSrtTimestamp", () => {
60
+ it("formats zero seconds", () => {
61
+ expect(formatSrtTimestamp(0)).toBe("00:00:00,000");
62
+ });
63
+ it("formats fractional seconds with correct rounding", () => {
64
+ expect(formatSrtTimestamp(5.4)).toBe("00:00:05,400");
65
+ });
66
+ it("formats hours, minutes, seconds, and milliseconds", () => {
67
+ expect(formatSrtTimestamp(3723.15)).toBe("01:02:03,150");
68
+ });
69
+ });
70
+ describe("generateSrt", () => {
71
+ it("generates valid SRT from 2 segments", () => {
72
+ const transcript = makeTranscript({
73
+ segments: [
74
+ {
75
+ start: 0.0,
76
+ end: 5.0,
77
+ text: "Hello world",
78
+ words: [],
79
+ speaker: null,
80
+ },
81
+ {
82
+ start: 5.0,
83
+ end: 10.5,
84
+ text: "Second segment here",
85
+ words: [],
86
+ speaker: null,
87
+ },
88
+ ],
89
+ });
90
+ const srt = generateSrt(transcript);
91
+ // 1-based indices
92
+ expect(srt).toContain("1\n");
93
+ expect(srt).toContain("2\n");
94
+ // Comma-separated timestamps with --> separator
95
+ expect(srt).toContain("00:00:00,000 --> 00:00:05,000");
96
+ expect(srt).toContain("00:00:05,000 --> 00:00:10,500");
97
+ // Segment text
98
+ expect(srt).toContain("Hello world");
99
+ expect(srt).toContain("Second segment here");
100
+ // Entries separated by blank lines
101
+ const entries = srt.trim().split("\n\n");
102
+ expect(entries).toHaveLength(2);
103
+ // Trailing newline
104
+ expect(srt.endsWith("\n")).toBe(true);
105
+ });
106
+ it("returns empty string for 0 segments", () => {
107
+ const transcript = makeTranscript({ segments: [] });
108
+ expect(generateSrt(transcript)).toBe("");
109
+ });
110
+ });
111
+ describe("exportSubtitles", () => {
112
+ beforeEach(() => {
113
+ vi.clearAllMocks();
114
+ });
115
+ it("reads transcript, generates SRT, and writes file", () => {
116
+ const transcript = makeTranscript({
117
+ segments: [
118
+ {
119
+ start: 0.0,
120
+ end: 5.0,
121
+ text: "Hello world",
122
+ words: [],
123
+ speaker: null,
124
+ },
125
+ {
126
+ start: 5.0,
127
+ end: 10.0,
128
+ text: "Goodbye",
129
+ words: [],
130
+ speaker: null,
131
+ },
132
+ ],
133
+ });
134
+ mockReadFileSync.mockReturnValue(JSON.stringify(transcript));
135
+ const result = exportSubtitles("/in/transcript.json", "/out/subtitles.srt");
136
+ expect(result.success).toBe(true);
137
+ expect(result.message).toContain("2");
138
+ expect(result.message).toContain("/out/subtitles.srt");
139
+ expect(mockReadFileSync).toHaveBeenCalledWith("/in/transcript.json", "utf-8");
140
+ expect(mockWriteFileSync).toHaveBeenCalledWith("/out/subtitles.srt", expect.any(String), "utf-8");
141
+ });
142
+ it("returns success false when transcript file does not exist", () => {
143
+ mockReadFileSync.mockImplementation(() => {
144
+ throw new Error("ENOENT: no such file or directory");
145
+ });
146
+ const result = exportSubtitles("/missing/transcript.json", "/out/subtitles.srt");
147
+ expect(result.success).toBe(false);
148
+ expect(result.message).toMatch(/ENOENT|no such file/i);
149
+ expect(mockWriteFileSync).not.toHaveBeenCalled();
150
+ });
151
+ });
152
+ //# sourceMappingURL=export-subtitles.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-subtitles.test.js","sourceRoot":"","sources":["../../src/tools/export-subtitles.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerGamesTool(server: McpServer): void;
3
+ //# sourceMappingURL=games.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"games.d.ts","sourceRoot":"","sources":["../../src/tools/games.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmCzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoDzD"}
@@ -0,0 +1,64 @@
1
+ import { z } from "zod";
2
+ import { getGames } from "cfbd";
3
+ import { cachedFetch } from "../cfbd-client.js";
4
+ import { formatGames } from "../formatters/game-formatter.js";
5
+ import { logger } from "../logger.js";
6
+ // Schema defined separately for readability. Type assertion needed because
7
+ // MCP SDK v1.27 resolves zod/v3 types from the hoisted zod v4 package,
8
+ // which are structurally identical but nominally distinct from the local
9
+ // zod v3 package's types. Runtime behavior is unaffected.
10
+ const inputSchema = {
11
+ team: z
12
+ .string()
13
+ .describe("Team school name (e.g. 'Alabama', 'Ohio State', 'Texas A&M')"),
14
+ year: z.number().describe("Season year (e.g. 2024)"),
15
+ week: z
16
+ .number()
17
+ .optional()
18
+ .describe("Week number - omit for full season"),
19
+ seasonType: z
20
+ .enum(["regular", "postseason", "both"])
21
+ .optional()
22
+ .describe("Season type filter - defaults to 'both' for full picture"),
23
+ };
24
+ export function registerGamesTool(server) {
25
+ server.registerTool("cfbd_games", {
26
+ title: "Game Results",
27
+ description: "Look up college football game results by team and season. Returns scores, dates, venues, and Elo ratings.",
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ inputSchema: inputSchema,
30
+ }, async (args) => {
31
+ const { team, year, week } = args;
32
+ const resolvedSeasonType = args.seasonType ?? "both";
33
+ try {
34
+ const games = await cachedFetch("getGames", { year, team, week, seasonType: resolvedSeasonType }, () => getGames({
35
+ query: { year, team, week, seasonType: resolvedSeasonType },
36
+ }));
37
+ const formatted = formatGames(games, team);
38
+ logger.info("cfbd_games tool invoked", {
39
+ team,
40
+ year,
41
+ week,
42
+ seasonType: resolvedSeasonType,
43
+ gameCount: games.length,
44
+ });
45
+ return {
46
+ content: [{ type: "text", text: formatted }],
47
+ };
48
+ }
49
+ catch (error) {
50
+ const message = `Failed to fetch games: ${error instanceof Error ? error.message : String(error)}`;
51
+ logger.error("cfbd_games tool error", {
52
+ team,
53
+ year,
54
+ week,
55
+ error: message,
56
+ });
57
+ return {
58
+ content: [{ type: "text", text: message }],
59
+ isError: true,
60
+ };
61
+ }
62
+ });
63
+ }
64
+ //# sourceMappingURL=games.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"games.js","sourceRoot":"","sources":["../../src/tools/games.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAA8B,MAAM,MAAM,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,2EAA2E;AAC3E,uEAAuE;AACvE,yEAAyE;AACzE,0DAA0D;AAC1D,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,QAAQ,CACP,8DAA8D,CAC/D;IACH,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IACpD,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,oCAAoC,CAAC;IACjD,UAAU,EAAE,CAAC;SACV,IAAI,CAAC,CAAC,SAAS,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;SACvC,QAAQ,EAAE;SACV,QAAQ,CAAC,0DAA0D,CAAC;CACxE,CAAC;AASF,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,YAAY,CACjB,YAAY,EACZ;QACE,KAAK,EAAE,cAAc;QACrB,WAAW,EACT,2GAA2G;QAC7G,8DAA8D;QAC9D,WAAW,EAAE,WAAkB;KAChC,EACD,KAAK,EAAE,IAAgB,EAAE,EAAE;QACzB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;QAClC,MAAM,kBAAkB,GAAe,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC;QAEjE,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,WAAW,CAC7B,UAAU,EACV,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,kBAAkB,EAAE,EACpD,GAAG,EAAE,CACH,QAAQ,CAAC;gBACP,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,kBAAkB,EAAE;aAC5D,CAAC,CACL,CAAC;YAEF,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE;gBACrC,IAAI;gBACJ,IAAI;gBACJ,IAAI;gBACJ,UAAU,EAAE,kBAAkB;gBAC9B,SAAS,EAAE,KAAK,CAAC,MAAM;aACxB,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;aACtD,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,0BAA0B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACnG,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE;gBACpC,IAAI;gBACJ,IAAI;gBACJ,IAAI;gBACJ,KAAK,EAAE,OAAO;aACf,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;gBACnD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerHeadToHeadTool(server: McpServer): void;
3
+ //# sourceMappingURL=head-to-head.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head-to-head.d.ts","sourceRoot":"","sources":["../../src/tools/head-to-head.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAoCzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAoE9D"}
@@ -0,0 +1,74 @@
1
+ import { z } from "zod";
2
+ import { getMatchup } from "cfbd";
3
+ import { cachedFetch } from "../cfbd-client.js";
4
+ import { formatHeadToHead } from "../formatters/head-to-head-formatter.js";
5
+ import { logger } from "../logger.js";
6
+ // See games.ts for why `as any` is needed on inputSchema.
7
+ const inputSchema = {
8
+ team1: z
9
+ .string()
10
+ .describe("First team school name (e.g. 'Alabama')"),
11
+ team2: z
12
+ .string()
13
+ .describe("Second team school name (e.g. 'Auburn')"),
14
+ startYear: z
15
+ .number()
16
+ .optional()
17
+ .describe("Start of year range filter (e.g. 2017) \u2014 omit for all-time series"),
18
+ endYear: z
19
+ .number()
20
+ .optional()
21
+ .describe("End of year range filter (e.g. 2024) \u2014 omit for all-time series"),
22
+ };
23
+ export function registerHeadToHeadTool(server) {
24
+ server.registerTool("cfbd_head_to_head", {
25
+ title: "Head-to-Head Matchup History",
26
+ description: "Get historical head-to-head series data between two teams. Shows all-time series record, last 10 and last 5 results, and venue breakdowns. Use startYear/endYear to scope to a coaching era or specific period.",
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ inputSchema: inputSchema,
29
+ }, async (args) => {
30
+ const queryParams = {
31
+ team1: args.team1,
32
+ team2: args.team2,
33
+ };
34
+ if (args.startYear != null)
35
+ queryParams.minYear = args.startYear;
36
+ if (args.endYear != null)
37
+ queryParams.maxYear = args.endYear;
38
+ try {
39
+ const matchup = await cachedFetch("getMatchup", queryParams, () => getMatchup({
40
+ query: {
41
+ team1: args.team1,
42
+ team2: args.team2,
43
+ minYear: args.startYear,
44
+ maxYear: args.endYear,
45
+ },
46
+ }));
47
+ const hasYearRange = args.startYear != null || args.endYear != null;
48
+ const formatted = formatHeadToHead(matchup, args.team1, args.team2, hasYearRange);
49
+ logger.info("cfbd_head_to_head tool invoked", {
50
+ team1: args.team1,
51
+ team2: args.team2,
52
+ startYear: args.startYear,
53
+ endYear: args.endYear,
54
+ gameCount: matchup.games.length,
55
+ });
56
+ return {
57
+ content: [{ type: "text", text: formatted }],
58
+ };
59
+ }
60
+ catch (error) {
61
+ const message = `Failed to fetch head-to-head data: ${error instanceof Error ? error.message : String(error)}`;
62
+ logger.error("cfbd_head_to_head tool error", {
63
+ team1: args.team1,
64
+ team2: args.team2,
65
+ error: message,
66
+ });
67
+ return {
68
+ content: [{ type: "text", text: message }],
69
+ isError: true,
70
+ };
71
+ }
72
+ });
73
+ }
74
+ //# sourceMappingURL=head-to-head.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"head-to-head.js","sourceRoot":"","sources":["../../src/tools/head-to-head.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerRatingsTool(server: McpServer): void;
3
+ //# sourceMappingURL=ratings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ratings.d.ts","sourceRoot":"","sources":["../../src/tools/ratings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgCzE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+D3D"}
@@ -0,0 +1,63 @@
1
+ import { z } from "zod";
2
+ import { getSp, getSrs, getElo, getFpi, } from "cfbd";
3
+ import { cachedFetch } from "../cfbd-client.js";
4
+ import { formatRatings } from "../formatters/ratings-formatter.js";
5
+ import { logger } from "../logger.js";
6
+ // See games.ts for why `as any` is needed on inputSchema.
7
+ const inputSchema = {
8
+ team: z
9
+ .string()
10
+ .describe("Team school name (e.g. 'Alabama', 'Ohio State')"),
11
+ year: z
12
+ .number()
13
+ .optional()
14
+ .describe("Season year (e.g. 2024) — defaults to current season"),
15
+ };
16
+ export function registerRatingsTool(server) {
17
+ server.registerTool("cfbd_ratings", {
18
+ title: "Team Ratings",
19
+ description: "Get multi-system ratings (SP+, SRS, Elo, FPI) for a team. Shows headline numbers: overall rating and ranking, offense/defense breakdowns where available. Use for comparing a team across rating systems or getting a comprehensive strength assessment.",
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ inputSchema: inputSchema,
22
+ }, async (args) => {
23
+ const year = args.year ?? new Date().getFullYear();
24
+ try {
25
+ const [spAll, srsAll, eloAll, fpiAll] = await Promise.all([
26
+ cachedFetch("getSp", { year }, () => getSp({ query: { year } })),
27
+ cachedFetch("getSrs", { year, team: args.team }, () => getSrs({ query: { year, team: args.team } })),
28
+ cachedFetch("getElo", { year, team: args.team }, () => getElo({ query: { year, team: args.team } })),
29
+ cachedFetch("getFpi", { year, team: args.team }, () => getFpi({ query: { year, team: args.team } })),
30
+ ]);
31
+ const teamLower = args.team.toLowerCase();
32
+ const sp = spAll.find((r) => r.team.toLowerCase() === teamLower);
33
+ const srs = srsAll.find((r) => r.team.toLowerCase() === teamLower);
34
+ const elo = eloAll.find((r) => r.team.toLowerCase() === teamLower);
35
+ const fpi = fpiAll.find((r) => r.team.toLowerCase() === teamLower);
36
+ const formatted = formatRatings(sp, srs, elo, fpi, args.team, year);
37
+ logger.info("cfbd_ratings tool invoked", {
38
+ team: args.team,
39
+ year,
40
+ hasSp: !!sp,
41
+ hasSrs: !!srs,
42
+ hasElo: !!elo,
43
+ hasFpi: !!fpi,
44
+ });
45
+ return {
46
+ content: [{ type: "text", text: formatted }],
47
+ };
48
+ }
49
+ catch (error) {
50
+ const message = `Failed to fetch team ratings: ${error instanceof Error ? error.message : String(error)}`;
51
+ logger.error("cfbd_ratings tool error", {
52
+ team: args.team,
53
+ year,
54
+ error: message,
55
+ });
56
+ return {
57
+ content: [{ type: "text", text: message }],
58
+ isError: true,
59
+ };
60
+ }
61
+ });
62
+ }
63
+ //# sourceMappingURL=ratings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ratings.js","sourceRoot":"","sources":["../../src/tools/ratings.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,KAAK,EACL,MAAM,EACN,MAAM,EACN,MAAM,GAKP,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,0DAA0D;AAC1D,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,QAAQ,CAAC,iDAAiD,CAAC;IAC9D,IAAI,EAAE,CAAC;SACJ,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,sDAAsD,CAAC;CACpE,CAAC;AAOF,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,YAAY,CACjB,cAAc,EACd;QACE,KAAK,EAAE,cAAc;QACrB,WAAW,EACT,0PAA0P;QAC5P,8DAA8D;QAC9D,WAAW,EAAE,WAAkB;KAChC,EACD,KAAK,EAAE,IAAkB,EAAE,EAAE;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAEnD,IAAI,CAAC;YACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBACxD,WAAW,CAAW,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAC5C,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,CAC3B;gBACD,WAAW,CAAY,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,CAC/D,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAC7C;gBACD,WAAW,CAAY,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,CAC/D,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAC7C;gBACD,WAAW,CAAY,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,CAC/D,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAC7C;aACF,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YAC1C,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,CAAC;YACjE,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,CAAC;YACnE,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,CAAC;YACnE,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC,CAAC;YAEnE,MAAM,SAAS,GAAG,aAAa,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACpE,MAAM,CAAC,IAAI,CAAC,2BAA2B,EAAE;gBACvC,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI;gBACJ,KAAK,EAAE,CAAC,CAAC,EAAE;gBACX,MAAM,EAAE,CAAC,CAAC,GAAG;gBACb,MAAM,EAAE,CAAC,CAAC,GAAG;gBACb,MAAM,EAAE,CAAC,CAAC,GAAG;aACd,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;aACtD,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,iCAAiC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1G,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE;gBACtC,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI;gBACJ,KAAK,EAAE,OAAO;aACf,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;gBACnD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { Transcript } from "./transcript-types.js";
3
+ /**
4
+ * Read a transcript JSON file from disk and validate its structure.
5
+ * Exported separately from the MCP registration for direct testing.
6
+ */
7
+ export declare function readTranscript(filePath: string): Transcript;
8
+ export declare function registerReadTranscriptTool(server: McpServer): void;
9
+ //# sourceMappingURL=read-transcript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-transcript.d.ts","sourceRoot":"","sources":["../../src/tools/read-transcript.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAQxD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CA4B3D;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAqClE"}
@@ -0,0 +1,72 @@
1
+ import { z } from "zod";
2
+ import { readFileSync } from "node:fs";
3
+ import { logger } from "../logger.js";
4
+ const inputSchema = {
5
+ file_path: z
6
+ .string()
7
+ .describe("Absolute path to the transcript JSON file"),
8
+ };
9
+ /**
10
+ * Read a transcript JSON file from disk and validate its structure.
11
+ * Exported separately from the MCP registration for direct testing.
12
+ */
13
+ export function readTranscript(filePath) {
14
+ let raw;
15
+ try {
16
+ raw = readFileSync(filePath, "utf-8");
17
+ }
18
+ catch (err) {
19
+ const code = err.code;
20
+ if (code === "ENOENT") {
21
+ throw new Error(`Transcript file not found: ${filePath}`);
22
+ }
23
+ throw err;
24
+ }
25
+ let parsed;
26
+ try {
27
+ parsed = JSON.parse(raw);
28
+ }
29
+ catch {
30
+ throw new Error(`Invalid JSON in transcript file: ${filePath}`);
31
+ }
32
+ const transcript = parsed;
33
+ if (transcript.version !== "1.0") {
34
+ throw new Error(`Unsupported transcript version "${transcript.version}" (expected "1.0")`);
35
+ }
36
+ return transcript;
37
+ }
38
+ export function registerReadTranscriptTool(server) {
39
+ server.registerTool("read_transcript", {
40
+ title: "Read Transcript",
41
+ description: "Reads a transcript JSON file from disk and returns its content. " +
42
+ "Validates the transcript version is 1.0. Use this to load a transcript " +
43
+ "before starting proper noun correction.",
44
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
+ inputSchema: inputSchema,
46
+ }, (args) => {
47
+ try {
48
+ const transcript = readTranscript(args.file_path);
49
+ logger.info("read_transcript tool invoked", {
50
+ file_path: args.file_path,
51
+ segments: transcript.segments.length,
52
+ });
53
+ return {
54
+ content: [
55
+ {
56
+ type: "text",
57
+ text: JSON.stringify(transcript, null, 2),
58
+ },
59
+ ],
60
+ };
61
+ }
62
+ catch (error) {
63
+ const message = `Failed to read transcript: ${error instanceof Error ? error.message : String(error)}`;
64
+ logger.error("read_transcript tool error", { error: message });
65
+ return {
66
+ content: [{ type: "text", text: message }],
67
+ isError: true,
68
+ };
69
+ }
70
+ });
71
+ }
72
+ //# sourceMappingURL=read-transcript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-transcript.js","sourceRoot":"","sources":["../../src/tools/read-transcript.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGtC,MAAM,WAAW,GAAG;IAClB,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,CAAC,2CAA2C,CAAC;CACzD,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,IAAI,GAAI,GAAyB,CAAC,IAAI,CAAC;QAC7C,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,UAAU,GAAG,MAAoB,CAAC;IAExC,IAAI,UAAU,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,mCAAmC,UAAU,CAAC,OAAO,oBAAoB,CAC1E,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,MAAiB;IAC1D,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EACT,kEAAkE;YAClE,yEAAyE;YACzE,yCAAyC;QAC3C,8DAA8D;QAC9D,WAAW,EAAE,WAAkB;KAChC,EACD,CAAC,IAA2B,EAAE,EAAE;QAC9B,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAClD,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE;gBAC1C,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,MAAM;aACrC,CAAC,CAAC;YACH,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;qBAC1C;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,8BAA8B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACvG,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YAC/D,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;gBACnD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=read-transcript.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-transcript.test.d.ts","sourceRoot":"","sources":["../../src/tools/read-transcript.test.ts"],"names":[],"mappings":""}