---
name: feishu-project-mcp
description: >
  连接飞书项目(Meegle) MCP Server，查询和管理工作项、待办、商机、客诉等。
  支持48个MCP工具。当需要拉取飞书项目数据、查询审批/客诉/商机/工作项、
  或自动化审批流转时触发。
triggers:
  - 飞书项目
  - 飞书空间
  - 销售管理空间
  - MCP飞书
  - 审批流转
  - 待办盘点
  - 客诉追踪
  - 商机Pipeline
---


# 飞书项目 MCP 集成

通过 MCP Server 直连飞书项目(Meegle)，48个工具覆盖空间查询、工作项CRUD、审批流转、排期管理等。

## 前置条件

**`mcp` Python SDK**：Hermes 必须安装 `mcp` 包才能注册 MCP 工具。缺失时 MCP 工具静默不出现，`hermes mcp list` 仍显示 `✓ enabled` 但工具不可用。

- **Python >= 3.10 必需**：macOS 系统 Python 是 3.9，不兼容。需用 Homebrew Python（本机路径：`/opt/homebrew/bin/python3.13`）。
- **安装命令**：
  ```bash
  /opt/homebrew/bin/python3.13 -m pip install mcp --break-system-packages
  ```
- **验证**：`/opt/homebrew/bin/python3.13 -c "import mcp; print('OK')"`
- **Hermes 重启**：安装后需重启 Hermes 进程，MCP 工具在启动时注册。

## 连接方式

### 商机/客诉批量提取（视图API模式，2026-07-11 攻克）

**核心突破**：直接用 `get_view_detail` + 视图ID 批量获取528条商机和64条客诉。

```python
# Step 1: 从飞书页面URL提取 view_id
# URL: https://project.feishu.cn/xsguanli/storyView/sm7MYQiNg
# → view_id = "sm7MYQiNg"
# URL: https://project.feishu.cn/br-shgl/workObjectView/khts/TDWUJhYHg
# → view_id = "TDWUJhYHg"

# Step 2: 批量获取
view = mcp('get_view_detail', {
    'project_key': '6593cd71471290e3cc6be6e6',  # 或售后管理PK
    'view_id': 'sm7MYQiNg',
    'page_size': 50, 'page_num': 1
})
# 返回 work_item_list，每项含 work_item_attribute + work_item_fields

# Step 3: 逐条查关联客户
for item in view['work_item_list']:
    wid = item['work_item_attribute']['work_item_id']
    relations = mcp('list_workitem_relations', {'project_key': pk, 'work_item_id': wid})
    # → 找包含"客户关联"的relation，用其relation_id查询linked customer
```

**⚠️ 关键：relation_id 必须精确，不能用推测的**
- 商机→客户关联: `relation_1706630317962`（实测正确）
- 商机→客户关联（错误推测）: `relation_1706635236372`（返回0，但是另一个关联）
- 客户→联系人关联: `relation_1715033831836`

**⚡ 二级跳转：客诉→销售订单→客户**
客诉（售后管理空间）不直接关联客户，而是关联销售订单：
1. 客诉 `list_related_workitem` → 销售订单（relation: 客户投诉单-销售订单，id=`1727283754885`）
2. 销售订单 `list_workitem_relations` → 找含\"客户\"的relation → `list_related_workitem` → 客户
3. ⚠️ 每笔销售订单的客户关联relation_id不同，需动态获取（不能硬编码）

实测结果：64条客诉→43家客户。

**项目→客户关联（客户项目管理空间）**
项目（csrw/test）直接关联客户：
1. `get_view_detail({project_key: CLIENT_PK, view_id: 'uAhLe5eIR'})` → 64条项目
2. `list_related_workitem(relation_id=...relation_1712924598201)` → 客户
3. 实测：64条项目→43家客户

### 客户档案页面架构

详见 `references/customer-profile-page-pattern.md`：
- 列表→详情双视图 + CSV导出 + IMA统计卡 + iframe决策链嵌入 + localStorage待办
- 决策链画板全宽1200px、3:2比例、用户已登录飞书时iframe可交互编辑

**各维度飞书详情链接格式**：
| 维度 | URL |
|------|-----|
| 联系人 | `https://project.feishu.cn/xsguanli/lxr/detail/{id}` |
| 商机 | `https://project.feishu.cn/xsguanli/story/detail/{id}` |
| 项目 | `https://project.feishu.cn/csrw/test/detail/{id}` |
| 客诉 | `https://project.feishu.cn/br-shgl/khts/detail/{id}` |

**视图ID发现方法**：当MCP `search_view_by_title` 无结果时，用 Chrome AppleScript 直接导航到飞书空间页面，从 `window.location.href` 提取 view_id。

### 客户档案全维度架构

六维度数据聚合：`references/customer-profile-pattern.md`
- 💰 ERP价格（本地JSON）
- 🔗 决策链（MQL WHERE精确查询）
- 👤 联系人（list_related_workitem, relation_id）
- 💼 商机（get_view_detail + list_related_workitem）
- 🔴 客诉（get_view_detail + 二级跳转: 客诉→订单→客户）
- ✅ 待办（localStorage，按客户隔离）
- 🏗️ 客户项目（同模式，待扩展）

Chrome AppleScript 控制：`references/macos-chrome-applescript.md`
- 导航、提取 innerText、点击视图链接、获取 view_id
- 前置条件：Chrome → 查看 → 开发者 → 允许Apple事件中的JavaScript

### ⚠️ 大批量分页拉取：直连 MCP 脚本模式（2026-07-24 实战）

当任务要求拉 **5+ 页** MQL 结果（如"拉 10 页金额字段写 JSON"），不要经 Hermes MCP 工具逐页拉——每页 ~45KB 原始 JSON 会灌满上下文，大结果还会被持久化到 `/var/folders/.../hermes-results/tool_*.txt` 需二次读取。

**正确做法：用脚本直连 Meego MCP HTTP 端点**，在进程内完成「拉取→解析→去重→写盘」，上下文零污染：

- 端点和凭据就在 `~/.hermes/config.yaml` 的 `mcp_servers` 节（`url` + `X-Mcp-Token`），普通 HTTP POST JSON-RPC 即可调用，无需任何 SDK。
- 模板脚本：`scripts/mcp_direct_pull.py`（改 MQL 模板、OFFSET 范围、输出路径即可复用）。脚本已处理三个坑：
  1. `initialize` 握手 + `Mcp-Session-Id` 头传递；
  2. 响应可能是 SSE 包装（`data:` 行），需抽取；
  3. `content[0].text` 尾部混有 `\nlog_id: xxx`，且外层可能是 `{"result": "<内层JSON字符串>"}` 需二次 `json.loads`（与持久化文件解析坑同款，见下节）。
- 分页仍用 OFFSET 并发（无日期上界时 DESC 可靠）；脚本内按物流单号等业务键去重，首条胜出。
- 实测：10 页（OFFSET 500–950，500 原始行）→ 221 个唯一物流单号，一次脚本运行完成。
- ⚠️ **持久化行为不确定（2026-07-24 batch3 实测）**：同一批 9 个 ~45KB 并发查询，5 个被持久化、4 个直接内联返回；内联结果**不会**写入 `hermes-results/`，重跑同一查询也不保证转为持久化。因此不要指望\"重跑拿文件路径\"，批量拉取一律首选直连脚本。
- ⚠️ **末页部分行属正常**：OFFSET 范围超出总数时末页行数 < 50（如总数 1425，OFFSET 1400 只回 25 行）。每页返回的 `list[0].count` 是总数，可用来预判末页。
- ⚠️ **跨批次页边界重叠**：同一物流单号的分录行可能被页边界切到相邻两个批次（batch2/batch3 实测 3 个 trackingNo 重叠）。批内去重不够，**父任务合并各批次 JSON 时必须按业务键再全局去重一次**。

### ⚠️ MQL 表名铁律：Python 后端必须用完整 type_key（2026-07-26 血泪验证）

**在 Python `urllib.request` 直连 MCP 时，表名必须用完整 `type_key`（如 `65ae1e403c87b152f3365ca6`），不能用 `api_name`（如 `kh`）！**

```sql
-- ❌ 错误（api_name — 报 metadata error: type 'kh' not found in project）
SELECT `name` FROM `6593cd71471290e3cc6be6e6`.`kh`

-- ✅ 正确（完整 type_key）
SELECT `name` FROM `6593cd71471290e3cc6be6e6`.`65ae1e403c87b152f3365ca6`
```

**已验证的正确 Python 后端 MQL 表名：**

| 类型 | api_name | ✅ Python MQL 正确表名 | 备注 |
|------|----------|----------------------|------|
| 客户 | kh | `65ae1e403c87b152f3365ca6` | 需 type_key |
| 活动 | sj | `65ae1e5d44338dbe7c39a29a` | 需 type_key |
| 销售订单 | xsdd | `662612aea6bb7089fea044ef` | 需 type_key |
| 商机 | story | `story` | 内置类型，api_name 可用 |
| 缺陷 | issue | `issue` | 内置类型，api_name 可用 |

> **注意**：Hermes MCP 工具（`mcp__feishu_project__search_by_mql`）内部做了 api_name → type_key 映射，所以工具调用时用 `kh`/`sj`/`xsdd` 仍可工作。但 **Python `urllib.request` 直连时必须用 type_key**。两套调用路径不可混用。

### 基本格式
```sql
SELECT field1, field2 FROM `空间名`.`工作项类型名`
  WHERE condition ORDER BY field LIMIT N OFFSET M
```
- **不支持 SELECT *** — 必须显式列出字段
- 字段名和类型名含中文需用反引号：`销售管理`.`销售订单`
- OFFSET 分页可靠无重复；session_id 分页早期观察到循环重复，但 2026-07-24 用 `session_id + group_pagination_list` 拉 500 条（10页×50）验证无重复 — 见下文「session_id 并行翻页模式」
- ⚠️ **OFFSET + DESC + 日期范围 = 分页假死**（2026-07-10 血泪教训）：`ORDER BY 创建时间 DESC` + WHERE含日期上界时，OFFSET翻页可能第2页就返回空，导致误判"只有50条"。**铁律：全量拉取用 `ORDER BY 创建时间 ASC`，不用 DESC**。详见 `references/activity-mql-pitfalls.md`
- ✅ **反例补充（2026-07-24）**：`销售管理.销售订单` 用 DESC + OFFSET（WHERE 仅日期下界 `创建时间 >= '2026-06-24'`，无上界）连续 30 页（1500 行，各页 count 恒定 1674）无假死，且支持**单轮并发多个独立 OFFSET 查询**（9 页并发全成功，无需 session_id）。结论：假死与"日期上界 + DESC"组合相关；仅下界场景 DESC+OFFSET 可用，健康检查看每页 `list[0].count` 是否恒定，合并时按（单据编号+货号#）/物流单号去重兜底
- WHERE 支持：`WHERE `创建时间` >= "2026-07-01"`
- MQL 的 `project_key` 是独立参数，不在 SQL 字符串中
- ⚠️ **分页停止条件不能仅靠 `len(page) < 50`**：DESC模式下中间页可能返回空但后面还有数据。安全做法：连续2页空才停止，或设 `max_expected` 上界

### ⛔ session_id 并行翻页模式 — 仅限手工/少量翻页，自动化禁用

> **🔴 2026-08-08 血泪教训：session_id 翻页在 cron/自动化脚本中会无限循环，严禁使用！**

**症状**：用 session_id + group_pagination_list 连续翻页时，**每页始终返回 50 条**，即使已超过数据总量。`len(items) < 50` 的停止条件永远不触发，翻页无限进行直到 max_pages 硬上限。

**实测（2026-08-08）**：
- 活动表 12,597 条 → session_id 翻了 300 页拉到 15,000 条仍不停（脚本被 timeout 截断）
- 客户表 1,693 条 → session_id 翻了 99+ 页拉到 4,950 条仍不停
- OFFSET 翻页完美停止：34 页精准结束（最后一页 43 条，再下一页 0 条）

**根因**：session_id 翻页的 `content[0].text` 返回结构与 OFFSET 模式不同，`list[i].count` 不可靠，数据边界判断失效。

**仅限手工短翻页**（<5 页，已知精确总数时可用）：
1. 第1次调用：正常 MQL，不传 `group_pagination_list`。取 `session_id` 和 `group_id`。
2. 第2~N页：`mql=""` + `session_id` + `group_pagination_list=[{"group_id":"1","page_num":N}]`。
3. ⚠️ 必须设硬上限 `max_pages` 防死循环。

### ✅ OFFSET 翻页模式 — cron/自动化首选（2026-08-08 验证可靠）

> **🔴 2026-09-09 血泪：MCP `search_by_mql` 的 LIMIT OFFSET 硬上限为 1000！**
> `LIMIT 50 OFFSET 1050` → `error=ErrMoqlInvalidArgument, LIMIT offset 1050 exceeds the maximum of 1000`。
> OFFSET 翻页最多拉 21 页 = 1050 行（offset 0..1000）。**表 >1000 行时 OFFSET 会静默截断**。
> 之前（2026-08-17）OFFSET 1250 还能用，说明该上限是 MCP 服务端近期新增的。
> **修复**：按 `start_time` 日期范围分段（每段 <1000 行）逐段拉取，再按 work_item_id 全局去重。
> 客户/活动/订单类型都有 `start_time` 字段可用于分段（中文「创建时间」报 syntax error，「created_at」报 attr not found）。

**自动化拉取唯一推荐方案**，cron job、大批量脚本必须用此模式：

```python
def pull_with_offset(mql, project_key, max_pages=300):
    """OFFSET 翻页 — 可靠停止，适合 cron 自动化"""
    all_items = []
    seen_ids = set()
    offset = 0
    empty_streak = 0
    
    for page in range(1, max_pages + 1):
        paginated_mql = f"{mql} LIMIT 50 OFFSET {offset}"
        result = mcp_call_simple(paginated_mql, project_key)
        items = parse_moql(result)
        
        if len(items) == 0:
            empty_streak += 1
            if empty_streak >= 2:
                break  # 连续2页空 → 真正结束
        else:
            empty_streak = 0
        
        # 按 work_item_id 去重（OFFSET 偶有边界重叠）
        for item in items:
            wid = item.get('work_item_id', '')
            if wid and wid in seen_ids:
                continue
            if wid:
                seen_ids.add(wid)
            all_items.append(item)
        
        offset += 50
    
    return all_items
```

**关键参数**：
- `max_pages=300`：硬上限防止意外（活动/订单等高频类型）
- `empty_streak >= 2`：连续2页空才停止（防止单页空是网络波动）
- `seen_ids` 去重：按 `work_item_id`（OFFSET 页边界可能有1条重叠）
- DESC + 仅日期下界（无上界）场景 OFFSET 可用，不会假死

**跨页漂移**（2026-07-24 实测）：并发翻页期间若有新数据写入，相邻页边界可能出现 1 条完全相同的行。合并批次时按整行 JSON 做跨页 exact-match 检查去重。

### 联系人（lxr）类型 — 决策链角色载体

联系人 MQL 字段：`联系人名称`, `电话`, `邮箱`, `work_item_id`

关系链：
- `联系人-客户关联` → 客户
- `联系人-商机管理关联` → 商机
- `联系人-线索管理关联` → 线索

### ✅ 决策链角色抓取（2026-09-07 攻克，纠正旧结论）

旧结论「决策角色、影响力等字段为表单自定义字段，MQL 不暴露」**只对 MQL SELECT 成立**。
**用 `get_workitem_brief(work_item_id, fields=["_all"])` 能完整拿到决策链角色字段**，这是拉客户决策链的正确姿势：

- `field_01e06d` = 联系人所在部门（如 研发/采购/仓库/分子研发部）
- `field_cd82a5` = 职务（如 研发工程师/经理/采购员/收货）
- `field_7aa285` = 联系人类别（关键联系人/一般联系人）
- `field_3fb3fb` 邮箱 / `field_b3af04` 手机 / `field_b445d1` 微信号
- `field_f828ac` 联系人关联商机（含商机名 → 可拼出「人→项目」映射）
- `field_3d3010`/`field_6b3789` 联系人对应/关联客户

**流程**：① 从客户 profile JSON 或 `list_related_workitem` 拿到该客户的联系人 work_item_id 列表 → ② 逐个 `get_workitem_brief(fields=["_all"])` 并行拉 → ③ 按 部门+职务+类别 分层拼决策链（决策层=关键联系人，研发/采购/仓储/质量 分层）。

⚠️ 白板 docx 决策链不必抓：`fetch_feishu_doc.py` 依赖飞书开放平台 docx 权限（需人工开 docx:document:readonly + 文档分享给 App），且画板块常无文本。**决策链数据真实落点在联系人(lxr)工作项，走 MCP get_workitem_brief 更可靠**。

### 注意事项

- `list_related_workitem` 可能超时，建议 **60s timeout + 3次重试**（实测30s不够）
- 批量查询时建立缓存：`{work_item_id: customer_name}`，可节省90%+的API调用
- **创建者≠销售员**：MQL `创建者` 返回统一自动化/集成账号（殷士海），非真实销售员。KPI部门拆分不能用创建者做归属
- **KPI严禁估算**：不能按目标占比分摊销售额到部门/个人。必须补全客户名后按真实客户归属计算
- URL格式：工作项详情 = `https://project.feishu.cn/{simple_name}/{type_key}/detail/{id}`，如活动商机用 `xsguanli/story/detail/`（非 `sj`）

### ⚠️ 批量生成防崩溃模式（2026-07-11 血泪教训）

在循环中逐条调用 MCP 批量生成档案时，`mcp()` 可能因网络波动返回 `None`。**必须对每个 `mcp()` 返回值做 None 检查**，否则 `TypeError: 'NoneType' object is not iterable` 导致整批中断。

```python
# ❌ 危险写法
r = mcp(...)
for item in r.get('data',{}).values():  # r 可能为 None → crash

# ✅ 安全写法  
r = mcp(...)
if r:
    for item in (r.get('data',{}) or {}).values():
        for i in (item or []):
            ...
```

**三重保护**：`if r:` + `r.get('data',{}) or {}` + `item or []`。每个环节都不能假设非空。

**续跑策略**：已生成的档案存在磁盘，通过检查 `existing` set 跳过，崩溃后修改脚本加防 None 保护直接续跑即可，无需从头开始。本次会话经历一次崩溃（20→中断，修复后43→全量完成）。

## ⚠️ 飞书URL短ID无法通过MCP解析（2026-07-10）

飞书项目分享链接使用短ID（如 `https://project.feishu.cn/xsguanli/workObjectView/sj/uslcQtLSg`），其中 `uslcQtLSg` 是**前端加密的 view_id**，不是 work_item_id。

**症状**：
- `url decode` 返回 `url_kind: view_workitem` + `view_id`，无 `work_item_id`
- `get_workitem_brief(view_id)` 返回空
- base36/base62/base64 解码均为无效 ID
- 浏览器打开需要飞书登录

**应对方案**：
1. 询问用户该链接的内容类型和标题关键词
2. 按日期/类型 MQL 搜索匹配的工作项
3. 示例：用户说"昨日活动日报" → 按 `创建时间 >= "昨天"` + `销售管理.活动` 全量拉取当日活动

**URL中的类型编码**：`/sj/` 可能代表 story(商机) 的 URL slug，具体映射因空间配置而异。

## 数据管道输出

### MCP→工作台集成模式（2026-07-10）

详见 `references/workbench-integration.md` — 完整架构（MCP→管道→JSON→HTML面板）、实现步骤、已集成入口清单。

客户价格表模式见 `references/customer-pricing-pattern.md` — ERP多年度订单聚合+货号#规格提取+交互式HTML面板。

## 详细资料（按需查阅）

> 以下文件不在本 SKILL.md 内，需要时再读；正文只保留每次都会用到的部分。

- **`references/auth-permission.md`** — 含 2 节：方式A：MCP Token 直连（推荐）、⚠️ MQL 字段级权限（2026-07-26 实战）
- **`references/data-pipeline.md`** — 含 14 节：价格单位提取（ERP→产品级）、客户概况提炼（客诉+订单+测试单+活动，2026-08-30 验证）、已验证字段（按工作项类型）、⚠️ 活动数据质量三大坑（2026-07-10 实测）、客户（kh）MQL 字段、关键发现：字段名映射
- **`references/details.md`** — 含 12 节：方式B：Meegle CLI（备选）、查询类（最常用）、编辑类、待办盘点、⚠️ 持久化大结果文件的解析坑（2026-07-24）、✅ 按跟进人过滤活动（2026-09-08 实测攻克）
- **`references/feishu-api.md`** — 含 5 节：⚠️ 活动 ≠ 商机（血泪教训）、审批阻塞检测、客诉追踪（2026-08-04 新增 MQL 直查方式）、⚠️ 工作项类型主页 URL（2026-07-25 发现）、飞书页面读取回退方案（2026-07-11）

### 既有参考文件（原正文未引用，此处补齐索引）

- **`references/api-server-pattern.md`** — API Server Pattern — 页面直连MCP
- **`references/blocker-analysis.md`** — 审批阻塞精确识别方法论（2026-07-10 实战教训）
- **`references/customer-profile-pipeline.md`** — 客户档案全维度数据管线
- **`references/decision-chain-automation.md`** — 飞书决策链自动化读写
- **`references/department-analysis.md`** — 按部门做月度经营分析（活动量 + 客诉进度 + 人员归属）
- **`references/direct-http-get-workitem-brief.md`** — Direct HTTP: get_workitem_brief 响应解析
- **`references/erp-ka-pipeline.md`** — ERP → KA 对比数据管道
- **`references/feishu-mcp-catalog.md`** — 飞书项目 MCP 工具完整目录（48 Tools）
- **`references/mql-persisted-output-parsing.md`** — MQL 持久化大结果解析模式（2026-07-24 验证）
- **`references/opportunity-field-mapping.md`** — 商机（story）自定义字段完整映射
- **`references/org-discovery-via-mcp.md`** — Discovering Team Members via Feishu MCP
