YouTube MCP Server
by iceener
README.md
# YouTube MCP Server
This server is a remote [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for YouTube. It finds videos, channels and playlists, and it reads video metadata. It uses the [YouTube Data API v3](https://developers.google.com/youtube/v3).
The server runs on **Cloudflare Workers** and on **Bun**. It is built on the [remote MCP server template](https://github.com/iceener/streamable-mcp-server-template), version 2.1, and the official [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) 2.3.0. It uses protocol version `2026-07-28`. It also accepts clients that use the 2025 protocol versions.
The server URL is the deployed Worker's `MCP_PUBLIC_URL`, for example `https://youtube-mcp.<subdomain>.workers.dev/mcp`.
> [!WARNING]
> The production server has no authentication. Anyone who knows the URL can call the tools. Each call uses the quota of the server's YouTube API key. Refer to [Authentication](#authentication).
> [!NOTE]
> Tool results come from YouTube. They can be incomplete or wrong. Examine them before you use them.
## Tools
All tools only read data. They do not change anything on YouTube.
| Tool | Function | Input |
|---|---|---|
| `find_channel` | Finds channels by name. It gives the channel IDs. | `query`, `maxResults` (1–10, default 5) |
| `scan_channel` | Gives the latest videos of a channel. | `channelId`, `maxResults` (1–50, default 10) |
| `search_videos` | Finds videos on all of YouTube. | `query`, `maxResults` (1–50, default 10), `order` (`relevance`, `date`, `viewCount` or `rating`), `publishedAfter` (ISO 8601) |
| `get_playlist` | Gives the playlists of a channel, or the videos in a playlist. | `channelId` or `playlistId`, `maxResults` (1–50, default 20) |
| `video_details` | Gives the details of one video: statistics, duration, tags and description. | `videoId` |
Each tool gives a text summary and structured content. The structured content agrees with the tool's output schema.
The server has no prompts and no resources.
## Connect a client
Use the server URL and the Streamable HTTP transport. Clients do not send a token or an API key.
| Client | Procedure |
|---|---|
| Claude Code | Run `claude mcp add --transport http youtube <server URL>`. |
| MCP Inspector | Run `bun run inspector`. Select **Streamable HTTP**. Enter the server URL. |
| VS Code | Add `{ "servers": { "youtube": { "type": "http", "url": "<server URL>" } } }` to `.vscode/mcp.json`. |
Browser clients must use an origin in `MCP_ALLOWED_ORIGIN_HOSTNAMES`. In production, these are `claude.ai`, `claude.com` and the hosts of the operator's own browser clients.
## Configuration
The server identity (name, version and instructions) is in `src/server.ts`. The production values of all variables are in `wrangler.production.jsonc`, which is gitignored; `wrangler.production.example.jsonc` shows its shape.
The server has two settings of its own. They are in `src/settings.ts`:
| Variable | Default | Function |
|---|---|---|
| `API_KEY` | | Required. The YouTube Data API v3 key. The server sends it to YouTube only, as the `key` query parameter. Store it as a secret. |
| `PROVIDER_API_URL` | `https://www.googleapis.com/youtube/v3` | The YouTube API address. Change it only to send tests to a local mock. |
The other variables belong to the template: `MCP_PUBLIC_URL`, `MCP_ALLOWED_HOSTS`, `MCP_ALLOWED_ORIGIN_HOSTNAMES`, `MCP_LEGACY_MODE`, `MCP_MAX_REQUEST_BYTES`, `AUTH_MODE`, `LOG_LEVEL`, `NODE_ENV`, `HOST` and `PORT`. The file `.env.example` describes all of them. The template README gives their defaults.
If a setting is not valid, the server shows all problems at the same time. Bun does not start. A Worker records the problems in the log and sends a 500 response to all requests.
## Authentication
In production, `AUTH_MODE` is `none`. The server accepts all requests that pass the `Host` and `Origin` checks. It does not use the caller's identity. It calls YouTube with its own key (`API_KEY`).
The risk: anyone who finds the URL can use the YouTube API quota of the key. When the quota is used, all tools give the error `YouTube API error: 403` until the quota resets.
To restrict access, use one of the template's other modes:
- `AUTH_MODE=bearer`: all clients send one shared token, `BEARER_TOKEN`. Each client must then send the header `Authorization: Bearer <token>`.
- `AUTH_MODE=oauth`: an external authorization server signs users in.
For the procedures, refer to `docs/auth.md` in the template. Before you change the mode, make sure that every client (Alice, Wonderlands, Claude.ai) can send the credentials.
## Deployment
Refer to [docs/deploy.md](docs/deploy.md). It gives the Worker, the secret, the Durable Object migrations and the steps to deploy.
## Development
Requirements: [Bun](https://bun.sh) 1.4 or later, and Node.js 22.18 or later.
1. Install the dependencies:
```sh
bun install
```
2. Copy `.env.example` to `.env`. Set `API_KEY` to a YouTube Data API v3 key.
3. Start the server:
```sh
bun run dev
```
The server URL is `http://127.0.0.1:3000/mcp`.
To use the Cloudflare local runtime, put `API_KEY=…` in `.dev.vars`, then run `bun run dev:worker`. The server URL is then `http://127.0.0.1:8787/mcp`.
| Script | Function |
|---|---|
| `bun run check` | Does the type check, the lint check and the tests. It also checks the generated Worker types. |
| `bun run test:smoke` | Starts the real server on Bun and on workerd. YouTube is replaced by a local mock. |
| `bun run deploy` | Deploys with `wrangler.production.jsonc`. |
| `bun run types:worker` | Makes the Worker types again. Run it after you change `wrangler.jsonc`. |
The project structure is the template's:
```
src/
server.ts Server identity, instructions and dependencies
settings.ts API_KEY and PROVIDER_API_URL
tools/ One file for each tool. index.ts lists them.
services/ youtube.ts: the YouTube Data API client
platform/ Template code. Do not change it.
bun.ts Entry point for Bun
worker.ts Entry point for Cloudflare Workers
tests/ Tests for each tool, the service, the platform, and the contract with the earlier server
scripts/ Smoke tests and the local YouTube mock
```
`tests/contract.test.ts` and `tests/routes.test.ts` compare the server with the deployed server before the template 2.1 migration. The recorded data is in `tests/fixtures/`. A change to a tool name, an input schema, an output schema or a route makes these tests fail.
## License
[MIT](LICENSE)
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues