news 2026/9/19 17:56:50

gbrain 下游 Agent 接入指南:MCP over HTTP 与本地 shell-job 双表面的正确选型与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
gbrain 下游 Agent 接入指南:MCP over HTTP 与本地 shell-job 双表面的正确选型与实战

gbrain 下游 Agent 接入指南:MCP over HTTP 与本地 shell-job 双表面的正确选型与实战

【免费下载链接】gbrainGarry's Opinionated OpenClaw/Hermes Agent Brain项目地址: https://gitcode.com/gh_mirrors/gb/gbrain

导读

本文面向所有需要从自身运行时调用 gbrain 能力的外部下游 Agent(你的 OpenClaw 实例、任何下游 fork、Claude Code / Codex / opencode 等 harness),完整讲解 gbrain 对外暴露的两套截然不同的接入面:MCP ops over HTTP(thin-client + OAuth)与本地 shell-jobinherit:。读完本文,你将掌握如何按"操作类型"而非"个人偏好"选择接入面、如何用一条命令完成带 OAuth 的 harness 接入、如何安全地把sync/embed/extract/dream等仅限本地的操作提交给 Minions worker 执行,以及如何从危险的env:传密迁移到只落名字不落值的inherit:模式。

先读本文可以替你省掉一轮排错:gbrain 有两个互不替代的表面,选错表面是下游 Agent 集成最常见的失败原因。

双表面总览:按操作选型,不按偏好选型

┌─────────────────────────────────────────────┐ │ gbrain process │ │ │ Agent (OpenClaw, │ ┌──────────────────┐ ┌────────────────┐ │ or any fork) ───────┼──▶ MCP ops surface │ │ local-only │ │ │ │ (HTTP + OAuth) │ │ commands │ │ │ │ │ │ │ │ │ │ search, query, │ │ sync, embed, │ │ │ │ put_page, │ │ extract, │ │ │ │ get_page, │ │ dream, │ │ │ │ find_experts, │ │ enrich, ... │ │ │ │ ... │ │ │ │ │ └──────────────────┘ └────────────────┘ │ │ ▲ ▲ │ │ │ │ │ │ │ │ │ │ thin-client OAuth shell-job `inherit:`│ │ (preferred for (only path for │ │ MCP-equivalent ops) local-only work) │ └─────────────────────────────┴───────────────┘

两套表面不可互换:MCP ops surface 面向所有在src/core/operations.ts中有对应 MCP 操作、且localOnly标志未置位的操作;local-only 命令则被两层机制(操作层过滤 + CLI 层拒绝)从远程表面隔离出去,唯一合法路径是作为 shell job 提交到宿主机上的 Minions worker。决策的唯一依据是操作本身属于哪个表面

表面一:MCP ops over HTTP(thin-client + OAuth)

适用操作

任何有 MCP 等价操作的能力都走 HTTP 表面:searchqueryput_pageget_pagefind_expertsfind_orphansfind_anomaliesget_recent_saliencefind_trajectory等等。权威清单src/core/operations.tslocalOnly标志未置位(或为false)的那组操作——文档里抄的任何列表都不如直接读源码可靠,且该清单会随着版本演进自动变化。

让宿主以 HTTP 服务形态常驻

宿主把 gbrain 作为长驻 HTTP 服务运行:

gbrain serve --http --port 3131

注意:serve本身位于src/cli.tsTHIN_CLIENT_REFUSED_COMMANDS集合中(见下文表面二),它必须运行在大脑宿主机器上,由可信的运维操作启动。

打包路径:gbrain agent register

对下游 Agent 而言,首选入口是gbrain agent register——它必须在大脑宿主上运行(这是一个受信任的本地操作,永远不是一种委派机制)。单条命令完成三件事:铸造一个带作用域的 OAuth client、签发一个 30 天有效的访问令牌、打印出目标 harness 的现成接线配置块

gbrain agent register aurora-coder \ --harness claude-code \ --preset coding-agent \ --federated-read proj-widget \ --url https://brain.example.com/mcp

从 agent-register.ts 可以看到完整参数面:--harness目前支持claude-code | codex | opencode | openclaw四种(REGISTER_HARNESSES硬校验);--preset支持daily-driver | coding-agent;此外还有--source(按 source 限定读写范围)、--scopes--token-ttl SECONDS--surface verbs|starter|full--allow-old-serve(对未强制作用域令牌的旧 serve 放行并自担风险)、--show-token--json输出控制。--reissue <client-id>用于令牌轮换。

gbrain agent register出于安全设计会打印接线块(默认脱敏,除非--show-token),不写入任何 harness 配置;且只允许read/write这类 agent 级作用域,operator 级作用域会被显式拒绝(见 agent-register.ts)。

底层原语:gbrain auth register-client

如果你需要完全自定义的流程——PKCE / authorization-code 客户端、绑定submit_agent的客户端、带 slug 前缀的写入围栏(write fence)、以及需要解析输出做自动化供给的脚本——则使用原始原语。它是一次性操作,只打印client_id+client_secret,不代办令牌交换与 harness 接线:

gbrain auth register-client aurora-coder \ --grant-types client_credentials \ --scopes "read write" # Prints client_id + client_secret one-time. Store securely.

Thin-client 模式:gbrain init --mcp-only

thin-client 安装(gbrain init --mcp-only)把上述 client-credentials 接线一次性配好:gbrainCLI 本身会把所有 MCP 可路由的命令透过已配置的远程 MCP 转发,Agent 可以直接调用gbrain search/gbrain query,OAuth 握手由 CLI 自动完成。

认证与审计面

Agent 运行时以client_credentials授权类型换取 bearer token,调用/mcp端点。密钥始终留在gbrain serve进程内,Agent 永远看不到DATABASE_URL或任何 API key。在 http-transport.ts 中可以看到,token 以 SHA-256 哈希形式存储于access_tokens表(auth.ts负责创建/列出/吊销),每次请求都会写入一行mcp_request_log(含 token 名 + 操作 + 状态 + 延迟),构成统一审计面。

接入路径决策表(onboarding paths)

这是接入路径的权威决策表,其他文档都引用此表、无人复制:

PathWhen to useCredential kindPrint vs writeServe location
gbrain agent register <name> --harness <h>The packaged path: onboarding an agent harness (Claude Code, Codex, opencode, your OpenClaw) onto a shared brain. Presets (daily-driver,coding-agent), starter tool surface, 30-day token TTL,--reissuesecret rotation.Scoped OAuth client + a minted access token (source-scoped, expiring)PRINTS the harness block (redacted unless--show-token); writes nothing to harness configsRuns ON the brain host against a remote-reachablegbrain serve --http;--urlor--portrequired (a live PGLite serve blocks it by design — stop the serve first; a serve too old to enforce scoped tokens is refused — upgrade it, or pass--allow-old-serveto accept the risk)
gbrain connect <mcp-url> --token <t>You already hold a bearer token and want ONE coding agent pointed at a running serve, from any machine.Legacy bearer token (full-access unless minted with--scopes);--oauthvariant for OAuth-capable connectors./mcpverifies both kinds; a client status flag ofneedsAuthfrom an unauthenticated probe is not a bearer failure — see DEPLOY.md — Dual-mode authPrints the add command by default;--installruns itAny machine; targets a remotegbrain serve --http
gbrain bootstrap harnessFramework-spawned harnesses (claude -p/codex exec/opencode run) on the SAME box that hosts the brain; wires MCP registration + lifecycle hooks with receipts and mint-first token rotation.Legacy bearer token, minted per run and rotated by receiptWRITES managed config blocks (Claude Code user scope, codex TOML, opencode JSONC) + hooksLocal loopback serve on the same box (non-loopback URL requires an explicit supplied token)
gbrain auth register-client <name>The raw primitive: custom flows — PKCE/authorization-code clients, boundsubmit_agentclients, slug-prefix write fences, provisioning scripts that parse output.Scoped OAuth client only (no token exchange, no TTL default beyond the server's)Printsclient_id+client_secretone time; you do all wiringCredential is server-side state; run on the brain host

关于needsAuth的常见误判:/mcp是双模式认证(OAuth 2.1 access token 优先,随后回退到access_tokens表校验 legacy bearer),未携带Authorization头的心跳探测会返回 401 + RFC 9728resource_metadata挑战,客户端因此显示needsAuth,但这不代表你配置的 token 失效。判断认证是否成功应以whoamitransport: legacy|oauth)或gbrain auth test <url> --token <t>为准,详见 DEPLOY.md — Dual-mode auth。

为什么 MCP ops 首选此表面

  • 密钥永不离开服务进程:Agent 只持有令牌,拿不到DATABASE_URL或供应商 API key。
  • OAuth 作用域天然隔离readwriteadmin三层分离,Agent 只拿到它所需的最小权限。
  • source-scoped 令牌register-client --source dept-x可把 Agent 限制在联邦大脑中的特定 source 内。
  • 统一审计面:每一次操作调用都均匀地落在mcp_request_log上,不存在旁路调用。

表面二:仅限本地的操作——shell-jobinherit:模式

两层机制把本地工作挡在远程表面之外

操作层(Op layer)src/core/operations.ts中标记localOnly: true的操作会直接从 HTTP MCP 表面被整体过滤掉——远程调用者根本看不到它们。实现见 serve-http.ts 的const mcpOperationsBase = operations.filter(op => !op.localOnly);。从源码看,connectorsentity_identityembedding-migrationfileschroniclesync-statustranscriptspages(部分写操作)、extractioncode-intel等操作族中都存在 localOnly 成员。

CLI 层(CLI layer):在 thin-client 安装上(已配置远程 MCP、无本地引擎),需要本地引擎或本地文件系统的命令会在分发时被拒绝,并附带一条指名最近替代方案的精确提示。权威集合是 src/cli.ts 中的THIN_CLIENT_REFUSED_COMMANDS——请直接读源码,而不是信任任何抄进文档的列表。它覆盖syncembedextractextract-conversation-factsenrichmigrateretrieval-upgradeapply-migrationsrepair-jsonborphansintegrityservecallwatchdreamtranscriptsstoragetakessourcespagesfilesevalcode-defcode-refscode-callerscode-calleesconfigsweepcompile-context等数十个命令。

每条拒绝都带具体提示(THIN_CLIENT_REFUSE_HINTS,见 src/cli.ts):例如sync会提示"在宿主机上运行gbrain sync或使用sync_brainMCP 操作",dream会提示"在宿主机运行gbrain dream"。refuseThinClient(src/cli.ts)在收到命中命令且当前是 thin-client 时,先尝试routeThinClientCommand做子命令级 MCP 路由,剩余不可路由部分才拒绝并以退出码 1 结束。

两个值得注意的非成员doctor在 thin-client 上不被拒绝——它会改道到出站 HTTP 探针集合(src/core/doctor-remote.ts);bootstraphook无引擎依赖,任何安装形态都可运行(THIN_CLIENT_REFUSED_COMMANDS的注释明确要求这两个命令"永远不得出现")。

本地操作的唯一路径:作为 shell job 提交

被拒绝的命令无法经由 HTTP MCP 路由。正确路径是把gbrain作为 CLI 子进程执行,且推荐将子进程作为shell job 提交给 gbrain Minions worker,从而免费获得重试 / 退避 / DLQ / 审计轨迹:

gbrain jobs submit shell --params '{ "cmd": "gbrain sync --skip-failed && gbrain embed --stale", "cwd": "/data/gbrain", "inherit": ["database_url"] }'

inherit:的底层原理

inherit: ["database_url"]告诉 worker 从它自己的loadConfig()(文件平面 + 环境变量合并)中查找database_url,把值以GBRAIN_DATABASE_URL注入子进程环境。minion_jobs.data的 DB 行里只存名字——inherit: ["database_url"]——永远不存值。完整校验规则与错误目录见 minions-shell-jobs.md#secrets。

实现细节在 shell-inherit.ts:

  • 名字格式被正则钉死INHERIT_NAME_RE = /^[a-z][a-z0-9_]*$/,用于防原型污染形态(__proto__constructor)和审计日志中的路径穿越形态;
  • 环境变量名派生规则deriveEnvKey(name):默认name.toUpperCase()anthropic_api_keyANTHROPIC_API_KEYvoyage_api_keyVOYAGE_API_KEY),唯一例外是database_urlGBRAIN_DATABASE_URL(因为裸DATABASE_URL在 Postgres 应用语境中过于歧义);
  • 值解析resolveInheritValue使用Object.hasOwn防御原型污染查询,仅接受非空字符串;
  • 快速失败:若 worker 上解析不到所请求的名字,校验器在入队前即拒绝,并给出可直接粘贴的gbrain config set database_url <value>提示(该命令走文件平面,写入~/.gbrain/config.json,正是 worker 的loadConfig()读取的位置,即使 DB 不可达也能生效)。

inherit:自由形态的:任何 snake_case 配置键都可以继承——database_urlanthropic_api_keyopenai_api_keyopenrouter_api_keyvoyage_api_keygroq_api_keyzeroentropy_api_key,乃至你塞进~/.gbrain/config.json的任何自定义字段。Agent 按需挑选。

为什么胜过把密钥写进每任务的env:

// Rejected at submit: the URL would persist in minion_jobs.data plaintext. { "cmd": "gbrain sync --skip-failed", "cwd": "/data/gbrain", "env": { "GBRAIN_DATABASE_URL": "postgresql://..." } }

每任务传env: { GBRAIN_DATABASE_URL: "postgresql://..." }会把 URL 以明文落入minion_jobs.data和 shell-audit JSONL——任何拥有大脑 DB 读权限的人(或一份大脑 dump,或通过 mounts 共享的大脑)都能看到。入队前校验会拒绝这种形态,错误消息直接指名inherit: ["database_url"]作为替代方案。

补充两条来自 minions-shell-jobs.md 的安全细节:

  • shell 子进程环境是极简的:只有PATH, HOME, USER, LANG, TZ, NODE_ENVOPENAI_API_KEY这类密钥不会自动传给孩子,需要按任务显式env:(仅非密钥值)或inherit:放行——这能阻止用户脚本里意外的$OPENAI_API_KEY插值;但它沙箱化文件系统读取(shell 脚本可以cat ~/.env),操作者选一个安全的cwd即是信任边界。
  • 输出侧泄漏inherit:只保证值不进任务行输入字段,不保证脚本不把它打印出来(echo "$GBRAIN_DATABASE_URL")。如果脚本打印了密钥,明文会落入result.stdout_tail/result.stderr_tail。按任务设置"redact_secrets": true(或 CLI 加--redact-secrets)可启用输出侧脱敏,把inherit:解析出的每个值在持久化前以<REDACTED:name>替换;注意这是字面字符串替换,对 base64 编码、逐字符输出等对抗性形态无效——它防的是意外 echo,而非蓄意外泄。
  • 审计是轨迹而非法证保障:每次提交写一行到~/.gbrain/audit/shell-jobs-YYYY-Www.jsonl(ISO 周轮转,GBRAIN_AUDIT_DIR可覆盖),但写入失败只记 stderr、不阻塞提交。

Worker 一次性设置(每台宿主一次)

Agent 所在宿主需要一个能处理 shell job 的 worker:

# One-shot inline execution (PGLite or Postgres): gbrain jobs submit shell --params '{...}' --follow # Persistent worker (Postgres only — PGLite uses --follow inline): gbrain jobs work --allow-shell-jobs # or: GBRAIN_ALLOW_SHELL_JOBS=1 gbrain jobs work

关键约束:

  • PGLite 不跑常驻 worker(独占文件锁),每个 crontab 触发都必须用--follow内联执行;Postgres 用户可跑常驻 worker,--max-attempts指定重试次数(指数退避),--timeout-ms指定超时。
  • --allow-shell-jobs(等价于在 worker 上导出GBRAIN_ALLOW_SHELL_JOBS=1;worker 目录里的.env不能设置它)是 worker 侧的一次性 opt-in。shell handler 总是注册但受守卫:未带旗标的 worker 一旦认领到 shell job 会立即死信(UnrecoverableError,不重试)——一个长期停留在waiting的 shell job 说明根本没有 worker 在跑。请把旗标放在 worker 的命令行(或部署单元 / launchd plist 的环境变量里),而不要放在每次提交里——提交方环境是 worker 环境的弱代理。
  • MCP 边界双保险submit_job携带name: 'shell'时,ctx.remote === true(MCP 调用者)会被拒绝,与 env 旗标相互独立——远程 Agent 永远无法提交 shell job;MinionQueue.add('shell', ...)自身也有守卫,进程内 handler 无法编程绕过。

操作决策表

OperationSurfaceWhy
search/queryHTTP MCP via thin-clientHas MCP op; OAuth-scoped.
get_page/list_pagesHTTP MCPSame.
put_pageHTTP MCPSame; respects subagent allow-list when applicable.
find_experts/find_orphansHTTP MCPSame.
sync/embed/extractShell job +inherit:Thin-client refused; needs local engine + FS.
dreamShell job +inherit:Thin-client refused; synthesis runs on the host.
doctorRun directly (any install)Not refused: thin clients get the remote probe set.
autopilotRun as a daemon directly on the hostLong-lived, not job-shaped.
init/configOne-time host setupOperator action, not agent action.

推荐模式总结

  • 想要不落进任务行的密钥,就用inherit:。名字落进minion_jobs.data,值在子进程生成时从 worker 配置解析。若大脑 DB 未来穿越任何信任边界,密钥不随行。
  • env:仍然可用于非密钥值,或你希望值出现在行里的场景(例如审计流程稍后要读回的 opaque 关联令牌)。校验器不会替你做主。
  • 绝不尝试把被拒命令路由穿 thin-client。CLI 在分发时就会带提示拒绝。宿主机上用 shell-job +inherit:(密钥)或env:(非密钥)代替。
  • 推式上下文:除请求/响应式操作外,MCP 客户端还可以通过volunteer_context操作接收大脑主动投递的上下文——详见 push-context.md。该通道共享一个零 LLM 核心(src/core/context/volunteer.ts),并带min_confidence(默认 0.7)置信度门控与 3 页默认上限(硬上限 5),确保推送噪声永远不会比拉取静默更糟。

迁移:从env:传密改为inherit:

如果你的 Agent 正在用env:向 shell job 传密钥,按下面两步迁移。

迁移前(提交时会被拒,URL 会以明文常驻minion_jobs.data

// Rejected at submit: the URL would persist in minion_jobs.data plaintext. { "cmd": "gbrain sync --skip-failed", "cwd": "/data/gbrain", "env": { "GBRAIN_DATABASE_URL": "postgresql://..." } }

迁移后(推荐形态,名字进行、值在子进程生成时从 worker 配置解析)

// Name in row, value resolved at child-spawn from worker config. { "cmd": "gbrain sync --skip-failed", "cwd": "/data/gbrain", "inherit": ["database_url"] }

前置条件:worker 宿主必须已配置database_url——要么通过gbrain config set database_url <value>(文件平面路由,落入~/.gbrain/config.json,正是 worker 的loadConfig()读取的位置,DB 不可达时也可用),要么在 worker 进程上导出GBRAIN_DATABASE_URL/DATABASE_URL环境变量。若 worker 无法解析该键,校验器会在提交时拒绝任务,并给出可直接粘贴的修复提示。

进阶形态:如需输出侧脱敏,在参数中加入"redact_secrets": true(或 CLI 加--redact-secrets);对于程序化调用方,可用argv数组替代cmd字符串(不经 shell、无注入面),例如{"argv":["node","scripts/fetch.mjs","--date","2026-04-19"],"cwd":"/data"}。失败后务必用gbrain jobs get <id>检查实际持久化内容。

延伸阅读

  • minions-shell-jobs.md:shell job 的完整校验规则、--follow内联执行与 Postgres 常驻 worker 的 crontab 迁移示例、redact_secrets输出侧脱敏细节
  • push-context.md:volunteer_context推式上下文通道的触发时机与置信度门控
  • DEPLOY.md:/mcp双模式认证(OAuth 2.1 + legacy bearer)、.well-known资源元数据发现、Tailnet / LAN-only 暴露形态
  • 源码级权威依据:操作清单与localOnly标志见 src/core/operations.ts,thin-client 拒绝集合与提示见 src/cli.ts,HTTP 表面过滤见 src/commands/serve-http.ts,inherit:机制见 src/core/minions/handlers/shell-inherit.ts,审计写入见 src/core/minions/handlers/shell-audit.ts,agent register参数解析见 src/commands/agent-register.ts

【免费下载链接】gbrainGarry's Opinionated OpenClaw/Hermes Agent Brain项目地址: https://gitcode.com/gh_mirrors/gb/gbrain

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 17:54:04

邮箱验证不只看正则:RFC 5322格式校验与MX/SMTP实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 17:53:04

将 HTML 静态站点迁移到 Gatsby:从零到生产部署的完整实战指南

将 HTML 静态站点迁移到 Gatsby&#xff1a;从零到生产部署的完整实战指南 【免费下载链接】gatsby React-based framework with performance, scalability, and security built in. 项目地址: https://gitcode.com/gh_mirrors/ga/gatsby 导读 本文基于 Gatsby 官方文档…

作者头像 李华
网站建设 2026/9/19 17:52:09

易灵思Ti60F100外挂HyperRAM实战:Native接口时序调试与性能优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 17:50:31

Demosaic算法全解析:从双线性插值到深度学习与FPGA实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华