youtube-knowledge-mcp 2.1.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 (478) hide show
  1. package/README.md +153 -38
  2. package/dist/brain-schemas.d.ts +10 -10
  3. package/dist/brain-schemas.d.ts.map +1 -1
  4. package/dist/brain-schemas.js +0 -4
  5. package/dist/brain-schemas.js.map +1 -1
  6. package/dist/harvest-schemas.d.ts +75 -0
  7. package/dist/harvest-schemas.d.ts.map +1 -0
  8. package/dist/harvest-schemas.js +106 -0
  9. package/dist/harvest-schemas.js.map +1 -0
  10. package/dist/http/app.d.ts +16 -0
  11. package/dist/http/app.d.ts.map +1 -0
  12. package/dist/http/app.js +176 -0
  13. package/dist/http/app.js.map +1 -0
  14. package/dist/http/auth.d.ts +38 -0
  15. package/dist/http/auth.d.ts.map +1 -0
  16. package/dist/http/auth.js +79 -0
  17. package/dist/http/auth.js.map +1 -0
  18. package/dist/http/config.d.ts +41 -0
  19. package/dist/http/config.d.ts.map +1 -0
  20. package/dist/http/config.js +65 -0
  21. package/dist/http/config.js.map +1 -0
  22. package/dist/http/rate-limiter.d.ts +24 -0
  23. package/dist/http/rate-limiter.d.ts.map +1 -0
  24. package/dist/http/rate-limiter.js +55 -0
  25. package/dist/http/rate-limiter.js.map +1 -0
  26. package/dist/http/sessions.d.ts +34 -0
  27. package/dist/http/sessions.d.ts.map +1 -0
  28. package/dist/http/sessions.js +62 -0
  29. package/dist/http/sessions.js.map +1 -0
  30. package/dist/http.d.ts +6 -48
  31. package/dist/http.d.ts.map +1 -1
  32. package/dist/http.js +35 -252
  33. package/dist/http.js.map +1 -1
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +11 -517
  36. package/dist/index.js.map +1 -1
  37. package/dist/prompts-brain.d.ts +4 -0
  38. package/dist/prompts-brain.d.ts.map +1 -0
  39. package/dist/prompts-brain.js +48 -0
  40. package/dist/prompts-brain.js.map +1 -0
  41. package/dist/prompts-research.d.ts +4 -0
  42. package/dist/prompts-research.d.ts.map +1 -0
  43. package/dist/prompts-research.js +74 -0
  44. package/dist/prompts-research.js.map +1 -0
  45. package/dist/prompts-shared.d.ts +13 -0
  46. package/dist/prompts-shared.d.ts.map +1 -0
  47. package/dist/prompts-shared.js +7 -0
  48. package/dist/prompts-shared.js.map +1 -0
  49. package/dist/prompts.d.ts.map +1 -1
  50. package/dist/prompts.js +5 -100
  51. package/dist/prompts.js.map +1 -1
  52. package/dist/registry/brain-tools.d.ts +4 -0
  53. package/dist/registry/brain-tools.d.ts.map +1 -0
  54. package/dist/registry/brain-tools.js +104 -0
  55. package/dist/registry/brain-tools.js.map +1 -0
  56. package/dist/registry/channel-tools.d.ts +4 -0
  57. package/dist/registry/channel-tools.d.ts.map +1 -0
  58. package/dist/registry/channel-tools.js +53 -0
  59. package/dist/registry/channel-tools.js.map +1 -0
  60. package/dist/registry/harvest-tools.d.ts +10 -0
  61. package/dist/registry/harvest-tools.d.ts.map +1 -0
  62. package/dist/registry/harvest-tools.js +109 -0
  63. package/dist/registry/harvest-tools.js.map +1 -0
  64. package/dist/registry/health-tools.d.ts +4 -0
  65. package/dist/registry/health-tools.d.ts.map +1 -0
  66. package/dist/registry/health-tools.js +39 -0
  67. package/dist/registry/health-tools.js.map +1 -0
  68. package/dist/registry/index.d.ts +8 -0
  69. package/dist/registry/index.d.ts.map +1 -0
  70. package/dist/registry/index.js +29 -0
  71. package/dist/registry/index.js.map +1 -0
  72. package/dist/registry/library-tools.d.ts +4 -0
  73. package/dist/registry/library-tools.d.ts.map +1 -0
  74. package/dist/registry/library-tools.js +116 -0
  75. package/dist/registry/library-tools.js.map +1 -0
  76. package/dist/registry/media-tools.d.ts +4 -0
  77. package/dist/registry/media-tools.d.ts.map +1 -0
  78. package/dist/registry/media-tools.js +100 -0
  79. package/dist/registry/media-tools.js.map +1 -0
  80. package/dist/registry/thumbnail-tools.d.ts +7 -0
  81. package/dist/registry/thumbnail-tools.d.ts.map +1 -0
  82. package/dist/registry/thumbnail-tools.js +72 -0
  83. package/dist/registry/thumbnail-tools.js.map +1 -0
  84. package/dist/registry/transcript-tools.d.ts +4 -0
  85. package/dist/registry/transcript-tools.d.ts.map +1 -0
  86. package/dist/registry/transcript-tools.js +68 -0
  87. package/dist/registry/transcript-tools.js.map +1 -0
  88. package/dist/registry/types.d.ts +41 -0
  89. package/dist/registry/types.d.ts.map +1 -0
  90. package/dist/registry/types.js +17 -0
  91. package/dist/registry/types.js.map +1 -0
  92. package/dist/registry/video-tools.d.ts +4 -0
  93. package/dist/registry/video-tools.d.ts.map +1 -0
  94. package/dist/registry/video-tools.js +101 -0
  95. package/dist/registry/video-tools.js.map +1 -0
  96. package/dist/resources.d.ts.map +1 -1
  97. package/dist/resources.js +13 -10
  98. package/dist/resources.js.map +1 -1
  99. package/dist/schemas.d.ts +250 -2
  100. package/dist/schemas.d.ts.map +1 -1
  101. package/dist/schemas.js +61 -0
  102. package/dist/schemas.js.map +1 -1
  103. package/dist/thumbnail-resource.d.ts +8 -0
  104. package/dist/thumbnail-resource.d.ts.map +1 -0
  105. package/dist/thumbnail-resource.js +38 -0
  106. package/dist/thumbnail-resource.js.map +1 -0
  107. package/dist/thumbnail-schemas.d.ts +512 -0
  108. package/dist/thumbnail-schemas.d.ts.map +1 -0
  109. package/dist/thumbnail-schemas.js +95 -0
  110. package/dist/thumbnail-schemas.js.map +1 -0
  111. package/dist/tools/ask-brain.js +1 -1
  112. package/dist/tools/ask-brain.js.map +1 -1
  113. package/dist/tools/batch.js +1 -1
  114. package/dist/tools/batch.js.map +1 -1
  115. package/dist/tools/brain-info.js +1 -1
  116. package/dist/tools/brain-info.js.map +1 -1
  117. package/dist/tools/build-brain.js +1 -1
  118. package/dist/tools/build-brain.js.map +1 -1
  119. package/dist/tools/check-health.d.ts +61 -0
  120. package/dist/tools/check-health.d.ts.map +1 -1
  121. package/dist/tools/check-health.js +94 -6
  122. package/dist/tools/check-health.js.map +1 -1
  123. package/dist/tools/clips.d.ts +9 -41
  124. package/dist/tools/clips.d.ts.map +1 -1
  125. package/dist/tools/clips.js +52 -128
  126. package/dist/tools/clips.js.map +1 -1
  127. package/dist/tools/fetch-channel-thumbnails.d.ts +179 -0
  128. package/dist/tools/fetch-channel-thumbnails.d.ts.map +1 -0
  129. package/dist/tools/fetch-channel-thumbnails.js +123 -0
  130. package/dist/tools/fetch-channel-thumbnails.js.map +1 -0
  131. package/dist/tools/fetch-videos.d.ts +18 -4
  132. package/dist/tools/fetch-videos.d.ts.map +1 -1
  133. package/dist/tools/fetch-videos.js +64 -20
  134. package/dist/tools/fetch-videos.js.map +1 -1
  135. package/dist/tools/frames-subtitles.d.ts +44 -0
  136. package/dist/tools/frames-subtitles.d.ts.map +1 -0
  137. package/dist/tools/frames-subtitles.js +104 -0
  138. package/dist/tools/frames-subtitles.js.map +1 -0
  139. package/dist/tools/get-channel-info.d.ts +2 -0
  140. package/dist/tools/get-channel-info.d.ts.map +1 -1
  141. package/dist/tools/get-channel-info.js +8 -1
  142. package/dist/tools/get-channel-info.js.map +1 -1
  143. package/dist/tools/get-comments.d.ts +238 -6
  144. package/dist/tools/get-comments.d.ts.map +1 -1
  145. package/dist/tools/get-comments.js +85 -21
  146. package/dist/tools/get-comments.js.map +1 -1
  147. package/dist/tools/get-coverage.d.ts +122 -0
  148. package/dist/tools/get-coverage.d.ts.map +1 -0
  149. package/dist/tools/get-coverage.js +105 -0
  150. package/dist/tools/get-coverage.js.map +1 -0
  151. package/dist/tools/get-playlist-info.d.ts.map +1 -1
  152. package/dist/tools/get-playlist-info.js +1 -0
  153. package/dist/tools/get-playlist-info.js.map +1 -1
  154. package/dist/tools/get-thumbnail.d.ts +38 -0
  155. package/dist/tools/get-thumbnail.d.ts.map +1 -0
  156. package/dist/tools/get-thumbnail.js +152 -0
  157. package/dist/tools/get-thumbnail.js.map +1 -0
  158. package/dist/tools/get-transcript.d.ts.map +1 -1
  159. package/dist/tools/get-transcript.js +2 -14
  160. package/dist/tools/get-transcript.js.map +1 -1
  161. package/dist/tools/harvest-channel.d.ts +92 -0
  162. package/dist/tools/harvest-channel.d.ts.map +1 -0
  163. package/dist/tools/harvest-channel.js +62 -0
  164. package/dist/tools/harvest-channel.js.map +1 -0
  165. package/dist/tools/harvest-comments.d.ts +81 -0
  166. package/dist/tools/harvest-comments.d.ts.map +1 -0
  167. package/dist/tools/harvest-comments.js +115 -0
  168. package/dist/tools/harvest-comments.js.map +1 -0
  169. package/dist/tools/library.d.ts.map +1 -1
  170. package/dist/tools/library.js +14 -4
  171. package/dist/tools/library.js.map +1 -1
  172. package/dist/tools/list-channel-thumbnails.d.ts +235 -0
  173. package/dist/tools/list-channel-thumbnails.d.ts.map +1 -0
  174. package/dist/tools/list-channel-thumbnails.js +79 -0
  175. package/dist/tools/list-channel-thumbnails.js.map +1 -0
  176. package/dist/tools/list-library.js +1 -1
  177. package/dist/tools/list-library.js.map +1 -1
  178. package/dist/tools/prune-harvest.d.ts +59 -0
  179. package/dist/tools/prune-harvest.d.ts.map +1 -0
  180. package/dist/tools/prune-harvest.js +108 -0
  181. package/dist/tools/prune-harvest.js.map +1 -0
  182. package/dist/tools/query-comments.d.ts +125 -0
  183. package/dist/tools/query-comments.d.ts.map +1 -0
  184. package/dist/tools/query-comments.js +106 -0
  185. package/dist/tools/query-comments.js.map +1 -0
  186. package/dist/tools/query-videos.d.ts +118 -0
  187. package/dist/tools/query-videos.d.ts.map +1 -0
  188. package/dist/tools/query-videos.js +97 -0
  189. package/dist/tools/query-videos.js.map +1 -0
  190. package/dist/tools/repair-store.d.ts +34 -0
  191. package/dist/tools/repair-store.d.ts.map +1 -0
  192. package/dist/tools/repair-store.js +58 -0
  193. package/dist/tools/repair-store.js.map +1 -0
  194. package/dist/tools/save-to-library.d.ts.map +1 -1
  195. package/dist/tools/save-to-library.js +5 -1
  196. package/dist/tools/save-to-library.js.map +1 -1
  197. package/dist/tools/search-channels.d.ts +6 -0
  198. package/dist/tools/search-channels.d.ts.map +1 -1
  199. package/dist/tools/search-channels.js +5 -1
  200. package/dist/tools/search-channels.js.map +1 -1
  201. package/dist/tools/search-transcript.d.ts.map +1 -1
  202. package/dist/tools/search-transcript.js +6 -13
  203. package/dist/tools/search-transcript.js.map +1 -1
  204. package/dist/tools/search-videos.d.ts +3 -0
  205. package/dist/tools/search-videos.d.ts.map +1 -1
  206. package/dist/tools/search-videos.js +1 -1
  207. package/dist/tools/search-videos.js.map +1 -1
  208. package/dist/utils/batches.d.ts +15 -0
  209. package/dist/utils/batches.d.ts.map +1 -0
  210. package/dist/utils/batches.js +31 -0
  211. package/dist/utils/batches.js.map +1 -0
  212. package/dist/utils/brain-build.d.ts.map +1 -1
  213. package/dist/utils/brain-build.js +1 -12
  214. package/dist/utils/brain-build.js.map +1 -1
  215. package/dist/utils/brain-index.d.ts.map +1 -1
  216. package/dist/utils/brain-index.js +3 -2
  217. package/dist/utils/brain-index.js.map +1 -1
  218. package/dist/utils/brain-lock.d.ts +2 -18
  219. package/dist/utils/brain-lock.d.ts.map +1 -1
  220. package/dist/utils/brain-lock.js +4 -80
  221. package/dist/utils/brain-lock.js.map +1 -1
  222. package/dist/utils/brain-lookup.d.ts +8 -0
  223. package/dist/utils/brain-lookup.d.ts.map +1 -1
  224. package/dist/utils/brain-lookup.js +5 -31
  225. package/dist/utils/brain-lookup.js.map +1 -1
  226. package/dist/utils/brain-storage.d.ts.map +1 -1
  227. package/dist/utils/brain-storage.js +5 -5
  228. package/dist/utils/brain-storage.js.map +1 -1
  229. package/dist/utils/caption-probe.d.ts +7 -0
  230. package/dist/utils/caption-probe.d.ts.map +1 -0
  231. package/dist/utils/caption-probe.js +36 -0
  232. package/dist/utils/caption-probe.js.map +1 -0
  233. package/dist/utils/channel-images.d.ts +16 -0
  234. package/dist/utils/channel-images.d.ts.map +1 -0
  235. package/dist/utils/channel-images.js +35 -0
  236. package/dist/utils/channel-images.js.map +1 -0
  237. package/dist/utils/channel-lookup.d.ts +5 -0
  238. package/dist/utils/channel-lookup.d.ts.map +1 -0
  239. package/dist/utils/channel-lookup.js +37 -0
  240. package/dist/utils/channel-lookup.js.map +1 -0
  241. package/dist/utils/chapters.d.ts +11 -0
  242. package/dist/utils/chapters.d.ts.map +1 -0
  243. package/dist/utils/chapters.js +24 -0
  244. package/dist/utils/chapters.js.map +1 -0
  245. package/dist/utils/clips.d.ts.map +1 -1
  246. package/dist/utils/clips.js +18 -26
  247. package/dist/utils/clips.js.map +1 -1
  248. package/dist/utils/comment-store.d.ts +71 -0
  249. package/dist/utils/comment-store.d.ts.map +1 -0
  250. package/dist/utils/comment-store.js +129 -0
  251. package/dist/utils/comment-store.js.map +1 -0
  252. package/dist/utils/comment-threads.d.ts +51 -0
  253. package/dist/utils/comment-threads.d.ts.map +1 -0
  254. package/dist/utils/comment-threads.js +76 -0
  255. package/dist/utils/comment-threads.js.map +1 -0
  256. package/dist/utils/coverage-text.d.ts +3 -0
  257. package/dist/utils/coverage-text.d.ts.map +1 -0
  258. package/dist/utils/coverage-text.js +62 -0
  259. package/dist/utils/coverage-text.js.map +1 -0
  260. package/dist/utils/coverage.d.ts +57 -0
  261. package/dist/utils/coverage.d.ts.map +1 -0
  262. package/dist/utils/coverage.js +142 -0
  263. package/dist/utils/coverage.js.map +1 -0
  264. package/dist/utils/env.d.ts +26 -0
  265. package/dist/utils/env.d.ts.map +1 -0
  266. package/dist/utils/env.js +72 -0
  267. package/dist/utils/env.js.map +1 -0
  268. package/dist/utils/errors.d.ts +1 -1
  269. package/dist/utils/errors.d.ts.map +1 -1
  270. package/dist/utils/errors.js +28 -2
  271. package/dist/utils/errors.js.map +1 -1
  272. package/dist/utils/file-lock.d.ts +34 -0
  273. package/dist/utils/file-lock.d.ts.map +1 -0
  274. package/dist/utils/file-lock.js +91 -0
  275. package/dist/utils/file-lock.js.map +1 -0
  276. package/dist/utils/flat-listing.d.ts +89 -0
  277. package/dist/utils/flat-listing.d.ts.map +1 -0
  278. package/dist/utils/flat-listing.js +68 -0
  279. package/dist/utils/flat-listing.js.map +1 -0
  280. package/dist/utils/format.d.ts +18 -4
  281. package/dist/utils/format.d.ts.map +1 -1
  282. package/dist/utils/format.js +2 -6
  283. package/dist/utils/format.js.map +1 -1
  284. package/dist/utils/guard.d.ts +21 -0
  285. package/dist/utils/guard.d.ts.map +1 -0
  286. package/dist/utils/guard.js +105 -0
  287. package/dist/utils/guard.js.map +1 -0
  288. package/dist/utils/harvest-catalog.d.ts +44 -0
  289. package/dist/utils/harvest-catalog.d.ts.map +1 -0
  290. package/dist/utils/harvest-catalog.js +164 -0
  291. package/dist/utils/harvest-catalog.js.map +1 -0
  292. package/dist/utils/harvest-lock.d.ts +3 -0
  293. package/dist/utils/harvest-lock.d.ts.map +1 -0
  294. package/dist/utils/harvest-lock.js +26 -0
  295. package/dist/utils/harvest-lock.js.map +1 -0
  296. package/dist/utils/harvest-receipts.d.ts +14 -0
  297. package/dist/utils/harvest-receipts.d.ts.map +1 -0
  298. package/dist/utils/harvest-receipts.js +110 -0
  299. package/dist/utils/harvest-receipts.js.map +1 -0
  300. package/dist/utils/image-dimensions.d.ts +19 -0
  301. package/dist/utils/image-dimensions.d.ts.map +1 -0
  302. package/dist/utils/image-dimensions.js +93 -0
  303. package/dist/utils/image-dimensions.js.map +1 -0
  304. package/dist/utils/image-fetch.d.ts +31 -0
  305. package/dist/utils/image-fetch.d.ts.map +1 -0
  306. package/dist/utils/image-fetch.js +141 -0
  307. package/dist/utils/image-fetch.js.map +1 -0
  308. package/dist/utils/json-file.d.ts +14 -5
  309. package/dist/utils/json-file.d.ts.map +1 -1
  310. package/dist/utils/json-file.js +24 -9
  311. package/dist/utils/json-file.js.map +1 -1
  312. package/dist/utils/listing-cursor.d.ts +31 -0
  313. package/dist/utils/listing-cursor.d.ts.map +1 -0
  314. package/dist/utils/listing-cursor.js +39 -0
  315. package/dist/utils/listing-cursor.js.map +1 -0
  316. package/dist/utils/paths.d.ts +10 -0
  317. package/dist/utils/paths.d.ts.map +1 -1
  318. package/dist/utils/paths.js +14 -0
  319. package/dist/utils/paths.js.map +1 -1
  320. package/dist/utils/pattern.d.ts +30 -0
  321. package/dist/utils/pattern.d.ts.map +1 -0
  322. package/dist/utils/pattern.js +130 -0
  323. package/dist/utils/pattern.js.map +1 -0
  324. package/dist/utils/pot-preflight.d.ts +53 -0
  325. package/dist/utils/pot-preflight.d.ts.map +1 -0
  326. package/dist/utils/pot-preflight.js +146 -0
  327. package/dist/utils/pot-preflight.js.map +1 -0
  328. package/dist/utils/search-index.d.ts.map +1 -1
  329. package/dist/utils/search-index.js +9 -4
  330. package/dist/utils/search-index.js.map +1 -1
  331. package/dist/utils/sleep.d.ts +9 -0
  332. package/dist/utils/sleep.d.ts.map +1 -0
  333. package/dist/utils/sleep.js +25 -0
  334. package/dist/utils/sleep.js.map +1 -0
  335. package/dist/utils/storage.d.ts.map +1 -1
  336. package/dist/utils/storage.js +14 -8
  337. package/dist/utils/storage.js.map +1 -1
  338. package/dist/utils/store-health.d.ts +37 -0
  339. package/dist/utils/store-health.d.ts.map +1 -0
  340. package/dist/utils/store-health.js +92 -0
  341. package/dist/utils/store-health.js.map +1 -0
  342. package/dist/utils/store-migrations.d.ts +33 -0
  343. package/dist/utils/store-migrations.d.ts.map +1 -0
  344. package/dist/utils/store-migrations.js +41 -0
  345. package/dist/utils/store-migrations.js.map +1 -0
  346. package/dist/utils/store-paths.d.ts +33 -0
  347. package/dist/utils/store-paths.d.ts.map +1 -0
  348. package/dist/utils/store-paths.js +48 -0
  349. package/dist/utils/store-paths.js.map +1 -0
  350. package/dist/utils/store-rows.d.ts +22 -0
  351. package/dist/utils/store-rows.d.ts.map +1 -0
  352. package/dist/utils/store-rows.js +62 -0
  353. package/dist/utils/store-rows.js.map +1 -0
  354. package/dist/utils/store-schema.d.ts +16 -0
  355. package/dist/utils/store-schema.d.ts.map +1 -0
  356. package/dist/utils/store-schema.js +168 -0
  357. package/dist/utils/store-schema.js.map +1 -0
  358. package/dist/utils/store.d.ts +34 -0
  359. package/dist/utils/store.d.ts.map +1 -0
  360. package/dist/utils/store.js +157 -0
  361. package/dist/utils/store.js.map +1 -0
  362. package/dist/utils/subtitles.d.ts +7 -0
  363. package/dist/utils/subtitles.d.ts.map +1 -0
  364. package/dist/utils/subtitles.js +30 -0
  365. package/dist/utils/subtitles.js.map +1 -0
  366. package/dist/utils/thumbnail-entry.d.ts +19 -0
  367. package/dist/utils/thumbnail-entry.d.ts.map +1 -0
  368. package/dist/utils/thumbnail-entry.js +119 -0
  369. package/dist/utils/thumbnail-entry.js.map +1 -0
  370. package/dist/utils/thumbnail-fetch.d.ts +37 -0
  371. package/dist/utils/thumbnail-fetch.d.ts.map +1 -0
  372. package/dist/utils/thumbnail-fetch.js +89 -0
  373. package/dist/utils/thumbnail-fetch.js.map +1 -0
  374. package/dist/utils/thumbnail-ladder.d.ts +44 -0
  375. package/dist/utils/thumbnail-ladder.d.ts.map +1 -0
  376. package/dist/utils/thumbnail-ladder.js +68 -0
  377. package/dist/utils/thumbnail-ladder.js.map +1 -0
  378. package/dist/utils/thumbnail-listing.d.ts +16 -0
  379. package/dist/utils/thumbnail-listing.d.ts.map +1 -0
  380. package/dist/utils/thumbnail-listing.js +26 -0
  381. package/dist/utils/thumbnail-listing.js.map +1 -0
  382. package/dist/utils/thumbnail-paths.d.ts +20 -0
  383. package/dist/utils/thumbnail-paths.d.ts.map +1 -0
  384. package/dist/utils/thumbnail-paths.js +35 -0
  385. package/dist/utils/thumbnail-paths.js.map +1 -0
  386. package/dist/utils/thumbnail-store.d.ts +19 -0
  387. package/dist/utils/thumbnail-store.d.ts.map +1 -0
  388. package/dist/utils/thumbnail-store.js +125 -0
  389. package/dist/utils/thumbnail-store.js.map +1 -0
  390. package/dist/utils/transcript-cache.d.ts +20 -0
  391. package/dist/utils/transcript-cache.d.ts.map +1 -0
  392. package/dist/utils/transcript-cache.js +127 -0
  393. package/dist/utils/transcript-cache.js.map +1 -0
  394. package/dist/utils/transcript-search.d.ts +20 -0
  395. package/dist/utils/transcript-search.d.ts.map +1 -0
  396. package/dist/utils/transcript-search.js +35 -0
  397. package/dist/utils/transcript-search.js.map +1 -0
  398. package/dist/utils/transcript.d.ts +10 -31
  399. package/dist/utils/transcript.d.ts.map +1 -1
  400. package/dist/utils/transcript.js +2 -64
  401. package/dist/utils/transcript.js.map +1 -1
  402. package/dist/utils/validate-youtube.d.ts +35 -0
  403. package/dist/utils/validate-youtube.d.ts.map +1 -0
  404. package/dist/utils/validate-youtube.js +87 -0
  405. package/dist/utils/validate-youtube.js.map +1 -0
  406. package/dist/utils/validate.d.ts +11 -4
  407. package/dist/utils/validate.d.ts.map +1 -1
  408. package/dist/utils/validate.js +43 -36
  409. package/dist/utils/validate.js.map +1 -1
  410. package/dist/utils/version.d.ts +2 -0
  411. package/dist/utils/version.d.ts.map +1 -0
  412. package/dist/utils/version.js +19 -0
  413. package/dist/utils/version.js.map +1 -0
  414. package/dist/utils/video-stats-cache.d.ts +16 -0
  415. package/dist/utils/video-stats-cache.d.ts.map +1 -0
  416. package/dist/utils/video-stats-cache.js +81 -0
  417. package/dist/utils/video-stats-cache.js.map +1 -0
  418. package/dist/utils/video-stats.d.ts +186 -0
  419. package/dist/utils/video-stats.d.ts.map +1 -0
  420. package/dist/utils/video-stats.js +168 -0
  421. package/dist/utils/video-stats.js.map +1 -0
  422. package/dist/utils/video-store.d.ts +69 -0
  423. package/dist/utils/video-store.d.ts.map +1 -0
  424. package/dist/utils/video-store.js +77 -0
  425. package/dist/utils/video-store.js.map +1 -0
  426. package/dist/utils/youtube-channel.d.ts +51 -0
  427. package/dist/utils/youtube-channel.d.ts.map +1 -0
  428. package/dist/utils/youtube-channel.js +91 -0
  429. package/dist/utils/youtube-channel.js.map +1 -0
  430. package/dist/utils/youtube-download.d.ts +27 -0
  431. package/dist/utils/youtube-download.d.ts.map +1 -0
  432. package/dist/utils/youtube-download.js +118 -0
  433. package/dist/utils/youtube-download.js.map +1 -0
  434. package/dist/utils/youtube-schemas.d.ts +492 -0
  435. package/dist/utils/youtube-schemas.d.ts.map +1 -0
  436. package/dist/utils/youtube-schemas.js +148 -0
  437. package/dist/utils/youtube-schemas.js.map +1 -0
  438. package/dist/utils/youtube-search.d.ts +14 -0
  439. package/dist/utils/youtube-search.d.ts.map +1 -0
  440. package/dist/utils/youtube-search.js +39 -0
  441. package/dist/utils/youtube-search.js.map +1 -0
  442. package/dist/utils/youtube-url.d.ts +25 -0
  443. package/dist/utils/youtube-url.d.ts.map +1 -0
  444. package/dist/utils/youtube-url.js +75 -0
  445. package/dist/utils/youtube-url.js.map +1 -0
  446. package/dist/utils/youtube-video.d.ts +68 -0
  447. package/dist/utils/youtube-video.d.ts.map +1 -0
  448. package/dist/utils/youtube-video.js +110 -0
  449. package/dist/utils/youtube-video.js.map +1 -0
  450. package/dist/utils/youtube.d.ts +10 -122
  451. package/dist/utils/youtube.d.ts.map +1 -1
  452. package/dist/utils/youtube.js +11 -486
  453. package/dist/utils/youtube.js.map +1 -1
  454. package/dist/utils/ytdlp-env.d.ts +33 -0
  455. package/dist/utils/ytdlp-env.d.ts.map +1 -0
  456. package/dist/utils/ytdlp-env.js +121 -0
  457. package/dist/utils/ytdlp-env.js.map +1 -0
  458. package/dist/utils/ytdlp-limiter.d.ts +27 -0
  459. package/dist/utils/ytdlp-limiter.d.ts.map +1 -0
  460. package/dist/utils/ytdlp-limiter.js +85 -0
  461. package/dist/utils/ytdlp-limiter.js.map +1 -0
  462. package/dist/utils/ytdlp-pacer.d.ts +64 -0
  463. package/dist/utils/ytdlp-pacer.d.ts.map +1 -0
  464. package/dist/utils/ytdlp-pacer.js +165 -0
  465. package/dist/utils/ytdlp-pacer.js.map +1 -0
  466. package/dist/utils/ytdlp-parse.d.ts +13 -0
  467. package/dist/utils/ytdlp-parse.d.ts.map +1 -0
  468. package/dist/utils/ytdlp-parse.js +48 -0
  469. package/dist/utils/ytdlp-parse.js.map +1 -0
  470. package/dist/utils/ytdlp-stream.d.ts +32 -0
  471. package/dist/utils/ytdlp-stream.d.ts.map +1 -0
  472. package/dist/utils/ytdlp-stream.js +61 -0
  473. package/dist/utils/ytdlp-stream.js.map +1 -0
  474. package/dist/utils/ytdlp.d.ts +23 -18
  475. package/dist/utils/ytdlp.d.ts.map +1 -1
  476. package/dist/utils/ytdlp.js +56 -134
  477. package/dist/utils/ytdlp.js.map +1 -1
  478. package/package.json +3 -2
@@ -0,0 +1,89 @@
1
+ import { z } from 'zod';
2
+ import type { VideoListItem } from './youtube-channel.js';
3
+ /**
4
+ * Reading a flat channel or playlist listing.
5
+ *
6
+ * `--flat-playlist` lists a channel in one request instead of one per video,
7
+ * and each entry carries its thumbnail URLs — which is what makes a channel's
8
+ * thumbnails reachable without extracting every video. Printed as one JSON
9
+ * object per line with exactly these fields, so a title containing a delimiter
10
+ * cannot shift the others, and the parser checks each field's type.
11
+ *
12
+ * Verified against yt-dlp 2026.07.04: a flat entry carries `thumbnails` but no
13
+ * `upload_date`, so the date stays empty here and is resolved per video by the
14
+ * callers that need it.
15
+ */
16
+ export declare const FLAT_PRINT_TEMPLATE = "%(.{id,title,duration,upload_date,timestamp,view_count,live_status,availability,thumbnails})j";
17
+ /** One entry of a thumbnails array; sizes are absent for some channel images. */
18
+ export declare const listedImageSchema: z.ZodObject<{
19
+ id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
20
+ url: z.ZodString;
21
+ width: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
22
+ height: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ url: string;
25
+ id?: string | null | undefined;
26
+ width?: number | null | undefined;
27
+ height?: number | null | undefined;
28
+ }, {
29
+ url: string;
30
+ id?: string | null | undefined;
31
+ width?: number | null | undefined;
32
+ height?: number | null | undefined;
33
+ }>;
34
+ export type ListedImage = z.infer<typeof listedImageSchema>;
35
+ export declare const flatEntrySchema: z.ZodObject<{
36
+ id: z.ZodString;
37
+ title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
38
+ duration: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
39
+ upload_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
40
+ view_count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
41
+ live_status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
42
+ thumbnails: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
43
+ id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
44
+ url: z.ZodString;
45
+ width: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
46
+ height: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
47
+ }, "strip", z.ZodTypeAny, {
48
+ url: string;
49
+ id?: string | null | undefined;
50
+ width?: number | null | undefined;
51
+ height?: number | null | undefined;
52
+ }, {
53
+ url: string;
54
+ id?: string | null | undefined;
55
+ width?: number | null | undefined;
56
+ height?: number | null | undefined;
57
+ }>, "many">>>;
58
+ }, "strip", z.ZodTypeAny, {
59
+ id: string;
60
+ title?: string | null | undefined;
61
+ duration?: number | null | undefined;
62
+ upload_date?: string | null | undefined;
63
+ view_count?: number | null | undefined;
64
+ live_status?: string | null | undefined;
65
+ thumbnails?: {
66
+ url: string;
67
+ id?: string | null | undefined;
68
+ width?: number | null | undefined;
69
+ height?: number | null | undefined;
70
+ }[] | null | undefined;
71
+ }, {
72
+ id: string;
73
+ title?: string | null | undefined;
74
+ duration?: number | null | undefined;
75
+ upload_date?: string | null | undefined;
76
+ view_count?: number | null | undefined;
77
+ live_status?: string | null | undefined;
78
+ thumbnails?: {
79
+ url: string;
80
+ id?: string | null | undefined;
81
+ width?: number | null | undefined;
82
+ height?: number | null | undefined;
83
+ }[] | null | undefined;
84
+ }>;
85
+ export type FlatEntry = z.infer<typeof flatEntrySchema>;
86
+ /** The largest image by area, then by width; `undefined` for an empty list. */
87
+ export declare function largestThumbnail(thumbnails: ListedImage[]): ListedImage | undefined;
88
+ export declare function toVideoListItem(entry: FlatEntry): VideoListItem;
89
+ //# sourceMappingURL=flat-listing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flat-listing.d.ts","sourceRoot":"","sources":["../../src/utils/flat-listing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,mBAAmB,kGACiE,CAAC;AAElG,iFAAiF;AACjF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;EAK5B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQ1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,WAAW,EAAE,GAAG,WAAW,GAAG,SAAS,CAQnF;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,aAAa,CAqB/D"}
@@ -0,0 +1,68 @@
1
+ import { z } from 'zod';
2
+ import { formatYouTubeDate } from './format.js';
3
+ import { formatDuration, watchUrl } from './youtube-url.js';
4
+ /**
5
+ * Reading a flat channel or playlist listing.
6
+ *
7
+ * `--flat-playlist` lists a channel in one request instead of one per video,
8
+ * and each entry carries its thumbnail URLs — which is what makes a channel's
9
+ * thumbnails reachable without extracting every video. Printed as one JSON
10
+ * object per line with exactly these fields, so a title containing a delimiter
11
+ * cannot shift the others, and the parser checks each field's type.
12
+ *
13
+ * Verified against yt-dlp 2026.07.04: a flat entry carries `thumbnails` but no
14
+ * `upload_date`, so the date stays empty here and is resolved per video by the
15
+ * callers that need it.
16
+ */
17
+ export const FLAT_PRINT_TEMPLATE = '%(.{id,title,duration,upload_date,timestamp,view_count,live_status,availability,thumbnails})j';
18
+ /** One entry of a thumbnails array; sizes are absent for some channel images. */
19
+ export const listedImageSchema = z.object({
20
+ id: z.string().nullish(),
21
+ url: z.string(),
22
+ width: z.number().nullish(),
23
+ height: z.number().nullish(),
24
+ });
25
+ export const flatEntrySchema = z.object({
26
+ id: z.string(),
27
+ title: z.string().nullish(),
28
+ duration: z.number().nullish(),
29
+ upload_date: z.string().nullish(),
30
+ view_count: z.number().nullish(),
31
+ live_status: z.string().nullish(),
32
+ thumbnails: z.array(listedImageSchema).nullish(),
33
+ });
34
+ /** The largest image by area, then by width; `undefined` for an empty list. */
35
+ export function largestThumbnail(thumbnails) {
36
+ const area = (image) => (image.width ?? 0) * (image.height ?? 0);
37
+ return thumbnails.reduce((best, image) => {
38
+ if (best === undefined)
39
+ return image;
40
+ if (area(image) > area(best))
41
+ return image;
42
+ if (area(image) === area(best) && (image.width ?? 0) > (best.width ?? 0))
43
+ return image;
44
+ return best;
45
+ }, undefined);
46
+ }
47
+ export function toVideoListItem(entry) {
48
+ const duration = entry.duration ?? 0;
49
+ const thumbnails = entry.thumbnails ?? [];
50
+ const largest = largestThumbnail(thumbnails);
51
+ return {
52
+ id: entry.id,
53
+ title: entry.title ?? 'Unknown title',
54
+ duration,
55
+ durationFormatted: formatDuration(duration),
56
+ uploadDate: formatYouTubeDate(entry.upload_date ?? ''),
57
+ url: watchUrl(entry.id),
58
+ ...(largest === undefined ? {} : { thumbnailUrl: largest.url }),
59
+ ...(thumbnails.length === 0 ? {} : { thumbnails }),
60
+ ...(entry.view_count === null || entry.view_count === undefined
61
+ ? {}
62
+ : { viewCount: entry.view_count }),
63
+ ...(entry.live_status === null || entry.live_status === undefined
64
+ ? {}
65
+ : { liveStatus: entry.live_status }),
66
+ };
67
+ }
68
+ //# sourceMappingURL=flat-listing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flat-listing.js","sourceRoot":"","sources":["../../src/utils/flat-listing.ts"],"names":[],"mappings":"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"}
@@ -2,13 +2,11 @@ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
2
  export declare function formatCount(count: number): string;
3
3
  export declare function formatYouTubeDate(yyyymmdd: string): string;
4
4
  export declare function formatFilesize(bytes?: number): string;
5
- export declare function textContent(text: string): CallToolResult;
6
5
  /**
7
6
  * A tool result carrying both a human-readable rendering and machine-readable
8
7
  * data.
9
8
  *
10
- * The text block is byte-identical to what `textContent` produced before, so
11
- * nothing a client already displays changes; `structuredContent` is additive and
9
+ * The text block is what a client displays; `structuredContent` is additive and
12
10
  * is what the tool's `outputSchema` describes. Every tool that declares an
13
11
  * output schema must return this, because the SDK validates the two against
14
12
  * each other.
@@ -22,7 +20,23 @@ export interface PageInfo {
22
20
  hasMore: boolean;
23
21
  nextOffset?: number;
24
22
  }
25
- export declare function pageInfo(total: number, count: number, offset?: number): PageInfo;
23
+ /**
24
+ * Takes an object, not three adjacent numbers.
25
+ *
26
+ * The bug this replaces was not in the arithmetic: it was five call sites that
27
+ * passed `count` where `total` belonged, so `hasMore` computed `n < n` and a
28
+ * caller with 20 of a channel's 5,000 videos was told it had all of them.
29
+ * Positional arguments of the same type made that invisible; an object makes
30
+ * it impossible, and changing the signature forced every call site to be
31
+ * revisited, which was the point.
32
+ */
33
+ export interface PageInput {
34
+ /** Items available in total. Never `count` — that is the bug this shape prevents. */
35
+ total: number;
36
+ count: number;
37
+ offset?: number;
38
+ }
39
+ export declare function pageInfo({ total, count, offset }: PageInput): PageInfo;
26
40
  /** A link to a file this server produced, so clients can offer to open it. */
27
41
  export declare function fileResourceLink(filePath: string, name: string, mimeType?: string): {
28
42
  type: 'resource_link';
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKjD;AAOD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAExD;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAK5F;AAED,wEAAwE;AACxE,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,QAAQ,CAS3E;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAOzE;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACtD,cAAc,CAQhB"}
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKjD;AAOD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAK5F;AAED,wEAAwE;AACxE,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,SAAS;IACxB,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAU,EAAE,EAAE,SAAS,GAAG,QAAQ,CAS1E;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAOzE;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACtD,cAAc,CAQhB"}
@@ -25,15 +25,11 @@ export function formatFilesize(bytes) {
25
25
  return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
26
26
  return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
27
27
  }
28
- export function textContent(text) {
29
- return { content: [{ type: 'text', text }] };
30
- }
31
28
  /**
32
29
  * A tool result carrying both a human-readable rendering and machine-readable
33
30
  * data.
34
31
  *
35
- * The text block is byte-identical to what `textContent` produced before, so
36
- * nothing a client already displays changes; `structuredContent` is additive and
32
+ * The text block is what a client displays; `structuredContent` is additive and
37
33
  * is what the tool's `outputSchema` describes. Every tool that declares an
38
34
  * output schema must return this, because the SDK validates the two against
39
35
  * each other.
@@ -44,7 +40,7 @@ export function toolResult(text, structured) {
44
40
  structuredContent: structured,
45
41
  };
46
42
  }
47
- export function pageInfo(total, count, offset = 0) {
43
+ export function pageInfo({ total, count, offset = 0 }) {
48
44
  const hasMore = offset + count < total;
49
45
  return {
50
46
  total,
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ /** Any tool handler: whatever it takes, it answers with a tool result. */
3
+ type ToolLike = (...args: never[]) => CallToolResult | Promise<CallToolResult>;
4
+ /**
5
+ * Wrap a tool handler, keeping its exact type.
6
+ *
7
+ * A Proxy rather than an arrow function because the SDK's `registerTool` is
8
+ * generic over the input schema and demands a callback of the precise type it
9
+ * derives from it; a new function would need a cast to claim that type, while
10
+ * a Proxy over the original *is* that type.
11
+ */
12
+ export declare function guarded<F extends ToolLike>(handler: F): F;
13
+ /**
14
+ * The resource counterpart. A read that fails used to propagate whatever was
15
+ * thrown — an `ENOENT` carrying an absolute local path, for instance — as the
16
+ * JSON-RPC error message. It now carries the same `[CODE] message` a tool
17
+ * would show, and nothing else.
18
+ */
19
+ export declare function guardedResource<A extends unknown[], R>(handler: (...args: A) => Promise<R>): (...args: A) => Promise<R>;
20
+ export {};
21
+ //# sourceMappingURL=guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/utils/guard.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAoEzE,0EAA0E;AAC1E,KAAK,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAE/E;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,QAAQ,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAazD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,CAAC,EACpD,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAClC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAc5B"}
@@ -0,0 +1,105 @@
1
+ import { z } from 'zod';
2
+ import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
3
+ import { runWithRequestContext } from './context.js';
4
+ import { asYouTubeError, toToolError } from './errors.js';
5
+ /**
6
+ * Wrapping every handler the server registers, once, so that each call gets a
7
+ * request context and no call can throw out of the server.
8
+ *
9
+ * The MCP request's AbortSignal is published to the request context so an
10
+ * in-flight yt-dlp is killed when the client cancels, and anything thrown is
11
+ * rendered as an actionable message rather than a raw stack trace, a yt-dlp
12
+ * command line, or a local path. Tools report failures inside the result with
13
+ * `isError`; resources have no such envelope, so theirs become protocol errors
14
+ * carrying the same normalised text.
15
+ */
16
+ /**
17
+ * The parts of the SDK's `RequestHandlerExtra` this server uses.
18
+ *
19
+ * `sendNotification` is described with `z.custom` because a function is not
20
+ * something Zod can take apart structurally — the predicate is a real runtime
21
+ * check, and it is what lets the property be called without asserting a type
22
+ * over it.
23
+ */
24
+ const requestExtraSchema = z.object({
25
+ signal: z.instanceof(AbortSignal).optional(),
26
+ sendNotification: z
27
+ .custom((value) => typeof value === 'function')
28
+ .optional(),
29
+ _meta: z.object({ progressToken: z.union([z.string(), z.number()]).optional() }).optional(),
30
+ });
31
+ /** The request context for a call, read from the SDK extra that arrives last. */
32
+ function contextOf(args) {
33
+ // Handlers declare only their own parameters; the SDK appends
34
+ // RequestHandlerExtra to every call, so it is whatever arrived last.
35
+ const parsed = requestExtraSchema.safeParse(args[args.length - 1]);
36
+ const extra = parsed.success ? parsed.data : undefined;
37
+ return {
38
+ signal: extra?.signal,
39
+ // Progress is only meaningful when the client asked for it by sending a
40
+ // token; without one the notification would be dropped anyway.
41
+ reportProgress: extra?.sendNotification && extra._meta?.progressToken !== undefined
42
+ ? (progress, total, message) => {
43
+ void extra.sendNotification?.({
44
+ method: 'notifications/progress',
45
+ params: {
46
+ progressToken: extra._meta?.progressToken,
47
+ progress,
48
+ ...(total === undefined ? {} : { total }),
49
+ ...(message === undefined ? {} : { message }),
50
+ },
51
+ });
52
+ }
53
+ : undefined,
54
+ log: extra?.sendNotification
55
+ ? (level, message) => {
56
+ void extra.sendNotification?.({
57
+ method: 'notifications/message',
58
+ params: { level, logger: 'youtube-knowledge-mcp', data: message },
59
+ });
60
+ }
61
+ : undefined,
62
+ };
63
+ }
64
+ /**
65
+ * Wrap a tool handler, keeping its exact type.
66
+ *
67
+ * A Proxy rather than an arrow function because the SDK's `registerTool` is
68
+ * generic over the input schema and demands a callback of the precise type it
69
+ * derives from it; a new function would need a cast to claim that type, while
70
+ * a Proxy over the original *is* that type.
71
+ */
72
+ export function guarded(handler) {
73
+ const run = (args) => runWithRequestContext(contextOf(args), async () => {
74
+ try {
75
+ return await handler(...args);
76
+ }
77
+ catch (error) {
78
+ return toToolError(error);
79
+ }
80
+ });
81
+ return new Proxy(handler, {
82
+ apply: (_target, _thisArg, args) => run(args),
83
+ });
84
+ }
85
+ /**
86
+ * The resource counterpart. A read that fails used to propagate whatever was
87
+ * thrown — an `ENOENT` carrying an absolute local path, for instance — as the
88
+ * JSON-RPC error message. It now carries the same `[CODE] message` a tool
89
+ * would show, and nothing else.
90
+ */
91
+ export function guardedResource(handler) {
92
+ return async (...args) => runWithRequestContext(contextOf(args), async () => {
93
+ try {
94
+ return await handler(...args);
95
+ }
96
+ catch (error) {
97
+ const failure = asYouTubeError(error);
98
+ const code = failure.code === 'INVALID_INPUT' || failure.code === 'NOT_FOUND'
99
+ ? ErrorCode.InvalidParams
100
+ : ErrorCode.InternalError;
101
+ throw new McpError(code, `[${failure.code}] ${failure.toToolMessage()}`);
102
+ }
103
+ });
104
+ }
105
+ //# sourceMappingURL=guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/utils/guard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { DatabaseSync } from 'node:sqlite';
2
+ import type { Coverage } from '../harvest-schemas.js';
3
+ /**
4
+ * Reading a channel's whole catalogue.
5
+ *
6
+ * The listing plane is cheap and is not bot-checked: measured 1,716 videos in
7
+ * 31 seconds from one spawn, so a catalogue costs about a minute per channel
8
+ * and the old 100-video cap was self-imposed rather than forced.
9
+ *
10
+ * Every tab is walked because a channel's videos are not all under /videos —
11
+ * shorts, streams, releases and podcasts each have their own. The first tab
12
+ * that lists a video owns it; later tabs record themselves in `also_in_tabs`.
13
+ * Last-writer-wins would mislabel most of a music channel's catalogue.
14
+ */
15
+ export declare const HARVEST_TABS: readonly ["videos", "shorts", "streams", "releases", "podcasts"];
16
+ export type HarvestTab = (typeof HARVEST_TABS)[number];
17
+ export declare const MAX_VIDEOS_PER_CATALOG = 10000;
18
+ export interface TabResult {
19
+ tab: HarvestTab;
20
+ listed: number;
21
+ added: number;
22
+ complete: boolean;
23
+ error?: string;
24
+ }
25
+ export interface CatalogResult {
26
+ channelId: string;
27
+ name: string;
28
+ handle: string;
29
+ tabs: TabResult[];
30
+ videosSeen: number;
31
+ videosAdded: number;
32
+ coverage: Coverage;
33
+ }
34
+ /**
35
+ * Walks every tab of a channel into the store.
36
+ *
37
+ * A tab the channel simply does not have is not a failure — yt-dlp says so in
38
+ * words, and treating that as an error would make every channel without a
39
+ * podcasts tab look broken.
40
+ */
41
+ export declare function harvestCatalog(database: DatabaseSync, channel: string, options?: {
42
+ maxVideos?: number;
43
+ }): Promise<CatalogResult>;
44
+ //# sourceMappingURL=harvest-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harvest-catalog.d.ts","sourceRoot":"","sources":["../../src/utils/harvest-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAahD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,YAAY,kEAAmE,CAAC;AAC7F,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAK7C,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,UAAU,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAyCD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,OAAO,CAAC,aAAa,CAAC,CAQxB"}
@@ -0,0 +1,164 @@
1
+ import { runYtDlp, TIMEOUTS } from './ytdlp.js';
2
+ import { FLAT_PRINT_TEMPLATE, flatEntrySchema, toVideoListItem } from './flat-listing.js';
3
+ import { parseYtDlpJsonLines } from './ytdlp-parse.js';
4
+ import { resolveListTarget } from './youtube-url.js';
5
+ import { getChannelInfo } from './youtube-channel.js';
6
+ import { coverageOf } from './coverage.js';
7
+ import { saveReceipt } from './harvest-receipts.js';
8
+ import { inTransaction } from './store.js';
9
+ import { throwIfAborted, reportProgress } from './context.js';
10
+ import { countRows } from './store-rows.js';
11
+ import { withChannelHarvestLock } from './harvest-lock.js';
12
+ import { YouTubeError } from './errors.js';
13
+ /**
14
+ * Reading a channel's whole catalogue.
15
+ *
16
+ * The listing plane is cheap and is not bot-checked: measured 1,716 videos in
17
+ * 31 seconds from one spawn, so a catalogue costs about a minute per channel
18
+ * and the old 100-video cap was self-imposed rather than forced.
19
+ *
20
+ * Every tab is walked because a channel's videos are not all under /videos —
21
+ * shorts, streams, releases and podcasts each have their own. The first tab
22
+ * that lists a video owns it; later tabs record themselves in `also_in_tabs`.
23
+ * Last-writer-wins would mislabel most of a music channel's catalogue.
24
+ */
25
+ export const HARVEST_TABS = ['videos', 'shorts', 'streams', 'releases', 'podcasts'];
26
+ export const MAX_VIDEOS_PER_CATALOG = 10_000;
27
+ /** yt-dlp says this, in these words, for a tab the channel does not have. */
28
+ const NO_SUCH_TAB = 'does not have a';
29
+ const UPSERT_VIDEO = `
30
+ INSERT INTO video (
31
+ video_id, channel_id, title, duration_s, upload_date, view_count,
32
+ live_status, thumbnail_url, tab, also_in_tabs, catalog_rank, listed_at
33
+ ) VALUES (?,?,?,?,?,?,?,?,?,'[]',?,?)
34
+ ON CONFLICT(video_id) DO UPDATE SET
35
+ title = excluded.title,
36
+ duration_s = excluded.duration_s,
37
+ view_count = excluded.view_count,
38
+ live_status = excluded.live_status,
39
+ thumbnail_url = excluded.thumbnail_url,
40
+ listed_at = excluded.listed_at,
41
+ -- The owning tab is kept; a later tab only records that it also lists this
42
+ -- video, so a re-walk in a different order cannot relabel the catalogue.
43
+ also_in_tabs = CASE
44
+ WHEN video.tab = excluded.tab THEN video.also_in_tabs
45
+ WHEN instr(video.also_in_tabs, excluded.tab) > 0 THEN video.also_in_tabs
46
+ ELSE json_insert(video.also_in_tabs, '$[#]', excluded.tab)
47
+ END`;
48
+ async function listTab(channelUrl, tab, limit) {
49
+ return runYtDlp([
50
+ '--skip-download',
51
+ '--flat-playlist',
52
+ '--lazy-playlist',
53
+ '--print',
54
+ FLAT_PRINT_TEMPLATE,
55
+ '--playlist-end',
56
+ String(limit),
57
+ ], {
58
+ label: `harvest_channel:${tab}`,
59
+ timeoutMs: TIMEOUTS.transcript,
60
+ target: resolveListTarget(`${channelUrl}/${tab}`),
61
+ });
62
+ }
63
+ /**
64
+ * Walks every tab of a channel into the store.
65
+ *
66
+ * A tab the channel simply does not have is not a failure — yt-dlp says so in
67
+ * words, and treating that as an error would make every channel without a
68
+ * podcasts tab look broken.
69
+ */
70
+ export async function harvestCatalog(database, channel, options = {}) {
71
+ const maxVideos = Math.min(options.maxVideos ?? 500, MAX_VIDEOS_PER_CATALOG);
72
+ // Resolving the channel comes before the lock because the lock is keyed on
73
+ // the channel id, and only YouTube can turn a handle into one.
74
+ const info = await getChannelInfo(channel);
75
+ return withChannelHarvestLock(info.channelId, () => walkTabs(database, info, maxVideos));
76
+ }
77
+ async function walkTabs(database, info, maxVideos) {
78
+ const now = Date.now();
79
+ database
80
+ .prepare(`INSERT INTO channel (channel_id, handle, name, channel_url, subscriber_count, description, first_seen_at, updated_at)
81
+ VALUES (?,?,?,?,?,?,?,?)
82
+ ON CONFLICT(channel_id) DO UPDATE SET
83
+ handle = excluded.handle, name = excluded.name, channel_url = excluded.channel_url,
84
+ subscriber_count = excluded.subscriber_count, description = excluded.description,
85
+ updated_at = excluded.updated_at`)
86
+ .run(info.channelId, info.handle, info.name, info.channelUrl, info.subscriberCount, info.description, now, now);
87
+ const tabs = [];
88
+ const seen = new Set();
89
+ let rank = 0;
90
+ // Counted from the store, not from `seen`: on a second run every video is
91
+ // new to the walk and none is new to the catalogue, and reporting the former
92
+ // as "added" would make a re-run look like a fresh harvest.
93
+ const countVideos = () => countRows(database.prepare('SELECT COUNT(*) FROM video WHERE channel_id = ?'), info.channelId);
94
+ const before = countVideos();
95
+ for (const tab of HARVEST_TABS) {
96
+ throwIfAborted();
97
+ reportProgress(tabs.length, HARVEST_TABS.length, `harvest_channel: ${tab}`);
98
+ let stdout;
99
+ try {
100
+ stdout = await listTab(info.channelUrl, tab, maxVideos);
101
+ }
102
+ catch (error) {
103
+ const message = error instanceof YouTubeError ? error.message : String(error);
104
+ const absent = error instanceof YouTubeError && error.message.includes(NO_SUCH_TAB);
105
+ tabs.push({
106
+ tab,
107
+ listed: 0,
108
+ added: 0,
109
+ // A tab the channel does not have is a complete answer, not a gap.
110
+ complete: absent,
111
+ ...(absent ? {} : { error: message }),
112
+ });
113
+ continue;
114
+ }
115
+ const entries = parseYtDlpJsonLines(stdout, flatEntrySchema).map(toVideoListItem);
116
+ const insert = database.prepare(UPSERT_VIDEO);
117
+ const tabBefore = countVideos();
118
+ inTransaction(database, () => {
119
+ for (const entry of entries) {
120
+ if (seen.size >= maxVideos)
121
+ break;
122
+ seen.add(entry.id);
123
+ insert.run(entry.id, info.channelId, entry.title, entry.duration, entry.uploadDate === '' ? null : entry.uploadDate, entry.viewCount ?? null, entry.liveStatus ?? null, entry.thumbnailUrl ?? null, tab, rank, now);
124
+ rank += 1;
125
+ }
126
+ });
127
+ tabs.push({
128
+ tab,
129
+ listed: entries.length,
130
+ added: countVideos() - tabBefore,
131
+ complete: entries.length < maxVideos,
132
+ });
133
+ }
134
+ const everyTabComplete = tabs.every((tab) => tab.complete);
135
+ const coverage = coverageOf({
136
+ scope: 'channel-catalog',
137
+ targetId: info.channelId,
138
+ have: seen.size,
139
+ source: `yt-dlp --flat-playlist over ${HARVEST_TABS.join(', ')}`,
140
+ // Only an unbroken walk of every tab proves the catalogue is whole. A tab
141
+ // that errored, or one that filled to the cap, leaves it unprovable.
142
+ ...(everyTabComplete
143
+ ? {
144
+ expected: { value: seen.size, source: 'source-exhausted' },
145
+ ranToExhaustion: true,
146
+ }
147
+ : {}),
148
+ ...(seen.size >= maxVideos ? { limitApplied: maxVideos } : {}),
149
+ ...(everyTabComplete ? {} : { resumeToken: `catalog:${info.channelId}` }),
150
+ });
151
+ inTransaction(database, () => {
152
+ saveReceipt(database, coverage, { startedAt: now });
153
+ });
154
+ return {
155
+ channelId: info.channelId,
156
+ name: info.name,
157
+ handle: info.handle,
158
+ tabs,
159
+ videosSeen: seen.size,
160
+ videosAdded: countVideos() - before,
161
+ coverage,
162
+ };
163
+ }
164
+ //# sourceMappingURL=harvest-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harvest-catalog.js","sourceRoot":"","sources":["../../src/utils/harvest-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function withChannelHarvestLock<T>(channelId: string, work: () => Promise<T>): Promise<T>;
2
+ export declare function withVideoHarvestLock<T>(videoId: string, work: () => Promise<T>): Promise<T>;
3
+ //# sourceMappingURL=harvest-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harvest-lock.d.ts","sourceRoot":"","sources":["../../src/utils/harvest-lock.ts"],"names":[],"mappings":"AAsBA,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,CAAC,CAAC,CAKZ;AAED,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAKjG"}