youtube-knowledge-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +225 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +65 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/download-video.d.ts +38 -0
- package/dist/tools/download-video.d.ts.map +1 -0
- package/dist/tools/download-video.js +107 -0
- package/dist/tools/download-video.js.map +1 -0
- package/dist/tools/fetch-videos.d.ts +15 -0
- package/dist/tools/fetch-videos.d.ts.map +1 -0
- package/dist/tools/fetch-videos.js +25 -0
- package/dist/tools/fetch-videos.js.map +1 -0
- package/dist/tools/get-transcript.d.ts +15 -0
- package/dist/tools/get-transcript.d.ts.map +1 -0
- package/dist/tools/get-transcript.js +25 -0
- package/dist/tools/get-transcript.js.map +1 -0
- package/dist/tools/get-video-info.d.ts +13 -0
- package/dist/tools/get-video-info.d.ts.map +1 -0
- package/dist/tools/get-video-info.js +32 -0
- package/dist/tools/get-video-info.js.map +1 -0
- package/dist/tools/list-library.d.ts +13 -0
- package/dist/tools/list-library.d.ts.map +1 -0
- package/dist/tools/list-library.js +44 -0
- package/dist/tools/list-library.js.map +1 -0
- package/dist/tools/save-to-library.d.ts +23 -0
- package/dist/tools/save-to-library.d.ts.map +1 -0
- package/dist/tools/save-to-library.js +41 -0
- package/dist/tools/save-to-library.js.map +1 -0
- package/dist/utils/storage.d.ts +38 -0
- package/dist/utils/storage.d.ts.map +1 -0
- package/dist/utils/storage.js +128 -0
- package/dist/utils/storage.js.map +1 -0
- package/dist/utils/youtube.d.ts +48 -0
- package/dist/utils/youtube.d.ts.map +1 -0
- package/dist/utils/youtube.js +288 -0
- package/dist/utils/youtube.js.map +1 -0
- package/package.json +79 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 teobouancheau
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# YouTube Knowledge MCP
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/youtube-knowledge-mcp)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://nodejs.org/)
|
|
6
|
+
|
|
7
|
+
MCP Server for extracting and managing YouTube video knowledge.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Fetch videos** from playlists or channels
|
|
12
|
+
- **Get video info** (title, channel, duration, description, tags)
|
|
13
|
+
- **Extract transcripts** (auto-generated or manual captions)
|
|
14
|
+
- **Download videos** with quality selection and format options
|
|
15
|
+
- **Save to library** (summaries, notes, skills)
|
|
16
|
+
- **List library** with tag filtering
|
|
17
|
+
|
|
18
|
+
## Prerequisites
|
|
19
|
+
|
|
20
|
+
- Node.js 20+
|
|
21
|
+
- yt-dlp: `brew install yt-dlp` (macOS) or [see installation guide](https://github.com/yt-dlp/yt-dlp#installation)
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
### Via npm (Recommended)
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install -g youtube-knowledge-mcp
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Via npx (no installation)
|
|
32
|
+
|
|
33
|
+
Configure directly with npx (see Configuration section).
|
|
34
|
+
|
|
35
|
+
### From source
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
git clone https://github.com/teobouancheau/youtube-knowledge-mcp.git
|
|
39
|
+
cd youtube-knowledge-mcp
|
|
40
|
+
npm install
|
|
41
|
+
npm run build
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Configuration
|
|
45
|
+
|
|
46
|
+
### With npx (Recommended)
|
|
47
|
+
|
|
48
|
+
Add to your Claude Code MCP configuration:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"mcpServers": {
|
|
53
|
+
"youtube-knowledge": {
|
|
54
|
+
"command": "npx",
|
|
55
|
+
"args": ["-y", "youtube-knowledge-mcp"]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### With npm global
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"mcpServers": {
|
|
66
|
+
"youtube-knowledge": {
|
|
67
|
+
"command": "youtube-knowledge-mcp"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### From source
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"mcpServers": {
|
|
78
|
+
"youtube-knowledge": {
|
|
79
|
+
"command": "node",
|
|
80
|
+
"args": ["/path/to/youtube-knowledge-mcp/dist/index.js"]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Then restart Claude Code to load the new MCP server.
|
|
87
|
+
|
|
88
|
+
## MCP Tools
|
|
89
|
+
|
|
90
|
+
### youtube_fetch_videos
|
|
91
|
+
|
|
92
|
+
List videos from a YouTube playlist or channel.
|
|
93
|
+
|
|
94
|
+
| Parameter | Type | Default | Description |
|
|
95
|
+
| --------- | ------ | -------- | ------------------------------- |
|
|
96
|
+
| `url` | string | required | YouTube playlist or channel URL |
|
|
97
|
+
| `limit` | number | 20 | Maximum videos to fetch |
|
|
98
|
+
|
|
99
|
+
### youtube_get_video_info
|
|
100
|
+
|
|
101
|
+
Get detailed metadata for a YouTube video.
|
|
102
|
+
|
|
103
|
+
| Parameter | Type | Description |
|
|
104
|
+
| --------- | ------ | --------------- |
|
|
105
|
+
| `video` | string | Video ID or URL |
|
|
106
|
+
|
|
107
|
+
**Returns:** title, channel, duration, description, tags, thumbnail
|
|
108
|
+
|
|
109
|
+
### youtube_get_transcript
|
|
110
|
+
|
|
111
|
+
Extract transcript/subtitles from a YouTube video.
|
|
112
|
+
|
|
113
|
+
| Parameter | Type | Default | Description |
|
|
114
|
+
| ---------- | ------ | -------- | ----------------------- |
|
|
115
|
+
| `video` | string | required | Video ID or URL |
|
|
116
|
+
| `language` | string | "en" | Preferred language code |
|
|
117
|
+
|
|
118
|
+
### youtube_list_formats
|
|
119
|
+
|
|
120
|
+
List available download formats for a YouTube video.
|
|
121
|
+
|
|
122
|
+
| Parameter | Type | Description |
|
|
123
|
+
| --------- | ------ | --------------- |
|
|
124
|
+
| `video` | string | Video ID or URL |
|
|
125
|
+
|
|
126
|
+
**Returns:** format IDs, resolutions, codecs, file sizes
|
|
127
|
+
|
|
128
|
+
### youtube_download_video
|
|
129
|
+
|
|
130
|
+
Download a YouTube video with quality selection.
|
|
131
|
+
|
|
132
|
+
| Parameter | Type | Default | Description |
|
|
133
|
+
| ----------- | ------ | ------- | -------------------------------------------------------- |
|
|
134
|
+
| `video` | string | required| Video ID or URL |
|
|
135
|
+
| `quality` | string | "best" | Quality preset (best, 2160p, 1440p, 1080p, 720p, 480p, 360p, audio) |
|
|
136
|
+
| `formatId` | string | - | Specific format code from youtube_list_formats |
|
|
137
|
+
| `outputDir` | string | - | Custom output directory |
|
|
138
|
+
|
|
139
|
+
### youtube_save_to_library
|
|
140
|
+
|
|
141
|
+
Save content to your personal YouTube knowledge library.
|
|
142
|
+
|
|
143
|
+
| Parameter | Type | Description |
|
|
144
|
+
| -------------- | -------- | -------------------- |
|
|
145
|
+
| `video_id` | string | YouTube video ID |
|
|
146
|
+
| `title` | string | Video title |
|
|
147
|
+
| `content` | string | Content to save |
|
|
148
|
+
| `content_type` | string | "summary" or "skill" |
|
|
149
|
+
| `tags` | string[] | Optional tags |
|
|
150
|
+
| `channel` | string | Optional channel name|
|
|
151
|
+
|
|
152
|
+
### youtube_list_library
|
|
153
|
+
|
|
154
|
+
List all saved items in your library.
|
|
155
|
+
|
|
156
|
+
| Parameter | Type | Description |
|
|
157
|
+
| --------- | ------ | ---------------------- |
|
|
158
|
+
| `tag` | string | Optional filter by tag |
|
|
159
|
+
|
|
160
|
+
## Library Storage
|
|
161
|
+
|
|
162
|
+
Content is stored in `~/.youtube-knowledge/`:
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
~/.youtube-knowledge/
|
|
166
|
+
├── transcripts/ # Cached transcripts
|
|
167
|
+
│ └── {video_id}.txt
|
|
168
|
+
├── library/ # Saved content
|
|
169
|
+
│ └── {video_id}/
|
|
170
|
+
│ ├── metadata.json
|
|
171
|
+
│ ├── summary.md
|
|
172
|
+
│ └── skill.md
|
|
173
|
+
├── downloads/ # Downloaded videos
|
|
174
|
+
│ └── {video_title}.{ext}
|
|
175
|
+
└── index.json # Searchable index
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Usage Examples
|
|
179
|
+
|
|
180
|
+
### Quick summary
|
|
181
|
+
|
|
182
|
+
```
|
|
183
|
+
"Summarize this video: https://youtube.com/watch?v=ABC123"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Explore a channel
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
"Show me the latest videos from @ThePrimeagen"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Download a video
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
"Download this video in 1080p: https://youtube.com/watch?v=ABC123"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Save to library
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
"Save this summary with tags: programming, productivity"
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Create a skill
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
"Create a Claude Code skill from this video's content"
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Development
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
npm run dev # Watch mode
|
|
214
|
+
npm run build # Build for production
|
|
215
|
+
npm run rebuild # Clean and rebuild
|
|
216
|
+
npm start # Run the server
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Contributing
|
|
220
|
+
|
|
221
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
222
|
+
|
|
223
|
+
## License
|
|
224
|
+
|
|
225
|
+
[MIT](LICENSE) © 2026 teobouancheau
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { fetchVideosSchema, fetchVideosHandler } from './tools/fetch-videos.js';
|
|
5
|
+
import { getVideoInfoSchema, getVideoInfoHandler } from './tools/get-video-info.js';
|
|
6
|
+
import { getTranscriptSchema, getTranscriptHandler } from './tools/get-transcript.js';
|
|
7
|
+
import { saveToLibrarySchema, saveToLibraryHandler } from './tools/save-to-library.js';
|
|
8
|
+
import { listLibrarySchema, listLibraryHandler } from './tools/list-library.js';
|
|
9
|
+
import { listFormatsSchema, listFormatsHandler, downloadVideoSchema, downloadVideoHandler, } from './tools/download-video.js';
|
|
10
|
+
const server = new McpServer({
|
|
11
|
+
name: 'youtube-knowledge-extractor',
|
|
12
|
+
version: '1.0.0',
|
|
13
|
+
});
|
|
14
|
+
// Tool 1: Fetch videos from playlist or channel
|
|
15
|
+
server.registerTool('youtube_fetch_videos', {
|
|
16
|
+
title: 'Fetch YouTube Videos',
|
|
17
|
+
description: 'List videos from a YouTube playlist or channel. Returns video IDs, titles, durations, and dates.',
|
|
18
|
+
inputSchema: fetchVideosSchema,
|
|
19
|
+
}, fetchVideosHandler);
|
|
20
|
+
// Tool 2: Get video info
|
|
21
|
+
server.registerTool('youtube_get_video_info', {
|
|
22
|
+
title: 'Get Video Info',
|
|
23
|
+
description: 'Get detailed metadata for a YouTube video including title, channel, duration, description, and tags.',
|
|
24
|
+
inputSchema: getVideoInfoSchema,
|
|
25
|
+
}, getVideoInfoHandler);
|
|
26
|
+
// Tool 3: Get transcript
|
|
27
|
+
server.registerTool('youtube_get_transcript', {
|
|
28
|
+
title: 'Get Video Transcript',
|
|
29
|
+
description: 'Extract the transcript/subtitles from a YouTube video. Supports auto-generated and manual captions.',
|
|
30
|
+
inputSchema: getTranscriptSchema,
|
|
31
|
+
}, getTranscriptHandler);
|
|
32
|
+
// Tool 4: Save to library
|
|
33
|
+
server.registerTool('youtube_save_to_library', {
|
|
34
|
+
title: 'Save to Library',
|
|
35
|
+
description: 'Save a summary, notes, or skill to your personal YouTube knowledge library.',
|
|
36
|
+
inputSchema: saveToLibrarySchema,
|
|
37
|
+
}, saveToLibraryHandler);
|
|
38
|
+
// Tool 5: List library
|
|
39
|
+
server.registerTool('youtube_list_library', {
|
|
40
|
+
title: 'List Library',
|
|
41
|
+
description: 'List all saved items in your YouTube knowledge library. Optionally filter by tag.',
|
|
42
|
+
inputSchema: listLibrarySchema,
|
|
43
|
+
}, listLibraryHandler);
|
|
44
|
+
// Tool 6: List video formats
|
|
45
|
+
server.registerTool('youtube_list_formats', {
|
|
46
|
+
title: 'List Video Formats',
|
|
47
|
+
description: 'List available download formats for a YouTube video. Returns format IDs, resolutions, codecs, and file sizes.',
|
|
48
|
+
inputSchema: listFormatsSchema,
|
|
49
|
+
}, listFormatsHandler);
|
|
50
|
+
// Tool 7: Download video
|
|
51
|
+
server.registerTool('youtube_download_video', {
|
|
52
|
+
title: 'Download Video',
|
|
53
|
+
description: 'Download a YouTube video. Use quality parameter (best, 1080p, 720p, etc.) for automatic best format selection with fallbacks. Or use formatId for specific formats from youtube_list_formats.',
|
|
54
|
+
inputSchema: downloadVideoSchema,
|
|
55
|
+
}, downloadVideoHandler);
|
|
56
|
+
// Connect via stdio transport
|
|
57
|
+
async function main() {
|
|
58
|
+
const transport = new StdioServerTransport();
|
|
59
|
+
await server.connect(transport);
|
|
60
|
+
}
|
|
61
|
+
main().catch((error) => {
|
|
62
|
+
console.error('Failed to start MCP server:', error);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,6BAA6B;IACnC,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,gDAAgD;AAChD,MAAM,CAAC,YAAY,CACjB,sBAAsB,EACtB;IACE,KAAK,EAAE,sBAAsB;IAC7B,WAAW,EACT,kGAAkG;IACpG,WAAW,EAAE,iBAAiB;CAC/B,EACD,kBAAkB,CACnB,CAAC;AAEF,yBAAyB;AACzB,MAAM,CAAC,YAAY,CACjB,wBAAwB,EACxB;IACE,KAAK,EAAE,gBAAgB;IACvB,WAAW,EACT,sGAAsG;IACxG,WAAW,EAAE,kBAAkB;CAChC,EACD,mBAAmB,CACpB,CAAC;AAEF,yBAAyB;AACzB,MAAM,CAAC,YAAY,CACjB,wBAAwB,EACxB;IACE,KAAK,EAAE,sBAAsB;IAC7B,WAAW,EACT,qGAAqG;IACvG,WAAW,EAAE,mBAAmB;CACjC,EACD,oBAAoB,CACrB,CAAC;AAEF,0BAA0B;AAC1B,MAAM,CAAC,YAAY,CACjB,yBAAyB,EACzB;IACE,KAAK,EAAE,iBAAiB;IACxB,WAAW,EAAE,6EAA6E;IAC1F,WAAW,EAAE,mBAAmB;CACjC,EACD,oBAAoB,CACrB,CAAC;AAEF,uBAAuB;AACvB,MAAM,CAAC,YAAY,CACjB,sBAAsB,EACtB;IACE,KAAK,EAAE,cAAc;IACrB,WAAW,EACT,mFAAmF;IACrF,WAAW,EAAE,iBAAiB;CAC/B,EACD,kBAAkB,CACnB,CAAC;AAEF,6BAA6B;AAC7B,MAAM,CAAC,YAAY,CACjB,sBAAsB,EACtB;IACE,KAAK,EAAE,oBAAoB;IAC3B,WAAW,EACT,+GAA+G;IACjH,WAAW,EAAE,iBAAiB;CAC/B,EACD,kBAAkB,CACnB,CAAC;AAEF,yBAAyB;AACzB,MAAM,CAAC,YAAY,CACjB,wBAAwB,EACxB;IACE,KAAK,EAAE,gBAAgB;IACvB,WAAW,EACT,+LAA+L;IACjM,WAAW,EAAE,mBAAmB;CACjC,EACD,oBAAoB,CACrB,CAAC;AAEF,8BAA8B;AAC9B,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IAC9B,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;IACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { VideoQuality } from '../utils/youtube.js';
|
|
3
|
+
export declare const listFormatsSchema: {
|
|
4
|
+
video: z.ZodString;
|
|
5
|
+
};
|
|
6
|
+
export declare function listFormatsHandler({ video }: {
|
|
7
|
+
video: string;
|
|
8
|
+
}): Promise<{
|
|
9
|
+
content: {
|
|
10
|
+
type: "text";
|
|
11
|
+
text: string;
|
|
12
|
+
}[];
|
|
13
|
+
}>;
|
|
14
|
+
export declare const downloadVideoSchema: {
|
|
15
|
+
video: z.ZodString;
|
|
16
|
+
quality: z.ZodOptional<z.ZodEnum<["best", "2160p", "1440p", "1080p", "720p", "480p", "360p", "audio"]>>;
|
|
17
|
+
formatId: z.ZodOptional<z.ZodString>;
|
|
18
|
+
outputDir: z.ZodOptional<z.ZodString>;
|
|
19
|
+
};
|
|
20
|
+
export declare function downloadVideoHandler({ video, quality, formatId, outputDir, }: {
|
|
21
|
+
video: string;
|
|
22
|
+
quality?: VideoQuality;
|
|
23
|
+
formatId?: string;
|
|
24
|
+
outputDir?: string;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
content: {
|
|
27
|
+
type: "text";
|
|
28
|
+
text: string;
|
|
29
|
+
}[];
|
|
30
|
+
isError: boolean;
|
|
31
|
+
} | {
|
|
32
|
+
content: {
|
|
33
|
+
type: "text";
|
|
34
|
+
text: string;
|
|
35
|
+
}[];
|
|
36
|
+
isError?: undefined;
|
|
37
|
+
}>;
|
|
38
|
+
//# sourceMappingURL=download-video.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download-video.d.ts","sourceRoot":"","sources":["../../src/tools/download-video.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAA8B,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAG/E,eAAO,MAAM,iBAAiB;;CAE7B,CAAC;AASF,wBAAsB,kBAAkB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;;;;;GAmDpE;AAGD,eAAO,MAAM,mBAAmB;;;;;CAc/B,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,EACzC,KAAK,EACL,OAAO,EACP,QAAQ,EACR,SAAS,GACV,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;;;;;;;;;;;;GAyCA"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { listFormats, downloadVideo } from '../utils/youtube.js';
|
|
3
|
+
// Tool 1: List available formats
|
|
4
|
+
export const listFormatsSchema = {
|
|
5
|
+
video: z.string().describe('YouTube video ID or URL'),
|
|
6
|
+
};
|
|
7
|
+
function formatFilesize(bytes) {
|
|
8
|
+
if (!bytes)
|
|
9
|
+
return 'Unknown';
|
|
10
|
+
if (bytes < 1024 * 1024)
|
|
11
|
+
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
12
|
+
if (bytes < 1024 * 1024 * 1024)
|
|
13
|
+
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
14
|
+
return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
15
|
+
}
|
|
16
|
+
export async function listFormatsHandler({ video }) {
|
|
17
|
+
const formats = await listFormats(video);
|
|
18
|
+
const lines = [`${formats.length} formats available`, ''];
|
|
19
|
+
const combined = formats.filter((f) => f.vcodec !== 'none' && f.acodec !== 'none');
|
|
20
|
+
const videoOnly = formats.filter((f) => f.vcodec !== 'none' && f.acodec === 'none');
|
|
21
|
+
const audioOnly = formats.filter((f) => f.vcodec === 'none' && f.acodec !== 'none');
|
|
22
|
+
if (combined.length > 0) {
|
|
23
|
+
lines.push('video + audio:');
|
|
24
|
+
combined.forEach((f) => {
|
|
25
|
+
const fps = f.fps ? ` ${f.fps}fps` : '';
|
|
26
|
+
lines.push(` ${f.formatId} · ${f.ext} · ${f.resolution}${fps} · ${formatFilesize(f.filesize)}`);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (videoOnly.length > 0) {
|
|
30
|
+
lines.push('');
|
|
31
|
+
lines.push('video only:');
|
|
32
|
+
videoOnly.forEach((f) => {
|
|
33
|
+
const fps = f.fps ? ` ${f.fps}fps` : '';
|
|
34
|
+
lines.push(` ${f.formatId} · ${f.ext} · ${f.resolution}${fps} · ${formatFilesize(f.filesize)}`);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
if (audioOnly.length > 0) {
|
|
38
|
+
lines.push('');
|
|
39
|
+
lines.push('audio only:');
|
|
40
|
+
audioOnly.forEach((f) => {
|
|
41
|
+
lines.push(` ${f.formatId} · ${f.ext} · ${f.acodec} · ${formatFilesize(f.filesize)}`);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (combined.length === 0) {
|
|
45
|
+
lines.push('');
|
|
46
|
+
lines.push('tip: combine formats like "137+140" for video+audio');
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
content: [
|
|
50
|
+
{
|
|
51
|
+
type: 'text',
|
|
52
|
+
text: lines.join('\n'),
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// Tool 2: Download video with selected format
|
|
58
|
+
export const downloadVideoSchema = {
|
|
59
|
+
video: z.string().describe('YouTube video ID or URL'),
|
|
60
|
+
quality: z
|
|
61
|
+
.enum(['best', '2160p', '1440p', '1080p', '720p', '480p', '360p', 'audio'])
|
|
62
|
+
.optional()
|
|
63
|
+
.describe('Quality preset (recommended). Uses smart format selection with fallbacks. Options: best, 2160p, 1440p, 1080p, 720p, 480p, 360p, audio'),
|
|
64
|
+
formatId: z
|
|
65
|
+
.string()
|
|
66
|
+
.optional()
|
|
67
|
+
.describe('Advanced: Specific format code from list_formats (e.g., "22", "137+140"). Use quality instead for automatic best format selection.'),
|
|
68
|
+
outputDir: z
|
|
69
|
+
.string()
|
|
70
|
+
.optional()
|
|
71
|
+
.describe('Output directory (defaults to ~/.youtube-knowledge/downloads/)'),
|
|
72
|
+
};
|
|
73
|
+
export async function downloadVideoHandler({ video, quality, formatId, outputDir, }) {
|
|
74
|
+
// Validate: at least one of quality or formatId must be provided
|
|
75
|
+
if (!quality && !formatId) {
|
|
76
|
+
return {
|
|
77
|
+
content: [
|
|
78
|
+
{
|
|
79
|
+
type: 'text',
|
|
80
|
+
text: 'Error: Please provide either quality (recommended: "best", "1080p", etc.) or formatId',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
isError: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// If quality is provided, use it; otherwise use formatId
|
|
87
|
+
const result = await downloadVideo(video, formatId ?? 'best', // formatId is only used if quality is not provided
|
|
88
|
+
outputDir, quality);
|
|
89
|
+
const qualityLabel = quality ? `quality: ${quality}` : `format: ${result.format}`;
|
|
90
|
+
const lines = [
|
|
91
|
+
`✓ Downloaded`,
|
|
92
|
+
'',
|
|
93
|
+
result.title,
|
|
94
|
+
qualityLabel,
|
|
95
|
+
'',
|
|
96
|
+
result.filePath,
|
|
97
|
+
];
|
|
98
|
+
return {
|
|
99
|
+
content: [
|
|
100
|
+
{
|
|
101
|
+
type: 'text',
|
|
102
|
+
text: lines.join('\n'),
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=download-video.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"download-video.js","sourceRoot":"","sources":["../../src/tools/download-video.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAgB,MAAM,qBAAqB,CAAC;AAE/E,iCAAiC;AACjC,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;CACtD,CAAC;AAEF,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAChF,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AACzD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EAAE,KAAK,EAAqB;IACnE,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC;IAEzC,MAAM,KAAK,GAAa,CAAC,GAAG,OAAO,CAAC,MAAM,oBAAoB,EAAE,EAAE,CAAC,CAAC;IAEpE,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACnF,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACpF,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IAEpF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC7B,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACrB,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,UAAU,GAAG,GAAG,MAAM,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CACrF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1B,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACtB,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CACR,KAAK,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,UAAU,GAAG,GAAG,MAAM,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CACrF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1B,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACtB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,MAAM,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACzF,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;IACpE,CAAC;IAED,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;aACvB;SACF;KACF,CAAC;AACJ,CAAC;AAED,8CAA8C;AAC9C,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IACrD,OAAO,EAAE,CAAC;SACP,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;SAC1E,QAAQ,EAAE;SACV,QAAQ,CAAC,uIAAuI,CAAC;IACpJ,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,oIAAoI,CAAC;IACjJ,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,gEAAgE,CAAC;CAC9E,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,EACzC,KAAK,EACL,OAAO,EACP,QAAQ,EACR,SAAS,GAMV;IACC,iEAAiE;IACjE,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC1B,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,uFAAuF;iBAC9F;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,MAAM,MAAM,GAAG,MAAM,aAAa,CAChC,KAAK,EACL,QAAQ,IAAI,MAAM,EAAG,mDAAmD;IACxE,SAAS,EACT,OAAO,CACR,CAAC;IAEF,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,OAAO,EAAE,CAAC,CAAC,CAAC,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC;IAElF,MAAM,KAAK,GAAa;QACtB,cAAc;QACd,EAAE;QACF,MAAM,CAAC,KAAK;QACZ,YAAY;QACZ,EAAE;QACF,MAAM,CAAC,QAAQ;KAChB,CAAC;IAEF,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;aACvB;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const fetchVideosSchema: {
|
|
3
|
+
url: z.ZodString;
|
|
4
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
5
|
+
};
|
|
6
|
+
export declare function fetchVideosHandler({ url, limit }: {
|
|
7
|
+
url: string;
|
|
8
|
+
limit: number;
|
|
9
|
+
}): Promise<{
|
|
10
|
+
content: {
|
|
11
|
+
type: "text";
|
|
12
|
+
text: string;
|
|
13
|
+
}[];
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=fetch-videos.d.ts.map
|
|
@@ -0,0 +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;AAGxB,eAAO,MAAM,iBAAiB;;;CAG7B,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;;;;;GAoBtF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { listVideos } from '../utils/youtube.js';
|
|
3
|
+
export const fetchVideosSchema = {
|
|
4
|
+
url: z.string().describe('YouTube playlist or channel URL'),
|
|
5
|
+
limit: z.number().min(1).max(100).default(20).describe('Maximum number of videos to fetch'),
|
|
6
|
+
};
|
|
7
|
+
export async function fetchVideosHandler({ url, limit }) {
|
|
8
|
+
const videos = await listVideos(url, limit);
|
|
9
|
+
const lines = [`✓ Found ${videos.length} video${videos.length !== 1 ? 's' : ''}`, ''];
|
|
10
|
+
videos.forEach((v, i) => {
|
|
11
|
+
lines.push(`${i + 1}. ${v.title}`);
|
|
12
|
+
lines.push(` ${v.durationFormatted} · ${v.uploadDate || 'Unknown date'}`);
|
|
13
|
+
lines.push(` ${v.url}`);
|
|
14
|
+
lines.push('');
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: 'text',
|
|
20
|
+
text: lines.join('\n'),
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=fetch-videos.js.map
|
|
@@ -0,0 +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;AAEjD,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;IAC3D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,mCAAmC,CAAC;CAC5F,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAkC;IACrF,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;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;aACvB;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const getTranscriptSchema: {
|
|
3
|
+
video: z.ZodString;
|
|
4
|
+
language: z.ZodDefault<z.ZodString>;
|
|
5
|
+
};
|
|
6
|
+
export declare function getTranscriptHandler({ video, language, }: {
|
|
7
|
+
video: string;
|
|
8
|
+
language: string;
|
|
9
|
+
}): Promise<{
|
|
10
|
+
content: {
|
|
11
|
+
type: "text";
|
|
12
|
+
text: string;
|
|
13
|
+
}[];
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=get-transcript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-transcript.d.ts","sourceRoot":"","sources":["../../src/tools/get-transcript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,mBAAmB;;;CAG/B,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,EACzC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;;;;;GAoBA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getTranscript } from '../utils/youtube.js';
|
|
3
|
+
export const getTranscriptSchema = {
|
|
4
|
+
video: z.string().describe('YouTube video ID or URL'),
|
|
5
|
+
language: z.string().default('en').describe('Preferred language code (e.g., en, fr, es)'),
|
|
6
|
+
};
|
|
7
|
+
export async function getTranscriptHandler({ video, language, }) {
|
|
8
|
+
const result = await getTranscript(video, language);
|
|
9
|
+
const wordCount = result.transcript.split(/\s+/).length;
|
|
10
|
+
const lines = [
|
|
11
|
+
`Transcript (${result.language})`,
|
|
12
|
+
`${wordCount.toLocaleString()} words`,
|
|
13
|
+
'',
|
|
14
|
+
result.transcript,
|
|
15
|
+
];
|
|
16
|
+
return {
|
|
17
|
+
content: [
|
|
18
|
+
{
|
|
19
|
+
type: 'text',
|
|
20
|
+
text: lines.join('\n'),
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=get-transcript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-transcript.js","sourceRoot":"","sources":["../../src/tools/get-transcript.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IACrD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,4CAA4C,CAAC;CAC1F,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,EACzC,KAAK,EACL,QAAQ,GAIT;IACC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAEpD,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IAExD,MAAM,KAAK,GAAa;QACtB,eAAe,MAAM,CAAC,QAAQ,GAAG;QACjC,GAAG,SAAS,CAAC,cAAc,EAAE,QAAQ;QACrC,EAAE;QACF,MAAM,CAAC,UAAU;KAClB,CAAC;IAEF,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;aACvB;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const getVideoInfoSchema: {
|
|
3
|
+
video: z.ZodString;
|
|
4
|
+
};
|
|
5
|
+
export declare function getVideoInfoHandler({ video }: {
|
|
6
|
+
video: string;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
content: {
|
|
9
|
+
type: "text";
|
|
10
|
+
text: string;
|
|
11
|
+
}[];
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=get-video-info.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-video-info.d.ts","sourceRoot":"","sources":["../../src/tools/get-video-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,kBAAkB;;CAE9B,CAAC;AAEF,wBAAsB,mBAAmB,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE;;;;;GA6BrE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getVideoInfo } from '../utils/youtube.js';
|
|
3
|
+
export const getVideoInfoSchema = {
|
|
4
|
+
video: z.string().describe('YouTube video ID or URL'),
|
|
5
|
+
};
|
|
6
|
+
export async function getVideoInfoHandler({ video }) {
|
|
7
|
+
const info = await getVideoInfo(video);
|
|
8
|
+
const lines = [
|
|
9
|
+
info.title,
|
|
10
|
+
`by ${info.channel}`,
|
|
11
|
+
'',
|
|
12
|
+
`${info.durationFormatted} · ${info.uploadDate || 'Unknown date'}`,
|
|
13
|
+
info.url,
|
|
14
|
+
];
|
|
15
|
+
if (info.tags.length > 0) {
|
|
16
|
+
lines.push('');
|
|
17
|
+
lines.push(`tags: ${info.tags.join(', ')}`);
|
|
18
|
+
}
|
|
19
|
+
if (info.description) {
|
|
20
|
+
lines.push('');
|
|
21
|
+
lines.push(info.description);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
content: [
|
|
25
|
+
{
|
|
26
|
+
type: 'text',
|
|
27
|
+
text: lines.join('\n'),
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=get-video-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-video-info.js","sourceRoot":"","sources":["../../src/tools/get-video-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;CACtD,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,EAAE,KAAK,EAAqB;IACpE,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;IAEvC,MAAM,KAAK,GAAa;QACtB,IAAI,CAAC,KAAK;QACV,MAAM,IAAI,CAAC,OAAO,EAAE;QACpB,EAAE;QACF,GAAG,IAAI,CAAC,iBAAiB,MAAM,IAAI,CAAC,UAAU,IAAI,cAAc,EAAE;QAClE,IAAI,CAAC,GAAG;KACT,CAAC;IAEF,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;aACvB;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const listLibrarySchema: {
|
|
3
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
4
|
+
};
|
|
5
|
+
export declare function listLibraryHandler({ tag }: {
|
|
6
|
+
tag?: string;
|
|
7
|
+
}): Promise<{
|
|
8
|
+
content: {
|
|
9
|
+
type: "text";
|
|
10
|
+
text: string;
|
|
11
|
+
}[];
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=list-library.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-library.d.ts","sourceRoot":"","sources":["../../src/tools/list-library.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,iBAAiB;;CAE7B,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;GAuCjE"}
|