{
  "markdown": "# VidWords YouTube MCP Server\n\n**A hosted [Model Context Protocol](https://modelcontextprotocol.io) server that lets an AI agent read YouTube videos — and cite the exact second it got the answer from.**\n\n[![MCP Registry](https://img.shields.io/badge/MCP_Registry-com.vidwords%2Fyoutube-blue)](https://registry.modelcontextprotocol.io)\n[![Docs](https://img.shields.io/badge/docs-vidwords.com-4f46e5)](https://vidwords.com/resources/youtube-mcp-server?utm_source=github&utm_medium=readme&utm_campaign=mcp)\n\nA language model cannot watch a video. Point it at this endpoint and it gains nine tools for\nsearching transcripts, reading a video's **frames** — slides, charts, demos, on-screen text — and\nanswering questions with citations that are verified before you see them.\n\nNo integration code. No scraping. No proxy pool.\n\n```\nPOST https://vidwords.com/mcp\nAuthorization: Basic <your-api-token>\n```\n\nRemote-only and hosted — there is nothing to install or self-host. This repository is the public\nmanifest, configuration reference and issue tracker for that endpoint.\n\n---\n\n## Quick start\n\n**Most clients need no token at all.** The server speaks OAuth, so the client registers itself,\nsends you to VidWords to sign in, and stores a credential it refreshes on its own. You can create\nthe account during that sign-in step. The free plan includes monthly credits and 10 Watch minutes,\nso you can wire this up and use it before paying anything.\n\n### claude.ai, ChatGPT and Claude Desktop — add a connector, nothing to paste\n\nAdd this as a custom connector:\n\n```\nhttps://vidwords.com/mcp\n```\n\nThe host registers itself, sends you to VidWords to sign in, and shows a consent screen naming\nexactly what it is asking for. Registration alone grants nothing — access begins only when a\nsigned-in person clicks **Approve**, and live connections can be revoked from your API page with\nimmediate effect.\n\n### Claude Code\n\n```bash\nclaude mcp add --transport http vidwords https://vidwords.com/mcp\n```\n\nThen type `/mcp` in a session and choose **Authenticate**.\n\n### Cursor — `.cursor/mcp.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"vidwords\": {\n      \"url\": \"https://vidwords.com/mcp\"\n    }\n  }\n}\n```\n\nCursor shows the server as **Needs login** — click that once and it runs the OAuth flow in your\nbrowser. Because this file carries no secret, it is safe to commit, which the header form below\nis not.\n\n## A static token instead\n\nFor CI, a container, or a client with no OAuth support, authenticate with a header. Create an\naccount at **[vidwords.com/register](https://vidwords.com/register?utm_source=github&utm_medium=readme&utm_campaign=mcp)**,\n**verify your email**, then copy the token from your profile.\n\n### Claude Code\n\n```bash\nclaude mcp add --transport http vidwords https://vidwords.com/mcp \\\n  --header \"Authorization: Basic YOUR_API_TOKEN\"\n```\n\n### Claude Desktop — `claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"vidwords\": {\n      \"type\": \"http\",\n      \"url\": \"https://vidwords.com/mcp\",\n      \"headers\": { \"Authorization\": \"Basic YOUR_API_TOKEN\" }\n    }\n  }\n}\n```\n\n### Cursor — `.cursor/mcp.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"vidwords\": {\n      \"url\": \"https://vidwords.com/mcp\",\n      \"headers\": { \"Authorization\": \"Basic YOUR_API_TOKEN\" }\n    }\n  }\n}\n```\n\nKeep this out of version control, or use `~/.cursor/mcp.json` instead — the header holds a live\ncredential.\n\n### Codex CLI — `~/.codex/config.toml`\n\n```toml\n[mcp_servers.vidwords]\nurl = \"https://vidwords.com/mcp\"\nenv_http_headers = { \"Authorization\" = \"VIDWORDS_MCP_AUTH\" }\n```\n\n```bash\nexport VIDWORDS_MCP_AUTH=\"Basic YOUR_API_TOKEN\"\n```\n\n> Do **not** use `bearer_token_env_var`. It is the obvious-looking field, but it sends\n> `Authorization: Bearer <value>` and this server authenticates with **Basic**.\n\n### Clients without custom-header support, and Docker\n\nThis repository also ships a small **stdio proxy** (`src/index.js`) that speaks MCP on\nstdin/stdout and forwards tool calls to the hosted endpoint. Use it when your client cannot\nsend a custom HTTP header, or when you want the server in a container:\n\n```json\n{\n  \"mcpServers\": {\n    \"vidwords\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"github:haljishi/vidwords-mcp\"],\n      \"env\": { \"VIDWORDS_API_TOKEN\": \"YOUR_API_TOKEN\" }\n    }\n  }\n}\n```\n\n> Run straight from this repository — the proxy is not published to npm, so a\n> bare `npx @vidwords/mcp` will not resolve.\n\n```bash\ndocker build -t vidwords-mcp .\ndocker run --rm -i -e VIDWORDS_API_TOKEN=YOUR_API_TOKEN vidwords-mcp\n```\n\nThe tool schemas are declared inline in the proxy, so `initialize` and `tools/list` answer\nwithout any credentials and the upstream is not contacted until a tool is actually called.\nA call without `VIDWORDS_API_TOKEN` returns a readable error rather than failing the\nhandshake. `VIDWORDS_MCP_URL` overrides the endpoint if you are pointing at a non-production\ninstance.\n\nThe generic [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) bridge works too:\n\n```json\n{\n  \"mcpServers\": {\n    \"vidwords\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"mcp-remote\", \"https://vidwords.com/mcp\",\n               \"--header\", \"Authorization:Basic YOUR_API_TOKEN\"]\n    }\n  }\n}\n```\n\nReady-made config files live in [`examples/`](./examples).\n\n---\n\n## The nine tools\n\n| Tool | What it does | Cost |\n| --- | --- | --- |\n| `search_transcript` | Find where a video discusses something. Takes one video **or a list of up to 25**, so one call can answer a question across a whole channel. Returns the matching moments with timestamps, quoted context, and `youtube.com/watch?v=…&t=…s` deep links. | 1 credit per video |\n| `get_transcript` | Full transcript text for up to 25 videos in one call. | 1 credit per video |\n| `list_channel_videos` | Resolve a channel handle, URL or `UC…` id to its recent uploads. | Free · Starter and up |\n| `list_watchlists` | The account's Radar watchlists and how much each has recorded. | Free |\n| `watchlist_activity` | Newest uploads Radar has recorded for one watchlist. | Free |\n| `account` | Plan and remaining credits, so the agent can price a job before running it. | Free |\n| `analyze_video` | Start a frame-level analysis — slides, charts, demos and on-screen text, not just captions. Returns an `analysisId` immediately. | Watch minutes |\n| `get_analysis` | Read a finished analysis: chapters, key points, timestamped evidence. | Free |\n| `ask_video` | Ask a question against a finished analysis. Citations are verified against stored evidence or dropped. | 1 Watch question |\n\n### Prefer `search_transcript` over `get_transcript`\n\nBoth cost one credit per video, so there is no billing reason to choose. The reason is context.\nAsk \"what did this two-hour interview say about pricing?\" and `get_transcript` returns roughly\n20,000 words, of which perhaps 300 are about pricing — those 300 now compete for attention with\n19,700 that are not, and the answer gets worse, slower and more expensive to generate.\n\n`search_transcript` returns only the matching stretches, each with a deep link. Reach for\n`get_transcript` when you genuinely want the whole text: an export, a diff, a corpus.\n\n### Ask for a span, not a whole video\n\nBoth transcript tools take optional `from` and `to` timecodes — seconds (`615`), `m:ss`\n(`10:20`) or `h:mm:ss` (`1:02:13`):\n\n```json\n{ \"videos\": [\"dQw4w9WgXcQ\"], \"from\": \"10:20\", \"to\": \"11:00\" }\n```\n\nThese are the same formats the tools print back, so a timestamp out of one answer can be\npasted straight into the next question. A timecode that cannot be parsed is refused before\nanything is fetched, so a typo costs no credit — it never silently widens to the whole video.\n\n### One call across a channel\n\n`search_transcript` accepts a list, which is how you answer \"what has this channel said about\nX\" without a round trip per video. Get the ids from `list_channel_videos` first:\n\n```json\n{ \"video\": [\"VIDEO_ID_1\", \"VIDEO_ID_2\", \"VIDEO_ID_3\"], \"query\": \"pricing\" }\n```\n\nEach video is billed at the usual 1 credit, and one unavailable video is reported in its own\nrow rather than failing the call — the others were fetched and charged for, so you still get\nthem.\n\n### It reads the picture, not only the captions\n\n`analyze_video` looks at slides, charts, code samples and on-screen text that is never spoken\naloud. `ask_video` then answers against that stored analysis, and **every citation is checked\nbefore you see it**: a visual claim has to match a frame that was actually recorded, a spoken\nclaim has to land on a real transcript segment. Anything that fails is dropped, and when nothing\nsurvives the answer says the evidence is insufficient rather than producing a confident guess.\n\nThat is occasionally annoying — a refusal is a worse demo than a fluent answer — and it is the\nonly version of this feature that is safe to put in front of an agent, because an agent repeats\nwhat it is told without the scepticism a human reader applies.\n\n---\n\n## Auth, cost and limits\n\n- **If you pasted a token: `Basic`, not `Bearer`.** The token is sent as-is; you do not base64-encode\n  a `user:pass` pair. Clients that signed in carry their own credential and this does not apply.\n- **Verify your email first.** Until you click the verification link every call returns `403`\n  with `{\"error\":\"email_unverified\"}` — the most common first-call failure on a new account.\n- **Credits are one pool** shared with the REST API and the website. One credit is one transcript.\n  Frame analysis draws Watch minutes instead, and a run refused before it starts costs nothing.\n- **Rate limit: 30 requests / 10s** — deliberately looser than the REST API's 5, because the server\n  is stateless and a client re-runs `initialize` before every call. `analyze_video` has its own\n  ceiling of 10 starts per minute, shared with the REST route.\n- **RapidAPI tokens are refused here.** That identity is metered per call and has no account\n  behind it, neither of which survives a tool-calling session. Use a VidWords API token.\n- **Stateless by design.** No resumable SSE streams, no session to delete; every tool answers in\n  one shot. `GET` and `DELETE` return a JSON-RPC error rather than an HTML 404.\n- **Captions have to exist.** For a video with no caption track, a signed-in account can transcribe\n  from audio instead — priced by length, quoted before you spend.\n\nFull numbers: [pricing](https://vidwords.com/pricing?utm_source=github&utm_medium=readme&utm_campaign=mcp).\n\n---\n\n## Agent skill\n\n[`skills/youtube-transcripts/SKILL.md`](skills/youtube-transcripts/SKILL.md) is a drop-in agent\nskill for this server — tool selection, timecode spans, channel-wide search, the cost table and\nthe error codes worth acting on, in the format Claude and compatible agents load directly.\n\nCopy the folder into your agent's skills directory:\n\n```bash\ngit clone --depth 1 https://github.com/haljishi/vidwords-mcp\ncp -r vidwords-mcp/skills/youtube-transcripts ~/.claude/skills/\n```\n\nIt assumes the MCP server is configured (see Quick start). The point of it is that an assistant\nwhich has read the skill knows to reach for `search_transcript` with a timecode span instead of\npulling a whole two-hour transcript into its context.\n\n## Documentation\n\n- [Agent skill (SKILL.md)](skills/youtube-transcripts/SKILL.md)\n- [YouTube MCP server — overview](https://vidwords.com/resources/youtube-mcp-server?utm_source=github&utm_medium=readme&utm_campaign=mcp)\n- [Setup in Claude Code](https://vidwords.com/resources/youtube-mcp-claude-code?utm_source=github&utm_medium=readme&utm_campaign=mcp)\n- [Setup in Claude Desktop](https://vidwords.com/resources/youtube-mcp-claude?utm_source=github&utm_medium=readme&utm_campaign=mcp)\n- [Setup in Cursor](https://vidwords.com/resources/youtube-mcp-cursor?utm_source=github&utm_medium=readme&utm_campaign=mcp)\n- [REST API documentation](https://vidwords.com/api-docs?utm_source=github&utm_medium=readme&utm_campaign=mcp)\n\n## Support\n\nOpen an issue here for anything about the MCP surface — a tool that misbehaves, a client whose\nconfig we have not documented, a schema that could be clearer. Account and billing questions go to\n[support](https://vidwords.com/contact?utm_source=github&utm_medium=readme&utm_campaign=mcp).\n\n## License\n\nThe contents of this repository (documentation and configuration examples) are MIT licensed. The\nhosted service itself is proprietary and governed by the\n[VidWords terms](https://vidwords.com/terms?utm_source=github&utm_medium=readme&utm_campaign=mcp).\n\n---\n\nIndependent product; not affiliated with YouTube or Google.\n",
  "bytes": 12519,
  "sha": "825628e4c204c906ef422439db9a0d099e62c69cf397aa0e4fb5715fc260092c",
  "repo_slug": "haljishi/vidwords-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_com_vidwords_youtube_46adf878/readme"
}