Skip to main content
Glama
tuyennn

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