UNPKG

mcp-server-feishu-bitable

Version:

飞书群聊机器人日报 MCP 服务器

215 lines (190 loc) 6.14 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import axios from 'axios'; const FEISHU_WEBHOOK_URL = process.env.FEISHU_WEBHOOK_URL; class FeishuWebhookMCPServer { constructor() { this.server = new Server({ name: "feishu-webhook-mcp-server", version: "1.0.3", }, { capabilities: { tools: {}, }, }); this.setupHandlers(); } async sendToFeishu(content) { if (!FEISHU_WEBHOOK_URL) { throw new Error('未配置飞书 Webhook URL,请在环境变量中设置 FEISHU_WEBHOOK_URL'); } try { console.error('正在发送到飞书...', { hasUrl: !!FEISHU_WEBHOOK_URL, contentLength: content.length }); const response = await axios.post(FEISHU_WEBHOOK_URL, { msg_type: "text", content: { text: content } }, { headers: { 'Content-Type': 'application/json', } }); console.error('飞书响应:', response.status, response.data); return response.data; } catch (error) { console.error('发送到飞书失败:', error.response?.data || error.message); if (error.response) { throw new Error(`发送失败: ${error.response.status} - ${JSON.stringify(error.response.data)}`); } else { throw new Error(`发送失败: ${error.message}`); } } } async testWebhook() { try { const testMessage = `🔍 连接测试 - ${new Date().toLocaleString('zh-CN')}`; await this.sendToFeishu(testMessage); return { success: true }; } catch (error) { return { success: false, error: error.message }; } } formatDailyReport(content) { const today = new Date(); const dateStr = today.toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', weekday: 'long' }); const timeStr = today.toLocaleTimeString('zh-CN'); return `📊 工作日报 - ${dateStr} ${content} --- ✨ 通过 Trae 自动提交 ⏰ 提交时间: ${timeStr}`; } setupHandlers() { // 使用正确的 schema 注册处理器 this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "test_webhook", description: "测试飞书群聊机器人连接", inputSchema: { type: "object", properties: {} } }, { name: "send_daily_report", description: "发送日报到飞书群聊", inputSchema: { type: "object", properties: { content: { type: "string", description: "日报内容" } }, required: ["content"] } }, { name: "send_message", description: "发送消息到飞书群聊", inputSchema: { type: "object", properties: { content: { type: "string", description: "消息内容" } }, required: ["content"] } } ] }; }); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case "test_webhook": const testResult = await this.testWebhook(); if (testResult.success) { return { content: [ { type: "text", text: `✅ 飞书群聊机器人连接测试成功!\n🤖 测试消息已发送到群聊\n🔗 Webhook 状态: 正常` } ] }; } else { return { content: [ { type: "text", text: `❌ 连接测试失败: ${testResult.error}` } ], isError: true }; } case "send_daily_report": const formattedContent = this.formatDailyReport(args.content); await this.sendToFeishu(formattedContent); return { content: [ { type: "text", text: `✅ 日报发送成功!\n📝 内容已发送到飞书群聊\n📄 日期: ${new Date().toLocaleDateString('zh-CN')}\n📋 预览: ${args.content.substring(0, 100)}${args.content.length > 100 ? '...' : ''}` } ] }; case "send_message": await this.sendToFeishu(args.content); return { content: [ { type: "text", text: `✅ 消息发送成功!\n📝 内容: ${args.content.substring(0, 100)}${args.content.length > 100 ? '...' : ''}` } ] }; default: throw new Error(`未知工具: ${name}`); } } catch (error) { return { content: [ { type: "text", text: `❌ 操作失败: ${error.message}` } ], isError: true }; } }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error("飞书群聊机器人 MCP 服务器已启动"); } } const server = new FeishuWebhookMCPServer(); server.run().catch(console.error);