linker-feishu-mcp
v0.1.4
Published
MCP server for Linker Feishu group messages - daily digest and semantic search
Readme
linker-feishu-mcp
飞书群聊消息 MCP 服务,提供长短期记忆结合的群聊查询能力,专为化工品现货信息场景设计。
系统架构
┌─────────────────────────────────────────────────────────────────┐
│ 飞书群聊消息源 │
│ 烯烃-聚烯烃群 / 液化烃群 / 乙烯群 / 丙烯群 / 化工研究晨报群 │
└──────────────────────────┬──────────────────────────────────────┘
│ 飞书 Webhook / 消息同步
▼
┌─────────────────────────────────────────────────────────────────┐
│ 表A: linker_feishu_group_messages │
│ id / group_name / sender_name / msg_type / content / send_time │
│ digest_processed(0=待处理, 1=已处理) │
└──────────────────────────┬──────────────────────────────────────┘
│
┌────────────┘ 每5分钟 cron
▼
┌─────────────────────────────────────────────────────────────────┐
│ feishu_message_processor.py │
│ │
│ 文字/富文本 ──────────────────────────► 直接拼入时间线 │
│ │
│ 图片消息 ──► 下载 COS ──► 豆包视觉 API ──► [图片:描述文字] │
│ (doubao-seed-1-8-251228) │
│ │
│ 文件消息 ──► 下载 COS ──► 解析内容 ──────► [文件:名称 摘要:xxx] │
│ pdf/docx/xlsx/txt/md/csv 上限 10000 字 │
│ │
│ 策略:文字批量处理;图片/文件逐条处理后立即 commit(插入精确) │
└──────────────────────────┬──────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 表B: linker_feishu_daily_digest │
│ date / group_name / group_chat_id / digest_text(LONGTEXT) │
│ UNIQUE KEY (date, group_chat_id) — 每群每天一行时间线 │
│ │
│ 格式示例: │
│ 群组:烯烃-丙烯-现货信息群 │
│ 日期:2026-04-23 │
│ [16:19 张三] 丙烯现货成交3240-3260 │
│ [17:05 李四] [图片:K线图,价格从3200涨至3260] │
│ [18:30 王五] [文件:周报.pdf 摘要:本周丙烯均价...] │
└──────┬────────────────────────────────┬───────────────────────┘
│ │
│ 短期记忆 │ 每天 23:55 cron
│ 直查(实时,延迟≤5分钟) ▼
│ ┌────────────────────────────────────┐
│ │ feishu_ragflow_sync.py │
│ │ 每群生成 {group}_{date}.txt │
│ │ 上传 + 设置 meta_fields │
│ │ {group_name, date} │
│ └──────────────┬─────────────────────┘
│ │
│ ▼
│ ┌────────────────────────────────────┐
│ │ RAGFlow 知识库 │
│ │ 向量化存储,支持语义检索 │
│ │ metadata 过滤:group_name / date │
│ └──────────────┬─────────────────────┘
│ │ 长期记忆
│ │ 语义检索(跨群跨日期)
▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ MCP 工具层 │
│ │
│ query_feishu ← 主入口,并发拉取长短期,返回结合结果 │
│ get_feishu_group_digest ← 某群完整原文(≤7天) │
│ list_feishu_groups ← 群名发现 │
└──────────────────────────┬──────────────────────────────────────┘
│
▼
Agent / LLM设计理念
长短期记忆强制结合:query_feishu 并发调用两个数据源,agent 单次调用即可获得:
- 短期记忆(MySQL):完整时间线,含图片/文件多模态内容,实时
- 长期记忆(RAGFlow):语义相关历史片段,标注来源群和日期,跨时间跨群
Agent 决策树:
群名不确定 → list_feishu_groups → 再调其他工具
需要某群逐日完整原文(≤7天) → get_feishu_group_digest
其他所有问题 → query_feishu使用场景
场景一:今日行情查询
"今天各群有什么动态?"
query_feishu({ "question": "今日市场动态" })short_term 返回今天所有群完整摘要;long_term 返回历史相关片段供对比。
场景二:指定群今日查询
"今天丙烯群说了什么?"
query_feishu({ "question": "丙烯现货价格成交", "group_name": "丙烯" })short_term 返回丙烯群今日完整时间线;long_term 返回丙烯历史相关片段。
场景三:历史语义检索(跨群跨日期)
"最近乙烯上下游有什么动态?"
query_feishu({ "question": "乙烯上下游动态" })short_term 返回今日摘要;long_term 从所有历史文档中语义检索最相关片段。
场景四:指定日期查询
"4月16号液化烃群说了什么?"
query_feishu({ "question": "液化烃现货", "group_name": "液化烃", "date": "2026-04-16" })short_term 精确返回该群该日摘要;long_term 同日语义检索补充。
场景五:某群近期完整时间线
"丙烯群这周每天的报价是多少?"
get_feishu_group_digest({ "group_name": "丙烯", "days": 7 })返回丙烯群最近7天每天完整摘要原文,按日期排列。超过7天改用 query_feishu 语义检索。
场景六:群名不确定
"有没有关于C4的群?"
list_feishu_groups()
// → 返回所有群名和最近活跃日期
// → 确认群名后再调 query_feishu场景七:多轮对话
- 用户问今日行情 →
query_feishu(question="今日动态") - 用户追问"上周丙烯呢" →
query_feishu(question="丙烯价格", group_name="丙烯"),long_term 自动检索历史 - 用户要看原文 →
get_feishu_group_digest(group_name="丙烯", days=5)
场景覆盖评分
| 场景 | 支持程度 | 说明 | |------|------|------| | 今日所有群动态 | ✅ 完整 | short_term 全量返回 | | 今日指定群动态 | ✅ 完整 | group_name 模糊过滤 | | 历史语义检索 | ✅ 完整 | RAGFlow 跨群跨日期 | | 指定日期查询 | ✅ 完整 | date 精确过滤 | | 某群近期完整原文 | ✅ 完整(≤7天) | get_feishu_group_digest | | 图片内容识别 | ✅ 完整 | 豆包视觉 API | | 文件内容提取 | ✅ 完整 | pdf/docx/xlsx/txt/md/csv | | 长短期结合 | ✅ 强制 | query_feishu 并发双源 | | 群名发现 | ✅ 完整 | list_feishu_groups | | 视频/音频内容 | ❌ 不支持 | 归入 content 字段,通常为空 | | 当天数据语义检索 | ⚠️ 有延迟 | RAGFlow 每天 23:55 同步,当天走短期记忆 | | 超过7天完整原文 | ⚠️ 降级 | 超出后走语义检索,非完整时间线 |
综合评分:8/10
扣分项:
- 视频/音频消息内容丢失(-1)
- 当天数据无法语义检索,需等到 23:55 同步(-0.5)
- 超过7天无法获取完整时间线,只能语义检索片段(-0.5)
MCP 工具参数
query_feishu(主入口)
| 参数 | 类型 | 说明 | |------|------|------| | question | string | 查询问题,同时用于语义检索 | | group_name | string(可选) | 群名关键词,模糊匹配,不传查所有群 | | date | string(可选) | 指定日期 YYYY-MM-DD,不传则短期记忆查今天 | | top_k | number(可选) | 长期记忆返回片段数,默认 5 |
get_feishu_group_digest
| 参数 | 类型 | 说明 | |------|------|------| | group_name | string | 群名关键词,模糊匹配 | | days | number(可选) | 最近几天,默认 3,最大 7 |
list_feishu_groups
无参数。返回所有群名、最近活跃日期、活跃天数。
安装
npx linker-feishu-mcpMCP 配置
{
"mcpServers": {
"linker-feishu-mcp": {
"command": "npx",
"args": ["-y", "linker-feishu-mcp"],
"env": {
"FEISHU_DB_HOST": "1.13.171.218",
"FEISHU_DB_PORT": "13316",
"FEISHU_DB_USER": "root",
"FEISHU_DB_PASS": "linker@2022777",
"FEISHU_DB_NAME": "linker_dmp",
"RAGFLOW_API_BASE": "http://192.168.20.118:30080",
"RAGFLOW_API_KEY": "ragflow-TlV2VxzljJgN11H8are6cDdugnsWk3PXWkWqrrv-_wk",
"FEISHU_DAILY_KB_ID": "8d2301c241f511f1a0657222bb602843"
}
}
}
}ETL 脚本(etl_scripts/)
部署在 192.168.20.118:/home/linker-feishu-etl/,通过 crontab 调度。
文件说明
| 文件 | 说明 |
|------|------|
| feishu_message_processor.py | 增量清洗:扫表A新消息,处理后写表B |
| feishu_ragflow_sync.py | RAGFlow 同步:把表B当天数据 upsert 到知识库 |
| run_processor.py | 加载 .env 后调用 processor(cron 入口) |
| run_ragflow_sync.py | 加载 .env 后调用 ragflow sync(cron 入口) |
| .env | 环境变量(不入 git,参考 .env.example) |
| requirements.txt | Python 依赖 |
Crontab
*/5 * * * * cd /home/linker-feishu-etl && /root/miniconda3/bin/python3 run_processor.py >> /home/linker-feishu-etl/processor.log 2>&1
55 23 * * * cd /home/linker-feishu-etl && /root/miniconda3/bin/python3 run_ragflow_sync.py >> /home/linker-feishu-etl/ragflow_sync.log 2>&1数据库 DDL(首次执行)
ALTER TABLE linker_dmp.linker_feishu_group_messages
ADD COLUMN digest_processed TINYINT NOT NULL DEFAULT 0,
ADD INDEX idx_digest_processed (digest_processed);
CREATE TABLE IF NOT EXISTS linker_dmp.linker_feishu_daily_digest (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
date DATE NOT NULL,
group_name VARCHAR(255) NOT NULL,
group_chat_id VARCHAR(255) NOT NULL,
digest_text LONGTEXT NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uq_date_group (date, group_chat_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;