search_youtube
Search YouTube by topic to find videos, channels, or playlists. Returns up to 50 results with metadata. Use for broad discovery when you do not know a specific channel.
Instructions
Search YouTube globally for videos, channels, or playlists on any topic. Returns up to 50 results with metadata. Use this for topic-based discovery when the user has not specified a channel — for searching within a known channel use search_channel_videos instead.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| q | Yes | Search query (same syntax as YouTube's search bar, e.g. 'rust async tutorial', 'lex fridman dario amodei'). | |
| type | No | Search type: 'video', 'channel', or 'playlist'. Default: 'video'. | |
| limit | No | Max results (1-50, default 20). |
Implementation Reference
- src/index.js:79-102 (schema)Input schema for search_youtube tool: accepts 'q' (required string query), optional 'type' (video/channel/playlist), and optional 'limit' (1-50).
inputSchema: { type: "object", properties: { q: { type: "string", description: "Search query (same syntax as YouTube's search bar, e.g. 'rust async tutorial', 'lex fridman dario amodei').", minLength: 1, }, type: { type: "string", description: "Search type: 'video', 'channel', or 'playlist'. Default: 'video'.", enum: ["video", "channel", "playlist"], }, limit: { type: "number", description: "Max results (1-50, default 20).", minimum: 1, maximum: 50, }, }, required: ["q"], }, - src/index.js:74-103 (registration)Tool registration entry in the TOOLS array at line 73. The search_youtube tool is declared with name, description, annotations (YT_READ: non-idempotent, not destructive, read-only), and its inputSchema.
{ name: "search_youtube", description: "Search YouTube globally for videos, channels, or playlists on any topic. Returns up to 50 results with metadata. Use this for topic-based discovery when the user has not specified a channel — for searching within a known channel use search_channel_videos instead.", annotations: { title: "Search YouTube", ...ANN.YT_READ }, inputSchema: { type: "object", properties: { q: { type: "string", description: "Search query (same syntax as YouTube's search bar, e.g. 'rust async tutorial', 'lex fridman dario amodei').", minLength: 1, }, type: { type: "string", description: "Search type: 'video', 'channel', or 'playlist'. Default: 'video'.", enum: ["video", "channel", "playlist"], }, limit: { type: "number", description: "Max results (1-50, default 20).", minimum: 1, maximum: 50, }, }, required: ["q"], }, }, - src/index.js:450-462 (handler)Generic handler that proxies all tool calls (including search_youtube) to the upstream MCP server at api.subdownload.com/mcp via callUpstream(). No local handler logic — the actual search_youtube execution is on the upstream side.
server.setRequestHandler(CallToolRequestSchema, async (request) => { try { return await callUpstream( request.params.name, request.params.arguments || {} ); } catch (err) { return { content: [{ type: "text", text: err.message || String(err) }], isError: true, }; } }); - src/index.js:408-441 (helper)Helper function callUpstream() that forwards tool call requests (including search_youtube) to the upstream SubDownload MCP API via HTTP POST with Bearer token authentication.
async function callUpstream(name, args) { if (!API_KEY) { throw new Error( "SUBDOWNLOAD_API_KEY env var is not set. Get one at https://subdownload.com/account, then run with -e SUBDOWNLOAD_API_KEY=<your-key>." ); } const res = await fetch(UPSTREAM_URL, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json, text/event-stream", Authorization: `Bearer ${API_KEY}`, }, body: JSON.stringify({ jsonrpc: "2.0", id: Date.now(), method: "tools/call", params: { name, arguments: args }, }), }); const text = await res.text(); let body; try { body = JSON.parse(text); } catch { throw new Error( `Upstream returned non-JSON response (HTTP ${res.status}): ${text.slice(0, 200)}` ); } if (body.error) { throw new Error(body.error.message || JSON.stringify(body.error)); } return body.result; }