UNPKG

mcp-universal-file-converter

Version:

MCP Universal File Converter - 支持压缩包、图片、PDF、Office文档等转换成可上传的 JPG (≤2MB)

150 lines (149 loc) 5.59 kB
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import fs from "fs"; import path from "path"; import { z } from "zod"; import { zodToJsonSchema } from "zod-to-json-schema"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js"; import { processSubFolder, setApiConfig } from "./tools/convert_folder.js"; // 解析命令行参数 const args = process.argv.slice(2); let apiKey = ''; let model = ''; // 解析参数格式: --apikey=xxx --model=xxx 或 apikey model for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg.startsWith('--apikey=')) { apiKey = arg.split('=')[1]; } else if (arg.startsWith('--model=')) { model = arg.split('=')[1]; } else if (i === 0 && !arg.startsWith('--')) { apiKey = arg; } else if (i === 1 && !arg.startsWith('--')) { model = arg; } } // 设置API配置 if (apiKey || model) { setApiConfig({ apiKey, model }); console.log(`API配置已设置: apiKey=${apiKey ? '***' : '未设置'}, model=${model || '未设置'}`); } /** * MCP 服务器设置 */ const server = new Server({ name: "universal-file-converter", version: "1.0.0" }, { capabilities: { tools: {}, }, }); server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "list_folders", description: "【第一步】检查指定目录下的所有子文件夹,返回文件夹路径列表。使用流程:1.先调用此工具获取所有子文件夹路径 2.然后对每个文件夹路径逐个调用convert_folder工具", inputSchema: zodToJsonSchema(z.object({ folderPath: z.string().describe("要检查的根目录路径"), })) }, { name: "convert_folder", description: "【第二步】将单个文件夹内所有可处理的文件转换为 JPG 格式(≤2MB),支持压缩包、图片、PDF、Office 文档等。注意:使用前必须先调用list_folders工具获取文件夹路径", inputSchema: zodToJsonSchema(z.object({ folderPath: z.string().describe("要转换的单个文件夹路径(从list_folders工具获取)"), })) }, ], }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { const { params } = request; const { name, arguments: args } = params; if (name === "list_folders") { const { folderPath } = args; console.log('检查目录--', folderPath); if (!fs.existsSync(folderPath)) { throw new Error(`文件夹不存在: ${folderPath}`); } const subFolders = fs.readdirSync(folderPath).filter(f => { return fs.statSync(path.join(folderPath, f)).isDirectory(); }); if (subFolders.length === 0) { return { content: [ { type: "text", text: `目录 ${folderPath} 下没有找到子文件夹` } ] }; } const folderPaths = subFolders.map(sub => path.join(folderPath, sub)); return { content: [ { type: "text", text: `找到 ${subFolders.length} 个子文件夹:\n${folderPaths.map((p, i) => `${i + 1}. ${p}`).join('\n')}\n\n请使用 convert_folder 工具逐个处理这些文件夹。` } ] }; } if (name === "convert_folder") { const { folderPath } = args; console.log('处理单个文件夹--', folderPath); if (!fs.existsSync(folderPath)) { throw new Error(`文件夹不存在: ${folderPath}`); } const allMessages = []; allMessages.push(`=== 开始处理文件夹: ${path.basename(folderPath)} ===`); try { const generator = processSubFolder(folderPath); let folderSuccess = true; for await (const result of generator) { // 实时输出处理进度 const statusIcon = result.type === 'success' ? '✅' : result.type === 'error' ? '❌' : result.type === 'warning' ? '⚠️' : 'ℹ️'; allMessages.push(`${statusIcon} ${result.message}`); if (result.type === 'error') { folderSuccess = false; } } if (folderSuccess) { allMessages.push(`✅ 文件夹处理成功`); } else { allMessages.push(`❌ 文件夹处理失败`); } } catch (error) { allMessages.push(`❌ 文件夹处理异常: ${error}`); } return { content: [ { type: "text", text: allMessages.join('\n') } ] }; } throw new Error(`未知的工具: ${name}`); }); // Start server async function runServer() { const transport = new StdioServerTransport(); await server.connect(transport); console.info("Universal File Converter Server running on stdio"); } runServer().catch((error) => { console.error("Fatal error running server:", error); process.exit(1); });