Skip to main content

BasePilot

面向企业交付的飞书多维表格 MCP Server —— 用 MCP 工具把多维表格变成 Claude Code / Cursor 可安全读写的业务台账。

CI Python License tests eval

English · 简体中文


这是什么

中小企业已经在用飞书多维表格承载业务台账(库存、广告、差评跟进), 数据靠人工从 Seller Central / 广告后台导 CSV 再粘贴进去,每天 1-2 小时。 公司想上 AI,但第一件事就卡住了:

卡点 飞书返回 根因
AI 给人员字段传了字符串 1254066 UserFieldConvFail 必须是 [{"id": "ou_xxx"}] 数组对象
AI 给日期字段传了秒级时间戳 1254064 DatetimeFieldConvFail 必须是 13 位毫秒,差 1000 倍
AI 给单选字段传了数组 1254062 SingleSelectFieldConvFail 必须是字符串,不是数组
AI 写得稍快一点 1254291 Write conflict 同一数据表不支持并发写,官方建议加 0.5-1秒延迟

这不是技术选型问题,是没有人把多维表格的真实约束包一层。 业务等不了,AI 落地就停在这里 —— 这是很多「客户买过 AI 工具但没用起来」的真实原因。

BasePilot 就是那一层。


看图说话(全部为真实运行输出,非手绘)

1. 入口宽容,出口严格—— 适配层把 LLM 的错误输入吃掉

scripts/demo_coerce.py 把LLM 最常犯的四种错误喂给适配层,看它们被自动纠正:

coerce 演示

2. 业务诊断:15 个环节逐条打分,明确劝退 2 个

诊断报告

四象限分布(7 个不需要 AI,4 个 AI 主导,2 个明确劝退):

四象限

3. 评测:9 项指标全部实算,无一手写

评测指标

4. 离线全量门禁:lint + 类型 + 测试 + 评测 + 文档校验

verify

5. cassette 重放:真实租户交互在 CI 可复现(已脱敏)

cassette 重放

6. 交付文档链:五份「报告即代码」自动生成

交付手册

排障 SOP由 errors.py 自动生成,与代码零漂移:

排障 SOP

全部截图由 scripts/make_screenshots.py 执行真实命令后渲染,不存在手绘图。 脚本内置「解释器污染」防护 —— 用错Python 环境会导致场景包静默降级, 生成数字错误的图,已加断言阻止出图。


架构

┌─ MCP 工具层 ──────────────────────────────────────────────┐
│  describe_table · create/update/delete · search            │
│  batch_upsert · dry_run_create · diagnose_scenarios        │
└────────────────────────┬───────────────────────────────────┘
                         │
┌─ 引擎五层 ────────────────────────────────────────────────┐
│  serialization.py  per-table 锁 + 0.5s 节流                │
│  client.py         串联调用链 · upsert_records             │
│  coerce.py         13 类编码器 + normalize_key 解码        │
│  ratelimit.py      分桶限流(write/search/list 独立)│
│  auth.py           token 缓存 + asyncio 单飞               │
└────────────────────────┬───────────────────────────────────┘
                         │
┌─ 横切三线 ────────────────────────────────────────────────┐
│  config.py飞书约束常量(每个数值标注官方出处)      │
│  errors.py       34 条错误码 → 客户现场动作               │
│  cassette.py     录制/重放 + 凭证与租户标识符脱敏           │
└────────────────────────┬───────────────────────────────────┘
                         │
              https://open.feishu.cn/open-apis

分层原则:不是把 API 包装成工具,而是把飞书的真实约束收敛到三层里。 工具层只表达业务意图(batch_upsert),约束由引擎层统一兜住 —— 否则同一条记录走不同入口会得到不同结果(见 ADR-004)。


三个适配层(核心)

不是把 API 包装成工具,而是治理飞书的真实约束。

1. 鉴权层 —— token 缓存 ✅

tenant_access_token 有效期 7200 秒。官方明确:剩余有效期小于 30 分钟时返回新 token, 大于等于 30 分钟时返回原 token。所以刷新窗口必须落在 [0, 30min] 区间内, 否则会拿到同一个 token,白白消耗配额。

实现:进程内缓存 + asyncio.Lock 单飞(并发下只换一次,其余复用)。

实测指标:100 次业务请求 → 向飞书换 token 1 次。 (tests/test_auth.py::test_100_requests_fetch_token_once,可复现)

2. 并发层 —— 单表写串行 ✅

官方错误码 1254291 的排查建议原文:「在接口与接口之间增加 0.5 或 1 秒的延迟」; 1254607 补充说明底层「基于版本维度的串行方式,不支持并发」。

实现:per-table_id 的锁(不是全局锁 —— 不同数据表之间仍可并行)+ 0.5s 请求节流, 主动规避 1254291 而不是撞上再重试。

实测指标:200 次压测下,单表最大并发写 = 1,1254291 计数 = 0。 (tests/test_client.py::test_same_table_writes_are_serialized,可复现)

3. 类型层 —— 字段编码适配 ✅

按 13 类字段自动编码为官方要求格式,并对不可写字段 fail-fast。 另有 normalize_key() 解码:API 读回的文本字段是富文本数组、URL 是对象, upsert 唯一键提取必须归一化,否则「已存在」判为「不存在」导致重复创建 (详见 docs/adr/006-read-write-schema-asymmetry.md)。

type 字段 正确格式 常见错误
3 SingleSelect str ❌ 传数组
4 MultiSelect list[str]
5 DateTime 13 位毫秒 ❌ 传秒级
7 Checkbox bool ❌ 传 "true"
11 User [{"id": "ou_xxx"}] ❌ 传字符串
15 Url {"link": "...", "text": "..."} ❌ 只传字符串
17 Attachment [{"file_token": "..."}] ❌ 传本地路径
18/21 关联字段 list[str](record_id)
19/20/1001-1005/3001 公式/查找引用/创建时间等 拒绝写入 ❌ 尝试写系统字段

设计原则:入口宽容,出口严格 —— 允许 LLM 传 ISO 日期、秒级时间戳、单元素数组, 适配层内部统一转成官方格式。LLM 出错的空间由适配层吃掉,而不是把 1254064 抛给客户。

实测指标:19 条黄金用例,字段编码正确率 100%,不可写拦截率 100%。 (eval/runner.py 实算,make eval 可复现)


MCP 工具(8 个)

工具 作用
describe_table 读表结构与字段类型
create_records / update_records / delete_records 增 / 改 / 删(删除默认 dry-run)
search_records 按条件检索
batch_upsert 按唯一键幂等 upsert(自动拆 create/update)
dry_run_create 预演:跑完整编码链路但零真实写请求
diagnose_scenarios 业务诊断:判断哪些环节值得上 AI

接入 Claude Code(免克隆,经 uvx 直接从 PyPI 运行):

{
  "mcpServers": {
    "basepilot": {
      "command": "uvx",
      "args": ["basepilot", "serve"],
      "env": {
        "BASEPILOT_APP_ID": "cli_xxx",
        "BASEPILOT_APP_SECRET": "xxx",
        "BASEPILOT_APP_TOKEN": "bascnxxx",
        "BASEPILOT_TABLE_INVENTORY": "tblxxx"
      }
    }
  }
}

远程模式(HTTP / SSE)

默认 serve 走 stdio,供 Claude Code / Cursor 本地接入 —— 凭证留在本机环境变量, 这是推荐用法。需要把 Server 部署到服务器、供多人或多客户端远程接入时, 用 HTTP 传输(FastMCP 4.x,streamable-http):

basepilot-mcp serve --transport http --host 127.0.0.1 --port 8000
# 客户端接入 http://127.0.0.1:8000/mcp/

basepilot-mcp serve --transport sse --port 8000        # 旧版 SSE 协议,挂载 /sse/
basepilot-mcp serve --transport http --path /custom    # 自定义挂载路径
  • --host 默认 127.0.0.1(仅本机);--port 默认 8000;--path 默认用 FastMCP 内置路径。
  • 鉴权注意:MCP 层没有内置鉴权 —— 能连上端口就能调用全部写工具, 等同于你的飞书 app 权限。不要把端口直接绑 0.0.0.0 暴露公网: 请放内网,或在前面加带鉴权的反向代理(nginx / Caddy + Bearer Token / mTLS)。
  • 飞书凭证只存在服务端环境变量(BASEPILOT_APP_ID / BASEPILOT_APP_SECRET), 不经过客户端与网络传输。

当前进度

全部模块已完成,已在真实飞书租户跑通全链路。 每个指标都由代码实算 (make eval),未实测的不会写成已达成 —— 这是本项目的铁律。 make verify 离线全绿(309 tests,含门禁脚本自身 3 个测试);make live-smoke 连真实飞书跑通 鉴权→建表→写入→读回→清理;跨境三表 batch_upsert 幂等(第一次全新增, 第二次全更新无重复)。

模块 状态
飞书约束常量(config.py) ✅ 已完成,每个数值标注官方出处
token 缓存(auth.py) ✅ 已完成,100 请求换 1 次 token 已实测断言
错误码处置(errors.py) ✅ 已完成,34 条规则,含客户现场指引
接口分桶限流(ratelimit.py) ✅ 已完成
字段编码适配(coerce.py) ✅ 已完成,13 类编码器 + normalize_key 解码
客户端与并发控制(client.py / serialization.py) ✅ 已完成,200 压测单表并发=1
MCP 工具层(8 个工具) ✅ 已完成(FastMCP,stdio / HTTP / SSE 可跑)
业务诊断打分器(diagnosis.py) ✅ 已完成,15 场景四象限
cassette 录制/重放(cassette.py) ✅ 已完成,真实交互 CI 可重放
跨境三表场景包(src/basepilot/scenarios/cross_border/__init__.py) ✅ 已完成,真实租户幂等验证
交付文档(playbook/training/troubleshooting/weekly_ops) ✅ 已完成,排障 SOP 由代码生成

判断进度的方式:uvx basepilot doctor(如实列出已实现项)。


快速开始

第 1 步:凭证从哪来

  1. 登录 飞书开放平台 →「创建企业自建应用」, 拿到 App ID(cli_ 开头)与 App Secret (官方指引)。
  2. 在应用后台「权限管理」开通多维表格权限(bitable:app),然后创建版本并发布。
  3. 把凭证配进环境变量,跑凭证引导向导 —— 它会真实调飞书 OpenAPI 验证凭证连通性、验证你的 app_token / table_id 可达, 最后输出可直接粘贴的 mcpServers 配置(uvx 与本地开发两份):
export BASEPILOT_APP_ID=cli_xxx
export BASEPILOT_APP_SECRET=xxx
basepilot-mcp init         # 三步引导:验证凭证 → 验证数据表 → 输出 mcpServers JSON

非交互环境(CI / 管道)里向导不会干等输入:检测到非 TTY 会打印 完整的环境变量配置指引后以退出码 2 退出。

第 2 步:跑起来

git clone https://github.com/Peterwong666/basepilot.git
cd basepilot
uv sync                    # 或 make setup

cp .env.example .env       # 填入你的飞书应用凭证(或直接沿用上面的 export)

make verify                # 离线全量校验:lint + 类型 + 测试 + 评测 + 文档校验
make eval                  # 实算评测指标(并发峰值/重试成功率/dry-run 一致率)
make live-smoke APP=<app_token> TBL=<table_id>   # 连真实飞书跑全链路
python scripts/seed_cross_border.py                # 跨境三表灌数(幂等,可重复)
make adoption APP=<app> TBL=<表ID> KEY=<唯一键>    # 上线后促活三指标,出周报

所有脚本都用项目自己的 venv 解释器。用系统 Python 可能缺少 PyYAML 导致 场景包静默降级为fallback(4 条内置场景),跑出的数字是错的 —— scripts/diagnose.py 等已通过 make verify 的门禁检查,但请优先用 make / uv run。


安全设计

  • 删除护栏:delete_records 默认 dry_run=true,须显式 confirm=true 才真删 —— 防 LLM 幻觉批量删库。
  • 不可写字段拦截:公式 / 查找引用 / 创建时间 / 自动编号等 13 类系统字段 fail-fast 拒绝写入, 不允许静默写坏数据。
  • 凭证隔离:.env 已 gitignore;cassette 里app_id / app_token / table_id / record_id 全部替换为占位符(cassette.redact_identifiers)—— 这些不是密钥,但会暴露租户身份。
  • 发布前门禁:tests/test_no_secrets_in_repo.py 在 CI 里扫描仓库, 检出真实租户标识符 / 泄露的 .env / 本机绝对路径即失败;失败信息只报位置不回显值。

非目标(Non-goals)

主动划边界比假装覆盖更可信。 本项目不做:

  • ❌ 删除整个多维表格(Base)—— 不可逆,风险远高于收益
  • ❌ 授予/变更权限 —— 应由表owner 在界面完成
  • ❌ OAuth 授权流程 —— 定位是企业内部工具 + 开源交付包
  • ❌ 直接发送飞书消息 —— 外部可见副作用应由上层决策
  • ❌ 事件订阅(长连接)—— 需公网与连接数管理,且不解决当前核心痛点

与官方 lark-mcp 的关系

官方 @larksuiteoapi/lark-mcp 把飞书 API 直出为 MCP 工具,覆盖度更广(40+ 工具)。 本项目不做覆盖度竞争,做交付可靠性:

能力 官方 lark-mcp BasePilot
单表写串行 + 节流 ✗ ✓
字段类型预检(dry-run) ✗ ✓
不可写字段拦截 ✗ ✓
错误码分类处置 + 现场指引 ✗ ✓
幂等键重生成 部分 ✓
离线录制回放测试 ✗ ✓
业务语义工具(CSV 同步 / 风险标注 / 差评闭环) ✗ ✓
客户交付手册 + 排障 SOP ✗ ✓

详见 docs/adr/005-why-not-wrap-official-lark-mcp.md。


FDE 交付方法论五连(报告即代码)

报告即代码:数字从 diagnosis.py/cassette/eval 实算,改源数据重跑自动更新,测试锁结构。 入口从**docs/delivery/delivery_handbook.md** 进 —— 它串起五份并标注每份的数字口径。

文档 回答 生成脚本
docs/delivery/discovery_report.md 先做哪个(五维诊断 + 四象限 + 劝退) scripts/gen_discovery_report.py
docs/delivery/solution_blueprint.md 怎么做(top3 环节展开成可签字方案) scripts/gen_solution_blueprint.py
docs/delivery/case_backtest.md 凭什么信你(真实证据回测当初预测) scripts/gen_case_backtest.py
docs/delivery/expansion_matrix.md 能复制到哪(15 场景归纳 4 种能力模式) scripts/gen_expansion_matrix.py
docs/delivery/rollout_calendar.md 按什么节奏铺(4 波次先稳后难推广日历) scripts/gen_rollout_calendar.py

文档

文档 内容
docs/PROJECT_RETROSPECTIVE.md 项目复盘:主要节点(问题→分析→解决)+ 结构分析,全面了解项目从这里入手
docs/delivery/delivery_playbook.md 客户现场 5 步交付手册
docs/delivery/delivery_handbook.md 交付手册合集页(五份方法论的入口与数字口径表)
docs/delivery/troubleshooting.md 错误码 → 现场动作排障 SOP(由 errors.py 自动生成)
docs/delivery/client_training.md 客户培训手册(给业务方的一页纸)
docs/delivery/weekly_ops.md 上线后 8 周运营手册(make adoption 出促活周报)
docs/limitations.md 已知限制与 badcase(含真实失败模式)
docs/adr/ 架构决策记录(含 006「读结构≠写结构」—— cassette 实证)
tests/cassettes/ 真实租户交互录制(脱敏),CI 可重放

开发

make verify    # 一条命令跑全部门禁(lint + mypy strict + pytest + eval + docs-check)
make docs      # 重新生成全部交付文档

技术栈:Python 3.11+ · httpx(裸客户端,不依赖官方 SDK)· FastMCP(工具层)· PyYAML(场景包)· pytest + respx(离线回放)· ruff + mypy strict。


License

MIT


English

BasePilot is a Feishu (Lark) Base MCP Server for enterprise delivery — it turns multi-dimensional tables (Base) into business ledgers that Claude Code / Cursor can safely read and write.

Why

Companies already keep inventory / ads / review tracking in Feishu Base. The moment they want AI involved, they hit these wallss:

Blocker Feishu error Root cause
AI passes a string to a user field 1254066 must be [{"id": "ou_xxx"}]
AI passes a second-level timestamp 1254064 must be 13-digit ms
AI passes an array to a single-select 1254062 must be a string
AI writes slightly too fast 1254291 a table does not support concurrent writes

This isn't a technology-selection problem — nobody wrapped Base's real constraints in a layer. AI adoption stalls here. BasePilot is that layer.

Three adaptation layers

  1. Auth — token cache with single-flight lock. Measured: 100 business requests → 1 token refresh.
  2. Concurrency — per-table_id lock + 0.5s throttle, so 1254291 is avoided proactively.
  3. Types — 13 field encoders, "lenient in, strict out". Refuses writes to computed/system fields.

8 MCP tools

describe_table, create_records, update_records, delete_records (dry-run by default), search_records, batch_upsert (idempotent), dry_run_create (zero real writes), diagnose_scenarios (which business steps deserve AI).

Verification

make verify runs lint + mypy strict + tests + eval + doc-link checks. All 9 eval metrics are computed from real code, never hand-written.

Docs

Delivery methodology and architecture decisions live in docs/. Start with docs/PROJECT_RETROSPECTIVE.md. All delivery docs are "reports as code" — numbers come from real computation.

MIT licensed.

Metadata

Release files for basepilot 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for basepilot 0.1.0
File Size Uploaded Provenance
basepilot-0.1.0.tar.gz 767.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for basepilot 0.1.0
File Interpreter ABI Platform
basepilot-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 836.5 kB

Release files / basepilot-0.1.0.tar.gz

Download URL basepilot-0.1.0.tar.gz
Size 767.0 kB
Tags Source
SHA-256 checksum
How to use checksums
3d3563293a2e86daf06bf0e17245df410bf32010b50103eecc387542d71454cf
BLAKE2b-256 checksum
How to use checksums
d953068b93411186009161eece9298f34353d151a1dd0e57a70529390106a6cd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Release files / basepilot-0.1.0-py3-none-any.whl

Download URL basepilot-0.1.0-py3-none-any.whl
Size 69.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e0fcfbc0a873f6de86216efb0d47895d278d84ce7436384c659b174d620b6461
BLAKE2b-256 checksum
How to use checksums
f0984a5574e384b98f83f7f80f8450a356ae5c426e1ff97203c2d86d4c83b71f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Security for basepilot 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for basepilot-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page