关于 BriefGate
BriefGate 是面向编码 Agent 的 MCP 服务,用于向客户收集文件、文案、凭据或结构化数据。它会创建提交入口、自动跟进,并返回 Agent 可直接使用的类型化结果。
主要功能
- 01收集文件、文本、选项和凭据
- 02创建客户资料提交入口
- 03向客户发送邮件并自动跟进
- 04验证提交的文件
- 05返回类型化结果和签名文件 URL
适用场景
- 01收集客户的品牌资料和网站文案
- 02为项目收集托管凭据
- 03请求营业时间等结构化信息
MCP 相关
BriefGate 向 MCP 客户端提供资料收集工具,包括定义请求和获取结果。它支持托管 HTTP 端点和本地程序包。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://mcp.briefgate.dev/mcpclaude mcp add --transport http sekera-radim-briefgate https://mcp.briefgate.dev/mcp{"mcpServers":{"sekera-radim-briefgate":{"type":"http","url":"https://mcp.briefgate.dev/mcp"}}}在 Cursor 中打开{"servers":{"sekera-radim-briefgate":{"type":"http","url":"https://mcp.briefgate.dev/mcp"}}}在 VS Code 中打开{"mcpServers":{"sekera-radim-briefgate":{"type":"http","url":"https://mcp.briefgate.dev/mcp"}}}{"mcpServers":{"sekera-radim-briefgate":{"serverUrl":"https://mcp.briefgate.dev/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
BriefGate
客户资料收集——通过浏览器,或由你的 AI 编码 Agent 完成。
你的 Agent 可以构建网站。 BriefGate 会向客户收集缺失的信息。
没有 Agent?你也不需要。 以下所有操作都可以手动在 app.briefgate.dev 完成:创建请求、发送链接、查看收到的回复,并将结果下载为一个 ZIP 文件——无需代码、API 密钥或 MCP 客户端。这个软件包适用于另一种工作方式:由 Agent 代你完成这些操作。请参阅控制台快速入门。
Claude Code / Cursor / Codex → BriefGate → Client portal
→ Files · copy · credentials · structured data → Agent continues building

网站 · MCP 参考文档 · llms.txt · 指南和检查清单
问题所在
Agent 速度很快,瓶颈在于项目另一端的人。
在构建过程中,Agent 总会需要一些只有客户才有的东西:徽标、首页文案、品牌颜色、营业时间、托管凭据、API 密钥,或价目表之类的结构化数据。这些信息不在聊天记录中,也无法靠猜测得出。
通常的做法是停下来,让开发者通过电子邮件去追问客户。换一种方式:Agent 创建一个 BriefGate 资料收集请求。BriefGate 会给客户发送电子邮件、收集回复;如果客户没有回复,还会自动跟进,并返回 Agent 可以直接使用的类型化结果。与此同时,Agent 可以继续构建。
快速入门
Claude Code — 托管服务,无需管理密钥:
claude mcp add --transport http briefgate https://mcp.briefgate.dev/mcp
然后在 Claude Code 中运行 /mcp,选择 briefgate,再选择 Authenticate。
Claude Code — 本地包:
claude mcp add briefgate -- npx -y @briefgate/mcp
npx -y @briefgate/mcp login
想完全跳过登录?在 briefgate.dev 获取密钥(免费套餐,无需信用卡),并将其作为 BRIEFGATE_API_KEY 传入。
Cursor — 添加到 .cursor/mcp.json:
{
"mcpServers": {
"briefgate": {
"command": "npx",
"args": ["-y", "@briefgate/mcp"]
}
}
}
然后运行 npx -y @briefgate/mcp login,或让 Agent 调用 login 工具。
Codex:
codex mcp add briefgate --env BRIEFGATE_API_KEY=bg_live_xxxxx -- npx -y @briefgate/mcp
Gemini CLI — 从此仓库的 gemini-extension.json 安装为扩展,并指向托管端点:
gemini extensions install https://github.com/sekera-radim/briefgate-mcp
它的身份验证方式与上面的其他托管客户端相同——首次使用时通过 OAuth 进行。该扩展还附带 GEMINI.md,这是一个上下文文件,用于告诉模型 BriefGate 是什么以及何时使用它。
默认情况下,gemini extensions install 获取的是仓库最新的 GitHub Release,而非 main 分支;如果该 Release 早于当前的 gemini-extension.json,且命令报告缺少配置文件,请改为直接从 main 安装:gemini extensions install --ref main https://github.com/sekera-radim/briefgate-mcp。
Claude Desktop — 一键安装为 桌面扩展(.mcpb),运行本地 @briefgate/mcp 包,而非托管端点。构建详情:见下方的 MCPB 捆绑包。
Cursor — 作为 插件 从此仓库的 .cursor-plugin/plugin.json 安装,该插件将相同的 MCP 配置与下方的 collect-from-client 技能打包在一起。
任何兼容 Agent Skills 的工具(OpenAI Codex、GitHub Copilot / VS Code、Cursor、Gemini CLI,以及采用该标准的其他客户端)——使用 skills CLI 安装 collect-from-client 技能:
npx skills add https://github.com/sekera-radim/briefgate-mcp/tree/main/skills/collect-from-client
截至 [email protected],CLI 自身文档所示的简写 owner/repo 不适用于此布局——它要么在其注册表中返回 404,要么在给出普通仓库 URL 时克隆整个仓库,并报告「No SKILL.md found」,因为我们的文件位于比根目录更深的目录中。上面的完整 /tree/main/skills/<name> URL 才能正常安装;在记录此说明前,已在空白临时目录中运行验证。此操作会将 SKILL.md 复制到该工具的本地技能目录;该技能仍假设已单独配置 briefgate MCP 服务(见上方针对各客户端的说明)。
完整设置详情、手动配置和 API 密钥优先级:见下方的参考。
面向读取项目指令的 Agent(AGENTS.md、Copilot、Cursor 规则)
如果你的 Agent 会读取项目指令文件,而非(或除了)MCP 工具说明或 Agent Skills 之外,还会读取这类文件,请将以下内容添加到你的 AGENTS.md、.github/copilot-instructions.md 或 .cursor/rules:
## BriefGate
BriefGate (MCP server `briefgate`, or `npx @briefgate/mcp`) collects files,
text, choices, or credentials from a human who is not in this conversation
(a client, colleague, or customer) — it emails them a no-account portal link
and chases them automatically until everything is submitted.
Use it when a task is blocked on input only that outside person can supply,
especially if they may take days and need reminders. Do not use it when the
information is already available, or when the person who should answer is
the user you're talking to.
Flow: `define_intake` (with items) -> tell the user it was sent ->
`get_intake_status` later ("not ready" is normal, not an error) ->
`get_intake_results` once completed. `request_revision` for a bad item.
Secret items are revealed in plaintext exactly once.
示例:为客户搭建网站
某个 Agent 正在为一家餐厅搭建网站。它已完成页面布局和预订流程,但仍需要 Logo、主视觉照片、营业时间、餐厅简介、社交媒体链接,以及客户 WordPress 安装的管理员访问权限。它调用 define_intake:
{
"project_name": "Website for Trattoria Bella",
"client": { "email": "[email protected]", "name": "Marco", "language": "en" },
"items": [
{ "key": "logo", "type": "image", "label": "Restaurant logo",
"constraints": { "formats": ["svg", "png"], "min_width": 512 } },
{ "key": "hero_image", "type": "image", "label": "Hero photo for the homepage" },
{ "key": "opening_hours", "type": "structured", "label": "Opening hours",
"schema": { "type": "object", "properties": { "mon_fri": { "type": "string" }, "sat": { "type": "string" }, "sun": { "type": "string" } } } },
{ "key": "about_copy", "type": "longtext", "label": "Short description of the restaurant" },
{ "key": "social_links", "type": "structured", "label": "Social media links" },
{ "key": "wp_admin", "type": "secret", "label": "WordPress admin credentials" }
]
}
接下来,BriefGate 会(1)创建品牌门户,(2)向客户发送电子邮件,(3)在每项素材提交时进行验证,(4)自动跟进客户,直至所有内容都已提交,(5)完成后通知 Agent。
Agent 继续搭建页面布局、预订流程,以及其他不依赖这些内容的部分;然后调用 get_intake_results(intake_id),获取类型化数据、文件的签名 URL,以及一次性显示的 WordPress 凭据。它保存该机密信息并继续工作。
为什么不用表单?
| 通用表单 | BriefGate |
|---|---|
| 人创建表单 | Agent 声明所需信息 |
| 人阅读结果 | Agent 使用类型化结果 |
| 通用回答 | 类型化条目 |
| 手动跟进 | 自动追问 |
| 电子表格思维 | API / MCP 工作流 |
| 凭据管理繁琐 | 密钥条目 + 受控展示 |
| 人的工作流 | Agent 工作流 |
BriefGate 并非要取代所有表单生成器,而是专为 AI Agent 需要向人获取信息的场景而设计。
免费套餐,无需信用卡。BriefGate 是一项托管服务;此仓库是开源 MCP 客户端,采用 MIT 许可证。请前往 briefgate.dev 注册。
参考
以下内容均为未更改的技术细节:手动设置、环境变量、HTTP/OAuth 模式、完整工具参考、Webhook、定价和法律信息。
Claude Code:手动设置和 API 密钥
粘贴 API 密钥(适用于 CI、脚本,或希望自行管理密钥的情况)。请前往 briefgate.dev 获取(提供免费套餐,无需信用卡):
claude mcp add briefgate \
-e BRIEFGATE_API_KEY=bg_live_... \
-- npx -y @briefgate/mcp
或者手动添加到 ~/.claude/settings.json:
{
"mcpServers": {
"briefgate": {
"command": "npx",
"args": ["-y", "@briefgate/mcp"],
"env": {
"BRIEFGATE_API_KEY": "bg_live_..."
}
}
}
}
如果设置了 BRIEFGATE_API_KEY(或命令行中的 --api-key),它始终优先于本地存储的 login 密钥;如果已配置密钥,此时运行 login 只会提示这一情况,不会执行任何操作。
验证是否已加载——在 Claude Code 中运行 /mcp,查找包含 15 个工具的 briefgate。
同样的本地软件包和 API 密钥设置适用于任何在本地运行该软件包的 MCP 客户端(Cursor、Codex 等):注册时不提供密钥,然后运行 login;或者像下面这样,将 BRIEFGATE_API_KEY 粘贴到该客户端自己的 MCP 配置中。
无需 API 密钥即可登录
有两种方式可以在不粘贴密钥的情况下将密钥添加到此计算机上——两者都通过同一凭据文件运行相同的设备授权流程(RFC 8628),选择适合你使用此软件包方式的即可。
在终端中——使用 login / logout 子命令:
npx -y @briefgate/mcp login # prints a code + URL, waits for approval, saves the key
npx -y @briefgate/mcp logout # removes the local key, best-effort revokes it remotely
login 会一直等待,直到你批准(或等待 10 分钟后超时),然后输出 Signed in as <account_name> 并以 0 退出;如果失败(被拒绝、已过期、发生错误),则会说明原因并以 1 退出。logout 始终会删除本地副本;它还会使用同一密钥发送 DELETE /v1/keys/current,以在服务器端撤销密钥。如果该调用失败(无网络、API 无法访问),它会说明情况并引导你前往 BriefGate 控制面板,而不会让你无法确定密钥是否仍然有效。
在 Agent 中——使用 login / logout 工具(参见工具):
流程相同,适用于无法在终端中等待你点击的客户端。login 分为两个阶段,因为工具调用无法持续等待几分钟:
- 第一次调用会启动流程并立即返回代码和 URL。在可能的情况下,它会自动打开浏览器。
- 随时再次调用
login,也可以在批准后调用,以检查进度。如果仍在等待,它会提示你;一旦获批,同一次调用就会报告成功并保存密钥。无需重启:下一次工具调用即可使用已登录身份。
作为工具的 logout 与子命令执行的操作完全相同,包括尽力在远程撤销密钥。
无论使用哪种方式,密钥都会保存到 ~/.briefgate/credentials.json(目录权限为 0700,文件权限为 0600;使用 BRIEFGATE_CREDENTIALS_FILE 可覆盖路径),并根据密钥对应的 BriefGate 服务器分别存储,因此暂存环境的 BRIEFGATE_BASE_URL 与生产环境的密钥不会冲突。显式密钥始终优先于已存储的密钥,优先级依次为 --api-key、BRIEFGATE_API_KEY,然后是上次由 login 保存的密钥;如果已设置其中任一项,login 会提示这一情况,而不会运行授权流程。子命令和工具均不适用于共享托管端点(mcp.briefgate.dev)——请参阅托管端点 + OAuth,在那里连接客户端会触发真正的 OAuth 流程。
环境变量
| 变量 | 必填 | 默认值 | 描述 |
|---|---|---|---|
BRIEFGATE_API_KEY | 否 | — | API 密钥(bg_live_... 或 bg_test_...)。优先于由 login 保存的凭据。如果未配置任何内容,工具调用会失败,并提示使用 login。 |
BRIEFGATE_BASE_URL | 否 | https://api.briefgate.dev | 用于暂存环境或本地开发的覆盖值。 |
BRIEFGATE_CREDENTIALS_FILE | 否 | ~/.briefgate/credentials.json | login/logout 保存密钥的位置。主要用于测试和特殊配置。 |
BRIEFGATE_NO_BROWSER | 否 | 未设置 | 设置为 1 可阻止 login 打开浏览器(无头服务器、CI);无论如何都会打印 URL。 |
BRIEFGATE_MCP_HTTP | 否 | — | 设置为 1 可启动 Streamable HTTP,而不是 stdio。 |
BRIEFGATE_MCP_PORT | 否 | 3000 | HTTP 模式使用的端口。 |
BRIEFGATE_MCP_PUBLIC_HOST | 否 | — | 将服务发布为供多个客户共享的 OAuth 端点。请参阅托管端点 + OAuth。 |
BRIEFGATE_MCP_AUTH_SERVER | 否 | BRIEFGATE_BASE_URL | 发布模式下向客户端公布的 OAuth 授权服务器。本地开发时默认为 BRIEFGATE_BASE_URL,因为两者通常是同一个地址;通过容器网络进行实际部署时,需要显式设置此项(见下文)。 |
命令行也接受 --api-key bg_live_...,其优先级高于 BRIEFGATE_API_KEY。也可以将 login 和 logout 作为第一个命令行参数(npx @briefgate/mcp login),而不是使用 --http/不加标志。
HTTP(Streamable HTTP)模式
对于远程或多会话部署,请以 HTTP 模式启动服务:
BRIEFGATE_API_KEY=bg_live_... npx @briefgate/mcp --http --port 3000
服务仅绑定到 127.0.0.1,并包含 DNS 重绑定防护。在反向代理后运行时,请在那里终止 TLS,并将请求转发到本地端口——不要直接暴露该端口。
托管端点 + OAuth
将 BRIEFGATE_MCP_PUBLIC_HOST 设置为服务器发布时使用的主机名,它就会变成一个共享的多客户端点:每个调用方都发送自己的密钥作为 Authorization: Bearer bg_live_...(对于此 API,OAuth 访问令牌 就是 同一个密钥——见下文),服务器则以该调用方的身份与 BriefGate API 通信。公共实例为 https://mcp.briefgate.dev/mcp。
BRIEFGATE_MCP_PUBLIC_HOST=mcp.example.com npx @briefgate/mcp --http --port 3000
有几项变化是有意为之:
- 监听器绑定到
0.0.0.0,Host 检查也接受该名称,因为反向代理后的服务器通过其公共名称访问; BRIEFGATE_API_KEY回退和本地login凭据都会被关闭。 保留其中任何一项,都会让匿名调用方使用运营者的密钥,或读取这台机器上次通过login保存的内容;login/logout、工具和子命令均不可用——连接客户端会触发真正的 OAuth 流程,详见下文;- 根据 MCP 授权规范,服务器会成为 OAuth 2.1 资源服务器,因此支持 OAuth 的客户端只需提供 URL 即可添加它。此软件包不会自行运行授权流程——它只公布授权服务器的位置,并确保请求携带令牌:
- 它提供
GET /.well-known/oauth-protected-resource(RFC 9728),并在/.well-known/oauth-protected-resource/mcp路径下再次提供相同内容(MCP 规范也会让客户端尝试此资源作用域路径);两者均开放 CORS,并将 BriefGate API 指定为授权服务器——见上文的BRIEFGATE_MCP_AUTH_SERVER; - 现在,每个 MCP 请求都需要 Bearer 令牌——包括过去无需令牌即可工作的
initialize和tools/list,以便注册表检查工具列表。没有令牌的请求会收到 HTTP401,以及WWW-Authenticate: Bearer resource_metadata="https://<host>/.well-known/oauth-protected-resource"标头;这是 OAuth 客户端开始登录的信号; - 如果工具调用所用的密钥已过期或被撤销(API 返回
401),响应会被改写为真正的 HTTP401,并附带相同的标头以及error="invalid_token",而不是普通的工具错误——这样客户端就知道应刷新令牌,而不是仅仅报告调用失败。
- 它提供
连接的客户端实际会针对元数据中指定的授权服务器执行以下操作:标准 OAuth 2.1 发现(GET /.well-known/oauth-authorization-server)、动态客户端注册(POST /v1/oauth/register),然后通过 PKCE(S256)进行授权码交换(POST /v1/oauth/token)——MCP 客户端是公共客户端,因此无需客户端密钥;最后通过 POST /v1/oauth/revoke 结束会话。这些都不属于此软件包的职责;它只需作为正确的资源服务器指向该授权服务器。最终获得的访问令牌是一个 bg_live_... 密钥,与其他密钥一样,API 会强制执行一小时的有效期。
如果未设置 BRIEFGATE_MCP_PUBLIC_HOST,以上行为均不适用:本地 --http 运行的行为与之前完全相同,包括不提供密钥时仍可调用 initialize/tools/list,以及使用普通的 Authorization: Bearer ... 标头且无需 OAuth。
工具
define_intake
创建新的客户资料收集表单——一个品牌门户,客户可在其中提交所需素材。BriefGate 会发送邀请邮件,并自动跟进客户,直到收集齐所有内容。
project_name: "Website for John Finance"
client: { email: "[email protected]", name: "John", language: "cs" }
// also_notify: [{ email: "[email protected]", name: "Jane" }]
// Others at the client who get the same link and the same reminders — either of
// them can supply the material. Each gets their own email; nobody sees the rest.
due_date: "2026-08-15"
branding: { accent_color: "#1B2A4A", sender_name: "Radim" }
// Custom branding (Solo plan and up). On Free these are stored but not used: the
// email and portal show a built-in sender name with the account owner's address.
chase_schedule: "default" // default | gentle | aggressive | custom | off
// chase_interval: 5, chase_interval_unit: "minutes" // only with "custom"; omit for every 3 days
// respect_quiet_hours: false, max_reminders: 12 // for a deliberately rapid cadence
items:
- { key: "logo", type: "image", label: "Company logo",
constraints: { formats: ["svg","png"], min_width: 512 } }
- { key: "hero_copy", type: "longtext", label: "Homepage headline",
constraints: { max_chars: 400 } }
- { key: "brand_colors", type: "color_list", label: "Brand colors", required: false }
- { key: "ga4_id", type: "text", label: "Google Analytics ID",
pattern: "^G-[A-Z0-9]+$", required: false }
- { key: "wp_admin", type: "secret", label: "WordPress admin credentials" }
- { key: "photos", type: "file_list", label: "Photos (5–10 images)",
constraints: { formats: ["jpg","png","heic"], min_count: 5, max_count: 15 } }
- { key: "opening_hours", type: "structured", label: "Opening hours",
schema: { type: "object", properties: { mon_fri: { type: "string" }, sat: { type: "string" } } } }
- { key: "has_existing_site", type: "boolean", label: "Does the client have an existing website?" }
- { key: "website_url", type: "url", label: "Current website URL", required: false }
- { key: "service_tier", type: "select", label: "Service package",
options: [{ value: "basic", label: "Basic" }, { value: "pro", label: "Pro" }] }
// folder_id: "fld_1"
// Put the intake straight into an existing folder from list_folders instead
// of leaving it unfiled.
// client_brief: "Here's the offer we agreed on, plus a few notes on scope..."
// Free text shown to the client above the requested items — information from
// you to them, not another thing you're asking them for. Up to 5000 characters.
// Documents go through POST /v1/intakes/:id/brief/files (dashboard or REST,
// not through MCP).
条目键规则: 必须使用 snake_case(例如 logo、hero_copy、ga4_id)。这些键会成为 get_intake_results 中的属性名——不得使用大写字母、空格或连字符。
返回 { intake_id, portal_url, status }。保存 intake_id 以供后续调用使用。
get_intake_status
检查哪些条目已提交、待处理或需要修改。包含自动跟进邮件的历史记录,以及客户上次打开门户的时间。
intake_id: "in_8f3k"
返回各条目的状态和完整的跟进历史记录。
get_intake_results
检索已提交的类型化值。文件为签名 URL(有效期 24 小时)。密钥仅可获取一次——仅在首次调用时解密并返回;继续操作前请先保存。
intake_id: "in_8f3k"
only_new: true // only items new since last call
include_pending: false // omit unsubmitted items
返回 { results: { logo: "https://signed...", hero_copy: "text...", wp_admin: "s3cr3t" }, meta: { ... } }。
request_revision
请客户端重新提交某个项目,并附上说明问题所在的备注。
intake_id: "in_8f3k"
item_key: "logo"
note: "Logo is blurry — we need at least 512 px wide in SVG or PNG with a transparent background"
返回 { status: "revision_requested", item_key }。
send_chase
在自动计划之外发送手动提醒。适用于截止日期临近或邮件发送尝试失败的情况。
intake_id: "in_8f3k"
返回 { sent: true }。
list_intakes
列出所有项目中的收集表,可按状态、客户端邮箱、文件夹或文本搜索进行筛选。
status: "in_progress" // draft | sent | in_progress | completed | archived
client_email: "[email protected]"
folder_id: "fld_1" // or "none" for intakes not in any folder
q: "Finance" // substring match on project name, client name, or client email
limit: 20
offset: 0
返回 { intakes: [...], total }。
add_items
向已发送的收集表中添加新项目,例如遗漏的网站图标,或项目中途需要的额外凭据。
intake_id: "in_8f3k"
items:
- { key: "favicon", type: "image", label: "Favicon (32×32 PNG or ICO)" }
返回更新后的收集表。
update_item
在收集表发送后更改项目定义,包括类型、标签、帮助文本或限制条件。当你提出了错误的要求时使用,例如你请求提供图片,但客户端只有 PDF。
intake_id: "in_8f3k"
item_key: "logo"
type: "file" // was "image"
constraints: { formats: ["pdf","ai","svg"] }
discard_submitted_value: false // true is required if the change invalidates what the client already sent
返回更新后的项目。如果客户端已提交的值不符合新定义,此调用会失败并返回 item_answer_would_be_discarded,除非你传入 discard_submitted_value: true。
update_intake
更改已发送收集表的设置,包括项目名称、截止日期、提醒频率、免打扰时段、客户端简介,或客户端的姓名、电话、语言和时区。请使用此工具,而不要删除并重新创建收集表,否则会重新发送邀请。
intake_id: "in_8f3k"
due_date: "2026-12-01"
chase_schedule: "gentle" // was "default"
max_reminders: "unlimited" // reactivates a stalled intake if it had hit its cap
// folder_id: "fld_1" // move it into a folder; null removes it from any folder
// client_brief: "Updated offer..." // replaces the brief shown above the items; null clears it
如果已发送收集表中的任何提醒相关字段(chase_schedule、chase_interval、chase_interval_unit、chase_at_time、max_reminders、respect_quiet_hours、due_date、client.timezone)发生更改,所有待发送提醒都会取消,并从现在开始重新安排——已发送的提醒仍计入 max_reminders。folder_id 不会影响提醒计划。
此处无法更改客户端的电子邮件地址,因为门户链接和登录凭据与该地址绑定。请使用 manage_recipients 更改。如果收集表已归档,此操作会失败。返回完整的更新后收集表对象。
manage_recipients
添加、移除或恢复收件人,让其接收收集表邀请和提醒;可与主要客户端并列或替代主要客户端。
intake_id: "in_8f3k"
action: "reinstate" // add | remove | reinstate
email: "[email protected]"
name: "Petr" // only used with action="add"
action="add" 会像在 define_intake 阶段使用 also_notify 一样,邀请另一个邮箱地址。action="remove" 会停止向该地址发送后续提醒。action="reinstate" 用于处理错误的退信——即该联系人确实收到了电子邮件;此操作会清除退信标记并恢复提醒。如果该地址是唯一仍在接收提醒的地址,还会从现在开始重新安排提醒计划。
manage_webhook
注册、列出或移除 webhook 端点,让事件推送到你的服务,而不必由你轮询获取。
action: "create" // create | list | delete
url: "https://your.service/hooks/briefgate"
events: ["intake.completed", "intake.overdue"]
format: "raw" // raw | slack | discord
action: "create" 只会返回一次 secret——请妥善保存;每次投递都需要用它验证签名,且之后无法再次获取。使用 action: "delete" 和 webhook_id 移除端点。
由于 Agent 会在工具结果中接收密钥,该密钥可能会留存在对话记录的存储位置。此处没有轮换端点:如果对话记录泄露,请删除该端点并创建一个新端点,以获取新密钥。
仅注册你确实能够接收请求的端点。在终端中运行的 Agent 没有公开的 HTTPS 地址;这种情况下请勿注册端点,改为按计划检查(见下文)。
list_folders
列出你账户中的文件夹,用于按客户或项目对 intake 进行分组。不接受任何参数。
在调用 create_folder 之前,或在为 define_intake、update_intake 或 list_intakes 设置 folder_id 之前,请先调用此工具——对于回头客户,请重复使用已有文件夹,而不是创建重复文件夹。
返回 { folders: [{ id, name, sort_order, intake_count, created_at }] }。
create_folder
创建一个新文件夹来对 intake 进行分组,例如为每位客户创建一个文件夹。
name: "Acme Inc"
请先调用 list_folders 并重复使用匹配的文件夹——仅在现有文件夹都不合适时才创建新文件夹。如果已有同名文件夹,则会失败并返回 folder_exists。返回创建的文件夹。
login
无需 API 密钥即可登录——参见无需 API 密钥登录。不接受任何参数。
如果其他工具报告“未登录”,或报告已存储的密钥已被撤销或过期,请调用此工具。首次调用会启动设备授权流程,并立即返回一个 URL 和一段短代码;之后可随时再次调用,以检查是否已获批准。如果 --api-key 或 BRIEFGATE_API_KEY 已提供密钥,则不会产生任何效果——工具会对此作出说明。托管端点不提供此功能。其流程与在终端中运行 npx @briefgate/mcp login 相同(后者会一直阻塞,直到获得批准,因此无需再次调用)——参见无需 API 密钥登录。
logout
移除 login 为此 BriefGate 服务本地存储的 API 密钥,并尽力在服务端撤销该密钥。不接受任何参数。
如果撤销请求失败——例如网络不可用或 API 无法访问——仍会移除本地副本;响应会说明这一点,并引导你前往 BriefGate 控制面板在那里撤销密钥。托管端点不提供此功能。其效果与在终端中运行 npx @briefgate/mcp logout 相同——参见无需 API 密钥登录。
决策——开发者待答问题
Agent 在构建过程中会遇到只有账户所有者才能决定的问题:优惠方案的价格是 $19 还是 $29? 停下来等待会浪费运行时间;默默选择则会掩盖这个假设。决策提供了第三种选择——提出问题,记录你据此继续推进的答案,然后继续构建。
{ "key": "discount_price", "type": "select", "assignee": "owner",
"label": "What does the discounted subscription cost?",
"options": [ { "value": "19", "label": "$19/month" },
{ "value": "29", "label": "$29/month" } ],
"proposed": { "value": "19", "rationale": "matches the competitor we benchmarked" } }
type: "multiselect" 支持多个答案,数量范围由 constraints.min_count / max_count 限定。
提议的答案与真实答案分开存储,因此绝不会被误认为是开发者给出的答案——即使提议被推翻,它也会保留下来,这正是其意义所在:三个月后,你仍能看到当时假设的是 $19,而不是双方达成一致的价格。可通过 get_intake_results 读取:
"results": { "discount_price": "19" },
"meta": { "discount_price": { "decided_by": "agent_proposal", "proposed_value": "19" } }
有人作出决定后,decided_by 为 "owner";如果仍是你自己的选择,则为 "agent_proposal"。即使没有设置 include_pending,也会返回提议中的决策——你需要知道自己正在依据什么假设进行构建。它不会增加 revision,因此 only_new 读取会准确显示之后由他人回答的决策。
你不能回答自己提出的问题。 回答端点需要控制面板会话,而不是 API 密钥:如果 Agent 可以确认自己的提议,并将其记录为开发者的答案,那么这种区分就毫无意义。决策需要在 BriefGate 控制面板中回答。
所有者事项不会出现在客户端门户或提醒中,也不会延迟完成——当 客户 完成后,intake 就完成了。
了解客户端何时完成
MCP 不会主动向客户端推送任何内容——MCP 采用请求/响应模式,因此服务端无法在客户端完成时唤醒你的 Agent。因此,define_intake 会返回一个 follow_up 区块,指出适合你设置的机制:
"follow_up": {
"recommended": "schedule", // or "webhook" when an endpoint already exists
"webhook": { "active_endpoints": 0, "events": ["intake.completed", "item.submitted"],
"register_with": "manage_webhook" },
"schedule": { "check_with": "get_intake_status", "every_hours": 24,
"until": "2026-10-01T08:00:00.000Z" }
}
- 你运行的是服务 → 使用
manage_webhook注册 webhook,并在收到intake.completed时采取行动。 - 你是在终端中运行的 Agent → 设置定期检查,每隔
every_hours小时调用一次get_intake_status,直到until。cron 条目、systemd 计时器,或 Agent 主机自带的调度器都可以。
值得采取行动的事件:intake.completed(所有内容均已提交)和 intake.overdue(截止时间已过,必需项目仍有缺失——项目受阻,客户需要人工协助,而不是再次收到提醒)。
临近截止时间时,检查频率会提高(通常为 24 小时一次,剩余一周内为 12 小时一次,剩余两天内为 6 小时一次),且与提醒计划无关:客户可能凌晨 2 点提交所有内容,此前从未打开过提醒。
端到端示例
# System prompt excerpt
You are a web development agent. When you need client assets:
1. Call define_intake with all assets needed for this project.
Use type=secret for passwords/credentials.
The chase engine runs automatically — do not poll more often than once per day.
2. Read follow_up in the response and set up how you will hear back:
register a webhook with manage_webhook if you have an HTTPS endpoint,
otherwise schedule a get_intake_status check at follow_up.schedule.every_hours.
3. When intake.completed arrives (or the scheduled check reports "completed"),
call get_intake_results. Download file URLs within 24 hours.
Secrets are shown only on the first retrieval.
4. If a submitted asset does not meet requirements (blurry logo, broken URL),
call request_revision with a clear note for the client.
If the client has the asset in another form, call update_item to change the type.
5. If the client is still unresponsive after 9 days, call send_chase for an
extra nudge outside the automatic schedule, or tell the developer the intake
is stuck and let them pick up the phone.
验证 webhook
BriefGate 使用 HMAC-SHA256 为每个 webhook 签名,以防止伪造和重放攻击。@briefgate/mcp 包提供了一个可直接使用的辅助函数:
import { verifyWebhookSignature, parseWebhookEvent } from "@briefgate/mcp/webhook";
签名位于 X-BriefGate-Signature 标头中,格式为 t=<unix>,v1=<hex>:
Fastify(推荐)
import Fastify from "fastify";
import { verifyWebhookSignature, parseWebhookEvent } from "@briefgate/mcp/webhook";
const app = Fastify();
// Parse body as raw string — JSON-parsing before verification breaks the HMAC.
app.addContentTypeParser("application/json", { parseAs: "string" }, (req, body, done) => {
done(null, body);
});
app.post("/briefgate/webhook", (request, reply) => {
const rawBody = request.body as string;
const ok = verifyWebhookSignature(
process.env.BRIEFGATE_WEBHOOK_SECRET!,
request.headers["x-briefgate-signature"] as string,
rawBody,
// { toleranceSec: 300 } ← default; increase for slow networks
);
if (!ok) {
return reply.status(401).send({ error: "Invalid signature" });
}
const event = parseWebhookEvent(rawBody);
console.log("BriefGate event:", event.event, event.intake_id);
reply.send({ ok: true });
});
Express
import express from "express";
import { verifyWebhookSignature, parseWebhookEvent } from "@briefgate/mcp/webhook";
const app = express();
// raw body parser — must come before express.json()
app.post(
"/briefgate/webhook",
express.raw({ type: "application/json" }),
(req, res) => {
const rawBody = Buffer.isBuffer(req.body)
? req.body.toString("utf8")
: String(req.body);
const ok = verifyWebhookSignature(
process.env.BRIEFGATE_WEBHOOK_SECRET!,
req.headers["x-briefgate-signature"] as string,
rawBody,
);
if (!ok) return res.status(401).json({ error: "Invalid signature" });
const event = parseWebhookEvent(rawBody);
console.log("BriefGate event:", event.event, event.intake_id);
res.sendStatus(200);
},
);
Webhook 事件
| 事件 | 触发时机 | 关键字段 |
|---|---|---|
item.submitted | 客户提交项目 | item_key、item_status |
intake.completed | 所有必需项目均已获批 | — |
client.viewed | 客户打开门户 | client_email |
chase.bounced | 提醒发送失败 | channel、reason、recipient、still_chasing |
intake.stalled | 已发送 3 次提醒,仍无回应 | attempts |
定价
| 免费版 | Solo — $29/mo | Agency — $79/mo | |
|---|---|---|---|
| 活跃 intake | 1 | 15 | 60 |
| 每个 intake 的项目数 | 10 | 不限 | 不限 |
| 存储空间 | 1 GB | 25 GB | 100 GB |
| 每日邀请数 | 10 | 无每日限制 | 无每日限制 |
| 品牌标识 | “powered by”、内置发件人名称 | 发件人名称、邮件措辞、标志 + 颜色 | + 自定义发件域名 |
| 催办 | 电子邮件、默认设置 | 电子邮件、所有计划 | 电子邮件、所有计划 |
| 密钥库 | — | 有 | 有 |
| Webhook + REST + MCP | 有 | 有 | 有 |
完整定价可通过 GET https://api.briefgate.dev/pricing.json 获取(无需认证——Agent 可直接读取)。
数据驻留
BriefGate 托管于欧盟:应用服务器位于德国纽伦堡的 netcup GmbH;文件存储在受欧盟管辖的 Cloudflare R2 中。请参阅 GDPR 说明 和 DPA。
隐私政策
此包是一个轻量客户端:它不持有自身数据,除使用你配置的 API 密钥向 BriefGate API(api.briefgate.dev)发送数据外,不会向任何地方发送数据。它不会写入遥测数据或分析数据。
BriefGate 自身收集哪些数据、保留多久、与谁共享,以及如何申请删除,均在以下页面中完整说明:
- 隐私政策 — https://briefgate.dev/docs/privacy
- 安全 — https://briefgate.dev/docs/security
- 数据处理协议 — https://briefgate.dev/docs/dpa
隐私请求联系邮箱:[email protected]
MCPB 捆绑包(Claude Desktop 扩展)
仓库根目录中的 manifest.json 会将本地
@briefgate/mcp 包打包为一键安装到 Claude Desktop 的扩展
(MCPB 规范)。它会在本地运行 dist/index.js,
并在安装时提示输入可选的 API 密钥——这与上文记录的
login/BRIEFGATE_API_KEY 设置相同,不是托管端点的 OAuth 流程。
构建捆绑包(仅包含生产依赖,并在临时暂存目录中打包,
不会触碰此仓库自己的 node_modules):
npm run package:mcpb
这会在仓库根目录生成 briefgate.mcpb(已加入 gitignore——可在本地安装测试,
不要提交)。目前尚未提交到任何地方;请参阅
scripts/build-mcpb.mjs,了解该命令的作用。
贡献
此仓库仅包含 BriefGate MCP 客户端——一个用于调用 BriefGate 公共 REST API 的轻量封装。BriefGate 服务本身为闭源。
npm install
npm run typecheck # TypeScript check
npm run lint # ESLint
npm run test # Vitest
npm run check # all three
npm run build # compile to dist/
许可证
MIT——可自由用于商业项目。
由 Radim Sekera 制作。相关项目:impri.dev——面向 AI Agent 的人工介入审批收件箱。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。