关于 formio-mcp
formio-mcp 是用于从 MCP 客户端管理 Form.io 项目的 MCP 服务,适合通过 Agent 操作表单、角色和动作。它通过 stdio 提供 25 个工具,并支持项目配置及表单版本管理。
主要功能
- 01创建、查询和更新表单
- 02管理表单草稿与修订版本
- 03创建和更新项目角色
- 04管理表单动作
- 05配置 Form.io 项目
适用场景
- 01从 Agent 创建或更新表单
- 02查看并发布表单草稿
- 03管理项目角色与表单动作
MCP 相关
该服务通过 stdio 向 MCP 客户端提供 25 个 Form.io 工具;不提供 HTTP 或 SSE 传输。项目凭据可通过环境变量或项目配置提供。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @formio/mcpFORMIO_PROJECT_URLOptional, and the WEAKEST of the three project sources: a committed formio.json found by walking up from the working directory wins, then the per-directory mapping project_set writes, then this. It pins nothing — project_set can redirect a directory whose environment names a different project. Useful for a launch with nowhere to record a project, such as CI or a container (e.g. https://examples.form.io on the hosted cloud; self-hosted it is either https://your-project.your-domain.com or https://your-host/project-name, depending on how that deployment routes projects). Leave it unset and the agent asks for a project and records it per directory.FORMIO_BASE_URLOptional, and usually unnecessary: the base URL is DERIVED from the project URL — https://api.form.io for a project on a form.io host, the parent path for a project addressed as a sub-directory — and is asked for only when it cannot be derived, which is a path-less project URL on a customer domain. There is no default. Like FORMIO_PROJECT_URL it is the weakest source, behind a committed formio.json and the per-directory mapping.FORMIO_API_KEY密钥Form.io project API key. Optional — applied only to the project FORMIO_PROJECT_URL names, so set FORMIO_PROJECT_URL beside it; any other project, and every project when it is omitted, uses the browser-based portal login flow to obtain a JWT.FORMIO_LOGIN_FORMURL of a custom login form used by the browser-based portal login flow. Defaults to the deployment's portal login form.FORMIO_AUTH_HOST密钥Address the browser-login page binds to. Optional; defaults to 127.0.0.1. Set it to 0.0.0.0, together with FORMIO_AUTH_PORT, when the server runs in a container or on a remote machine and the login page must be reachable through a published port. 0.0.0.0 exposes the page on every interface for the duration of a login.FORMIO_AUTH_PORT密钥Fixed port for the browser-login page, so a container can publish it (e.g. 43117). Optional; a positive integer, and by default the page takes an ephemeral port.FORMIO_AUTH_TIMEOUT密钥Seconds to wait for a browser login before the call fails with an error naming the remedies. Optional; a positive integer no larger than 2147483, and any other value is ignored. Defaults to 900.FORMIO_FORCE_BROWSERSet to 1 to attempt the browser login even where the server detects it cannot present one (CI, a container, a remote shell with no display). Use it when the login page is reachable from a browser elsewhere.FORMIO_REQUEST_TIMEOUTSeconds a Form.io request may go unanswered before the call fails with a network error naming the URL. Optional; a positive integer no larger than 2147483, and any other value is ignored. Defaults to 60. project_import and project_export wait 300 seconds, or this value when it is longer.FORMIO_INSECURE_TLSSet to 1 to skip TLS certificate verification only for requests to the configured deployment (the hosts of the resolved project URL and base URL); every other host is verified as usual. For local development against self-signed certificates only — never enable in production.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
21收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 否 | 要问候的姓名 |
详细介绍
Formio MCP 服务
MCP 服务(@formio/mcp)可独立供任何支持 MCP 的客户端使用。它使用 stdio:客户端负责启动它,并管理 stdin/stdout。无需开放端口,也无需手动启动任何内容。
从此仓库的克隆版本中,入口点是 src/stdio.ts:
pnpm install
pnpm --filter @formio/mcp exec tsx src/stdio.ts
这样运行时,它会等待 stdin 上的 MCP 流量;这只能说明它可以正常启动——应改为让客户端调用该命令。构建后的软件包会将同一入口点作为 formio-mcp 可执行文件和 dist/stdio.js 提供。
传输方式
| 传输方式 | 命令 | 兼容客户端 |
|---|---|---|
| stdio | npx -y @formio/[email protected](或 node dist/stdio.js) | Claude Code、Claude Desktop、Cursor、VS Code、Codex、Windsurf、Cline——任何通过 stdio 使用 MCP 的客户端 |
不支持 HTTP 或 SSE 传输。该服务唯一的 HTTP 监听器是身份验证中所述的临时浏览器登录页面,不承载任何 MCP 流量。
连接客户端
同一个 stdio 入口适用于所有客户端,但配置文件的位置以及所在的键名会因客户端而异:Claude Code 使用 mcpServers 下的 .mcp.json,Cursor 使用 mcpServers 下的 .cursor/mcp.json,VS Code 使用 servers 下的 .vscode/mcp.json,Codex 则使用 TOML 格式的 .codex/config.toml。不存在通用的 .mcp.json。根 README列出了各客户端的完整配置表;JSON 的 mcpServers 格式如下:
{
"mcpServers": {
"formio-mcp": {
"command": "npx",
"args": ["-y", "@formio/[email protected]"],
"env": {
"FORMIO_PROJECT_URL": "https://your-project.form.io"
}
}
}
}
每个访问 Form.io 的工具都需要一个项目。项目可以来自已提交的 formio.json、由 project_set 工具写入的目录映射,或环境中的 FORMIO_PROJECT_URL;顺序按作用范围从窄到宽,因此映射会覆盖环境变量,而已提交的文件会覆盖两者。FORMIO_BASE_URL 是可选的,通常不需要:系统会根据项目 URL 的形式推导基础 URL——位于 form.io 主机上的项目使用 https://api.form.io,通过子目录路由的项目则使用其父路径;只有在无法推导时才会要求提供。没有任何插件清单会提示输入这两个值;每个客户端都会通过 project_set 或已提交的 formio.json 按目录记录这些值。.mcpb 桌面套件是唯一例外,因为桌面主机没有可供交互配置的工作目录。
即使这两个值都未设置,服务也能启动,因此客户端可以先连接并列出工具,再进行配置——只有在工具需要项目 URL 时才会要求提供,而 server_status 始终可用。
在 Docker 中运行
该服务提供 Dockerfile,并以 formio/mcp 的名称发布到 Docker Hub,支持 linux/amd64 和 linux/arm64。该镜像使用 stdio,因此 MCP 客户端负责管理 stdin/stdout,容器必须使用 -i 运行:
docker run -i --rm \
-e FORMIO_PROJECT_URL=https://your-project.form.io \
-e FORMIO_API_KEY=your-api-key \
formio/mcp
接入客户端时——与连接客户端使用相同的入口,只需将 command 和 args 指向 Docker——配置如下(此处展示 JSON 的 mcpServers 格式;如上所述,VS Code 使用 servers,Codex 使用 TOML):
{
"mcpServers": {
"formio-mcp": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "FORMIO_PROJECT_URL",
"-e", "FORMIO_API_KEY",
"formio/mcp"
],
"env": {
"FORMIO_PROJECT_URL": "https://your-project.form.io",
"FORMIO_API_KEY": "your-api-key"
}
}
}
}
容器中的身份验证
推荐使用 FORMIO_API_KEY,无需浏览器,也无需交互操作。发布身份验证端口后,也可以通过浏览器登录;这两种方式请参阅无头环境。
无论采用哪种身份验证方式,都有两点容器专属注意事项。优先使用 FORMIO_PROJECT_URL 环境变量,而不是 project_set 工具:project_set 会将每个目录的映射持久化到 ~/.formio/projects.json,该文件位于容器内,会在容器退出时被丢弃。此外,每个工具接受的 cwd 参数都指向容器内的路径,而非主机上的路径;客户端报告的工作区根目录则是主机路径,因此请显式传入 cwd。
要在多次容器运行之间复用令牌,请挂载缓存目录。该目录必须可写,因为令牌刷新或清除时,服务会重写文件:
-v "$HOME/.formio:/root/.formio"
自托管部署
部署未公开时,通常会遇到以下两个问题:
主机名解析。 容器内无法解析私有主机名。请显式映射:
docker run -i --rm --add-host forms.internal:10.0.0.5 \
-e FORMIO_BASE_URL=https://forms.internal \
-e FORMIO_PROJECT_URL=https://forms.internal/my-project \
-e FORMIO_API_KEY=your-api-key \
formio/mcp
私有或自签名证书。 此镜像仅信任标准 CA 证书包。即使主机通过 macOS 钥匙串等方式信任某个证书,该证书在容器内仍会验证失败,工具会只显示 fetch failed。有两种情况,处理方式各不相同:
由私有 CA 签发。 挂载 CA 证书,并将 Node 指向该证书:
-v /path/to/rootCA.pem:/certs/rootCA.pem:ro -e NODE_EXTRA_CA_CERTS=/certs/rootCA.pem
完全自签名的服务器证书——其主题与颁发者相同,且没有 CA:TRUE 基本约束。NODE_EXTRA_CA_CERTS 无法解决此问题,即使挂载服务器自己的证书也不行:Node 要求信任锚必须是 CA,并会以 DEPTH_ZERO_SELF_SIGNED_CERT 错误拒绝证书链。使用以下命令确认属于哪种情况:
echo | openssl s_client -connect your-host:443 -servername your-host 2>/dev/null \
| openssl x509 -noout -subject -issuer
如果主题与颁发者相同,唯一的选择是使用 FORMIO_INSECURE_TLS=1。它只会对发往已配置部署的请求跳过证书验证;服务访问的其他所有主机仍会进行验证。仅用于本地开发,切勿用于生产部署。
在本地构建镜像
构建上下文是仓库根目录,而不是当前目录:镜像使用仓库的 pnpm-lock.yaml 安装依赖,并启用冻结锁文件,因此镜像中包含的版本与仓库测试过的版本完全一致。请在仓库根目录运行:
docker build -f packages/mcp-server/Dockerfile -t formio-mcp .
使用 MCP Inspector 检查
MCP Inspector 可连接到服务,让你手动浏览和调用其工具 — 在将配置接入 Agent 前,可用它确认配置是否正常。启动 Web 门户:
npx @modelcontextprotocol/inspector
它会打印一个带有身份验证令牌的 URL 并打开浏览器。默认端口为 6274;如果该端口已被占用,可将两者改为 CLIENT_PORT=6284 SERVER_PORT=6285。

将 inspector-config.example.json 复制为 inspector-config.json,填入项目 URL 和 API 密钥,就得到了下一步所需的文件。该文件名已添加到 gitignore 中,因此填好内容的副本不会被意外提交。
同一流程的逐步说明:
1. 选择 Add Servers → Import from client config。

2. 点击“From file…”。 对话框接受客户端配置文件或这台机器上已安装的客户端 — 没有可粘贴 JSON 的位置。

**3. 选择你的 inspector-config.json,**其中定义的服务会列为新增服务。点击“Import 1 server”确认。

4. 使用服务卡片上的切换开关启用服务。 容器启动后,开关会变为绿色并显示协商后的协议版本;首次连接较慢,因为 Docker 需要启动容器。

5. 打开 Tools 选项卡,查看此服务提供的工具。每个服务都会列出全部 25 个工具 — 包括为每个客户端注册的 project_set 和 project_get。

6. 选择一个工具,填写参数,然后点击“Execute Tool”。 结果会显示在中间窗格中,JSON-RPC 交互则显示在右侧的 Protocol 面板中。server_status 不会访问凭据,也不会发出 Form.io 请求,因此可用于区分传输问题和身份验证问题;下方的 form_list 则会针对项目发起真实调用。

导入会将服务写入 Inspector 自己的目录 ~/.mcp-inspector/mcp.json,因此下次使用时它仍会保留 — 用完后可从服务卡片中移除。如果某个工具只报出 fetch failed,通常是部署问题,而非服务问题:请参阅可自托管部署,了解容器内的主机名解析和证书信任。
MCP 服务工具
捆绑的 @formio/mcp 服务提供以下 25 个工具。只要操作有对应工具,技能就会优先使用它们,而不是原始 HTTP。
表单
| 工具 | 用途 |
|---|---|
form_create | 创建新表单。先使用 formio-schema 技能构建 JSON 定义。在支持修订版本的部署中,revisions 默认为 "original"。 |
form_get | 根据 _id 或路径(formIdOrPath)获取单个表单定义。draft: true 则获取其草稿。 |
form_list | 分页列出表单,可按 type 和 tags 筛选(表单需包含给出的所有标签)。除非 select 指定其他字段,否则返回摘要字段。 |
form_update | 使用编辑后的 JSON 更新表单。先调用 form_get,使用 formio-schema 编辑,然后更新。draft: true 会保存草稿,而不是当前生效的表单。 |
form_publish | 将表单草稿发布为当前生效版本(formId、note)。表单没有草稿时会失败并返回 NO_DRAFT。需要修订版本许可证(Security Module)。 |
form_revert | 将先前修订版本的组件、标签、属性和显示设置还原到当前生效的表单(formId、version、note)。需要修订版本许可证(Security Module)。 |
form_revision_list | 按时间倒序列出表单的修订版本摘要(_id、_vid、_vnote、_vuser、created、modified)。需要启用表单修订版本。 |
form_revision_get | 根据 _vid 或修订版本文档 _id 获取单个不可变的表单修订版本。 |
角色
| 工具 | 用途 |
|---|---|
role_create | 创建新的项目角色,参数为 role: { title, description?, default?, admin? }。 |
role_list | 分页列出项目角色。 |
role_update | 更新角色(roleId、role)。未提供的字段会保留已存储的值。 |
操作
| 工具 | 用途 |
|---|---|
action_type_list | 列出服务上所有可用的操作类型——完整目录,Form.io 不会对其分页。 |
action_type_get | 获取操作类型的设置架构。目录中没有列出的类型会失败并返回 UNKNOWN_ACTION_TYPE。 |
action_create | 向表单添加新操作。 |
action_list | 分页列出表单上的操作。 |
action_get | 根据 ID 获取单个操作。 |
action_update | 更新操作。未提供的字段会保留已存储的值。 |
action_delete | 从表单中移除操作。 |
项目
| 工具 | 用途 |
|---|---|
project_export | 将项目的完整模板(角色、资源、表单、操作)导出为可移植的 JSON 文档。指定 tag 时,导出存储在该版本标签中的模板——工作区的 template.json 刷新方式即是如此。 |
project_import | 导入模板 JSON 以进行首次构建。模板中列出的每个表单都会在原位置替换,其操作会被删除并重新创建;模板中的 access 会替换项目的 access;未列出的表单、角色和操作会保留。使用表单、角色和操作工具更改现有项目。 |
project_tag_list | 列出项目的当前版本及其版本标签,按时间从新到旧排列。使用 compare: true 时,列出自当前版本以来发生变更的角色、资源、表单和操作。 |
project_tag_create | 为项目创建版本:Form.io 会将其当前状态保存为带有 description 的 semver tag。 |
project_get | 报告目录解析到哪个项目、哪个部署主机托管该项目,以及各项信息来自哪个层级。这是在首次调用读取或写入工具前应运行的预检。它在服务内部使用与其他工具相同的解析器返回结果,因此无需运行 shell 命令。返回的 status 为 ok、not-configured 或 base-url-unresolved。 |
project_set | 将目录的 Project URL 保存到 ~/.formio/projects.json。若要将目标与代码一同记录,请在应用自身文件夹中编写并提交 formio.json——服务会读取该文件,但绝不会写入该文件。一个服务可为多个工作区提供服务。此映射会应用于对应目录及其下的所有子目录,直到遇到首个包含 .git 的文件夹——这与搜索 formio.json 时使用的边界相同,因此父文件夹上的映射不会延伸到其下克隆的代码仓库中;当工作目录位于多个已映射文件夹中时,以最近的已映射文件夹为准。此处写入的映射会覆盖服务环境中的 FORMIO_PROJECT_URL,后者的优先级最低。 |
project_set 为什么采用这种方式
工具的描述只包含调用方需要遵循的规则。背后的原因如下:
- 调用本身就是持久化操作。 Agent 如果只在文本中回答“切换到项目 X”,实际上什么也没改变;只有工具调用才能写入映射。
- 映射以调用解析到的目录为键。 如果传入了
cwd,就是该目录;否则就是其他工具解析到的同一目录(参见下文的约定)。唯一固定的是最后的回退值——服务进程自身的工作目录,它在客户端启动服务时确定,而且通常不是用户当前工作的目录,因此以该目录为键写入映射就会造成这种情况。 - 无需重启,但映射不一定始终生效。 每个工具都会在每次调用时解析项目,因此下一次调用就会读取新映射。只有在映射是实际生效记录的情况下,它才会起作用:如果存在已提交的
formio.json,映射会在该文件消失时作为回退值。这就是为什么结果会报告实际解析出的那一对值(projectUrl、ok),而不是刚刚记录的值。 - 基础 URL 是推导出来的,不需要询问。 它用于构造门户登录 URL,并作为缓存令牌的键;因此,错误的基础 URL 会导致登录失败,而不是请求失败;猜测出的基础 URL 则会将登录请求发送到用户并未使用的部署。对于
form.io主机(https://api.form.io,所有托管项目共用的基础 URL)和子目录项目(父路径),基础 URL 都可以推导出来。例外情况是客户域名上没有路径的项目 URL:其部署位于同级子域名,而项目 URL 中没有任何信息能指出该子域名。 - 部署与项目绑定。 基础 URL 会按目录存储在与之关联的项目旁边,因此每个目录都可以指向不同的部署,而且任何部署都不会响应其他项目的请求。因此,若某次调用将目录重新指向另一个项目,就不会保留基础 URL:旧值属于被替换的项目。
- 映射仅限本机。 映射以绝对路径为键,因此克隆后不会保留。已提交的
formio.json会进行版本控制、显示在差异中,并与克隆仓库的所有人共享,因此当目标属于应用时,优先使用它。 - 拒绝未知参数。 输入架构是严格的:工具不接受的参数(例如已移除的
scope)会被拒绝,而不是直接丢弃,因此根据旧文档编写的调用不会错误地报告一项实际未发生的写入。
诊断
| 工具 | 用途 |
|---|---|
server_status | 报告服务的名称和版本,以及 cwd 如何解析到项目,与 project_get 相同。它不会发出 Form.io 请求,也不需要凭据,因此可用于区分传输问题和身份验证或配置问题——其他工具失败时请先调用它。 |
每个工具都遵循的约定
cwd. 每个解析项目的工具都接受可选的cwd,并在每次调用时按以下顺序为一个目录进行解析:cwd参数;客户端的工作区根目录(当客户端声明了 MCProots能力时)——只有一个根目录时直接使用;有多个根目录时,由包含项目记录(已提交的formio.json或目录映射,包括损坏的映射)的根目录决定;如果它们都包含相同的记录,则使用其中第一个;如果都不包含记录,则使用下一个来源;如果包含不同记录,则拒绝并返回列出这些根目录的INVALID_ARGUMENT;绝对路径的CLAUDE_PROJECT_DIR环境变量;最后是服务进程自身的工作目录,即客户端启动服务时所在的目录。每个会话开始时读取一次根目录,并在收到notifications/roots/list_changed后再次读取;如果roots/list失败或在 2 秒内没有响应,则继续使用上一次成功读取的列表;只有从未成功读取过时才视为没有根目录。project_get和server_status会通过cwdSource报告来源(argument、client-root、claude-project-dir或server)。当cwdSource为server或claude-project-dir时(这两者都是对用户所在位置的猜测),请传入绝对路径形式的cwd;如果要指定其他目录,也请传入cwd,例如在 monorepo 中指定某个应用,而每个应用都有自己的formio.json。formId和formIdOrPath。formId始终是表单的 24 字符 ObjectId_id。formIdOrPath接受_id或表单路径,且仅用于 Form.io 按路径提供的读取操作:form_get、form_revision_list和form_revision_get。如果将路径作为formId传入,则会以INVALID_ARGUMENT拒绝;请使用form_get读取表单的_id。- 列表。
form_list、role_list、action_list和form_revision_list接受limit(默认值为 100)、skip、sort和select。每个操作都会在各自的键(forms、roles、actions、revisions)下返回条目,并同时返回total(整个查询匹配的条目数)和hasMore(如果还有下一页则为 true):请增大skip再次调用,直到hasMore为 false。如果 Form.io 未报告总数,则不返回total;当返回的页面已满时,hasMore为 true。action_type_list以相同方式返回actionTypes,且hasMore始终为false。 - 更新会覆盖发送的内容。
form_update、role_update和action_update会发送 PUT 请求,由 Form.io 将其应用于已存储的文档:请求体中的每个字段都会覆盖已存储的对应字段,而未包含的顶层字段会保留其已存储的值。请求体中的数组或对象会按原样存储,即整个替换已存储的内容,而不是与之合并,因此请发送该字段应保留的所有组件、访问条目或设置。 - 修订历史。 如果
form_create或form_update保存时不会保留修订历史(部署未获得修订功能许可、请求体将revisions设为"",或更新目标表单已关闭修订功能),则会以HISTORY_NOT_ACCEPTED拒绝且不会写入任何内容,除非调用传入acceptNoHistory: true。服务本身绝不会提示用户:Agent 会转达拒绝信息,并根据用户的答复重试。草稿、form_publish和form_revert需要修订功能许可;没有许可时会以LICENSE_REQUIRED拒绝。 - 错误。 调用失败时会返回
isError: true,文本以方括号中的错误代码开头([NOT_FOUND] …),后接错误消息;同时返回_meta["io.form/error"]: { code, status?, body? },其中status是 Form.io 的 HTTP 状态码,body是其响应正文,截断至 2,000 个字符。错误结果不包含structuredContent。错误代码包括NOT_CONFIGURED、BASE_URL_UNRESOLVED、CONFIG_UNREADABLE、INVALID_ARGUMENT、AUTH_REQUIRED、FORBIDDEN、NOT_FOUND、VALIDATION_FAILED、LICENSE_REQUIRED、HISTORY_NOT_ACCEPTED、NO_DRAFT、UNKNOWN_ACTION_TYPE、REDIRECTED、UPSTREAM_ERROR、NETWORK_ERROR和INTERNAL。不符合工具输入架构的参数会由 MCP SDK 以纯文本报告,不带错误代码。
身份验证
MCP 服务支持两种身份验证模式:
- JWT 模式(默认)。 一个短期运行的本地 Express 服务会呈现 Form.io 门户登录表单;用户登录一次后,JWT 会通过
/callback端点返回,formioFetch会在之后的每个请求中附加x-jwt-token。此流程是隐式的——缓存未命中时,首次经过身份验证的工具调用会触发登录。不存在显式的authenticate工具。 - API 密钥模式。 在
FORMIO_PROJECT_URL旁设置FORMIO_API_KEY环境变量。对项目FORMIO_PROJECT_URL的请求会附加x-token,并完全跳过浏览器流程;任何由已提交的formio.json或目录映射解析出的其他项目,则会通过门户登录进行身份验证,project_get会说明原因。
JWT 会缓存在 ~/.formio/mcp-tokens.json 中(模式为 0600),并以解析后的 Base URL 为键——同一部署上的所有项目共用一个令牌。令牌的有效期约为七天;命中缓存时,服务会在本地检查是否过期,然后向服务器重新验证;如果任一检查失败,则会重新登录。
授予 Agent 的权限。 JWT 模式会将登录者的 JWT交给 Agent,因此在令牌有效期内,Agent 将以该用户的权限执行操作——如果以管理员身份登录,Agent 就会继承对该部署的管理员访问权限。API 密钥则仅限于其所属项目。对于无人值守或共享环境,建议使用 API 密钥模式;使用 JWT 模式时,请以权限最低的用户身份登录。
无头环境
默认情况下,登录页面会在绑定到 127.0.0.1 的临时端口上提供,服务会直接启动默认浏览器,而不通过 shell:macOS 使用 open,Linux 使用 xdg-open,Windows 使用 url.dll 协议处理程序——这要求同一台机器上有桌面浏览器。
如果不满足这一条件——例如在容器、SSH 会话或 CI 中——你有以下三种选择:
-
在
FORMIO_PROJECT_URL旁设置FORMIO_API_KEY环境变量,完全跳过浏览器。最适合无人值守使用。 -
手动完成登录。 每次尝试登录时,都会在尝试启动浏览器之前将登录 URL 写入 stderr——不只是出错时才写入。如果启动失败,系统会额外输出一行说明,而不会将错误吞掉。该 URL 也会出现在超时错误中,客户端会将其作为工具输出展示,因此即使你看不到服务日志,也能获取该 URL。
使用 stderr 是因为采用 stdio 传输时,stdout 承载的是 MCP 协议本身——向其中写入其他内容会破坏数据流。
-
绑定到可访问的地址。 将
FORMIO_AUTH_HOST=0.0.0.0和FORMIO_AUTH_PORT设为固定的已发布端口,然后从你自己的机器打开 URL:docker run -i --rm -p 43117:43117 \ -e FORMIO_PROJECT_URL=https://your-project.form.io \ -e FORMIO_AUTH_HOST=0.0.0.0 -e FORMIO_AUTH_PORT=43117 \ formio/mcpFORMIO_AUTH_HOST=0.0.0.0会在登录期间将登录页面暴露到所有网络接口。只有在可以接受的情况下才使用此设置。
无论通过哪种方式访问,都请按打印的原样打开登录 URL,包括其中的 ?s= 值:页面仅针对该值提供服务,该值会在每次登录时生成。通过转发端口访问(例如 devcontainer、Codespaces)时,请保留 ?s= 值,只更改主机和端口。
如果在 FORMIO_AUTH_TIMEOUT 秒内(默认值为 900)没有收到登录请求,调用会失败并返回说明这些选项的错误,而不是一直挂起直到客户端放弃。
登录表单自动解析
未设置 FORMIO_LOGIN_FORM 时,服务会在首次登录尝试时探测以下候选地址,并缓存第一个有响应的地址(每个候选地址的超时为 1.5 秒):
{baseUrl}/formio/user/login(门户基础地址){projectUrl}/admin/login(项目管理员){projectUrl}/user/login(项目用户)
{baseUrl} 和 {projectUrl} 是解析后的值——即 project get 为该目录报告的值——而不是名称相似的环境变量。
此探测会延迟执行——只有实际提供本地身份验证页面时才会运行。
环境变量
| 名称 | 必需 | 默认值 | 用途 | 托管式 SaaS 示例 | 自托管示例 |
|---|---|---|---|---|---|
FORMIO_PROJECT_URL | 是* | — | Form.io 项目的完整 URL。三个来源中优先级最低:从工作目录向上查找时找到的已提交 formio.json 优先,其次是由 project_set 写入的目录映射,最后才是此变量。对于自托管部署,它是部署的子目录或自有域名的子域名(https://myproject.example.com),具体取决于该部署如何路由项目。 | https://myproject.form.io | https://forms.example.com/myproject |
FORMIO_BASE_URL | 否 | 根据说明推导 | Form.io 部署的完整基础 URL。通常由项目 URL 推导,而不是手动设置——对于位于 form.io 主机上的项目,该值为 https://api.form.io;对于通过子目录寻址的项目,该值为父路径。仅当项目 URL 是自有域名上没有路径的地址,且无法从部署中推导时才设置此变量。三个来源中优先级最低:已提交的 formio.json 优先,其次是目录映射,最后才是此变量。在托管云上,该值始终为 https://api.form.io,而不是项目的 *.form.io 子域名。 | https://api.form.io | https://forms.example.com |
FORMIO_API_KEY | 否 | undefined | 长期有效的项目 API 密钥,仅应用于 FORMIO_PROJECT_URL 指定的项目——请同时设置 FORMIO_PROJECT_URL。适用时,服务会跳过浏览器登录流程——这是在没有浏览器的主机上进行身份验证的唯一方式。 | CHANGEME | CHANGEME |
FORMIO_LOGIN_FORM | 否 | 自动解析 | 覆盖 JWT 登录流程使用的门户登录表单 URL。 | https://formio.form.io/user/login | https://forms.example.com/formio/user/login |
FORMIO_AUTH_HOST | 否 | 127.0.0.1 | 浏览器登录页面的绑定地址。0.0.0.0 可使其从容器外部访问。 | ||
FORMIO_AUTH_PORT | 否 | 临时端口 | 浏览器登录页面使用的固定端口,以便容器可以发布该端口。 | 43117 | 43117 |
FORMIO_AUTH_TIMEOUT | 否 | 900 | 等待浏览器登录的秒数,超时后调用将失败。必须是大于 0 且不超过 2147483 的整数;其他值将被忽略。 | ||
FORMIO_REQUEST_TIMEOUT | 否 | 60 | Form.io 请求等待响应的秒数,超时后调用将失败,并返回包含 URL 和等待时长的 NETWORK_ERROR。必须是大于 0 且不超过 2147483 的整数;其他值将被忽略。project_import 和 project_export 会等待 300 秒;如果此变量设置的时间更长,则使用该值。 | ||
FORMIO_INSECURE_TLS | 否 | undefined | 设置为 1 可仅对发往已配置部署(已解析的 Project URL 和 Base URL 所属主机)的请求跳过 TLS 验证;其他所有主机仍按常规方式验证。仅用于本地开发——绝不可用于生产环境。 | ||
FORMIO_FORCE_BROWSER | 否 | 0 | 设置为 1,即使服务检测不到浏览器(CI、容器、没有显示器的 SSH 环境),也尝试进行浏览器登录。 | ||
* 非启动时要求——服务器会启动、列出所有工具,并在没有它的情况下响应 server_status;只有读取或写入 Form.io 数据的工具会报错,并指出 project_set 和此变量。替代方案是 project_set 工具,它会将工作目录映射到 ~/.formio/projects.json 中的一个项目。解析按作用域进行,从最窄范围开始:从调用方的 cwd 向上查找时找到的已提交 formio.json,然后是 cwd 或其最近映射的祖先目录对应的映射,接着是环境中的 FORMIO_PROJECT_URL(优先级最低),最后才报错。在任何客户端连接之前,先用 npx -y @formio/[email protected] project set --project-url <url> --cwd <path> 映射目录——只要能从项目 URL 推导出部署地址,系统就会自动推导,因此只有当服务器提示无法确定时才添加 --base-url <url>。在两个 URL 参数旁添加 --force,即可记录一组不符合域名规则的 URL——规则唯一无法判断是误操作的情况,是部署在 *.form.io 域名下的内部部署;这两个 URL 必须在同一次调用中提供,此设置会在之后的每次读取中生效,并且这是仅限 Shell 使用的标志,project_set 工具不支持它。project set --reset --cwd <path> 会清除目录的条目,这也是取消强制设置的方法:如果一次写入没有更改这两个值,则会保留该覆盖设置,因此取消强制后再记录不会产生任何变化。project get --cwd <path> 会打印解析结果以及胜出的来源。解析成功时退出码为 0;该目录没有映射时退出码为 1;命令无法给出结果时退出码为 2(例如用法错误、URL 格式错误、无法读取 ~/.formio/projects.json);项目已解析但无法确定其 Base URL 时退出码为 3——这样调用方就能区分“这里尚未配置”“操作失败”和“配置了一半,且缺少以下值”。project set --cwd <path> 在目录已准备好处理调用时退出码为 0;仍缺少指定值时退出码为 1;命令无法给出结果时退出码为 2;记录已写入但目录仍无法解析出 Base URL 时退出码为 3——已提交的 formio.json 会优先控制该目录,但没有提供 Base URL,因此应修改该文件,而不是再次写入。 |
CLI 参考:project get、project set 和 project logout
formio-mcp 二进制文件(npx -y @formio/[email protected] project …)会报告某个目录解析到的内容,并在任何客户端连接之前为该目录记录项目。project logout 会退出一个部署的登录状态——即该目录解析到的部署(解析方式与 project get 完全相同),或由 --base-url 指定的部署——方法是从 ~/.formio/mcp-tokens.json 中删除该部署缓存的令牌,同时保留所有其他条目。正在运行的服务会在下次调用时检测到这一变化并重新登录,因此退出登录或切换账户无需重启。这些标志和退出代码属于 1.0 版的接口。
| 标志 | 命令 | 含义 |
|---|---|---|
--cwd <absolute path> | 全部三个命令 | 要报告、记录或退出登录的目录。默认为当前目录;不接受相对路径。 |
--project-url <url> | project set | 要记录的 Project URL。 |
--base-url <url> | project set | 托管该项目的部署。仅当服务表示无法从 Project URL 推导出此地址时才传入。 |
--force | project set | 按照给定内容原样记录这一对值,跳过域名检查。要求在同一次调用中同时提供 --project-url 和 --base-url。project_set 工具没有对应选项。 |
--reset | project set | 清除此目录在 ~/.formio/projects.json 中的条目。不接受 URL。 |
--base-url <url> | project logout | 要退出登录的部署,替代 --cwd 所解析到的部署。 |
| 退出代码 | project get | project set | project logout |
|---|---|---|---|
0 | 该目录解析到了一个项目及其 Base URL。 | 该目录已准备好处理调用。 | 令牌已删除,或该部署没有缓存令牌;输出会说明是哪种情况。 |
1 | 未为该目录映射任何内容。 | 仍缺少一个已指定的值。 | 未为该目录映射任何内容,因此无法解析出部署;请使用 --base-url 指定一个部署。或者,给定的 --base-url 不是有效 URL;请重新索取。 |
2 | 命令无法作出判断:用法错误、URL 格式错误,或无法读取 ~/.formio/projects.json。 | 命令无法作出判断。 | 命令无法作出判断:用法错误,或无法读取或写入 ~/.formio/mcp-tokens.json。 |
3 | 已解析出项目,但无法确定其 Base URL。 | 记录已写入,但该目录仍无法解析出 Base URL:已提交的 formio.json 对其生效且未提供 Base URL,因此需要编辑该文件。 | 已解析出项目,但无法确定其部署;请使用 --base-url 指定部署。 |
隐私政策
Form.io 的隐私政策涵盖此服务连接的 Form.io 服务:https://form.io/privacy
此服务自身如何处理数据,以下内容说明了上述政策无法描述的部分:
您的数据会去往何处。 仅发送至您配置的 Form.io 部署。每个请求都会发送至为您的工作目录解析出的 Project URL 和 Base URL — 您自己的 SaaS 项目或自托管服务。自托管时,此服务不会向 Form.io 发送任何内容,也不会进行任何形式的遥测、分析或使用情况报告。
您的机器上存储了什么。 ~/.formio/ 下的两个文件,写入时的权限均为 0600:
| 文件 | 内容 | 写入时机 |
|---|---|---|
mcp-tokens.json | 浏览器登录获得的 JWT,以解析出的 Base URL 为键 | 您通过浏览器登录时 |
projects.json | 每个目录对应的项目和基础 URL 映射 | 运行 project_set 时 |
表单数据和提交内容绝不会写入磁盘 — 它们仅在内存中传递,用于响应工具调用。
凭据。 设置 FORMIO_API_KEY 环境变量后,此服务会从环境中读取该变量,并且仅在向名称为 FORMIO_PROJECT_URL 的项目发出请求时,将其作为身份验证标头发送;该变量绝不会写入磁盘。缓存的 JWT 有效期约为 7 天,之后此服务会重新进行身份验证。删除 ~/.formio/mcp-tokens.json 可立即退出登录。
第三方。 此服务不会联系任何第三方服务。有一个例外值得说明:浏览器登录页面由本地提供,而该页面所加载的 Form.io 渲染器及其样式表来自 cdn.jsdelivr.net,网页字体来自 fonts.googleapis.com,Form.io 徽标来自 portal.form.io,因此这些主机在该页面打开期间会看到您的浏览器 IP 地址。页面上的其他所有内容均来自您自己的部署。在 FORMIO_PROJECT_URL 旁设置 FORMIO_API_KEY 环境变量,即可完全跳过浏览器登录流程,避免上述情况。
保留期限。 上述文件会一直保留,直到您将其删除。Form.io 项目中的数据遵循您自己的部署所设定的保留规则;对于托管在 Form.io 上的项目,则遵循上方链接中的政策。
有关数据处理的问题,请联系:[email protected]
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。