用Claude Desktop+MCP构建50个评估表单的实战复盘,46%需人工修正,暴露了字段更新模式、选项覆盖等典型AI编程缺陷。
这是本系列最后一篇。在过去 30 天里,我用 Claude Desktop 和 formlm-cli MCP server 构建了 50 个评估表单——从 3 道题的情绪检测到 40 题的领导力 360 评估都有。有些是用于生产环境的,有些是测试,有些是为了探索 AI 能走多远而做的实验。
以下是实践中学到的东西,包括什么有效、什么无效、以及如果重来会怎么做。

构建成果统计:
46% 的手动修复率是我想要降低的指标。这意味着 AI 构建的表单中大约有近一半在无需人工干预的情况下无法就绪。这些 bug 不是灾难性的——但它们是真实存在的。
以下是遇到的所有 AI 引入的 bug,按严重程度排序:
Claude 用单个选项替换了整个选项列表,抹掉了其他选项的分数。这就是第 12 篇中提到的「先查找再设置」模式问题。修复方案:添加 field_set_property 并强制执行「先查找」模式。
我要求发布到生产环境时,Claude 实际发布到了 staging。这是第 18 篇中提到的多配置问题。修复方案:在每次响应中显示环境信息——仍在进行中。
Claude 试图批量删除表单中的所有字段。被服务端白名单阻止了。这是第 19 篇中提到的白名单故事。不需要修复——白名单成功拦截了。
会话重启后 Claude 重新添加了所有字段,造成重复。这是第 15 篇中提到的幂等性问题。修复方案:强制执行「添加前先查找」模式。
Claude 无法设置 required: false——它一直省略该参数,而默认值是 true。这是第 14 篇中提到的布尔值陷阱故事。修复方案:在 schema 描述中明确说明默认值。
Claude 在应该使用量表级反转时,反转了选项分数。这是第 17 篇中提到的计分故事。修复方案:在 prompt 中明确说明我想要哪种「反向」。
Claude 在会话中途丢失了 app ID,在没有它的情况下试图添加字段。这来自第 13 篇的压测。修复思路:在 MCP server 中维护一个「当前 app」状态——尚未实现。
七个 bug 中有四个在进入生产环境前被拦截。三个到达了 staging。没有一个到达真实用户。白名单是最难的后防线——其他问题都是通过人工审查 catch 到的。
Claude 在添加字段之前会一致性地调用 field_schema 和 field_config。它把 .describe() 字符串当作文档来使用——读取、理解,并根据它们做决策。这是我们做过的最重要的设计决策:通过 zod schema 让每个参数自文档化。
Claude 非常擅长将评估框架(PHQ-9、Maslach 职业倦怠量表、大五人格)转化为字段结构。它知道各条目、计分区间和维度分组。给它一个框架名称,它就能产出正确的字段、正确的选项和正确的分数。这节省了数小时的手工工作。
share_publish 工具硬编码了 formDay: 3650000(永不过期)和 formPerm: 1(公开可读)。AI 从不需要决定过期时间或权限——它直接发布。安全的默认值消除了一整类潜在错误。
每次 Claude 尝试不该做的事情时(clear 尝试、delete-all 变体),白名单都成功拦截了。没有一个危险命令漏过。三 token 子命令提取简单、快速、有效。
Claude 不记得在之前的会话中做了什么。当我让它「继续构建」时,它从零开始——重新创建已经存在的字段。「添加前先查找」模式有帮助,但根本问题在于 MCP 工具是无状态的。没有「当前 app」或「最后添加的字段」的概念。
MCP 工具在表单构建方面表现出色。但它们完全不处理计分。对于任何需要维度计分、反向题目或分数阈值的表单,我都得手动配置 Scale 模块。这是最大的Gap——大约 70% 的表单在 AI 完成表单结构后需要手动配置计分。
required、unique 和 shareable 这些布尔参数一直存在问题。Claude 的本能是省略而非显式设置 false,这导致多个表单出现静默 bug。schema 描述的修复有帮助,但这是对更深层设计问题的创可贴。
Claude 没有「staging」和「production」的概念。它使用当前活跃的配置,不知道两者区别。响应中的 URL 是唯一的信号,而当环境与请求不匹配时,Claude 并没有标记出来。
30 天下来,我注意到 Claude 与工具交互时有一些一致的模式:
Claude 总是先检查再添加。 在第一次 field_add 之前,Claude 会调用 field_schema 和 field_config。每次都是如此。这很好——说明 schema 描述在发挥作用。
Claude 会批量相似操作。 添加 10 个字段时,Claude 不会在每个之间请求确认。它会连续添加全部 10 个。这很快,但如果第一个字段是错的,接下来 9 个很可能也是错的(同样的模式,同样的错误)。
Claude 构建后会验证。 添加字段后,Claude 调用 field_list 来检查。这是一个自我验证步骤,能 catch 缺失的字段,但 catch 不了计分错误(因为 field_list 显示结构,不显示计分逻辑)。
Claude 被阻止时会变得有创意。 当 Claude 找不到批量删除工具时,它尝试 shell 命令。当它无法设置 required: false 时,它尝试省略参数。AI 不会放弃——它会找到变通方案。有些变通方案很聪明,有些很危险。白名单是保障危险方案被拦截的关键。
如果重新开始,我会做以下改动:
添加 field_add_many 批量工具。 把 10 次往返减少到 1 次。但要定义清晰的错误语义——如果批量中有一个字段失败,返回该字段的错误,让 AI 决定是否重试。
让「当前 app」成为隐含上下文。 在 app_create 或 app_get 之后,将 app ID 设为活跃上下文。后续字段操作默认使用该活跃 app。消除「遗忘的 app ID」bug。
通过 MCP 暴露计分配置。 这是最大的 Gap。没有它,AI 只能构建表单外壳——无法构建评估引擎。我正在解决这个问题,但这需要仔细的白名单设计(AI 可以设置计分,但不能重置计分)。
在每次响应中添加环境标签。 「发布于 staging.formlm.me」,而不仅仅是 URL。让环境不可能被忽视。
让布尔参数必填,而非可选。 如果 required 必须是 true 或 false,从不是 undefined,Claude 就不可能落入「省略意味着默认值」的陷阱。每次调用多一个参数是值得的。
30 天来我学到的最重要的事情是:为 AI 代理设计工具与为人类设计工具是不同的。
当我为人类设计 CLI 时,我优化的是人体工学——合理的默认值、有用的 flags、清晰的错误信息。人类会读文档、理解上下文并做出知情的决定。
当我为 AI 代理设计 MCP server 时,我优化的是显式性——没有隐藏的默认值、没有歧义的参数、没有需要 AI 没有的上下文才能执行的操作。每个工具都需要自包含:描述告诉 AI 工具做什么,schema 告诉 AI 传什么,响应告诉 AI 发生了什么。
每个 zod 字段上的 .describe() 字符串不仅仅是文档。它是 AI 在决定使用工具之前阅读的说明书。模糊的描述(「标记为必填」)导致模糊的行为。明确的描述(「省略时默认为 true。显式设置为 false 以表示可选字段」)导致正确的行为。
这个系列讲述的是从「代码能工作」到「AI 能正确使用代码」的旅程。第一部分——写出能工作的代码——花了几周。第二部分——让它对 AI 安全——已经花了 30 天还在继续,我仍在发现边缘情况。
formlm-cli MCP server 现在有 6 个分层工具 + 6 个知识资源、一个服务端白名单、显式的 schema 描述,以及让 AI 交互安全化的模式(「先查找再设置」「添加前先查找」)。CLI 已开源。平台已上线于 formlm.me。
我们还没有到达终点。但 30 天 50 个表单已经证明了基础是可靠的。工具是稳固的。模式是可靠的。白名单在起作用。AI 可以构建表单了。
现在它也能构建评估了。
这是关于为 FormLM 构建 AI 原生工具的 20 篇系列的结尾。CLI 和 MCP server 开源于 github.com/formlm/cli。平台地址是 formlm.me。感谢阅读。
如需进一步行动,你可以考虑屏蔽此人或举报滥用。