youtube-knowledge-mcp 2.2.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/README.md +62 -18
  2. package/dist/harvest-schemas.d.ts +75 -0
  3. package/dist/harvest-schemas.d.ts.map +1 -0
  4. package/dist/harvest-schemas.js +106 -0
  5. package/dist/harvest-schemas.js.map +1 -0
  6. package/dist/registry/harvest-tools.d.ts +10 -0
  7. package/dist/registry/harvest-tools.d.ts.map +1 -0
  8. package/dist/registry/harvest-tools.js +109 -0
  9. package/dist/registry/harvest-tools.js.map +1 -0
  10. package/dist/registry/health-tools.d.ts.map +1 -1
  11. package/dist/registry/health-tools.js +18 -0
  12. package/dist/registry/health-tools.js.map +1 -1
  13. package/dist/registry/index.d.ts.map +1 -1
  14. package/dist/registry/index.js +2 -0
  15. package/dist/registry/index.js.map +1 -1
  16. package/dist/registry/video-tools.js +1 -1
  17. package/dist/registry/video-tools.js.map +1 -1
  18. package/dist/schemas.d.ts +239 -0
  19. package/dist/schemas.d.ts.map +1 -1
  20. package/dist/schemas.js +56 -0
  21. package/dist/schemas.js.map +1 -1
  22. package/dist/thumbnail-schemas.d.ts +28 -28
  23. package/dist/tools/ask-brain.js +1 -1
  24. package/dist/tools/ask-brain.js.map +1 -1
  25. package/dist/tools/brain-info.js +1 -1
  26. package/dist/tools/brain-info.js.map +1 -1
  27. package/dist/tools/check-health.d.ts +59 -0
  28. package/dist/tools/check-health.d.ts.map +1 -1
  29. package/dist/tools/check-health.js +85 -6
  30. package/dist/tools/check-health.js.map +1 -1
  31. package/dist/tools/fetch-channel-thumbnails.d.ts +8 -8
  32. package/dist/tools/fetch-videos.d.ts +15 -4
  33. package/dist/tools/fetch-videos.d.ts.map +1 -1
  34. package/dist/tools/fetch-videos.js +63 -22
  35. package/dist/tools/fetch-videos.js.map +1 -1
  36. package/dist/tools/get-comments.d.ts +238 -6
  37. package/dist/tools/get-comments.d.ts.map +1 -1
  38. package/dist/tools/get-comments.js +85 -21
  39. package/dist/tools/get-comments.js.map +1 -1
  40. package/dist/tools/get-coverage.d.ts +122 -0
  41. package/dist/tools/get-coverage.d.ts.map +1 -0
  42. package/dist/tools/get-coverage.js +105 -0
  43. package/dist/tools/get-coverage.js.map +1 -0
  44. package/dist/tools/harvest-channel.d.ts +92 -0
  45. package/dist/tools/harvest-channel.d.ts.map +1 -0
  46. package/dist/tools/harvest-channel.js +62 -0
  47. package/dist/tools/harvest-channel.js.map +1 -0
  48. package/dist/tools/harvest-comments.d.ts +81 -0
  49. package/dist/tools/harvest-comments.d.ts.map +1 -0
  50. package/dist/tools/harvest-comments.js +115 -0
  51. package/dist/tools/harvest-comments.js.map +1 -0
  52. package/dist/tools/library.js +1 -1
  53. package/dist/tools/library.js.map +1 -1
  54. package/dist/tools/list-channel-thumbnails.d.ts +10 -10
  55. package/dist/tools/list-channel-thumbnails.js +1 -1
  56. package/dist/tools/list-channel-thumbnails.js.map +1 -1
  57. package/dist/tools/list-library.js +1 -1
  58. package/dist/tools/list-library.js.map +1 -1
  59. package/dist/tools/prune-harvest.d.ts +59 -0
  60. package/dist/tools/prune-harvest.d.ts.map +1 -0
  61. package/dist/tools/prune-harvest.js +108 -0
  62. package/dist/tools/prune-harvest.js.map +1 -0
  63. package/dist/tools/query-comments.d.ts +125 -0
  64. package/dist/tools/query-comments.d.ts.map +1 -0
  65. package/dist/tools/query-comments.js +106 -0
  66. package/dist/tools/query-comments.js.map +1 -0
  67. package/dist/tools/query-videos.d.ts +118 -0
  68. package/dist/tools/query-videos.d.ts.map +1 -0
  69. package/dist/tools/query-videos.js +97 -0
  70. package/dist/tools/query-videos.js.map +1 -0
  71. package/dist/tools/repair-store.d.ts +34 -0
  72. package/dist/tools/repair-store.d.ts.map +1 -0
  73. package/dist/tools/repair-store.js +58 -0
  74. package/dist/tools/repair-store.js.map +1 -0
  75. package/dist/tools/search-channels.d.ts.map +1 -1
  76. package/dist/tools/search-channels.js +5 -1
  77. package/dist/tools/search-channels.js.map +1 -1
  78. package/dist/tools/search-videos.js +1 -1
  79. package/dist/tools/search-videos.js.map +1 -1
  80. package/dist/utils/comment-store.d.ts +71 -0
  81. package/dist/utils/comment-store.d.ts.map +1 -0
  82. package/dist/utils/comment-store.js +129 -0
  83. package/dist/utils/comment-store.js.map +1 -0
  84. package/dist/utils/comment-threads.d.ts +51 -0
  85. package/dist/utils/comment-threads.d.ts.map +1 -0
  86. package/dist/utils/comment-threads.js +76 -0
  87. package/dist/utils/comment-threads.js.map +1 -0
  88. package/dist/utils/coverage-text.d.ts +3 -0
  89. package/dist/utils/coverage-text.d.ts.map +1 -0
  90. package/dist/utils/coverage-text.js +62 -0
  91. package/dist/utils/coverage-text.js.map +1 -0
  92. package/dist/utils/coverage.d.ts +57 -0
  93. package/dist/utils/coverage.d.ts.map +1 -0
  94. package/dist/utils/coverage.js +142 -0
  95. package/dist/utils/coverage.js.map +1 -0
  96. package/dist/utils/errors.d.ts +1 -1
  97. package/dist/utils/errors.d.ts.map +1 -1
  98. package/dist/utils/errors.js +9 -1
  99. package/dist/utils/errors.js.map +1 -1
  100. package/dist/utils/format.d.ts +17 -1
  101. package/dist/utils/format.d.ts.map +1 -1
  102. package/dist/utils/format.js +1 -1
  103. package/dist/utils/format.js.map +1 -1
  104. package/dist/utils/harvest-catalog.d.ts +44 -0
  105. package/dist/utils/harvest-catalog.d.ts.map +1 -0
  106. package/dist/utils/harvest-catalog.js +164 -0
  107. package/dist/utils/harvest-catalog.js.map +1 -0
  108. package/dist/utils/harvest-lock.d.ts +3 -0
  109. package/dist/utils/harvest-lock.d.ts.map +1 -0
  110. package/dist/utils/harvest-lock.js +26 -0
  111. package/dist/utils/harvest-lock.js.map +1 -0
  112. package/dist/utils/harvest-receipts.d.ts +14 -0
  113. package/dist/utils/harvest-receipts.d.ts.map +1 -0
  114. package/dist/utils/harvest-receipts.js +110 -0
  115. package/dist/utils/harvest-receipts.js.map +1 -0
  116. package/dist/utils/listing-cursor.d.ts +31 -0
  117. package/dist/utils/listing-cursor.d.ts.map +1 -0
  118. package/dist/utils/listing-cursor.js +39 -0
  119. package/dist/utils/listing-cursor.js.map +1 -0
  120. package/dist/utils/pot-preflight.d.ts +53 -0
  121. package/dist/utils/pot-preflight.d.ts.map +1 -0
  122. package/dist/utils/pot-preflight.js +146 -0
  123. package/dist/utils/pot-preflight.js.map +1 -0
  124. package/dist/utils/sleep.d.ts +9 -0
  125. package/dist/utils/sleep.d.ts.map +1 -0
  126. package/dist/utils/sleep.js +25 -0
  127. package/dist/utils/sleep.js.map +1 -0
  128. package/dist/utils/store-health.d.ts +37 -0
  129. package/dist/utils/store-health.d.ts.map +1 -0
  130. package/dist/utils/store-health.js +92 -0
  131. package/dist/utils/store-health.js.map +1 -0
  132. package/dist/utils/store-migrations.d.ts +33 -0
  133. package/dist/utils/store-migrations.d.ts.map +1 -0
  134. package/dist/utils/store-migrations.js +41 -0
  135. package/dist/utils/store-migrations.js.map +1 -0
  136. package/dist/utils/store-paths.d.ts +33 -0
  137. package/dist/utils/store-paths.d.ts.map +1 -0
  138. package/dist/utils/store-paths.js +48 -0
  139. package/dist/utils/store-paths.js.map +1 -0
  140. package/dist/utils/store-rows.d.ts +22 -0
  141. package/dist/utils/store-rows.d.ts.map +1 -0
  142. package/dist/utils/store-rows.js +62 -0
  143. package/dist/utils/store-rows.js.map +1 -0
  144. package/dist/utils/store-schema.d.ts +16 -0
  145. package/dist/utils/store-schema.d.ts.map +1 -0
  146. package/dist/utils/store-schema.js +168 -0
  147. package/dist/utils/store-schema.js.map +1 -0
  148. package/dist/utils/store.d.ts +34 -0
  149. package/dist/utils/store.d.ts.map +1 -0
  150. package/dist/utils/store.js +157 -0
  151. package/dist/utils/store.js.map +1 -0
  152. package/dist/utils/video-stats-cache.d.ts +16 -0
  153. package/dist/utils/video-stats-cache.d.ts.map +1 -0
  154. package/dist/utils/video-stats-cache.js +81 -0
  155. package/dist/utils/video-stats-cache.js.map +1 -0
  156. package/dist/utils/video-stats.d.ts +186 -0
  157. package/dist/utils/video-stats.d.ts.map +1 -0
  158. package/dist/utils/video-stats.js +168 -0
  159. package/dist/utils/video-stats.js.map +1 -0
  160. package/dist/utils/video-store.d.ts +69 -0
  161. package/dist/utils/video-store.d.ts.map +1 -0
  162. package/dist/utils/video-store.js +77 -0
  163. package/dist/utils/video-store.js.map +1 -0
  164. package/dist/utils/youtube-channel.d.ts +9 -2
  165. package/dist/utils/youtube-channel.d.ts.map +1 -1
  166. package/dist/utils/youtube-channel.js +33 -3
  167. package/dist/utils/youtube-channel.js.map +1 -1
  168. package/dist/utils/youtube-schemas.d.ts +98 -0
  169. package/dist/utils/youtube-schemas.d.ts.map +1 -1
  170. package/dist/utils/youtube-schemas.js +30 -0
  171. package/dist/utils/youtube-schemas.js.map +1 -1
  172. package/dist/utils/youtube-video.d.ts +22 -1
  173. package/dist/utils/youtube-video.d.ts.map +1 -1
  174. package/dist/utils/youtube-video.js +40 -28
  175. package/dist/utils/youtube-video.js.map +1 -1
  176. package/dist/utils/ytdlp-limiter.d.ts +3 -0
  177. package/dist/utils/ytdlp-limiter.d.ts.map +1 -1
  178. package/dist/utils/ytdlp-limiter.js +19 -3
  179. package/dist/utils/ytdlp-limiter.js.map +1 -1
  180. package/dist/utils/ytdlp-pacer.d.ts +64 -0
  181. package/dist/utils/ytdlp-pacer.d.ts.map +1 -0
  182. package/dist/utils/ytdlp-pacer.js +165 -0
  183. package/dist/utils/ytdlp-pacer.js.map +1 -0
  184. package/dist/utils/ytdlp-stream.d.ts +32 -0
  185. package/dist/utils/ytdlp-stream.d.ts.map +1 -0
  186. package/dist/utils/ytdlp-stream.js +61 -0
  187. package/dist/utils/ytdlp-stream.js.map +1 -0
  188. package/dist/utils/ytdlp.d.ts +10 -0
  189. package/dist/utils/ytdlp.d.ts.map +1 -1
  190. package/dist/utils/ytdlp.js +36 -25
  191. package/dist/utils/ytdlp.js.map +1 -1
  192. package/package.json +2 -2
@@ -39,17 +39,76 @@ export declare const checkHealthOutputSchema: {
39
39
  active: z.ZodNumber;
40
40
  queued: z.ZodNumber;
41
41
  limit: z.ZodNumber;
42
+ ceiling: z.ZodNumber;
43
+ cooldownMs: z.ZodNumber;
44
+ circuitOpen: z.ZodBoolean;
42
45
  }, "strip", z.ZodTypeAny, {
43
46
  limit: number;
44
47
  active: number;
45
48
  queued: number;
49
+ ceiling: number;
50
+ cooldownMs: number;
51
+ circuitOpen: boolean;
46
52
  }, {
47
53
  limit: number;
48
54
  active: number;
49
55
  queued: number;
56
+ ceiling: number;
57
+ cooldownMs: number;
58
+ circuitOpen: boolean;
50
59
  }>;
51
60
  cookies: z.ZodEnum<["file", "browser", "none"]>;
52
61
  proxy: z.ZodBoolean;
62
+ session: z.ZodObject<{
63
+ potProviders: z.ZodArray<z.ZodString, "many">;
64
+ jsRuntimes: z.ZodArray<z.ZodString, "many">;
65
+ impersonateTargets: z.ZodArray<z.ZodString, "many">;
66
+ probeFailed: z.ZodOptional<z.ZodString>;
67
+ }, "strip", z.ZodTypeAny, {
68
+ potProviders: string[];
69
+ jsRuntimes: string[];
70
+ impersonateTargets: string[];
71
+ probeFailed?: string | undefined;
72
+ }, {
73
+ potProviders: string[];
74
+ jsRuntimes: string[];
75
+ impersonateTargets: string[];
76
+ probeFailed?: string | undefined;
77
+ }>;
78
+ store: z.ZodObject<{
79
+ enabled: z.ZodBoolean;
80
+ exists: z.ZodBoolean;
81
+ storeVersion: z.ZodOptional<z.ZodNumber>;
82
+ sizeBytes: z.ZodNumber;
83
+ walBytes: z.ZodNumber;
84
+ integrity: z.ZodEnum<["ok", "failed", "unchecked"]>;
85
+ channels: z.ZodNumber;
86
+ videos: z.ZodNumber;
87
+ comments: z.ZodNumber;
88
+ error: z.ZodOptional<z.ZodString>;
89
+ }, "strip", z.ZodTypeAny, {
90
+ videos: number;
91
+ comments: number;
92
+ channels: number;
93
+ sizeBytes: number;
94
+ walBytes: number;
95
+ enabled: boolean;
96
+ exists: boolean;
97
+ integrity: "failed" | "ok" | "unchecked";
98
+ error?: string | undefined;
99
+ storeVersion?: number | undefined;
100
+ }, {
101
+ videos: number;
102
+ comments: number;
103
+ channels: number;
104
+ sizeBytes: number;
105
+ walBytes: number;
106
+ enabled: boolean;
107
+ exists: boolean;
108
+ integrity: "failed" | "ok" | "unchecked";
109
+ error?: string | undefined;
110
+ storeVersion?: number | undefined;
111
+ }>;
53
112
  };
54
113
  /**
55
114
  * Diagnostics for the two external binaries everything here depends on.
@@ -1 +1 @@
1
- {"version":3,"file":"check-health.d.ts","sourceRoot":"","sources":["../../src/tools/check-health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAKzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,iBAAiB,IAAK,CAAC;AAEpC,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAanC,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,cAAc,CAAC,CAoBlE"}
1
+ {"version":3,"file":"check-health.d.ts","sourceRoot":"","sources":["../../src/tools/check-health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAQzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,iBAAiB,IAAK,CAAC;AAEpC,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgDnC,CAAC;AAEF;;;;;GAKG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,cAAc,CAAC,CAqElE"}
@@ -1,4 +1,7 @@
1
1
  import { formatPreflightReport, runPreflight } from '../utils/preflight.js';
2
+ import { runSessionPreflight } from '../utils/pot-preflight.js';
3
+ import { readStoreHealth, storeFailsHealth } from '../utils/store-health.js';
4
+ import { pacerState } from '../utils/ytdlp-pacer.js';
2
5
  import { concurrencyState } from '../utils/ytdlp.js';
3
6
  import { describeYtDlpEnv, readYtDlpEnv } from '../utils/ytdlp-env.js';
4
7
  import { toolResult } from '../utils/format.js';
@@ -12,12 +15,43 @@ export const checkHealthOutputSchema = {
12
15
  concurrency: z.object({
13
16
  active: z.number().int(),
14
17
  queued: z.number().int(),
15
- limit: z.number().int(),
18
+ limit: z.number().int().describe('The level in force now, which throttling can lower'),
19
+ ceiling: z.number().int().describe('The configured maximum the level never exceeds'),
20
+ cooldownMs: z.number().int().describe('How long new spawns are being held back'),
21
+ circuitOpen: z.boolean().describe('True when repeated refusals have paused requests entirely'),
16
22
  }),
17
23
  cookies: z
18
24
  .enum(['file', 'browser', 'none'])
19
25
  .describe('Which kind of yt-dlp cookies are configured; never the value'),
20
26
  proxy: z.boolean().describe('Whether yt-dlp is configured to use a proxy'),
27
+ session: z
28
+ .object({
29
+ potProviders: z.array(z.string()).describe('Usable PO token providers yt-dlp reports'),
30
+ jsRuntimes: z.array(z.string()).describe('Usable JS challenge runtimes yt-dlp reports'),
31
+ impersonateTargets: z.array(z.string()).describe('Usable --impersonate targets'),
32
+ probeFailed: z.string().optional(),
33
+ })
34
+ .describe('What yt-dlp can prove about its own session capabilities. Reported, never used to ' +
35
+ 'fail `ok`: a missing PO token provider does not predict a blocked player plane, ' +
36
+ 'and a health check that cries wolf gets ignored.'),
37
+ store: z
38
+ .object({
39
+ enabled: z.boolean(),
40
+ exists: z.boolean(),
41
+ storeVersion: z.number().int().optional(),
42
+ sizeBytes: z.number().int(),
43
+ walBytes: z
44
+ .number()
45
+ .int()
46
+ .describe('A -wal file that never shrinks means a reader is pinning it'),
47
+ integrity: z.enum(['ok', 'failed', 'unchecked']),
48
+ channels: z.number().int(),
49
+ videos: z.number().int(),
50
+ comments: z.number().int(),
51
+ error: z.string().optional(),
52
+ })
53
+ .describe('The harvested store. A missing store does not fail `ok` — a fresh install has none. ' +
54
+ 'A failed integrity check, or a version this build does not understand, does.'),
21
55
  };
22
56
  /**
23
57
  * Diagnostics for the two external binaries everything here depends on.
@@ -26,22 +60,67 @@ export const checkHealthOutputSchema = {
26
60
  * like "YouTube is broken"; this turns that into one readable answer.
27
61
  */
28
62
  export async function checkHealthHandler() {
29
- const report = await runPreflight({ force: true });
30
- const { active, queued, limit } = concurrencyState();
63
+ const [report, capabilities, store] = await Promise.all([
64
+ runPreflight({ force: true }),
65
+ runSessionPreflight(),
66
+ readStoreHealth(),
67
+ ]);
68
+ const { active, queued, limit, ceiling } = concurrencyState();
69
+ const pacer = pacerState();
31
70
  const session = readYtDlpEnv();
71
+ const available = (entries) => entries.filter((entry) => entry.available).map((entry) => entry.name);
72
+ const potProviders = available(capabilities.potProviders);
73
+ const jsRuntimes = available(capabilities.jsRuntimes);
32
74
  const lines = [
33
75
  formatPreflightReport(report),
34
76
  '',
35
- `yt-dlp concurrency: ${active}/${limit} active, ${queued} queued`,
77
+ `yt-dlp concurrency: ${String(active)}/${String(limit)} active, ${String(queued)} queued` +
78
+ (pacer.circuitOpen
79
+ ? ' — requests paused after repeated refusals'
80
+ : pacer.cooldownMs > 0
81
+ ? ` — cooling down for ${String(Math.ceil(pacer.cooldownMs / 1000))}s`
82
+ : ''),
36
83
  describeYtDlpEnv(session),
84
+ `PO token providers: ${potProviders.length > 0 ? potProviders.join(', ') : 'none'}`,
85
+ `Impersonate targets: ${capabilities.impersonateTargets.length > 0
86
+ ? `${String(capabilities.impersonateTargets.length)} available`
87
+ : 'none (install curl_cffi into yt-dlp to enable --impersonate)'}`,
88
+ store.exists
89
+ ? `Store: ${String(store.videos)} videos, ${String(store.comments)} comments, integrity ${store.integrity}`
90
+ : 'Store: empty (nothing harvested yet)',
37
91
  ];
38
92
  return toolResult(lines.join('\n'), {
39
- ok: report.ok,
93
+ ok: report.ok && !storeFailsHealth(store),
40
94
  ytDlp: report.ytDlp,
41
95
  ffmpeg: report.ffmpeg,
42
- concurrency: { active, queued, limit },
96
+ concurrency: {
97
+ active,
98
+ queued,
99
+ limit,
100
+ ceiling,
101
+ cooldownMs: pacer.cooldownMs,
102
+ circuitOpen: pacer.circuitOpen,
103
+ },
43
104
  cookies: session.cookies,
44
105
  proxy: session.proxy,
106
+ session: {
107
+ potProviders,
108
+ jsRuntimes,
109
+ impersonateTargets: capabilities.impersonateTargets,
110
+ ...(capabilities.probeFailed === undefined ? {} : { probeFailed: capabilities.probeFailed }),
111
+ },
112
+ store: {
113
+ enabled: store.enabled,
114
+ exists: store.exists,
115
+ ...(store.storeVersion === undefined ? {} : { storeVersion: store.storeVersion }),
116
+ sizeBytes: store.sizeBytes,
117
+ walBytes: store.walBytes,
118
+ integrity: store.integrity,
119
+ channels: store.channels,
120
+ videos: store.videos,
121
+ comments: store.comments,
122
+ ...(store.error === undefined ? {} : { error: store.error }),
123
+ },
45
124
  });
46
125
  }
47
126
  //# sourceMappingURL=check-health.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"check-health.js","sourceRoot":"","sources":["../../src/tools/check-health.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEnD,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAEpC,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE;IACf,KAAK,EAAE,kBAAkB;IACzB,MAAM,EAAE,kBAAkB;IAC1B,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;QACxB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;QACxB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;KACxB,CAAC;IACF,OAAO,EAAE,CAAC;SACP,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;SACjC,QAAQ,CAAC,8DAA8D,CAAC;IAC3E,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;CAC3E,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,gBAAgB,EAAE,CAAC;IACrD,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;IAE/B,MAAM,KAAK,GAAG;QACZ,qBAAqB,CAAC,MAAM,CAAC;QAC7B,EAAE;QACF,uBAAuB,MAAM,IAAI,KAAK,YAAY,MAAM,SAAS;QACjE,gBAAgB,CAAC,OAAO,CAAC;KAC1B,CAAC;IAEF,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAClC,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;QACtC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"check-health.js","sourceRoot":"","sources":["../../src/tools/check-health.ts"],"names":[],"mappings":"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"}
@@ -62,9 +62,9 @@ export declare const fetchChannelThumbnailsOutputSchema: {
62
62
  file?: string | undefined;
63
63
  width?: number | undefined;
64
64
  height?: number | undefined;
65
+ fetchedAt?: string | undefined;
65
66
  bytes?: number | undefined;
66
67
  format?: "png" | "jpg" | "webp" | undefined;
67
- fetchedAt?: string | undefined;
68
68
  sourceUrl?: string | undefined;
69
69
  variant?: string | undefined;
70
70
  }, {
@@ -74,9 +74,9 @@ export declare const fetchChannelThumbnailsOutputSchema: {
74
74
  file?: string | undefined;
75
75
  width?: number | undefined;
76
76
  height?: number | undefined;
77
+ fetchedAt?: string | undefined;
77
78
  bytes?: number | undefined;
78
79
  format?: "png" | "jpg" | "webp" | undefined;
79
- fetchedAt?: string | undefined;
80
80
  sourceUrl?: string | undefined;
81
81
  variant?: string | undefined;
82
82
  }>>;
@@ -99,9 +99,9 @@ export declare const fetchChannelThumbnailsOutputSchema: {
99
99
  file?: string | undefined;
100
100
  width?: number | undefined;
101
101
  height?: number | undefined;
102
+ fetchedAt?: string | undefined;
102
103
  bytes?: number | undefined;
103
104
  format?: "png" | "jpg" | "webp" | undefined;
104
- fetchedAt?: string | undefined;
105
105
  sourceUrl?: string | undefined;
106
106
  variant?: string | undefined;
107
107
  }, {
@@ -111,9 +111,9 @@ export declare const fetchChannelThumbnailsOutputSchema: {
111
111
  file?: string | undefined;
112
112
  width?: number | undefined;
113
113
  height?: number | undefined;
114
+ fetchedAt?: string | undefined;
114
115
  bytes?: number | undefined;
115
116
  format?: "png" | "jpg" | "webp" | undefined;
116
- fetchedAt?: string | undefined;
117
117
  sourceUrl?: string | undefined;
118
118
  variant?: string | undefined;
119
119
  }>>;
@@ -142,24 +142,24 @@ export declare const fetchChannelThumbnailsOutputSchema: {
142
142
  videoCount: number;
143
143
  failedCount: number;
144
144
  pendingCount: number;
145
- savedCount: number;
146
- totalBytes: number;
147
145
  tabs: {
148
146
  videoCount: number;
149
147
  tab: "videos" | "shorts" | "streams";
150
148
  savedCount: number;
151
149
  }[];
150
+ savedCount: number;
151
+ totalBytes: number;
152
152
  }, {
153
153
  videoCount: number;
154
154
  failedCount: number;
155
155
  pendingCount: number;
156
- savedCount: number;
157
- totalBytes: number;
158
156
  tabs: {
159
157
  videoCount: number;
160
158
  tab: "videos" | "shorts" | "streams";
161
159
  savedCount: number;
162
160
  }[];
161
+ savedCount: number;
162
+ totalBytes: number;
163
163
  }>;
164
164
  };
165
165
  /**
@@ -3,13 +3,15 @@ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
3
3
  export declare const fetchVideosSchema: {
4
4
  url: z.ZodString;
5
5
  limit: z.ZodDefault<z.ZodNumber>;
6
+ cursor: z.ZodOptional<z.ZodString>;
6
7
  };
7
8
  export declare const fetchVideosOutputSchema: {
8
- total: z.ZodNumber;
9
9
  count: z.ZodNumber;
10
- offset: z.ZodNumber;
11
10
  hasMore: z.ZodBoolean;
12
- nextOffset: z.ZodOptional<z.ZodNumber>;
11
+ nextCursor: z.ZodOptional<z.ZodString>;
12
+ total: z.ZodOptional<z.ZodNumber>;
13
+ totalSource: z.ZodOptional<z.ZodEnum<["youtube:playlist_count", "local-store", "source-exhausted"]>>;
14
+ driftDetected: z.ZodBoolean;
13
15
  source: z.ZodString;
14
16
  videos: z.ZodArray<z.ZodObject<{
15
17
  id: z.ZodString;
@@ -43,8 +45,17 @@ export declare const fetchVideosOutputSchema: {
43
45
  thumbnailUrl?: string | undefined;
44
46
  }>, "many">;
45
47
  };
46
- export declare function fetchVideosHandler({ url, limit, }: {
48
+ /**
49
+ * One page of a playlist or channel listing.
50
+ *
51
+ * Previously this reported `total` as the number of videos it happened to
52
+ * return, so a caller asking for 20 of a 5,000-video channel was told it had
53
+ * all 5,000 — `hasMore` was structurally false. Now `total` is only present
54
+ * when YouTube states one, and its absence means unknown rather than none.
55
+ */
56
+ export declare function fetchVideosHandler({ url, limit, cursor, }: {
47
57
  url: string;
48
58
  limit: number;
59
+ cursor?: string;
49
60
  }): Promise<CallToolResult>;
50
61
  //# sourceMappingURL=fetch-videos.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-videos.d.ts","sourceRoot":"","sources":["../../src/tools/fetch-videos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,eAAO,MAAM,iBAAiB;;;CAa7B,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAInC,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,EACvC,GAAG,EACH,KAAK,GACN,EAAE;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,cAAc,CAAC,CA0B1B"}
1
+ {"version":3,"file":"fetch-videos.d.ts","sourceRoot":"","sources":["../../src/tools/fetch-videos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,eAAO,MAAM,iBAAiB;;;;CAmB7B,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAInC,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,GAAG,EACH,KAAK,EACL,MAAM,GACP,EAAE;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAAC,cAAc,CAAC,CA2D1B"}
@@ -1,7 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { listVideos } from '../utils/youtube.js';
3
- import { pageInfo, toolResult } from '../utils/format.js';
4
- import { paginationShape, videoSummarySchema } from '../schemas.js';
3
+ import { toolResult } from '../utils/format.js';
4
+ import { cursorPageShape, videoSummarySchema } from '../schemas.js';
5
+ import { decodeCursor, encodeCursor } from '../utils/listing-cursor.js';
6
+ import { playlistTotal } from '../utils/youtube-channel.js';
5
7
  export const fetchVideosSchema = {
6
8
  url: z
7
9
  .string()
@@ -9,38 +11,77 @@ export const fetchVideosSchema = {
9
11
  .describe('YouTube playlist URL, channel URL, or channel handle (e.g., https://www.youtube.com/@channel)'),
10
12
  limit: z
11
13
  .number()
14
+ .int()
12
15
  .min(1)
13
- .max(100)
16
+ .max(500)
14
17
  .default(20)
15
- .describe('Maximum number of videos to return (1-100, default: 20)'),
18
+ .describe('Videos per page (1-500, default 20)'),
19
+ cursor: z
20
+ .string()
21
+ .max(512)
22
+ .optional()
23
+ .describe('Opaque token from a previous nextCursor. Omit for the first page.'),
16
24
  };
17
25
  export const fetchVideosOutputSchema = {
18
26
  source: z.string(),
19
27
  videos: z.array(videoSummarySchema),
20
- ...paginationShape,
28
+ ...cursorPageShape,
21
29
  };
22
- export async function fetchVideosHandler({ url, limit, }) {
23
- const videos = await listVideos(url, limit);
24
- const lines = [`✓ Found ${videos.length} video${videos.length !== 1 ? 's' : ''}`, ''];
25
- videos.forEach((v, i) => {
26
- lines.push(`${i + 1}. ${v.title}`);
27
- lines.push(` ${v.durationFormatted} · ${v.uploadDate || 'Unknown date'}`);
28
- lines.push(` ${v.url}`);
30
+ /**
31
+ * One page of a playlist or channel listing.
32
+ *
33
+ * Previously this reported `total` as the number of videos it happened to
34
+ * return, so a caller asking for 20 of a 5,000-video channel was told it had
35
+ * all 5,000 — `hasMore` was structurally false. Now `total` is only present
36
+ * when YouTube states one, and its absence means unknown rather than none.
37
+ */
38
+ export async function fetchVideosHandler({ url, limit, cursor, }) {
39
+ const position = cursor === undefined ? { v: 1, start: 1, anchor: '' } : decodeCursor(cursor);
40
+ const [page, total] = await Promise.all([
41
+ listVideos(url, limit, position.start),
42
+ playlistTotal(url),
43
+ ]);
44
+ // A new upload shifts every index by one, so the item we ended on can
45
+ // reappear at the top of the next page. Dropping it is the honest fix; yt-dlp
46
+ // cannot offer a cursor stable against edits.
47
+ const driftDetected = position.anchor !== '' && page.some((video) => video.id === position.anchor);
48
+ const videos = driftDetected ? page.filter((video) => video.id !== position.anchor) : page;
49
+ const nextStart = position.start + page.length;
50
+ const hasMore = total === undefined ? page.length === limit : nextStart <= total && page.length > 0;
51
+ const last = videos.at(-1);
52
+ const lines = [
53
+ `✓ ${String(videos.length)} video${videos.length === 1 ? '' : 's'}${total === undefined ? '' : ` of ${String(total)}`}`,
54
+ ...(total === undefined && hasMore
55
+ ? ['YouTube states no total for this listing, so the number remaining is unknown.']
56
+ : []),
57
+ ...(driftDetected ? ['The listing changed between pages; a duplicate was dropped.'] : []),
58
+ '',
59
+ ];
60
+ videos.forEach((video, index) => {
61
+ lines.push(`${String(position.start + index)}. ${video.title}`);
62
+ lines.push(` ${video.durationFormatted} · ${video.uploadDate || 'Unknown date'}`);
63
+ lines.push(` ${video.url}`);
29
64
  lines.push('');
30
65
  });
31
66
  return toolResult(lines.join('\n'), {
32
67
  source: url,
33
- videos: videos.map((v) => ({
34
- id: v.id,
35
- title: v.title,
36
- durationSeconds: v.duration,
37
- durationFormatted: v.durationFormatted,
38
- url: v.url,
39
- uploadDate: v.uploadDate,
40
- ...(v.thumbnailUrl === undefined ? {} : { thumbnailUrl: v.thumbnailUrl }),
41
- ...(v.viewCount === undefined ? {} : { viewCount: v.viewCount }),
68
+ videos: videos.map((video) => ({
69
+ id: video.id,
70
+ title: video.title,
71
+ durationSeconds: video.duration,
72
+ durationFormatted: video.durationFormatted,
73
+ url: video.url,
74
+ uploadDate: video.uploadDate,
75
+ ...(video.thumbnailUrl === undefined ? {} : { thumbnailUrl: video.thumbnailUrl }),
76
+ ...(video.viewCount === undefined ? {} : { viewCount: video.viewCount }),
42
77
  })),
43
- ...pageInfo(videos.length, videos.length),
78
+ count: videos.length,
79
+ hasMore,
80
+ ...(hasMore && last !== undefined
81
+ ? { nextCursor: encodeCursor({ v: 1, start: nextStart, anchor: last.id }) }
82
+ : {}),
83
+ ...(total === undefined ? {} : { total, totalSource: 'youtube:playlist_count' }),
84
+ driftDetected,
44
85
  });
45
86
  }
46
87
  //# sourceMappingURL=fetch-videos.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-videos.js","sourceRoot":"","sources":["../../src/tools/fetch-videos.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGpE,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,GAAG,EAAE,CAAC;SACH,MAAM,EAAE;SACR,GAAG,CAAC,IAAI,CAAC;SACT,QAAQ,CACP,+FAA+F,CAChG;IACH,KAAK,EAAE,CAAC;SACL,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,OAAO,CAAC,EAAE,CAAC;SACX,QAAQ,CAAC,yDAAyD,CAAC;CACvE,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC;IACnC,GAAG,eAAe;CACnB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EACvC,GAAG,EACH,KAAK,GAIN;IACC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAE5C,MAAM,KAAK,GAAa,CAAC,WAAW,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAEhG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACtB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,iBAAiB,MAAM,CAAC,CAAC,UAAU,IAAI,cAAc,EAAE,CAAC,CAAC;QAC5E,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAClC,MAAM,EAAE,GAAG;QACX,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACzB,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,eAAe,EAAE,CAAC,CAAC,QAAQ;YAC3B,iBAAiB,EAAE,CAAC,CAAC,iBAAiB;YACtC,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,GAAG,CAAC,CAAC,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC;YACzE,GAAG,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC;SACjE,CAAC,CAAC;QACH,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;KAC1C,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"fetch-videos.js","sourceRoot":"","sources":["../../src/tools/fetch-videos.ts"],"names":[],"mappings":"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"}