YouTube数据API服务器

一个基于YouTube Data API v3的MCP服务器,提供视频、频道、播放列表、评论和字幕等数据的获取功能。

  • by rayven122
  • TypeScript
  • 本地部署
  • 2 星标
  • 更新于
在 GitHub 查看 rayven122/youtube-mcp

使用说明

YouTube MCP服务器

YouTube Data API v3 使用MCP (Model Context Protocol) 服务器。

机能

动画关连

  • get_video - YouTube获取视频详细信息
  • search_videos - YouTube搜索视频

通道关系

  • get_channel -获取频道信息
  • get_channel_videos -获取频道视频列表

播放列表相关

  • get_playlist -获取播放列表信息
  • get_playlist_items -获取播放列表中的视频列表

注释关联

  • get_comment_threads -获取视频评论文章(支持页面对齐)
  • get_comment_replies -获取评论回复(支持分页)

字幕关连

  • get_transcript_metadata -获取可用于视频的字幕元数据(语言、类型、更新时间等)
  • get_transcript -获取视频字幕(需要:yt-dlp)

前提条件

  • YouTube Data API v3的,之API钥匙
  • yt-dlp(get_transcript使用功能时)
    • 安装方法:https://github.com/yt-dlp/yt-dlp/wiki/Installation
      • macOS: brew install yt-dlp
      • 窗户: winget install yt-dlp

安装,安装

1. YouTube Data API v3 获取密钥

  1. 谷歌云控制台 访问
  2. 创建新项目或选择现有项目
  3. 「API和服务-从库中启用YouTube数据API v3
  4. 「API和服务-从凭据API创建密钥

2.构建

pnpm clean
pnpm install
pnpm build

使用方法

{
  "mcpServers": {
    "youtube-mcp": {
      "type": "stdio",
      "command": "node",
      "args": ["./dist/index.js"],
      "env": {
        "YOUTUBE_API_KEY": "${YOUTUBE_API_KEY}"
      }
    }
  }
}

在动态输入提示中单击YouTube MCP工具可用。

目录配置(src/)

src/
├── index.ts        # エントリポイント
├── api/            # YouTube API
├── lib/            # 外部ライブラリ連携
├── mcp/            # MCPプロトコル実装
│   └── tools/      # ツール定義
└── __tests__/      # テスト

制限事项

  • YouTube Data API v3 的配额限制(默认值:10000个设备/天)
  • API请妥善管理密钥,注意不要公开

测试编码约定

neverthrow Result类型验证模式

import { err, ok } from "neverthrow";

// ✅ 成功ケースの検証
expect(result.isOk()).toBe(true);
expect(result.isErr()).toBe(false);
expect(result._unsafeUnwrap()).toStrictEqual(expectedData);

// ✅ エラーケースの検証
expect(result.isOk()).toBe(false);
expect(result.isErr()).toBe(true);
expect(result._unsafeUnwrapErr()).toStrictEqual(new Error("error message"));

MCP工具测试模式

// 成功レスポンスの検証
test("正常系: データを取得して正しいレスポンスを返す", async () => {
  mockGetVideo.mockResolvedValueOnce(ok(mockVideoData));

  const result = await handleVideoTool(
    YOU_TUBE_TOOL_NAMES.GET_VIDEO,
    { videoId: "test-id" },
    mockApiKey,
  );

  expect(result.isOk()).toBe(true);
  if (result.isOk()) {
    expect(result.value).toStrictEqual({
      content: [
        {
          type: "text",
          text: JSON.stringify(mockVideoData),
        },
      ],
    } satisfies CallToolResult);
  }
});

// API呼び出し失敗の検証
test("異常系: API呼び出しが失敗した場合にエラーを返す", async () => {
  mockGetVideo.mockResolvedValueOnce(err(new Error("API Error")));

  const result = await handleVideoTool(
    YOU_TUBE_TOOL_NAMES.GET_VIDEO,
    { videoId: "test-id" },
    mockApiKey,
  );

  expect(result.isOk()).toBe(false);
  expect(result.isErr()).toBe(true);
  expect(result._unsafeUnwrapErr()).toStrictEqual(new Error("API Error"));
});

区分错误验证

// 具体的なエラーメッセージの検証
expect(result._unsafeUnwrapErr()).toStrictEqual(new Error("Channel not found"));

// エラーの型のみ検証(メッセージは問わない)
expect(result._unsafeUnwrapErr()).toStrictEqual(expect.any(Error));

// カスタムエラークラスの検証
expect(result._unsafeUnwrapErr()).toBeInstanceOf(TranscriptError);

设置莫克函数的返回值

// 成功ケース
mockFunction.mockResolvedValueOnce(ok(data));

// エラーケース
mockFunction.mockResolvedValueOnce(err(new Error("error")));

// 例外をスロー
mockFunction.mockRejectedValueOnce(new Error("exception"));