mcpField
N
Nofax

Nofax

本地服务
github.com/AKzar1elAI 与智能体11 天前更新

关于 Nofax

Nofax 是连接 AI 编码 Agent 与人员的开源桥接工具,可在本地发起审批请求、发送通知并接收明确决定。可选的自托管 Cloudflare Worker 提供范围更窄的远程接口,用于通知和安全地查看请求。

主要功能

  1. 01暂停工作流以等待明确的人为决定
  2. 02发送手机通知
  3. 03请求批准、选择或修改意见
  4. 04超时或传输错误时默认拒绝
  5. 05可选远程通知和请求查看

适用场景

  1. 01要求 Agent 继续前先获得人工批准
  2. 02请人员选择选项或修改请求
  3. 03工作流需要关注时通知手机
  4. 04通过自托管 Worker 查看待处理请求

MCP 相关

本地 stdio MCP 服务提供通知、批准和选择请求、修改意见、等待及请求查看工具。可选的远程 MCP 接口支持单向通知和只读请求查看,不提供远程审批或响应工具。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"akzar1el-nofax": {
"command": "npx",
"args": [
"-y",
"nofax"
]
}
}
}
启动命令npx -y nofax

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmnofax0.2.45

工具

7

收录的工具列表 · 更新于 3 天前

参数类型必填说明
titlestring否可选通知标题,显示给用户;默认为 "Nofax"。
messagestring是向用户显示的通知正文。

详细介绍

Nofax

CI 许可证:MIT Node.js >=20 MCP

为 AI 编码 Agent 提供人工审核和通知,无需运行 Nofax SaaS。

Nofax 是连接 Agent 与人工的小型开源桥梁。本地模式可以暂停 AI 工作流、向手机发送通知,并返回明确的决定。可选的自行部署 Cloudflare Worker 提供范围更窄的远程 MCP 接口,用于单向通知和安全地检查请求。

无需 Nofax 账户。无需付费模型 API。无需在你的机器上开放入站端口。采用 MIT 许可证。

**当前状态:**本地 Nofax 处于稳定的 0.2.x 版本线。可选的 Cloudflare Worker 是即将推出的 0.3.0 远程接口,与本地包并行开发。

为什么选择 Nofax

Agent 工作流越来越需要清晰地回答一个问题:当自动化遇到需要人工决策的边界时,如何发起询问,而不假装沉默就代表批准?

Nofax 会明确保留这个边界:

  • 待处理状态绝不代表批准;
  • 超时和传输失败时默认拒绝;
  • 第一个被接受的终态响应生效;
  • 针对特定 Agent 的钩子架构彼此隔离在适配器中;
  • 远程访问的范围有意小于本地访问;
  • Nofax 不会授予调用 Agent 原本不具备的权限。

两种运行模式

能力本地 Nofax 0.2远程 Worker 0.3
传输方式stdio / CLI 钩子MCP Streamable HTTP
单向通知是是
允许 / 拒绝是否
明确选项是否
自由文本调整是否
等待人工响应是否
读取请求元数据是是
持久化状态本地文件现有 SQLite Durable Object 行
由 Nofax 托管否否 — 自行部署的 Worker
远程身份验证本地进程边界私有 bearer 密钥

远程 Worker 不是托管式远程审批服务。它可以发送通知信息并检查现有请求状态,但不提供审批回调、选项、调整、等待、Webhook 或任意远程写入端点。

快速开始

1. 安装
npm install -g nofax

需要 Node.js 20 或更高版本。

2. 初始化
nofax init

Nofax 会创建 ~/.nofax/config.json 并生成高熵通知主题。使用默认传输方式时,请在 ntfy 移动应用中订阅显示的主题。

3. 测试
nofax test
4. 使用
nofax notify --title "Build finished" "All tests passed"
nofax approve --title "Deploy?" "Release 1.4.0 is ready"
nofax refine --title "Refine draft" "Tell me what to change"

审批会解析为稳定的终态 JSON:

{"decision":"allow"}

或者:

{"decision":"deny"}

如果请求仍处于待处理状态、超时、断开连接或遇到传输错误,Nofax 绝不会将这些情况转换为批准。

MCP

启动本地 stdio MCP 服务:

nofax mcp
连接 MCP 客户端

Claude Code 可以直接启动已发布的本地 MCP 服务:

claude mcp add nofax -- npx -y nofax mcp

Codex CLI 可以注册同一个 stdio 服务:

codex mcp add nofax -- npx -y nofax mcp

Gemini CLI 可以在用户设置中注册该服务:

gemini mcp add --scope user --transport stdio nofax npx -- -y nofax mcp

如果当前工作区不受信任,Gemini CLI 可能会将已配置的服务标记为 Disabled。请通过 Gemini 的常规信任流程检查并信任你控制的工作区;不要使用 --trust 绕过 MCP 工具调用确认。注册 MCP 服务不会自动安装下文所述的独立权限钩子。

VS Code 可以在用户配置文件的 MCP 配置中注册 Nofax。打开命令面板,选择 MCP: Open User Configuration,然后在 mcp.json 中添加以下条目:

{
  "servers": {
    "nofax": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "nofax", "mcp"]
    }
  }
}

请将 nofax 条目与现有服务合并,而不是替换它们。启动前,请查看 VS Code 的常规服务信任提示;注册 MCP 不会安装独立的权限钩子。

对于其他 stdio MCP 客户端,将命令设为 npx,参数设为 ["-y", "nofax", "mcp"]。必须提供最后一个 mcp 参数:如果运行 npx -y nofax 而未提供该参数,程序会打印 CLI 用法并退出,而不会启动服务。使用通知或审批工具前,请完成快速入门配置。

本地 MCP 提供:

  • nofax_notify
  • nofax_request_approval
  • nofax_request_choice
  • nofax_request_refinement
  • nofax_wait_for_response
  • nofax_get_request
  • nofax_list_pending

交互式请求会返回一个持久请求 ID。nofax_wait_for_response 会执行有时限的等待;只要请求仍处于待处理状态,调用方就必须重复等待,不能据此推断请求已获批准。

Agent 集成

Claude Code

在 ~/.claude/settings.json 中将 Nofax 用作本地 PermissionRequest 钩子:

{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "nofax hook claude"
          }
        ]
      }
    ]
  }
}
Codex

Codex 钩子默认已启用。配置 ~/.codex/hooks.json:

{
  "hooks": {
    "PermissionRequest": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "nofax hook codex",
            "statusMessage": "Waiting for Nofax approval"
          }
        ]
      }
    ]
  }
}

重启 Codex,运行 /hooks,并在依赖该钩子前检查并信任 Nofax 钩子的确切定义。Codex 会跳过尚未信任的非托管钩子;如果钩子定义发生变化,必须重新检查。如果管理员或本地策略已明确禁用钩子,请在 ~/.codex/config.toml 中使用 [features] hooks = true 重新启用。

Codex 目前会在其配置的审批审查器之前执行 PermissionRequest 钩子。终结性的 Nofax Allow/Deny 会在 Codex 将请求路由至 approvals_reviewer = "auto_review"(或旧版 guardian_subagent 值)之前解决请求。如果你希望 Nofax 成为人工审批入口,请使用 approvals_reviewer = "user";不要将此 Nofax 审批钩子与 Auto-review/Guardian 结合使用并期待两个审查器都会运行。当前 Codex 钩子输入不会公开有效审查器,因此 Nofax 无法安全地区分路由给用户审批的请求与 Codex 计划自动审查的请求。

PermissionRequest 钩子还会与 Codex 原生审批界面串行执行:Nofax 等待期间,常规 Codex 审批提示不会同时出现。如果 Nofax 未返回决定(例如超时或传输失败),Codex 会回退到常规审批流程。Nofax 绝不会将这种回退情况转换为批准。

Gemini CLI

当前版本的 Gemini CLI 提供同步的 BeforeTool 钩子,可允许或拒绝工具调用。在 ~/.gemini/settings.json 中将选定工具路由至 Nofax:

{
  "hooks": {
    "BeforeTool": [
      {
        "matcher": "run_shell_command|write_file|replace",
        "hooks": [
          {
            "name": "nofax-approval",
            "type": "command",
            "command": "nofax hook gemini",
            "timeout": 305000
          }
        ]
      }
    ],
    "Notification": [
      {
        "matcher": "ToolPermission",
        "hooks": [
          {
            "name": "nofax-notification",
            "type": "command",
            "command": "nofax hook gemini"
          }
        ]
      }
    ]
  }
}

BeforeTool 会等待明确的 Nofax Allow/Deny 结果。Nofax 超时或传输失败时,会返回 Gemini 的 ask 决策,强制进行原生交互式确认,而不是让自动批准策略将缺失的 Nofax 决策视为许可。Notification 钩子仅提供提示,并且只会转发为手机通知。

请调整匹配器,指定你希望由 Nofax 管控的工具。钩子超时应长于 Nofax 配置的审批超时时间(默认情况下,timeoutSeconds 为 300 秒)。

Pi(原生 MCP 支持)

具备原生 MCP 支持的 Pi 版本(例如 @earendil-works/pi-coding-agent 发布版本)可以启动本地 Nofax stdio 服务。运行 nofax init 后,注册并检查它:

pi mcp add nofax -- npx -y nofax mcp
pi mcp list

Pi 的默认 MCP 请求超时时间为 60 秒。如果你使用 nofax_wait_for_response,且等待时间超过此限制(最长可达 Nofax 的 240 秒上限),请在 ~/.pi/agent/mcp.json 现有的 nofax 条目中添加 "timeout": 300。不要替换其他无关的服务条目或设置:

{
  "mcpServers": {
    "nofax": {
      "command": "npx",
      "args": ["-y", "nofax", "mcp"],
      "timeout": 300
    }
  }
}

此操作注册的是 MCP 工具,并非自动权限钩子或空闲会话唤醒功能。请求待处理期间,Agent 必须再次调用 nofax_wait_for_response;缺少回复、超时或断开连接都不代表获得批准。请使用 Pi 的常规信任/权限工作流,并在应用这些说明前确认你安装的 Pi 版本支持 pi mcp。

可选的远程 Cloudflare Worker

worker/ 软件包提供一个私有、由你自行部署的 MCP 端点:

remote MCP client
       |
       | authenticated Streamable HTTP
       v
Cloudflare Worker
       |
       +--> nofax_notify ------> ntfy ------> phone
       |
       +--> SQLite Durable Object
              |
              +--> get request metadata
              +--> list pending requests

它恰好提供三个工具:

  • nofax_notify — 仅发送单向通知;
  • nofax_get_request — 读取一条安全的请求投影;
  • nofax_list_pending — 读取尚未解决且未过期的请求投影。

从 worker/ 部署:

npm ci
npx wrangler login
npx wrangler secret put NOFAX_REMOTE_KEY
npx wrangler secret put NTFY_TOPIC
npm run check
npm run deploy

首选 MCP 连接方式:

https://<worker>.workers.dev/mcp
Authorization: Bearer <NOFAX_REMOTE_KEY>

无法附加静态授权标头的客户端可以使用兼容性能力路径:

https://<worker>.workers.dev/mcp/<NOFAX_REMOTE_KEY>

请将完整的能力 URL 视同密码保管。

有关部署、威胁边界和资格认证详情,请参阅 docs/remote-mcp.md。

重要:公共 ntfy + 无服务器出站流量

默认的公共 ntfy.sh 服务会对发布者实施配额。Cloudflare Workers 等无服务器平台可能共用出站 IP 地址空间,因此,即使某个 Worker 发送的流量很少,也可能收到 ntfy 的 42908 每日配额响应。此限制由 ntfy 实施,而非 Cloudflare Workers 的请求配额。

对于对可靠性要求较高的部署,请使用配额与自己的认证账户/身份绑定的通知提供商,或运行可信的自托管传输服务。不要基于对匿名公共主题配额的假设构建关键工作流。

安全模型

Nofax 是一种传输和人机交互组件,不是授权策略引擎。

本地模式:

  • 待处理、超时、断开连接、状态格式错误和网络故障都不代表获得批准;
  • 第一个有效的终态响应优先;
  • 通知主题和一次性响应主题属于能力凭据;
  • 公共 ntfy 不提供从服务提供商端到端加密;
  • 脱敏仅尽力而为,无法可靠识别任意自由文本中嵌入的机密信息。

远程模式:

  • 只有明确调用 nofax_notify 才会产生外部消息副作用;
  • 请求检查操作是只读的,不会执行隐藏的清理写入;
  • 不提供远程批准、回调、Webhook、细化、选择和等待接口;
  • NOFAX_REMOTE_KEY 是持有者凭据;
  • 远程投影会省略回调能力、提示词/消息文本以及内部允许的决策列表。

使用 Nofax 处理敏感信息前,请阅读 SECURITY.md。

配置

默认本地配置位于 ~/.nofax/config.json:

{
  "version": 1,
  "server": "https://ntfy.sh",
  "topic": "nofax_<random>",
  "timeoutSeconds": 300
}

使用 NOFAX_HOME 覆盖主目录:

NOFAX_HOME=/path/to/nofax-home nofax config

使用其他兼容 ntfy 的服务器:

nofax init --server https://ntfy.example.com --force

开发

本地软件包:

npm ci
npm run check
npm test
npm pack --dry-run

远程 Worker:

cd worker
npm ci
npm run check

CI 会为本地软件包验证 Node.js 20、22 和 24。Worker 的门禁流程会运行 TypeScript、Vitest、生产依赖审计和 Wrangler 部署试运行。

项目文档

非目标

Nofax 特意不提供:

  • 由 Nofax 运营的审批 SaaS;
  • 对付费模型 API 的依赖;
  • 持久的 always approve 策略;
  • 任意远程 Shell 端点;
  • 多个用户共用一个部署密钥的公共 Worker;
  • 将 MCP 注解本身视为安全边界的说法。

许可证

MIT © Tomi Šeregi。参见 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。