YtDlpTool.js•3.44 kB
import { MCPTool } from "mcp-framework";
import { z } from "zod";
import { exec } from "child_process";
import { promisify } from "util";
const execPromise = promisify(exec);
class YtDlpTool extends MCPTool {
    name = "yt_dlp";
    description = "使用yt-dlp下载视频或获取视频信息";
    schema = {
        url: {
            type: z.string(),
            description: "要下载或获取信息的视频URL",
        },
    };
    async execute(input) {
        // 使用正确的绝对路径
        const ytDlpPath = "F:\\Github\\yt-mcp-server\\yt-dlp.exe";
        try {
            console.log(`yt-dlp.exe路径: ${ytDlpPath}`);
            // 处理URL,移除可能导致命令行解析错误的参数
            const cleanUrl = this.cleanUrl(input.url);
            // 构建命令行参数,使用双引号包裹URL,并添加下载路径
            const downloadPath = "H:\\B站视频";
            const command = `${ytDlpPath} -P "${downloadPath}" "${cleanUrl}"`;
            console.log(`执行命令: ${command}`);
            const { stdout, stderr } = await execPromise(command);
            // yt-dlp有时会将警告信息输出到stderr,但这不一定是错误
            if (stderr) {
                console.log(`yt-dlp警告或信息: ${stderr}`);
            }
            // 即使有stderr输出,如果stdout也有内容,我们仍然认为命令执行成功
            if (stdout) {
                return {
                    content: [
                        {
                            type: "text",
                            text: `使用yt-dlp路径: ${ytDlpPath}\n\n${stdout}`
                        }
                    ]
                };
            }
            else {
                // 如果没有stdout输出,则视为错误
                return {
                    isError: true,
                    content: [
                        {
                            type: "text",
                            text: `使用yt-dlp路径: ${ytDlpPath}\n\n执行yt-dlp时出错: ${stderr}`
                        }
                    ]
                };
            }
        }
        catch (error) {
            console.error(`执行yt-dlp时出错:`, error);
            // 返回符合MCP协议的错误
            return {
                isError: true,
                content: [
                    {
                        type: "text",
                        text: `使用yt-dlp路径: ${ytDlpPath}\n\n执行yt-dlp时出错: ${error instanceof Error ? error.message : String(error)}`
                    }
                ]
            };
        }
    }
    // 清理URL,移除可能导致命令行解析错误的参数
    cleanUrl(url) {
        // 提取基本URL,移除查询参数
        const urlObj = new URL(url);
        const baseUrl = `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}`;
        // 只保留必要的查询参数(例如视频ID)
        // 对于B站,通常只需要保留BV号即可
        if (url.includes('bilibili.com')) {
            // B站URL通常格式为 https://www.bilibili.com/video/BV1p2Q6YsEGk/
            // 我们只需要保留到BV号的部分
            const bvMatch = baseUrl.match(/(\/video\/[A-Za-z0-9]+)/);
            if (bvMatch) {
                return `https://www.bilibili.com${bvMatch[0]}`;
            }
        }
        return baseUrl;
    }
}
export default YtDlpTool;