@thenavidm/youtube-mcp-cli 2.0.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.
- package/README.md +108 -38
- package/SKILL.md +6 -3
- package/dist/app.d.ts +9 -0
- package/dist/app.js +70 -0
- package/dist/app.js.map +1 -0
- package/dist/config.js +5 -4
- package/dist/config.js.map +1 -1
- package/dist/doctor.d.ts +13 -5
- package/dist/doctor.js +60 -59
- package/dist/doctor.js.map +1 -1
- package/dist/guide.d.ts +5 -0
- package/dist/guide.js +16 -0
- package/dist/guide.js.map +1 -0
- package/dist/index.d.ts +5 -9
- package/dist/index.js +9 -129
- package/dist/index.js.map +1 -1
- package/dist/npx.d.ts +2 -0
- package/dist/npx.js +14 -0
- package/dist/npx.js.map +1 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +1 -1
- package/dist/tools/account.js +4 -3
- package/dist/tools/account.js.map +1 -1
- package/dist/tools/kit.d.ts +20 -32
- package/dist/tools/kit.js +63 -56
- package/dist/tools/kit.js.map +1 -1
- package/dist/tools/research.js +4 -3
- package/dist/tools/research.js.map +1 -1
- package/dist/tools/transcripts.js +2 -1
- package/dist/tools/transcripts.js.map +1 -1
- package/dist/youtube/transcripts.d.ts +2 -2
- package/dist/youtube/transcripts.js +5 -3
- package/dist/youtube/transcripts.js.map +1 -1
- package/dist/youtube/ytdlp.js +3 -1
- package/dist/youtube/ytdlp.js.map +1 -1
- package/package.json +11 -7
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<img src="https://cdn.navid.
|
|
1
|
+
<img src="https://cdn.navid.me/connectors/youtube-icon.png" alt="YouTube" width="88">
|
|
2
2
|
|
|
3
3
|
# YouTube MCP Server & CLI
|
|
4
4
|
|
|
@@ -18,7 +18,7 @@ does not return.
|
|
|
18
18
|
|
|
19
19
|
Connect as many channels as you run, with one login each and no config file.
|
|
20
20
|
|
|
21
|
-
Built and maintained by [Navid Moazzez](https://navid.me?utm_source=github&utm_medium=
|
|
21
|
+
Built and maintained by [Navid Moazzez](https://navid.me?utm_source=github&utm_medium=referral&utm_campaign=youtube-mcp-cli&utm_content=readme). Built on [Slipway](https://github.com/thenavidm/slipway), which turns one definition of each tool into the MCP server and the CLI.
|
|
22
22
|
|
|
23
23
|
```
|
|
24
24
|
You: what does this video actually say about pricing?
|
|
@@ -59,7 +59,7 @@ errors are JSON on stderr whichever output you pick.
|
|
|
59
59
|
receives for that tool, which is how you can check the two surfaces really are
|
|
60
60
|
one thing.
|
|
61
61
|
|
|
62
|
-
### MCP server, for AI
|
|
62
|
+
### MCP server, for your AI app
|
|
63
63
|
|
|
64
64
|
`youtube-mcp` is what Claude Code, Claude Desktop, Cursor and the rest launch.
|
|
65
65
|
You never run it by hand:
|
|
@@ -70,6 +70,9 @@ claude mcp add youtube -- npx -y @thenavidm/youtube-mcp-cli@latest
|
|
|
70
70
|
|
|
71
71
|
Then just ask: _"which of this channel's last 30 videos actually overperformed?"_
|
|
72
72
|
|
|
73
|
+
Replying to a comment and deleting a video wait for your approval in the client,
|
|
74
|
+
as [section 9](#9-writing-safely-) explains.
|
|
75
|
+
|
|
73
76
|
Channels you connected with `youtube-cli login` on this machine are read
|
|
74
77
|
automatically, so the command needs no credentials. Every other client is in
|
|
75
78
|
[section 4](#4-connect-your-client-).
|
|
@@ -85,7 +88,24 @@ automatically, so the command needs no credentials. Every other client is in
|
|
|
85
88
|
They are the same program reading the same tool definitions, so anything one
|
|
86
89
|
can do, the other can.
|
|
87
90
|
|
|
88
|
-
##
|
|
91
|
+
## Features
|
|
92
|
+
|
|
93
|
+
Every tool is both a command and an MCP tool, with the same name. The command
|
|
94
|
+
is the tool name with dashes.
|
|
95
|
+
|
|
96
|
+
| Capability | CLI command | MCP tool |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| Transcripts of any public video, no credentials | `youtube-cli get-transcript` / `get-transcripts` / `search-transcript` / `list-transcript-languages` | `get_transcript` / `get_transcripts` / `search_transcript` / `list_transcript_languages` |
|
|
99
|
+
| Research any channel or video | `youtube-cli search-videos` / `get-channel` / `analyze-channel` / `get-video` | `search_videos` / `get_channel` / `analyze_channel` / `get_video` |
|
|
100
|
+
| Your channels and their numbers | `youtube-cli list-accounts` / `get-my-channel` / `get-channel-analytics` / `list-my-videos` | `list_accounts` / `get_my_channel` / `get_channel_analytics` / `list_my_videos` |
|
|
101
|
+
| Comments | `youtube-cli list-comments` / `reply-to-comment` | `list_comments` / `reply_to_comment` |
|
|
102
|
+
| Edit or delete your videos | `youtube-cli update-video` / `delete-video` | `update_video` / `delete_video` |
|
|
103
|
+
| Connect a channel or an API key | `youtube-cli login` / `logout` | not tools |
|
|
104
|
+
| Check your setup | `youtube-cli doctor` | not a tool |
|
|
105
|
+
|
|
106
|
+
All 16 are in [section 7](#7-tools-).
|
|
107
|
+
|
|
108
|
+
## Contents
|
|
89
109
|
|
|
90
110
|
| # | Section | What is in it |
|
|
91
111
|
|---|---|---|
|
|
@@ -211,8 +231,9 @@ A browser opens, you pick the channel, and it is saved. **Run `youtube-cli
|
|
|
211
231
|
login` once per channel.** Then `youtube-cli list-accounts` shows them all.
|
|
212
232
|
[Section 10](#10-several-channels-) covers using several.
|
|
213
233
|
|
|
214
|
-
You do not need Google to verify the app
|
|
215
|
-
|
|
234
|
+
You do not need Google to verify the app, but do click **Publish app** under
|
|
235
|
+
**Audience**. An app left in testing issues refresh tokens that expire after
|
|
236
|
+
seven days, so login would stop working every week.
|
|
216
237
|
|
|
217
238
|
## 4. Connect your client 🔌
|
|
218
239
|
|
|
@@ -405,12 +426,12 @@ not: check the client before reconnecting anything.
|
|
|
405
426
|
Both surfaces are the same program with the same 16 tools. The
|
|
406
427
|
difference is when the model pays for them. Measured in Claude Code:
|
|
407
428
|
|
|
408
|
-
| | MCP server | CLI |
|
|
429
|
+
| Cost | MCP server | CLI |
|
|
409
430
|
|---|---|---|
|
|
410
|
-
| Every message, with every tool loaded |
|
|
431
|
+
| Every message, with every tool loaded | 4,500 tokens | nothing |
|
|
411
432
|
| Every message, Claude Code's default | 490 tokens | nothing |
|
|
412
|
-
| When YouTube comes up | nothing more, or the tools it picks | 2,
|
|
413
|
-
| 20 messages with YouTube in 1, every tool loaded |
|
|
433
|
+
| When YouTube comes up | nothing more, or the tools it picks | 2,350 tokens for `SKILL.md`, once |
|
|
434
|
+
| 20 messages with YouTube in 1, every tool loaded | 90,000 tokens | 2,350 tokens |
|
|
414
435
|
|
|
415
436
|
Claude Code's [tool search](https://code.claude.com/docs/en/mcp#scale-with-mcp-tool-search)
|
|
416
437
|
is on by default: it sends only the tool names and the server instructions,
|
|
@@ -423,12 +444,26 @@ To spend less, turn the server off when you are not using it, which in Claude
|
|
|
423
444
|
Code is the `/mcp` panel. `YOUTUBE_READ_ONLY=1` takes the 3 write tools off the list, leaving 13.
|
|
424
445
|
Or install the CLI and add the server on the days it earns its place.
|
|
425
446
|
|
|
426
|
-
Measured on 2026-
|
|
447
|
+
Measured on 2026-10-05 with Claude Code 2.1.286 on Claude Opus 5.5: one
|
|
427
448
|
short prompt with and without the server connected, once with
|
|
428
449
|
`ENABLE_TOOL_SEARCH=false` and once with the default, the difference read
|
|
429
450
|
from the API's own usage figures. `SKILL.md` was measured the same way. Other
|
|
430
451
|
apps and models count tokens a little differently.
|
|
431
452
|
|
|
453
|
+
Against 2.0.0, measured the same day: every tool loaded costs 4,458 tokens
|
|
454
|
+
instead of 4,984, tool search 489 instead of 493, and `SKILL.md` 93 more,
|
|
455
|
+
because it now says how approval works over MCP and lists every exit code. In
|
|
456
|
+
Codex 0.159.3 on gpt-6.1-sol, the same task, "find the command that scores a
|
|
457
|
+
channel's recent videos against that channel's own median, and the flags it
|
|
458
|
+
requires", read a median of 83,295 input tokens on 3.0.0 against 83,565 on
|
|
459
|
+
2.0.0 over the CLI, five runs each: Codex now asks `which` instead of reading
|
|
460
|
+
the full command list, and the general help is shorter. Over MCP, Codex prints
|
|
461
|
+
the tool list with a script and answers from that printout, 6,133 tokens on
|
|
462
|
+
3.0.0 against 6,126; the 7 more are the description of `confirm` on the two
|
|
463
|
+
irreversible tools. The input totals, a median of 45,053 against 44,924, also
|
|
464
|
+
carry the model's reasoning into its second request, which three of the five
|
|
465
|
+
2.0.0 runs skipped; the two that kept it read 45,065 and 45,074.
|
|
466
|
+
|
|
432
467
|
## 7. Tools 🛠️
|
|
433
468
|
|
|
434
469
|
Every tool is also a command: the tool name with dashes. `*` marks a write, `!`
|
|
@@ -499,21 +534,26 @@ Everything a script needs to branch on.
|
|
|
499
534
|
| `--select a,b.c` | only the named fields of a JSON result, dotted paths descend |
|
|
500
535
|
|
|
501
536
|
Results go to stdout. Errors go to stderr, always as JSON, so one parse handles
|
|
502
|
-
both outcomes
|
|
537
|
+
both outcomes. `code` names the kind of failure, and `hint` and `details`, such
|
|
538
|
+
as Google's own reason, come along when there is one:
|
|
503
539
|
|
|
504
540
|
```json
|
|
505
|
-
{
|
|
541
|
+
{
|
|
542
|
+
"error": "No API key is configured. Run `youtube-cli login --api-key KEY` or set YOUTUBE_API_KEY for public data, or `youtube-cli login` for your own channels.",
|
|
543
|
+
"code": "not_configured"
|
|
544
|
+
}
|
|
506
545
|
```
|
|
507
546
|
|
|
508
547
|
| Code | Means |
|
|
509
548
|
|---|---|
|
|
510
549
|
| `0` | it worked |
|
|
511
|
-
| `
|
|
550
|
+
| `1` | an unexpected error |
|
|
551
|
+
| `2` | you typed it wrong, an unknown command, a write hidden by `YOUTUBE_READ_ONLY`, or a guarded write refused for want of `--confirm` |
|
|
512
552
|
| `3` | not found |
|
|
513
553
|
| `4` | authentication failed: reconnect the channel |
|
|
514
554
|
| `5` | an API error upstream |
|
|
515
555
|
| `7` | rate limited or out of quota: wait |
|
|
516
|
-
| `10` | nothing configured: run `youtube-cli login` or `login --api-key
|
|
556
|
+
| `10` | nothing configured: run `youtube-cli login` or `login --api-key`, or install yt-dlp for transcripts |
|
|
517
557
|
|
|
518
558
|
So a script can tell a mistake it should fix from a failure it should retry:
|
|
519
559
|
|
|
@@ -533,19 +573,27 @@ Writes work by default, because managing a channel is the point.
|
|
|
533
573
|
|
|
534
574
|
Two tools are guarded: `reply_to_comment`, because it is public the moment it
|
|
535
575
|
lands and notifies someone, and `delete_video`, because YouTube removes a video
|
|
536
|
-
immediately with no trash and no undo. Both
|
|
537
|
-
|
|
538
|
-
|
|
576
|
+
immediately with no trash and no undo. Both wait for your approval. The CLI goes
|
|
577
|
+
through the same guard as the server, so the rules are identical.
|
|
578
|
+
|
|
579
|
+
Over MCP a person approves each of the two where the client can ask: Claude Code
|
|
580
|
+
(2.1.246 and later) shows its own prompt, and a client that can show forms asks
|
|
581
|
+
with an approval form whose one box starts unticked. Each approval is signed,
|
|
582
|
+
bound to that exact call and works once. Where a client can do neither, the
|
|
583
|
+
model's `confirm: true` counts, and it should pass it only when you asked for
|
|
584
|
+
that exact reply or delete. `YOUTUBE_CONFIRM=model` makes `confirm: true` enough
|
|
585
|
+
everywhere, for an agent with no person to ask. In a terminal it is `--confirm`,
|
|
586
|
+
which `--agent` never adds.
|
|
539
587
|
|
|
540
588
|
`update_video` is not guarded. A title is one keystroke to put back, and asking
|
|
541
|
-
to
|
|
542
|
-
which is worse protection than not asking.
|
|
589
|
+
to approve reversible things teaches people and models to approve everything
|
|
590
|
+
reflexively, which is worse protection than not asking.
|
|
543
591
|
|
|
544
592
|
| Setting | Effect |
|
|
545
593
|
|---|---|
|
|
546
594
|
| `YOUTUBE_READ_ONLY=1` | Every write disappears from the tool list and the command list |
|
|
547
595
|
| `YOUTUBE_ALLOW_DESTRUCTIVE=0` | `update_video` stays, the two irreversible tools are blocked |
|
|
548
|
-
| `YOUTUBE_AUDIT_LOG=<path>` | One JSON line per attempted write, allowed and blocked alike |
|
|
596
|
+
| `YOUTUBE_AUDIT_LOG=<path>` | One JSON line per attempted write, allowed and blocked alike, and who approved it |
|
|
549
597
|
|
|
550
598
|
Comments, titles, descriptions and transcripts are written by other people. The
|
|
551
599
|
tool descriptions and the shipped `SKILL.md` tell the model to treat them as
|
|
@@ -670,6 +718,11 @@ are in its output.
|
|
|
670
718
|
| A command refuses and lists your channels | Two or more are connected. Pass `--account` |
|
|
671
719
|
| Every write command has vanished | `YOUTUBE_READ_ONLY=1` is set |
|
|
672
720
|
| Server missing in Claude Desktop | Use the absolute path to `npx`, check the JSON, and fully quit the app |
|
|
721
|
+
| "will not run without --confirm" | Working as intended: a reply is public and a delete is permanent. See [section 9](#9-writing-safely-) |
|
|
722
|
+
| `claude -p` will not reply or delete | Headless Claude Code refuses tools that need a person. Give that agent `YOUTUBE_CONFIRM=model` |
|
|
723
|
+
| No approval form appears | The client cannot show forms, so the model's `confirm: true` counts, and only for an action you asked for |
|
|
724
|
+
| YouTube asks yt-dlp to prove it is not a bot | Set `YOUTUBE_YTDLP_COOKIES` to a cookies.txt exported from a browser signed in to YouTube |
|
|
725
|
+
| A piped request gets no answer | Stdin closed before the answer. The MCP stdio binding stops a server when its input ends; keep stdin open until you read the answer, or use the CLI |
|
|
673
726
|
|
|
674
727
|
## Environment variables
|
|
675
728
|
|
|
@@ -696,7 +749,8 @@ you ran `youtube-cli login`.
|
|
|
696
749
|
|---|---|---|
|
|
697
750
|
| `YOUTUBE_READ_ONLY` | `0` | `1` hides every write |
|
|
698
751
|
| `YOUTUBE_ALLOW_DESTRUCTIVE` | `1` | `0` blocks the two irreversible tools |
|
|
699
|
-
| `YOUTUBE_AUDIT_LOG` | none | Append-only log of every attempted write |
|
|
752
|
+
| `YOUTUBE_AUDIT_LOG` | none | Append-only log of every attempted write, and who approved it |
|
|
753
|
+
| `YOUTUBE_CONFIRM` | `human` | `model` lets `confirm: true` alone approve over MCP, for an agent with no person to ask |
|
|
700
754
|
|
|
701
755
|
**Tuning**
|
|
702
756
|
|
|
@@ -705,11 +759,16 @@ you ran `youtube-cli login`.
|
|
|
705
759
|
| `YOUTUBE_REQUEST_TIMEOUT_MS` | `30000` | Per-request deadline |
|
|
706
760
|
| `YOUTUBE_TRANSCRIPT_LANG` | `en` | Default transcript language |
|
|
707
761
|
| `YOUTUBE_YTDLP_PATH` | `yt-dlp` on PATH | Where yt-dlp is |
|
|
762
|
+
| `YOUTUBE_YTDLP_COOKIES` | none | A cookies.txt from a browser signed in to YouTube, for when YouTube asks yt-dlp to prove it is not a bot |
|
|
708
763
|
| `YOUTUBE_MCP_HOME` | `~/.youtube-mcp-cli` | Where `login` saves channels |
|
|
709
764
|
| `YOUTUBE_OAUTH_PORT` | `8765` | The localhost port `login` listens on |
|
|
710
765
|
| `YOUTUBE_HTTP_PORT` | `8787` | For `--http` |
|
|
711
766
|
| `YOUTUBE_HTTP_HOST` | `127.0.0.1` | For `--http` |
|
|
712
|
-
| `YOUTUBE_HTTP_TOKEN` | none | Bearer token
|
|
767
|
+
| `YOUTUBE_HTTP_TOKEN` | none | Bearer token for `--http`. Any address but localhost refuses to start without one |
|
|
768
|
+
| `YOUTUBE_HTTP_ALLOWED_ORIGINS` | none | Comma-separated browser origins allowed to connect; a page from any other site is refused |
|
|
769
|
+
| `YOUTUBE_SURFACE` | `full` | `search` lists three tools that find, describe and run the rest |
|
|
770
|
+
| `YOUTUBE_TOOL_TIMEOUT_MS` | none | Give up on any tool after this long |
|
|
771
|
+
| `YOUTUBE_DEBUG` | `0` | `1` prints debug lines on stderr |
|
|
713
772
|
|
|
714
773
|
## Versions
|
|
715
774
|
|
|
@@ -790,10 +849,11 @@ afternoon by hand.
|
|
|
790
849
|
<details>
|
|
791
850
|
<summary><b>Can it delete one of my videos by accident?</b></summary>
|
|
792
851
|
|
|
793
|
-
It cannot delete anything without
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
852
|
+
It cannot delete anything without your approval: Claude Code shows its own
|
|
853
|
+
prompt for each delete, a client that can show forms asks with one, and
|
|
854
|
+
elsewhere the model has to pass `confirm: true` deliberately after reading a
|
|
855
|
+
description saying the action is permanent. If you want the possibility gone
|
|
856
|
+
entirely, set `YOUTUBE_READ_ONLY=1` and every write disappears.
|
|
797
857
|
|
|
798
858
|
</details>
|
|
799
859
|
|
|
@@ -823,6 +883,16 @@ the app to stop that, or run `youtube-cli login` again when it happens.
|
|
|
823
883
|
|
|
824
884
|
</details>
|
|
825
885
|
|
|
886
|
+
<details>
|
|
887
|
+
<summary><b>Can it reply to a comment without me asking?</b></summary>
|
|
888
|
+
|
|
889
|
+
It replies when you ask it to. A reply is public the moment it lands and
|
|
890
|
+
notifies the person you replied to, so each one waits for your approval in the
|
|
891
|
+
client, as a delete does. `YOUTUBE_READ_ONLY=1` removes replying, editing and
|
|
892
|
+
deleting from the list entirely.
|
|
893
|
+
|
|
894
|
+
</details>
|
|
895
|
+
|
|
826
896
|
<details>
|
|
827
897
|
<summary><b>How do I disconnect it?</b></summary>
|
|
828
898
|
|
|
@@ -833,19 +903,19 @@ the Cloud project removes the API key and the OAuth client together.
|
|
|
833
903
|
|
|
834
904
|
</details>
|
|
835
905
|
|
|
836
|
-
## Questions
|
|
906
|
+
## Questions
|
|
837
907
|
|
|
838
908
|
Run into a problem or have a question? [Open an issue](https://github.com/thenavidm/youtube-mcp-cli/issues) and I will help.
|
|
839
909
|
|
|
840
|
-
## About the author
|
|
910
|
+
## About the author
|
|
841
911
|
|
|
842
|
-
Navid Moazzez is a leading AI business strategist, and the host of the AI Creator Summit, watched by 100,000+ creators. He helps creators and founders master AI and build their own AI Operating System (AI OS) to automate their business and life.
|
|
912
|
+
Navid Moazzez is a leading AI business strategist, and the host of the AI Creator Summit, watched by 100,000+ creators. He helps creators and founders master AI and build their own AI Operating System (AI OS) to automate their business and life. He creates useful free tools, MCP servers and CLIs that creators and founders can use in their own workflows.
|
|
843
913
|
|
|
844
914
|
**Links**
|
|
845
915
|
|
|
846
|
-
- Personal website: [navid.me](https://navid.me?utm_source=github&utm_medium=
|
|
847
|
-
- Link in bio: [navid.bio](https://navid.bio?utm_source=github&utm_medium=
|
|
848
|
-
- Navid Media: [navid.media](https://navid.media?utm_source=github&utm_medium=
|
|
916
|
+
- Personal website: [navid.me](https://navid.me?utm_source=github&utm_medium=referral&utm_campaign=youtube-mcp-cli&utm_content=readme)
|
|
917
|
+
- Link in bio: [navid.bio](https://navid.bio?utm_source=github&utm_medium=referral&utm_campaign=youtube-mcp-cli&utm_content=readme)
|
|
918
|
+
- Navid Media: [navid.media](https://navid.media?utm_source=github&utm_medium=referral&utm_campaign=youtube-mcp-cli&utm_content=readme)
|
|
849
919
|
- YouTube: [@thenavidm](https://youtube.com/@thenavidm?sub_confirmation=1) and [@thenavidai](https://youtube.com/@thenavidai?sub_confirmation=1)
|
|
850
920
|
- X: [@thenavidm](https://x.com/thenavidm)
|
|
851
921
|
- Instagram: [@thenavidm](https://instagram.com/thenavidm)
|
|
@@ -853,19 +923,19 @@ Navid Moazzez is a leading AI business strategist, and the host of the AI Creato
|
|
|
853
923
|
|
|
854
924
|
If this is useful, star the repo and come say hi on [X](https://x.com/thenavidm).
|
|
855
925
|
|
|
856
|
-
## Dependencies
|
|
926
|
+
## Dependencies
|
|
857
927
|
|
|
858
928
|
| Library | License | What it does |
|
|
859
929
|
|---|---|---|
|
|
860
|
-
| [
|
|
930
|
+
| [Slipway](https://github.com/thenavidm/slipway) | Apache-2.0 | The MCP server and the CLI from one definition of each tool, with the write guard |
|
|
931
|
+
| [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) | Apache-2.0 | The MCP protocol and transports, through Slipway |
|
|
861
932
|
| [zod](https://github.com/colinhacks/zod) | MIT | Tool argument schemas and validation |
|
|
862
|
-
| [zod-to-json-schema](https://github.com/StefanTerdell/zod-to-json-schema) | ISC | Turns those schemas into what an MCP client receives |
|
|
863
933
|
|
|
864
934
|
[yt-dlp](https://github.com/yt-dlp/yt-dlp) is an optional external command, used
|
|
865
935
|
only to fetch caption tracks. It is not bundled and is never loaded into this
|
|
866
936
|
process.
|
|
867
937
|
|
|
868
|
-
## License
|
|
938
|
+
## License
|
|
869
939
|
|
|
870
940
|
[MIT](./LICENSE). Free to use, modify, and share.
|
|
871
941
|
|
|
@@ -874,4 +944,4 @@ trademark of Google LLC.
|
|
|
874
944
|
|
|
875
945
|
---
|
|
876
946
|
|
|
877
|
-
© 2026 [
|
|
947
|
+
© 2026 [Navid Media](https://navid.media?utm_source=github&utm_medium=referral&utm_campaign=youtube-mcp-cli&utm_content=readme). Made with ❤️ by [Navid Moazzez](https://navid.me?utm_source=github&utm_medium=referral&utm_campaign=youtube-mcp-cli&utm_content=readme).
|
package/SKILL.md
CHANGED
|
@@ -52,7 +52,7 @@ The CLI describes itself, so nothing here needs to list 16 tools and go stale:
|
|
|
52
52
|
```bash
|
|
53
53
|
youtube-cli # every command, one line each, writes marked
|
|
54
54
|
youtube-cli <command> --help # arguments, types, which are required
|
|
55
|
-
youtube-cli
|
|
55
|
+
youtube-cli which <words> # the command for a task, without the full list
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
The command is the tool name with dashes: `list_comments` runs as
|
|
@@ -111,7 +111,8 @@ user.
|
|
|
111
111
|
| Code | Meaning |
|
|
112
112
|
|---|---|
|
|
113
113
|
| 0 | Success |
|
|
114
|
-
|
|
|
114
|
+
| 1 | Unexpected error |
|
|
115
|
+
| 2 | Usage error: wrong or missing arguments, an unknown command, a write hidden by `YOUTUBE_READ_ONLY=1`, or a write refused for want of `--confirm` |
|
|
115
116
|
| 3 | Not found |
|
|
116
117
|
| 4 | Authentication failed, reconnect the channel |
|
|
117
118
|
| 5 | API error upstream |
|
|
@@ -132,7 +133,9 @@ specific thing.
|
|
|
132
133
|
**`--confirm` is enforced, not advisory.** `reply-to-comment` is public the
|
|
133
134
|
moment it lands and notifies the person. `delete-video` is final: no trash, and
|
|
134
135
|
the views, comments and URL go with it. Both refuse without `--confirm`. Pass it
|
|
135
|
-
when the user has actually asked, never to get past the refusal.
|
|
136
|
+
when the user has actually asked, never to get past the refusal. Over MCP the
|
|
137
|
+
person approves each in the client's own prompt or form; `confirm: true` counts
|
|
138
|
+
only where the client cannot ask.
|
|
136
139
|
|
|
137
140
|
`update-video` is not guarded, because a title is a keystroke to put back. Only
|
|
138
141
|
the fields you pass change.
|
package/dist/app.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The YouTube app: everything Slipway needs to ship the MCP server and the CLI.
|
|
3
|
+
*
|
|
4
|
+
* This file only describes. It never starts anything, so `slipway check` and
|
|
5
|
+
* tests can import it; `index.ts` is what runs.
|
|
6
|
+
*/
|
|
7
|
+
import { type ToolContext } from "./tools/kit.js";
|
|
8
|
+
export declare const VERSION: string;
|
|
9
|
+
export declare const app: import("@thenavidm/slipway").App<ToolContext>;
|
package/dist/app.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The YouTube app: everything Slipway needs to ship the MCP server and the CLI.
|
|
3
|
+
*
|
|
4
|
+
* This file only describes. It never starts anything, so `slipway check` and
|
|
5
|
+
* tests can import it; `index.ts` is what runs.
|
|
6
|
+
*/
|
|
7
|
+
import { createRequire } from "node:module";
|
|
8
|
+
import { slipway } from "@thenavidm/slipway";
|
|
9
|
+
import { loadConfig } from "./config.js";
|
|
10
|
+
import { doctor } from "./doctor.js";
|
|
11
|
+
import { INSTRUCTIONS } from "./guide.js";
|
|
12
|
+
import { ALL_TOOLS } from "./tools/index.js";
|
|
13
|
+
import { makeContext } from "./tools/kit.js";
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
export const VERSION = require("../package.json").version;
|
|
16
|
+
const signIn = async (_io, args) => {
|
|
17
|
+
const { login } = await import("./auth.js");
|
|
18
|
+
return login([...args]);
|
|
19
|
+
};
|
|
20
|
+
export const app = slipway({
|
|
21
|
+
name: "youtube",
|
|
22
|
+
title: "YouTube",
|
|
23
|
+
version: VERSION,
|
|
24
|
+
package: "@thenavidm/youtube-mcp-cli",
|
|
25
|
+
description: "YouTube transcripts for any public video, channel research, and your own channels' videos, comments and analytics",
|
|
26
|
+
instructions: INSTRUCTIONS,
|
|
27
|
+
// Transcripts need no credentials, so nothing here is required before the first call.
|
|
28
|
+
context: () => makeContext(loadConfig()),
|
|
29
|
+
secrets: ({ config }) => [config.apiKey, ...config.accounts.flatMap((account) => [account.refreshToken, account.accessToken])],
|
|
30
|
+
tools: ALL_TOOLS,
|
|
31
|
+
doctor,
|
|
32
|
+
// yt-dlp, the API key and every channel's token each fail differently, and only a request tells, so doctor makes one per source every time, as 2.0 did.
|
|
33
|
+
doctorNetwork: true,
|
|
34
|
+
login: {
|
|
35
|
+
usage: "login [--api-key KEY]",
|
|
36
|
+
help: "connect a channel, once per channel; --api-key saves a research key",
|
|
37
|
+
run: signIn,
|
|
38
|
+
},
|
|
39
|
+
commands: [
|
|
40
|
+
{ name: "auth", usage: "auth [--api-key KEY]", help: "the same as login, by the name 1.x used", hidden: true, run: signIn },
|
|
41
|
+
{
|
|
42
|
+
name: "logout",
|
|
43
|
+
usage: "logout <channel> | logout --api-key",
|
|
44
|
+
help: "forget a saved channel, or the saved API key",
|
|
45
|
+
run: async (_io, args) => {
|
|
46
|
+
const { logout } = await import("./auth.js");
|
|
47
|
+
return logout([...args]);
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
settings: [
|
|
52
|
+
{ env: "YOUTUBE_API_KEY", description: "Public search and channel lookup, or `login --api-key`.", secret: true },
|
|
53
|
+
{ env: "YOUTUBE_ACCOUNTS", description: "Several channels at once, as a JSON array.", secret: true },
|
|
54
|
+
{ env: "YOUTUBE_REFRESH_TOKEN", description: "One channel.", secret: true },
|
|
55
|
+
{ env: "YOUTUBE_ACCESS_TOKEN", description: "One channel, short-lived, for testing.", secret: true, tuning: true },
|
|
56
|
+
{ env: "YOUTUBE_CHANNEL_NAME", description: "What to call that one channel. Defaults to default.", tuning: true },
|
|
57
|
+
{ env: "YOUTUBE_CLIENT_ID", description: "Your OAuth client, which `login` needs." },
|
|
58
|
+
{ env: "YOUTUBE_CLIENT_SECRET", description: "Its secret.", secret: true },
|
|
59
|
+
{ env: "YOUTUBE_MCP_HOME", description: "Where `login` saves channels. Defaults to ~/.youtube-mcp-cli.", tuning: true },
|
|
60
|
+
{ env: "YOUTUBE_TRANSCRIPT_LANG", description: "Default transcript language. Defaults to en.", tuning: true },
|
|
61
|
+
{ env: "YOUTUBE_YTDLP_PATH", description: "Path to yt-dlp, if it is not on PATH.", tuning: true },
|
|
62
|
+
{ env: "YOUTUBE_YTDLP_COOKIES", description: "A cookies.txt from a browser signed in to YouTube, for the bot check.", secret: true },
|
|
63
|
+
{ env: "YOUTUBE_OAUTH_CLIENT_ID", description: "Another name for YOUTUBE_CLIENT_ID.", tuning: true },
|
|
64
|
+
{ env: "YOUTUBE_OAUTH_CLIENT_SECRET", description: "Another name for YOUTUBE_CLIENT_SECRET.", secret: true, tuning: true },
|
|
65
|
+
{ env: "YOUTUBE_OAUTH_PORT", description: "The localhost port `login` listens on. Defaults to 8765.", tuning: true },
|
|
66
|
+
{ env: "YOUTUBE_REQUEST_TIMEOUT_MS", description: "Per-request deadline. Defaults to 30000.", tuning: true },
|
|
67
|
+
],
|
|
68
|
+
links: { repository: "https://github.com/thenavidm/youtube-mcp-cli" },
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=app.js.map
|
package/dist/app.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* by `youtube-cli login --api-key`. Transcripts need none of these.
|
|
13
13
|
*/
|
|
14
14
|
import { loadStore } from "./accounts/store.js";
|
|
15
|
+
import { NotConfiguredError, UsageError } from "@thenavidm/slipway";
|
|
15
16
|
function bool(value, fallback) {
|
|
16
17
|
if (value === undefined || value.trim() === "")
|
|
17
18
|
return fallback;
|
|
@@ -56,11 +57,11 @@ function envAccounts() {
|
|
|
56
57
|
parsed = JSON.parse(raw);
|
|
57
58
|
}
|
|
58
59
|
catch {
|
|
59
|
-
throw new
|
|
60
|
+
throw new NotConfiguredError("YOUTUBE_ACCOUNTS is not valid JSON. It should be an array like " +
|
|
60
61
|
'[{"name":"Main","refresh_token":"1//..."}].');
|
|
61
62
|
}
|
|
62
63
|
if (!Array.isArray(parsed))
|
|
63
|
-
throw new
|
|
64
|
+
throw new NotConfiguredError("YOUTUBE_ACCOUNTS must be a JSON array.");
|
|
64
65
|
return parsed.map((entry, i) => {
|
|
65
66
|
const a = entry;
|
|
66
67
|
const name = a.name ?? a.account_name ?? a.channel ?? `account-${i + 1}`;
|
|
@@ -118,12 +119,12 @@ export function resolveAccount(config, requested) {
|
|
|
118
119
|
const match = accounts.find((a) => a.id === want || a.name.toLowerCase() === want) ??
|
|
119
120
|
accounts.find((a) => a.name.toLowerCase().includes(want) || a.id.includes(want));
|
|
120
121
|
if (!match) {
|
|
121
|
-
throw new
|
|
122
|
+
throw new UsageError(`No connected channel matches "${requested}". Connected: ${accounts.map((a) => a.name).join(", ")}. Call list_accounts to see them.`);
|
|
122
123
|
}
|
|
123
124
|
return match;
|
|
124
125
|
}
|
|
125
126
|
if (accounts.length > 1) {
|
|
126
|
-
throw new
|
|
127
|
+
throw new UsageError(`${accounts.length} channels are connected (${accounts.map((a) => a.name).join(", ")}). Pass account=<name or @handle> so this runs against the right one.`);
|
|
127
128
|
}
|
|
128
129
|
return accounts[0];
|
|
129
130
|
}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,SAAS,EAAc,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/doctor.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `youtube-cli doctor`:
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* `youtube-cli doctor`: check each of the three things this server can reach,
|
|
3
|
+
* the way it would reach them.
|
|
4
|
+
*
|
|
5
|
+
* Transcripts need yt-dlp and nothing else, research needs an API key, and a
|
|
6
|
+
* connected channel needs a refresh token that still works. Each fails for a
|
|
7
|
+
* different reason with a different fix, so each is checked on its own, with a
|
|
8
|
+
* real request, as 2.0 did. Slipway runs this on every `doctor`, after its own
|
|
9
|
+
* checks.
|
|
6
10
|
*/
|
|
7
|
-
|
|
11
|
+
import type { DoctorCheck } from "@thenavidm/slipway";
|
|
12
|
+
import type { ToolContext } from "./tools/kit.js";
|
|
13
|
+
export declare function doctor({ config }: ToolContext, options: {
|
|
14
|
+
network: boolean;
|
|
15
|
+
}): Promise<DoctorCheck[]>;
|