关于 formio-uag
formio-uag 使用 MCP 将 Form.io 表单结构转为 Agent 可理解的格式,面向需要将对话输入或表单提交接入 AI 自动化的团队。它支持按表单上下文生成结构化提交数据,也能在工作流中分析现有提交并填写指定字段。
主要功能
- 01将表单 JSON 转为 Markdown 上下文
- 02自然语言对话生成结构化表单数据
- 03按标准分析提交并填写指定字段
- 04通过动态表单上下文调整 Agent 行为
- 05支持自定义 MCP 工具与表单操作
适用场景
- 01把聊天输入转换为 Form.io 表单提交
- 02自动评估申请并写回表单字段
- 03基于角色权限让 Agent 操作表单
MCP 相关
它通过 MCP 向 AI Agent 提供表单解释和操作能力。扩展模块可加入自定义 MCP 工具、表单操作、预定义表单和资源。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @formio/uagPROJECTAPI endpoint to Enterprise project or OSS serverPROJECT_KEY密钥Project API Key (Enterprise) or ADMIN_KEY (OSS)ADMIN_KEY密钥Server admin key for Community Edition. Not required for Enterprise deployment.UAG_LICENSE密钥License for Enterprise deployment. Not required for Community Edition.JWT_SECRET密钥Secret used to generate and validate JWT tokensPORTServer port (default: 3200)PROJECT_TTLProject cache refresh interval in seconds (default: 900)JWT_EXPIRE_TIMEJWT token expiration in seconds (default: 3600)PORTAL_SECRET密钥Enterprise Portal connection secretMONGO密钥Direct MongoDB connection URI (Enterprise)MONGO_CONFIGMongoDB driver configuration (JSON)BASE_URLThe URL clients reach the UAG at. Published in the .well-known OIDC (PKCE) definitions and used for authentication callbacks, so remote agents cannot authenticate without it. Must be a public URL when remote agents connect in; a private or localhost URL is fine for a local MCP client.LOGIN_FORMPublic URL to login form JSON endpointCORSCORS domain or JSON configuration (default: *)DEBUGDebug logging filter (e.g. formio.*)本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
通用 Agent 网关(UAG)利用 Model Context Protocol(MCP),通过 Form.io 实现进程内 Agent 自动化。它为 AI Agent 提供的功能与我们的 JavaScript 渲染器为人类提供的功能相同:将 Form JSON 架构解读为易于理解的格式。对于 UAG,它会将 Form JSON 模型转换为 AI 可读的 Markdown 格式,使 Agent 能够轻松理解需要收集的数据的用途和结构。

UAG 支持两种主要场景:
- 将非结构化“聊天”输入转换为确定性的表单提交:此功能使用 Form.io 表单的 JSON 架构,根据自然语言对话输入生成确定性的结构化数据对象。

如需体验此流程的实际示例,请试用对话表单示例。
- Agent 式 Form.io 工作流:UAG 使 AI Agent 能够利用现有提交数据和“上下文”标准,在工作流场景中提示 AI Agent 提供自己的数据和分析。以下示例展示了使用 Form.io 申请表的大学申请流程,说明了这一主要场景的工作方式。

如需了解有关 Agent 式工作流的更多信息,请查看专门的 Agent 式工作流部分。如需体验此流程的实际示例,请试用 Agent 式工作流示例。
UAG 的众多优势之一,是能够在 AI 处理周期中注入动态上下文。这得益于 Form JSON 架构的动态特性:无需更新应用或重新训练流程中的 Agent,即可轻松修改架构并将其部署到任何环境。因此,动态上下文变更可以无缝注入正在运行的流程,并自动更新使用 UAG 的 Agent 的行为。
试用一下!
本仓库中有三个可运行的示例,每个示例都会通过 Docker Compose 同时启动 Form.io 服务和 UAG。请选择与你正在构建的内容相匹配的示例。
| 示例 | 模式 | 许可 |
|---|---|---|
| 自定义模块 | 对话式,使用现有客户端。 将 Claude Desktop 连接到你的表单并与之对话:“我想添加一位新客户。”此示例构建为自定义模块,因此 Agent 可以执行哪些操作由角色和权限决定。 | 开源 — 免费 |
| 对话式表单 | 对话式,使用自己的 UI。 一个聊天应用,其问题完全来自表单。大约 200 行代码,代码中没有字段名称——编辑表单,对话就会随之变化。 | 开源 — 免费 |
| Agent 工作流 | 自主运行。 一次提交会触发一个 Agent,根据评分标准对其进行评分并写回决定,进而触发第二个 Agent。无需人工参与,也不需要聊天窗口。 | 企业版 |
此外还有一个 流程查看器——一个小型代理,可实时显示 Agent 运行过程中的每个环节,是了解 Agent 实际行为最快的方式。
本仓库中的文档
本文档是主要参考资料:介绍 UAG 是什么、如何为其配置表单、如何部署以及如何排查问题。其余文档位于相关代码旁边。
| 文档 | 内容 |
|---|---|
| README.md(本文档) | 概念、Agent 工作流设置、MCP 工具、部署、环境变量和故障排查。 |
| module/Readme.md | 构建自定义模块——添加自己的 MCP 工具、表单操作、预定义表单和资源,以及配置覆盖,然后将其挂载到 Docker 容器中。 |
| integrations/claude/Readme.md | Claude 集成:其 API 端点和命令、如何通过 Node 或 Docker 运行、环境变量,以及如何通过 Form.io Webhook 操作触发。 |
| examples/custom-module/Readme.md | 示例——通过 Claude Desktop 以对话方式使用自定义模块,由角色和权限决定 Agent 可以执行哪些操作。 |
| examples/conversation-form/Readme.md | 示例——一个自行构建的聊天应用,其问题完全来自表单。 |
| examples/agentic-workflow/Readme.md | 示例——一个由 Webhook 触发的自主工作流,包含两个串联的 Agent 角色。 |
| examples/flow-viewer/Readme.md | 一个小型代理,可实时显示 Agent 运行过程中的每个环节——令牌请求、每次工具调用以及写回操作。是了解 Agent 行为最快的方式。 |
| examples/custom-module/module/templates/Readme.md | 使用 Lodash 模板覆盖 UAG 返回给 Agent 的响应模板。 |
| test/e2e/Readme.md | 端到端测试套件——包含的三个层级、各自的覆盖范围以及运行方法。 |
Agentic 工作流
UAG 的一项强大功能是 agent_provide_data 工具。此工具能够指示通用训练的 Agent 如何分析现有提交数据,然后根据可配置的标准生成自己的数据。过去,只有使用专门训练的 Agent 才能实现这种行为,但这无法发挥 Form.io 平台提供的动态配置优势。此工具通过向通用训练的 Agent 提供准确生成自身数据所需的“上下文”,使其能够在自动化工作流中完成这一目标。如果你希望在 Agentic 工作流中使用 UAG,此功能尤其有用:AI Agent 能够理解结构化数据,并根据 UAG 提供的配置标准“上下文”贡献自己的数据。
例如,假设你希望自动化管理大学申请流程的后台。在此示例中,潜在学生会提交一份申请,其中包含许多不同的数据字段,例如学业、课外活动、荣誉、志愿服务,以及可能的书面论文。过去,管理员会审核这些申请,以评估候选人是否符合录取资格。如下图所示,现在可以通过 agent_provide_data 工具将此流程自动化。

为实现这一目标,agent_provide_data 工具会使用以下信息,并将其提供给通用训练的 Agent,以生成自己的提交数据。
- 现有提交数据:为了让 Agent 能够贡献自己的数据,必须先有一个现有提交,供 Agent 根据配置的标准进行分析。
- 标准:此内容为 Agent 提供分析数据时应遵循的标准,同时还会说明 Agent 应如何填写必填字段。
- 必填字段:这些是 Agent 在
agent_provide_data流程中必须填写的表单字段。
设置
要将表单配置为使用 agent_provide_data 工具,必须先指定表单中的一个区段,供 AI Agent 读取和使用。这类似于表单中的“仅供办公室使用”区段,只不过此区段的值不是由人工填写,而是由自动化 AI Agent 填写。可在表单中添加两种字段,以将其配置为供 agent_provide_data 工具使用:标准和Agent 字段
完整设置分为四个步骤,且必须全部完成:
- 为表单添加
uag标签(如下所述)——否则 UAG 完全不会识别该表单。 - 添加标准内容组件,指导 Agent 应执行的操作。
- 添加 Agent 允许填写的Agent 字段。
- 添加 Webhook 操作,在提交时触发 Agent——请参阅 Claude 集成。此步骤需要 Enterprise Server,因为该操作必须设置请求标头并转换其有效负载;在 Community Edition 中,请在创建提交后通过自己的代码触发集成。
如需包含全部四项的可运行参考示例,请参阅 Agentic 工作流示例。
为表单添加 uag 标签
UAG 只会注册带有 uag 标签的表单。没有该标签的表单对所有 Agent 和所有工具(包括 get_forms)都不可见。在 Form Builder 中,可在 Form Settings → Tags 下设置此标签;在表单的 JSON 中,它如下所示:
"tags": ["uag"]
每当 Agent 坚称某个表单不存在时,都值得先检查这一项,因为缺少标签不会在任何地方引发错误——在 Agent 看来,这个表单就根本不存在。另请注意,新添加标签的表单要等到下次项目缓存过期后才会被识别,因此最长可能需要等待 PROJECT_TTL 秒(参见项目缓存和 TTL)。
Agent“Criteria”组件
首先需要配置一个特殊的内容组件,用于指示 AI Agent 如何解读数据。例如,以下是一个 Criteria 内容块,用于指导 AI Agent 如何评估大学申请文书的提交内容。

编写此内容时,应将其视为写给新员工的操作手册,帮助他们学习如何分析和理解提供的提交数据。此内容还用于指导 AI Agent 如何填写为该 Criteria 配置的表单值。编写好此 Criteria 后,需要添加一个名为 uag 的属性,将其标记为 UAG 字段;该属性的值可视为 Agent 的 persona。这样,多个 Agent 就可以承担不同角色,分析提交数据并给出各自的值。此外,“criteria”内容还需要添加一个 uagField 属性,其值为 criteria。以下是正确配置的 uag criteria 内容组件示例。

将此 Criteria 内容组件添加到表单后,接下来要添加希望 Agent 填写的字段。这些字段称为Agent 字段。
Agent 字段
你可以在表单中的任意位置拖放字段,并将其标记为 Agent 字段。以上面的示例为例,假设表单中有一个“仅供办公室使用”部分(可能是一个 Panel)。在此 Panel 内,首先会看到一个内容组件,其中包含如何填写后续字段的说明。这就是我们刚才介绍的 Criteria。接下来是 Agent 需要填写的字段。任何 uag 属性值与 Criteria 内容组件相同的字段,都会被用作 Agent 字段。
例如,假设我们创建了一个用于大学申请文书的表单。在Criteria下方,可能会有一些字段,要求 Agent 根据提供的Criteria为文书“评分”。示例如下……

要将这些字段逐一“标记”为 Agent 字段,只需添加 uag 属性,并将其设为与 Criteria 内容相同的 persona 标记。

嵌套组件
也可以使用 uag 属性“标记”一组字段。为此,可以将这些字段全部放入一个嵌套组件中(例如 Panel、Container、Fieldset 等),这样该嵌套组件中的所有字段都会添加到具有相应 persona 的 Agent 的上下文中。
每个表单配置多个角色
也可以在每个表单中配置多个角色。如果一个流程中需要进行多项相互独立的评估,这会非常有用。例如,查看上方的流程图,可以看到一份大学申请表。申请人提交表单时会进行第一次 Agentic 评估,以判断申请是否通过。从这一步开始,如果申请人通过了,就需要进行完全不同的评估,以决定是否向申请人提供助学金,甚至奖学金。这些评估需要使用完全不同的标准,以不同方式评估提交的数据。
要实现这一点,只需为组件的 uag 属性设置不同的值,标明适用于该字段的角色。在上面的示例中,你需要添加一个 Content 组件,用于评估申请人是否应该通过,然后为该内容添加以下 uag 属性:uag="application"。需要由 AI Agent 填写、用于审批申请的所有字段也应添加属性 uag="application"。然后,在表单的另一个部分创建一个独立的 Content 组件,其中包含财务管理员 AI Agent 使用的评估标准。该内容应添加属性 uag="finance"。财务管理员 AI Agent 需要填写的所有字段也应添加 uag="finance"。这提供了真正灵活、动态的 AI 交互方式,让多个经过通用训练的 Agent 能够根据需要动态“学习”如何读取和解读仅与 Agentic 流程相应阶段相关的数据。
Agent 字段不必紧挨着评估标准。例如,一个面板中的 status 字段可以标记为 uag="application",旁边的字段则可以标记为 uag="finance"。这样,工作流中的同一个字段可以由负责相应阶段的角色接管。
将多个角色串联成工作流
只有在有事件触发后续角色时,在表单中配置多个角色才有用。由于每个角色都会写入提交内容,因此第二个角色的自然触发条件就是第一个角色的写入操作。
此配置通过第二个 Webhook 操作完成:它在 update 而非 create 时触发,并根据第一个角色设置的字段添加条件进行筛选:
{
"name": "webhook", "handler": ["after"], "method": ["update"], "priority": 0,
"condition": {
"conjunction": "all",
"conditions": [
{ "component": "status", "operator": "isEqual", "value": "scholarshipEvaluation" }
]
},
"settings": {
"method": "post",
"url": "http://formio-uag-claude:3300/agent/claude/agent_provide_data",
"headers": [{ "header": "x-token", "value": "<your project API key>" }],
"transform": "payload = {formName: 'application', submissionId: payload.submission._id, persona: 'finance'};",
"block": false
}
}
在大学申请工作流中,招生角色仅对符合奖学金申请条件的申请人将 status 设为 scholarshipEvaluation,因此只有这些提交内容会触发财务角色。仅获准或被拒的申请人不会触发该角色。
避免循环。 第二个角色也会写入提交内容,从而再次触发同一个
updatewebhook。请确保每个角色自己的写入操作不会再次匹配触发该角色的条件——在上面的示例中,财务角色会将status设为scholarshipGranted,因此不再满足该条件,工作流便会终止。如果角色运行后条件仍为真,工作流就会无限循环,并持续消耗 API 额度,直到你停止容器。
这个双角色工作流的完整可运行版本见 Agentic Workflow 示例。
集成
为了推动 UAG 的“Agent 化”,我们还提供了一些“集成”,可用于直接与经过通用训练的 AI Agent 通信,从而利用 UAG 实现 AI Agent 的自动化行为。这包括提供一个 API 端点,用于触发 AI Agent 流程,并连接到已部署的 UAG。随后,可以通过表单中的简单 Webhook 操作触发这些 API 端点,以便在提交表单后启动 Agent 流程。以下示意图展示了如何通过特定集成实现一次 API 调用来完成 Agent 任务。

每个集成都运行自己的 MCP 客户端,并主动连接到 UAG,因此 UAG 无需公开访问也能正常工作——只要集成能够访问它即可,例如通过私有 Docker 网络或 localhost。
这些集成位于 integrations 文件夹中。我们提供了以下 集成,以支持自动化 Agent 工作流。
请点击其中一个集成链接,了解其工作方式。
集成版本兼容性
集成的版本独立于 UAG。它们与 UAG 不共享代码——每个集成都运行自己的 MCP 客户端,并通过 MCP/HTTP 与 UAG 通信——因此,发布集成新版本并不意味着 UAG 也会发布新版本,反之亦然。让两者的版本号保持一致只会造成误导,并无益处。
请使用此矩阵选择兼容的版本组合。每一行记录了已知可与某个集成版本配合使用的 UAG 版本范围:
| 集成 | 版本 | 兼容的 UAG 版本 | 备注 |
|---|---|---|---|
@formio/uag-claude | 1.3.x | >= 1.12.0 | 当前版本。 |
@formio/uag-claude | 1.2.x | 1.10.0 – 1.11.x |
每次自身版本发生变化时,都会在发布中发布这两个构件:
- npm:
@formio/uag、@formio/uag-claude - Docker Hub:
formio/uag、formio/uag-claude
**添加行时:**请递增集成自身的 package.json 版本。CI 会在下一个发布标签上将其发布到 npm 和 Docker Hub;如果该版本已发布,则会自动跳过,因此仅核心部分的发布不会重新构建未更改的集成。
examples/ 中的 compose 文件引用 formio/uag 和 formio/uag-claude 时未指定标签,因此始终会拉取当前版本,不会出现版本过时的问题。如果需要可复现的环境,请根据上方矩阵为两个镜像固定兼容的版本组合。
技术概述
UAG 可以看作由多个功能层组成。每一层大体上要么用于获取动态上下文,要么用于提交确定性数据结构。UAG 采用了以下各层:
- MCP 接口:UAG 的入口是 MCP 接口,它位于 AI Agent 与服务器上执行的工具之间。
- 授权:根据 MCP 规范,AI Agent 与后端服务之间的每次交互都必须经过采用 OIDC(PKCE)身份验证的授权流程。不过,UAG 在此基础上更进一步,在 Form.io 已提供的现有身份验证灵活性之上增加了一层 OIDC(PKCE)身份验证。因此,如果你通过 Form.io 平台使用 SAML、Form.io 身份验证、OIDC,甚至自定义身份验证流程,都可以通过 UAG 进行身份验证。
- 提供动态上下文的预定义 MCP 工具:UAG 利用 MCP 提供了一系列预定义工具,这些工具根据 Form.io 平台中标记为兼容的表单和资源,为 AI Agent 提供动态上下文。下文将对此类工具进行更详细的介绍。
- 自定义工具(由自定义模块提供):开发者可以借此引入任何新工具,利用 Form.io 表单和提交数据结构为 AI Agent 提供额外功能。这样便可针对特定用例,通过自定义 Agent 交互实现特定目标。
- 自定义操作(由自定义模块提供):开发者可以创建可组合的中间件,在 AI Agent 提供的所有数据经过清理和验证后执行。这使开发者能够将从 AI Agent 收集的数据对接到任何后端系统或工作流。
- 内置操作:除了通过模块引入的自定义操作外,UAG 还支持少量现有操作,可分配给任何表单或资源。例如,Webhook 会在 AI Agent 提交任何内容后向任意端点发送 REST API 调用。它可以指向任何无服务器函数,以启动由 AI Agent 交互触发的后端工作流。
- 预定义表单和资源(由自定义模块提供):开发者可以发布一个为 AI Agent 提供默认数据结构的模块。如果开发者想要创建一个实现特定目标的模块,而该目标所需的数据结构必须遵循表单或资源提供的一组预定义字段,这项功能就很有用。例如,如果开发者想要为 UAG 发布一个 CRM 模块,那么该模块同时提供通常随大多数 CRM 实现一同出现的默认 客户和公司资源就很合理。
- 自定义数据库(由自定义模块提供):默认情况下,UAG 通过“提交代理”执行数据收集和检索,而数据则通过 REST API 提交到企业服务器项目或开源服务器。不过,也可以修改此行为,改为直接从数据库读取数据并向数据库写入数据。这可以通过 UAG 提供的数据库接口实现。更多信息请参阅模块文档。此功能要求 UAG 连接到企业服务器。
以下示意图展示了这些层如何组织构成 UAG。

提供动态上下文的预定义 MCP 工具
UAG 提供的以下工具可描述如下:
| 工具名称 | 工具描述 |
|---|---|
| get_forms | 向 AI Agent 提供可用表单列表。 它只会返回标记为 uag 的表单。 |
| get_form_fields | 当 AI Agent 推断出用户打算使用特定表单时,此工具会向 Agent 提供提交该表单所需的所有字段的概览(以及字段数据路径)。 |
| get_field_info | 使用 get_form_fields 确定字段后,此工具会提供所请求字段的具体信息,例如验证规则、条件、输入格式等。 此工具会指导 AI Agent 如何格式化和组织发送到 MCP 服务的数据。 |
| collect_field_data | 为 AI Agent 提供动态收集用户所需信息的机制。它可以一次将用户输入解析为多个字段,并在需要时识别用户需要提供的其他输入。 此工具支持复杂的结构化数据收集,并兼容嵌套表单、数据网格等嵌套或多值字段。 |
| confirm_form_submission | 此工具用于在提交表单前汇总所有已收集的数据。 |
| submit_completed_form | 使 AI Agent 能够提交从用户收集的所有数据,以创建表单提交记录。 |
| find_submissions | 使 Agent 能够将用户的自然语言请求解析为针对某条提交记录或特定字段的查询。 |
| submission_update | 使 AI Agent 能够更新现有提交记录,既可以填写尚未填写的字段,也可以在允许的情况下更新现有字段。它会提供现有字段值的上下文,允许进行内联更改或编辑。 |
| agent_provide_data | 使 AI Agent 能够根据可配置的 Criteria 所定义的规则分析现有提交数据。随后,它会指导 Agent 使用 submission_update 工具,为特定 persona 配置的字段提供生成的数据。有关此工具集的更多信息,请参阅Agentic Workflows 部分。 |
| fetch_external_data | 此工具使 AI Agent 能够通过 Resource 组件、带 URL 的 Select 或 Data Source 组件,将外部数据引入表单工作流。 |
自定义模块
虽然可以将 UAG 作为独立系统,用于实现 AI Agent 与动态 JSON 表单之间的交互,但只有在开发者通过自定义模块和工具扩展平台功能,以解决特定行业的用例时,才能真正发挥该平台的强大能力。开发者可以创建一个 模块,引入多个自定义工具、操作以及预定义资源和表单,以实现与特定行业技术的交互。开发者可以通过以下机制实现此类自定义集成:
- 预定义表单和资源:借助 Form.io 模板系统,自定义模块可以包含 Form.io 项目的模板导出,其中包括多个表单、资源和操作(以及关联的任何角色和权限)。使用该模块后,这些资产会自动“注册”,使 AI Agent 能立即了解这些资产。
例如,假设某个模块包含一个具有“名字”“姓氏”和“电子邮箱”字段的客户资源。如果你只需向 AI Agent 提出“我想新增一位客户”,Agent 就会自动了解客户数据结构的上下文,并准确理解你提出该请求的意图。 - 自定义操作:操作可视为可组合的中间件函数,支持将可配置的 Express.js 中间件函数附加到任意表单和资源,并在 AI Agent 提交的数据通过适当的数据验证和清理后执行。这些操作可用于与后端流程和工作流进行自定义集成。
- 自定义工具:除了提供自定义操作外,模块还可以引入自定义 MCP 工具,为 UAG 与 AI Agent 之间的交互提供定制能力,以满足特定行业的需求。
- 自定义身份验证:模块还可以修改“身份验证”落地页,以满足身份验证方面的任何自定义需求。
- 行为覆盖:模块还可以“覆盖” UAG 的任何默认行为。这样,模块使用者就可以“调整”某些工具和响应,以更好地满足其特定行业需求。
Form.io 致力于让开发者能够构建自己的自定义模块,并通过 GitHub 和 NPM 分享给更广泛的社区。
使用自定义模块
开发好自定义模块后,任何人都可以(通过 NPM)安装该模块,然后按以下方式轻松使用……
这只是一个示例。
import { UAGServer } from '@formio/uag';
import { ExampleUAG } from '@example/uag';
import Express from 'express';
try {
(async function () {
const server = new UAGServer();
server.use(ExampleUAG);
const app = Express();
app.use(await server.router());
const port = process.env.PORT || 3200;
app.listen(port, () => {
console.log(`Form.io UAG server running on port ${port}`);
console.log(`Visit http://localhost:${port} to access the application`);
});
})();
} catch (error) {
console.error('Failed to start server:', error);
process.exit(1);
}
要开始构建自己的自定义模块,请参阅帮助文档中的 模块 Readme。
部署 UAG
以下部分介绍如何创建正在运行的 UAG 实例,将其连接到 Form.io 平台,并配置 AI Agent 使用它。
本文档重点介绍将 UAG 与 Form.io 开源版搭配使用。有关将 UAG 与 Form.io 企业版搭配使用的文档,请参阅 https://help.form.io/uag。
Agent 如何连接
部署前,值得先确定 哪一方发起与 UAG 的 /mcp 端点的连接,因为这一个决定将决定 UAG 是否需要公开访问。
| 连接模式 | 谁运行 MCP 客户端 | UAG 是否需要公共域名? |
|---|---|---|
| 本地 MCP 客户端 | 与 UAG 一起运行的自有应用或集成 | 不需要。 UAG 只需能从该进程访问——http://localhost:3200 或私有 Docker 网络地址均可。 |
| 远程 MCP 客户端 | 连接到 UAG 的托管 Agent(Claude.ai 和 Claude Desktop 连接器、Anthropic MCP 连接器或其他远程 MCP 主机) | 需要。 Agent 必须能够通过公共互联网访问 /mcp 和 OAuth 发现端点。 |
使用本地 MCP 客户端时,应用会向外连接到 UAG,自行调用工具,并将结果传递给其使用的模型。没有任何连接会从外部发起,因此 UAG 可以完全留在你的网络内部。这正是 Claude 集成的工作方式,也是服务器到服务器及由 webhook 触发的自动化的推荐模式——包括在开发者的计算机上运行整个技术栈。
如果你使用的是已发布的 Claude 集成镜像,则需要
formio/uag-claude:1.3.0或更高版本。更早的镜像会将 MCP 服务 URL 作为远程连接器传递给 Anthropic API,这意味着 API 会连接到你的 UAG,因此必须提供公共 URL。旧镜像指向私有地址时会收到 Anthropic API 返回的400错误,内容为Connection error while communicating with MCP server。这看起来像是 UAG 故障,但实际并非如此。
使用远程 MCP 客户端时,Agent 位于你的网络之外并从外部连接进来,因此 /mcp 和 .well-known OAuth 发现端点必须可通过 HTTPS 公共访问,且 BASE_URL 必须是该公共 URL。请参阅域名和 URL 配置。
两种模式可以同时用于同一个 UAG 部署。
对本地 MCP 客户端进行身份验证
远程 Agent 通过基于浏览器的 OAuth(PKCE)流程进行身份验证。本地客户端没有浏览器,因此会使用服务器端密钥,通过 client_credentials 授权类型向 {{ BASE_URL }}/auth/token 换取访问令牌,然后在其 /mcp 请求中将该令牌作为 Bearer 令牌发送。
client_id 必须以项目名称为前缀——开源部署的项目名称为 formio-oss:
POST /auth/token
Content-Type: application/json
{
"grant_type": "client_credentials",
"client_id": "formio-oss-x-admin-key",
"client_secret": "{{ ADMIN_KEY }}"
}
对于 Enterprise,请使用项目端点中的项目名称以及项目 API 密钥——例如,使用 "client_id": "myproject-x-token" 和 "client_secret": "{{ PROJECT_KEY }}"。
响应中包含一个 access_token,需将其作为 Authorization: Bearer {{ access_token }} 传递给 UAG。令牌会根据 JWT_EXPIRE_TIME 到期,因此长时间运行的客户端应缓存令牌,并在令牌到期前刷新。请参阅 integrations/claude/auth.js 了解可正常运行的实现。
运行环境
目前有两种可与 UAG 配合使用的运行环境:
Docker
在 Docker 中运行 UAG,可在 AWS 和 Azure 等常见托管环境中采用多种部署方案。此外,还可使用 Kubernetes 和 Docker Compose 等常见编排运行时。运行 UAG 的容器如下:
formio/uag
此容器可以通过两种方式运行:
- Docker-Compose.yml - 推荐方式,以多容器 Docker Compose 堆栈的形式部署。
- Docker Run - 使用常见的
docker run命令运行独立容器。
Docker Compose(推荐)
推荐通过 Docker Compose 启动 UAG。这样可以编排多个容器,在单个实例中运行,从而以更无缝、更简单的方式管理部署。以下是一个简单示例,展示如何在同一实例上同时运行 Form.io UAG 和 Form.io OSS 服务端。
docker-compose.yml
services:
mongo:
image: mongo
restart: always
volumes:
- ./data/db:/data/db
environment:
- MONGO_INITDB_ROOT_USERNAME
- MONGO_INITDB_ROOT_PASSWORD
formio:
image: formio/formio:rc
restart: always
links:
- mongo
depends_on:
- mongo
environment:
PORT: 3000
DEBUG: formio.*
NODE_CONFIG: '{"mongo": "mongodb://mongo:27017/formio-oss", "jwt": {"secret": "CHANGEME"}, "mongoSecret": "CHANGEME"}'
ROOT_EMAIL: [email protected]
ROOT_PASSWORD: CHANGEME
ADMIN_KEY: CHANGEME
ports:
- "3000:3000"
formio-uag:
image: formio/uag
restart: always
links:
- formio
depends_on:
- formio
environment:
PORT: 3200
DEBUG: formio.*
PROJECT: http://formio:3000
ADMIN_KEY: CHANGEME
JWT_SECRET: CHANGEME
JWT_EXPIRE_TIME: 525600
LOGIN_FORM: http://localhost:3000/user/login
# The address clients reach the UAG at — this is the UAG's own port,
# not the Form.io server's. See the BASE_URL section below.
BASE_URL: http://localhost:3200
ports:
- "3200:3200"
输入以下命令即可运行……
docker compose up -d
Docker Run
以下是使用 docker run 命令运行 UAG 的一些示例。
将 UAG 指向开源服务端
docker run -d \
-e "PROJECT=https://forms.mysite.com" \
-e "ADMIN_KEY=CHANGEME" \
-e "JWT_SECRET=CHANGEME" \
-e "BASE_URL=https://forms.mysite.com" \
-e "LOGIN_FORM=https://forms.mysite.com/user/login" \
-e "PORT=3200" \
--restart unless-stopped \
--network formio \
--name formio-uag \
-p 3200:3200 \
formio/uag
将 UAG 指向 Form.io Enterprise 服务端
docker run -d \
-e "PROJECT=https://forms.mysite.com/myproject" \
-e "PROJECT_KEY=CHANGEME" \
-e "UAG_LICENSE=YOUR-LICENSE" \
-e "JWT_SECRET=CHANGEME" \
-e "PORTAL_SECRET=CHANGEME" \
-e "BASE_URL=https://forms.mysite.com" \
-e "LOGIN_FORM=https://forms.mysite.com/myproject/user/login" \
-e "PORT=3200" \
--restart unless-stopped \
--network formio \
--name formio-uag \
-p 3200:3200 \
formio/uag
运行后,可通过以下地址访问 OSS 部署和 UAG 服务端:
在 Node.js 运行时环境和 Docker 中,都可以通过使用环境变量和模块来控制 UAG。
环境变量
此模块可通过多种方式进行配置,其中一种是使用环境变量,具体说明如下。
| 变量 | 描述 | 示例 |
|---|---|---|
| PROJECT | 必填。 Enterprise 项目端点或 OSS 服务端 URL 的 API 端点。 | http://localhost:3000 |
| PROJECT_KEY | (仅限 Enterprise)此 UAG 所绑定项目的 API 密钥,可在项目设置 → API 密钥中找到。开源部署使用 ADMIN_KEY 代替。 | CHANGEME |
| ADMIN_KEY | (仅限开源)用于提供 ADMIN_KEY,以安装并连接到 OSS 服务端。 | CHANGEME |
| UAG_LICENSE | 用于在 Form.io Enterprise 部署中运行 UAG 的许可证。 | |
| PROJECT_TTL | 项目缓存 TTL(秒)。此设置控制检查项目是否有任何“更改”并刷新 UAG 中表单和资源的间隔时间。 | 900 |
| PORT | 要运行服务端的端口。 | 3200 |
| DEBUG | 用于记录服务端活动调试日志的变量 | formio.* |
| PORTAL_SECRET | 仅限 Enterprise:允许从 Form.io Enterprise Portal 连接到 UAG。 | CHANGEME |
| JWT_SECRET | 必填。 用于在 UAG 身份验证过程中生成并验证 JWT 令牌的密钥。此密钥无需与其连接的 Enterprise 服务端的 JWT_SECRET 相同。 | CHANGEME |
| JWT_EXPIRE_TIME | jwt 密钥的过期时间。 | 3600 |
| MONGO | (仅限 Enterprise)允许将 UAG 直接连接到 mongo 数据库,而无需将提交内容重定向到 Form.io Submission API。 | |
| MONGO_CONFIG | Node.js Mongo Driver 的 JSON 配置。 | |
| BASE_URL | 必填。 客户端可访问 UAG 的 URL。此 URL 会发布在 .well-known OIDC (PKCE) 定义中,并用于身份验证回调。远程 Agent 连接时,此 URL 必须是公开 URL;对于本地 MCP 客户端,私有 URL 或 localhost URL 均可。 | https://forms.yoursite.com |
| LOGIN_FORM | 登录表单 JSON 端点的 URL,由 /auth/authorize 页面加载。仅用于基于浏览器的登录流程,因此该浏览器必须能够访问此 URL。 | https://mysite.com/project/user/login |
| CORS | cors 域名,或用于配置“cors” node.js 模块跨域资源共享的 JSON 配置。 | . |
| NODE_TLS_REJECT_UNAUTHORIZED | 标准 Node.js 变量。当 PROJECT 是由自签名或其他不受信任证书保护的 https URL 时,将此项设为 0;本地和内部部署中常见这种情况。不设置此项时,UAG 无法连接到服务端,所有工具调用都会失败。对于可从网络外部访问的部署,切勿设置此项,因为它会禁用所有出站请求的证书验证。 | 0 |
项目缓存和 TTL
默认情况下,UAG 会使用 TTL 来“获取”项目资源,将其注册并缓存到 UAG 中。这意味着,如果你对底层项目表单和资源做出任何更改(直接修改或通过部署修改),需要等待最长为 TTL 设置值(以秒为单位)的时间,才能看到所做的更新。例如,如果 TTL 设置为 900(即 15 分钟),而你更改了任何表单和资源,则最多需要等待 15 分钟,这些更改才会在 UAG 中生效。请注意,每次发生“刷新”时,都会对底层项目端点调用“export”方法。这是一个处理器密集型 API 调用,因此不建议将 TTL 设置为小于 60 的值。值为 0 时表示“无 TTL”,也就是说,刷新项目表单和资源的唯一方法是重启 UAG。
以下表格说明了如何使用此参数。
| 环境变量 | 值 | 结果 |
|---|---|---|
| PROJECT_TTL | 0 | 不会发生 TTL(刷新)。这可用于“禁用”任何刷新;要确保只有通过重启 UAG 服务才能重新获取已更新的表单和资源。 |
| PROJECT_TTL | 60 | 每分钟检查一次更改 |
| PROJECT_TTL | 3600 | 每小时检查一次更改 |
此缓存会导致表单编辑不会立即生效。任何会改变 Agent 所知内容的更改——添加 uag 标签、重写 Criteria 内容组件、添加或移除 Agent Fields——都要等到下次过期后才会应用于 Agent。在你积极迭代条件时,重启 UAG 可立即重新注册项目,无需等待:
docker restart formio-uag
域名和 URL 配置
有 3 个相关的“域名”环境变量,具体配置方式取决于你的使用场景,因此了解如何配置它们非常重要。它们是否需要设为公开,取决于 Agent 的连接方式——请参阅Agent 如何连接。
如果远程 Agent 连接到 UAG,则必须正确配置这些变量并将其设为公开,否则 Agent 将无法进行身份验证。如果你只使用本地 MCP 客户端,则这三个变量都可以指向私有地址或 localhost 地址。
PROJECT
PROJECT 环境变量用于建立从 UAG 服务到项目端点(Enterprise)或 OSS 基础 URL 的连接。它不需要是公开的 DNS 记录,而只需是一个能够将 UAG 容器连接到服务容器的 URL。以下示例说明了如何进行配置。
连接到本地 OSS 服务
如果你使用本地连接(例如在 Docker Compose 文件中),可以将 PROJECT 环境变量配置为直接指向本地 URL,如下所示。
docker-compose.yml
services:
formio:
image: formio/formio:rc
restart: always
environment:
PORT: 3000
ADMIN_KEY: CHANGEME
formio-uag:
image: formio/uag
restart: always
links:
- formio
depends_on:
- formio
environment:
PROJECT: http://formio:3000
ADMIN_KEY: CHANGEME
在此示例中,Docker Compose 会启动 OSS Form.io 容器,并为此次部署设置 ADMIN_KEY。UAG 使用 http://formio:3000 连接,该地址是本地 Docker 网络名称(通过 docker compose 文件中的 "links" 属性提供)。
连接到本地 Enterprise 服务项目
如果你在本地环境中将 Enterprise Form.io 服务与 UAG 配合使用,则需要确保 UAG 使用 PROJECT_KEY 连接到独立项目,如下所示。
docker-compose.yml
services:
formio-enterprise:
image: formio/formio-enterprise
restart: always
environment:
PORT: 3000
formio-uag:
image: formio/uag
restart: always
links:
- formio-enterprise
depends_on:
- formio-enterprise
environment:
PROJECT: http://formio-enterprise:3000/myproject
PROJECT_KEY: CHANGEME
公开 DNS
如果你的项目与 UAG 不在同一网络中,可以按如下所示将域名设为 PROJECT。
docker-compose.yml:连接到 Enterprise(formio/formio-enterprise)
services:
formio-uag:
image: formio/uag
restart: always
environment:
PROJECT: https://forms.mydomain.com/myproject
PROJECT_KEY: CHANGEME
docker-compose.yml:连接到开源版本(formio/formio)
services:
formio-uag:
image: formio/uag
restart: always
environment:
PROJECT: https://forms.mydomain.com
ADMIN_KEY: CHANGEME
BASE_URL
BASE_URL 用于告知 UAG 它可通过哪个 URL 访问。此值会发布在 OIDC(PKCE)身份验证的 .well-known 定义中,并用于身份验证回调。
BASE_URL 始终必填,本地客户端也不例外。只有设置了该值,UAG 的身份验证提供程序才会启用;如果省略,/mcp 会对每个请求返回 401,且 /auth/token 和 /.well-known/* 端点都不会存在(404)。/auth/token 返回 404 是缺少 BASE_URL 最明显的信号。
具体应设置为什么值,取决于 Agent 的连接方式:
- 远程 Agent 连接:必须设置为托管 UAG 的公开可访问域名,因为 Agent 会收到此地址,并使用它进行身份验证。例如,
BASE_URL: https://forms.mysite.com。 - 仅限本地 MCP 客户端:设置为客户端用于访问 UAG 的地址。可以使用私有 URL 或 localhost URL,例如
BASE_URL: http://localhost:3200,或 Docker 网络内的BASE_URL: http://formio-uag:3200。
如果远程 Agent 无法进行身份验证,最常见的原因是 BASE_URL 不匹配:Agent 会从发现文档中读取此值并据此访问,因此如果该地址无法被 Agent 访问,即使 UAG 本身运行正常,身份验证也会失败。
LOGIN_FORM
这是项目或 OSS 部署的登录表单 URL。用户访问 {{ BASE_URL }}/auth/authorize 时,会加载此表单。如果访问此 URL 后,页面提示无法加载表单,说明你的 LOGIN_FORM 环境变量未指向项目中正确的表单 JSON 端点。
此 URL 仅用于基于浏览器的登录流程,因此必须能由执行登录的浏览器访问。使用 client_credentials 授权类型进行身份验证的本地 MCP 客户端不会加载此页面。
例如:
- Enterprise 示例:
LOGIN_FORM: https://forms.mysite.com/myproject/user/login - OSS 示例:
LOGIN_FORM: https://forms.mysite.com/user/login
Node.js(Express):
在 Node.js 环境中,你可以在本地运行的 Node.js 和 Express.js 环境中导入 UAG。具体来说,先导入 UAG 模块,再在 Express.js 应用中对其调用“use”。首先,按照以下示例,在 Node.js Express 应用中安装 UAG。
npm install --save @formio/uag
or
yarn add @formio/uag
You can then mount the UAG within your Express application, as seen in the following example:
import 'dotenv/config';
import Express from 'express';
import { UAGServer } from '@formio/uag';
try {
(async function () {
const server = new UAGServer();
const app = Express();
app.use(await server.router());
const port = process.env.PORT || 3200;
app.listen(port, () => {
console.log(`Form.io UAG server running on port ${port}`);
console.log(`Visit http://localhost:${port} to access the application`);
});
})();
} catch (error) {
console.error('Failed to start server:', error);
process.exit(1);
}
还可以通过使用模块来扩展 UAG 的功能,相关说明见 模块自述文件。
与 Form.io Enterprise Server 一起使用
将 UAG 与 Form.io Enterprise Server 配合使用,可以解锁多项优势,帮助您管理 UAG 中的表单和资源。使用我们的 Enterprise Server,您可以获得以下功能:
- 表单修订版本 - 我们的表单修订版本系统可以跟踪表单的所有变更,并将这些变更与针对相应修订版本提交的数据关联起来。此功能可确保表单架构发生变化时,提交的数据与其提交时所用的表单修订版本相对应。除了这项强大的功能,您还可以利用表单修订版本回滚表单变更导致的错误或回归问题。您无需针对任何架构重新训练或取消训练 AI Agent,只需恢复到之前的修订版本,AI Agent 就会相应地进行调整。
- 提交修订版本 - 提交修订版本可以跟踪提交数据的所有变更,并提供更改数据者的信息。结合 UAG 的强大功能,系统可以审计工作流流程中由 AI Agent 和人工所做的任何数据变更。
- 阶段版本和部署 - 阶段版本可以为项目中的所有表单和资源创建一个“标签”版本。这有助于您确定一个时间点,让 AI Agent(可能会使用多种不同的表单和资源)以确定的方式与整个项目交互。此外,它还提供了一种更简洁的回滚机制,可对整个项目的表单和资源进行版本控制并独立部署。
针对 Enterprise Server 运行 UAG
要针对 Enterprise Server 运行 UAG,您需要提供几个不同于此模块 OSS 运行时的环境变量。针对 Enterprise 项目运行时,必须设置以下环境变量。
| Variable | Description | Example |
|---|---|---|
| PROJECT | 对于 Enterprise Server,此变量指向您希望 UAG 绑定到的项目端点。 | https://mydeployment.com/myproject |
| PROJECT_KEY | 该项目的 API 密钥,可在项目设置中获取 | CHANGEME |
| UAG_LICENSE | Form.io License 团队提供给您的许可证。请联系 [email protected] 获取“临时”或完整许可证。 |
设置好这些环境变量后,您就可以运行指向 Enterprise 项目的 UAG。
故障排除
大多数 UAG 问题出在配置上,而非代码上,并且问题出现的位置往往与根因相距甚远——缺少标签看起来像是缺少表单,缺少 BASE_URL 看起来像是权限错误。下表将你可能看到的症状对应到实际成因。
| 症状 | 可能原因 |
|---|---|
Agent 提示表单不存在,或 get_forms 未列出该表单 | 表单未标记为 uag,或者更改尚未在项目缓存中生效。请参阅为表单添加 uag 标签和项目缓存与 TTL。 |
/auth/token 返回 404,并且 /.well-known/* 也不存在 | 未设置 BASE_URL。只有在设置了该变量时,身份验证提供方才会启用,因此这些端点根本不存在。请参阅 BASE_URL。 |
每个 /mcp 请求都返回 401 | 要么未设置 BASE_URL(如上所述),要么客户端未发送 Authorization: Bearer <token>。如果是服务端客户端,请参阅验证本地 MCP 客户端。 |
| 远程 Agent(claude.ai、Claude Desktop connector)无法进行身份验证 | BASE_URL 指向的不是可公开访问的 HTTPS URL。Agent 会从发现文档中读取该值并访问该地址,因此该值必须从 Agent 的视角来看是正确的,而不只是从服务端的视角来看正确。 |
Claude 集成返回 400 ... Connection error while communicating with MCP server | formio/uag-claude 镜像版本早于 1.3.0,并将 UAG 视为远程 MCP 服务,因此 Anthropic API 会尝试连接到私有地址。请升级到 1.3.0 或更高版本。请参阅 Agent 如何连接。 |
| UAG 完全无法连接到服务端,且所有工具都失败 | 如果 PROJECT 是使用自签名证书的 https URL,请设置 NODE_TLS_REJECT_UNAUTHORIZED=0。否则,请检查能否在 UAG 容器内部解析 PROJECT——这是容器到容器的地址,而不是浏览器地址。请参阅 PROJECT。 |
| 创建提交时没有任何反应 | Webhook 操作未触发。请确认其 handler 为 after,且 method 包含 create,并且 API 密钥标头与集成的 PROJECT_KEY(Enterprise)或 ADMIN_KEY(OSS)匹配。 |
| 已创建提交,但响应长时间挂起 | Webhook 操作设置了 block: true。Agent 运行需要几十秒;请设置 block: false,这样提交者就不必等待。 |
| Agent 持续运行并消耗 API 额度 | 链式调用的 persona 正在重新触发自身。它自己的写入仍满足启动它的 update webhook 上的条件。请参阅将 persona 串联成工作流。 |
| Agent 填写了部分字段,但没有填写其他字段 | 这些字段缺少 uag 属性,或其值与 Criteria 组件上的 persona 不完全一致。Agent 可能写入的每个字段都必须带有相同的 persona,可以直接设置,也可以从父组件继承。 |
| Agent 写入的值被表单拒绝 | Criteria 对格式和允许值的说明不够具体。请说明单位、舍入规则和确切的选项值,并逐字写出字段键名。 |
| 运行失败,但日志不足以查明问题位置 | 在 UAG 前面放置 Flow Viewer。它会按顺序显示令牌请求、tools/list、每次带参数的工具调用,以及回写过程。 |
如果以上情况都不适用,请运行一个示例,确认环境本身正常,然后将示例配置与你的配置进行比较。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。