Xiaozhi YouTube MCP
by tuyennn
README.md
# Xiaozhi YouTube MCP
A complete Model Context Protocol server that lets Xiaozhi or another MCP client search songs through the official **YouTube Data API v3** and receive a YouTube playback URL.
## What it provides
- `youtube_search_song`: returns up to 10 Music-category results.
- `youtube_play_song`: returns the best result for direct voice commands.
- `youtube_get_video`: resolves an 11-character video ID to metadata and playback links.
- YouTube title, channel, description, thumbnail, ISO-8601 duration, duration in seconds, view count, and embeddability.
- stdio transport for desktop/local MCP clients.
- Streamable HTTP transport for a hosted Xiaozhi backend.
- Docker, Docker Compose, validation, error handling, cache, and tests.
## Playback limitation
The official YouTube Data API returns video metadata and YouTube URLs; it does **not** return direct MP3/AAC media streams. This MCP therefore returns:
- `youtubeUrl`: `https://www.youtube.com/watch?v=...`
- `embedUrl`: `https://www.youtube.com/embed/...`
Playback requires a YouTube-capable client or an approved handoff to a YouTube player. This project intentionally does not extract or proxy YouTube media streams.
## 1. Create an API key
1. Create or select a Google Cloud project.
2. Enable **YouTube Data API v3**.
3. Create an API key.
4. Restrict the key to YouTube Data API v3 and, where practical, to your server IP.
## 2. Run locally
```bash
cp .env.example .env
# Edit .env and set YOUTUBE_API_KEY
npm install
npm run build
npm start
```
The default transport is stdio. Never write normal logs to stdout in stdio mode; this server logs startup messages to stderr.
Example MCP client configuration:
```json
{
"mcpServers": {
"youtube": {
"command": "node",
"args": ["/absolute/path/xiaozhi-youtube-mcp/dist/src/index.js"],
"env": {
"YOUTUBE_API_KEY": "YOUR_KEY",
"YOUTUBE_REGION_CODE": "VN",
"YOUTUBE_RELEVANCE_LANGUAGE": "vi"
}
}
}
}
```
## Run directly with npx
After the package is published to npm:
```bash
YOUTUBE_API_KEY=YOUR_KEY npx --yes xiaozhi-youtube-mcp
```
For Streamable HTTP mode:
```bash
YOUTUBE_API_KEY=YOUR_KEY MCP_TRANSPORT=http PORT=3000 \
npx --yes xiaozhi-youtube-mcp
```
MCP client configuration using npx:
```json
{
"mcpServers": {
"youtube": {
"command": "npx",
"args": ["--yes", "xiaozhi-youtube-mcp"],
"env": {
"YOUTUBE_API_KEY": "YOUR_KEY",
"YOUTUBE_REGION_CODE": "VN",
"YOUTUBE_RELEVANCE_LANGUAGE": "vi"
}
}
}
}
```
You can also run a GitHub repository before publishing to npm:
```bash
YOUTUBE_API_KEY=YOUR_KEY npx --yes github:YOUR_GITHUB_USER/xiaozhi-youtube-mcp
```
For repeatable production deployments, pin a package version rather than always using the latest version:
```bash
npx --yes xiaozhi-youtube-mcp@1.0.0
```
## 3. Host for Xiaozhi
```bash
cp .env.example .env
# Set YOUTUBE_API_KEY and MCP_TRANSPORT=http
npm install
npm run build
npm run start:http
```
Endpoints:
- MCP: `http://YOUR_SERVER:3000/mcp`
- Health: `http://YOUR_SERVER:3000/health`
For public use, put the service behind HTTPS using Nginx, Caddy, Cloudflare Tunnel, or another trusted reverse proxy. Configure the resulting HTTPS MCP URL in the server-side MCP section of your Xiaozhi backend/control panel. The exact UI varies by the Xiaozhi server distribution.
## Docker
```bash
cp .env.example .env
# Edit .env
docker compose up -d --build
curl http://localhost:3000/health
```
## Voice behavior
A user says:
> Play Numb by Linkin Park
The model should call:
```json
{
"name": "youtube_play_song",
"arguments": {
"query": "Numb Linkin Park",
"officialOnly": true
}
}
```
The structured response contains a `playback.url`. A Xiaozhi integration that can open YouTube should hand that URL to its player. Otherwise, the assistant can read out or display the selected title and URL.
## Configuration
| Variable | Default | Description |
|---|---:|---|
| `YOUTUBE_API_KEY` | required | Google API key |
| `MCP_TRANSPORT` | `stdio` | `stdio` or `http` |
| `HOST` | `0.0.0.0` | HTTP bind host |
| `PORT` | `3000` | HTTP port |
| `MCP_PATH` | `/mcp` | MCP HTTP route |
| `YOUTUBE_REGION_CODE` | `VN` | ISO two-letter region |
| `YOUTUBE_RELEVANCE_LANGUAGE` | `vi` | Search relevance language |
| `YOUTUBE_SAFE_SEARCH` | `moderate` | `none`, `moderate`, or `strict` |
| `YOUTUBE_DEFAULT_MAX_RESULTS` | `5` | Default result count, maximum 10 |
| `YOUTUBE_CACHE_TTL_SECONDS` | `300` | In-memory API response cache |
## Verify
```bash
npm run check
```
## Security and production notes
- Keep the API key server-side and out of source control.
- Apply API restrictions and quota alerts in Google Cloud.
- Use HTTPS and network access controls for HTTP deployment.
- Add reverse-proxy authentication if the endpoint is publicly reachable.
- Cache searches to reduce API usage.
- The server filters searches to YouTube video category 10 (Music), requests embeddable videos, and enables configurable SafeSearch.
## Publish to GitHub and npm
```bash
git init
git add .
git commit -m "Initial Xiaozhi YouTube MCP"
git branch -M main
git remote add origin git@github.com:YOUR_GITHUB_USER/xiaozhi-youtube-mcp.git
git push -u origin main
npm login
npm publish
```
The npm package name must be available. If `xiaozhi-youtube-mcp` is already owned by someone else, use a scoped name such as `@YOUR_GITHUB_USER/xiaozhi-youtube-mcp`, update `package.json`, and run it with:
```bash
npx --yes @YOUR_GITHUB_USER/xiaozhi-youtube-mcp
```
### Automated npm publishing
The included GitHub Actions workflow publishes when you create a GitHub Release. Add an npm automation token as the repository secret `NPM_TOKEN`, then create a release whose tag matches the version, for example `v1.0.0`.
TDQS
A3.8/5.0
Scored across 3 tools
Disambiguation4/5
Tools are distinct: search returns multiple URLs, play returns one best match, get provides metadata. However, search and play both handle song queries, causing slight overlap, but descriptions clarify their usage.
Naming Consistency5/5
All tools follow a consistent 'youtube_verb_noun' pattern (search_song, play_song, get_video), using underscores and clear action-object format.
Tool Count5/5
Three tools is appropriate for a focused YouTube music MCP server, covering search, playback, and metadata without unnecessary bloat.
Completeness4/5
Covers core music workflows: searching songs, playing, and getting video details. Minor gaps like playlist or recommendation support exist but are outside stated scope.
Maintenance
ActivityMaintained
ResponsivenessSyncing