mcpField
P
pendnt

pendnt

远程服务
pendnt.devAI 与智能体06 周前更新

关于 pendnt

pendnt 是面向交互式或无头 Agent 的 Claude Code 插件,可将权限请求交由人工审批并转发通知。它结合审批钩子与 MCP 权限工具,让无人值守运行等待明确决定,而非依赖终端。

主要功能

  1. 01无头运行权限审批
  2. 02MCP 权限提示工具
  3. 03通知与运行结束钩子
  4. 04持久化审批请求
  5. 05出错时默认拒绝

适用场景

  1. 01审批无人值守 Claude Code 运行中的工具调用
  2. 02接收 Agent 运行结束通知
  3. 03通过手机处理审批请求

MCP 相关

插件注册 pendnt 远程 MCP 服务及其工具,包括供 Claude Code 无头权限机制使用的 `permission_prompt`。其他工具支持审批、通知、Webhook、唤醒和键值存储。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://api.pendnt.dev/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

全部服务地址
Streamable HTTPhttps://api.pendnt.dev/mcp需要授权

工具

详细介绍

pendnt(Claude Code 插件)

10 秒上手——无需账户: curl https://api.pendnt.dev/try?plain=1 会返回一个有效期为 72 小时的试用密钥(20 次请求)和快速入门指南。

将 Claude Code 会话(交互式或无头模式 claude -p)连接到 pendnt 工作区:支持持久的人类审批、通知和“运行完成”提醒,无需 Agent 使用终端。

“pendnt”是一个占位产品名称。它只保存在一个位置——lib/config.mjs 中的 PRODUCT_NAME——此外还出现在 plugin.json、marketplace.json 和 .mcp.json 中的 name 字段,以及在 /app/src/routes/mcp.ts 注册的对应 MCP 服务名称中。将这些位置的名称一并重命名,就能完成所有相关位置的重命名。

此插件提供两种相互独立的方式,用于在无头模式下响应权限提示——任选其一(或同时使用;若两者都已接入,则优先使用 --permission-prompt-tool,见下文 §1a):

  1. PermissionRequest 钩子(hooks/permission-request.mjs)——适用于原生 claude -p,无需额外标志。每次工具使用提示前都会自动运行。
  2. 通过 --permission-prompt-tool mcp__pendnt__permission_prompt 使用 permission_prompt MCP 工具——Claude Code 专为无头权限提示提供的机制(见 INTEGRATIONS.md §1a)。

此外还有一个 Notification 钩子和一个 Stop 钩子,都会将通知转发到 POST /v1/notify——见下文包含内容。

安装

本地插件市场(用于发布前试用)

此仓库也可作为自己的本地插件市场——.claude-plugin/marketplace.json 将此插件列出,并设置 source: "./" 指向 plugin.json 所在的同一目录。在 Claude Code 中:

/plugin marketplace add Pendnt/pendnt-plugin
/plugin install pendnt@pendnt

(或以非交互方式运行:claude plugin marketplace add Pendnt/pendnt-plugin && claude plugin install pendnt@pendnt)

之后若要正式发布,请将 marketplace.json 拆分到独立仓库,并将 source 指向此插件的仓库(有关市场清单格式以及 github/git-subdir/npm/archive 源类型,请见 INTEGRATIONS.md §1d),然后可在任意位置运行 claude plugin marketplace add <owner>/<repo>。

环境变量
变量必需默认值含义
PENDNT_API_KEY是—每次调用 API 时使用的 Authorization: Bearer <key>(aio_...,本地环境中由 POST /dev/bootstrap 获取,或在生产环境中使用真实工作区的 API 密钥)。如果未设置,PermissionRequest/Notification/Stop 钩子都会安全失败关闭(拒绝 / 不执行任何操作),而不是让会话报错。
PENDNT_URL否https://api.pendnt.devpendnt REST API 的基础 URL——不包含 /mcp 或 /v1。在本地开发时,可将其设为 http://localhost:8787,以通过 wrangler dev 连接本地服务(见下文)。
PENDNT_APPROVAL_TIMEOUT_S否600(10 分钟)PermissionRequest 钩子反复轮询、直至放弃并拒绝前可用的总墙钟时间预算。每次轮询的服务端时限为 25 秒(wait_s),因此钩子会循环调用 GET /v1/requests/:id?wait_s=25,直到预算耗尽。

可在 shell 中设置这些变量,也可在 .claude/settings.json 的 env 中设置——见 settings.json 文档。.mcp.json 中的 ${PENDNT_URL:-...} / ${PENDNT_API_KEY} 语法是 Claude Code 自带的 .mcp.json 值环境变量展开功能,适用于请求头和 URL——见 INTEGRATIONS.md §1e。

包含内容

  • .mcp.json — 注册 pendnt 远程 MCP 服务(${PENDNT_URL:-https://api.pendnt.dev}/mcp、 Authorization: Bearer ${PENDNT_API_KEY}),使模型可以直接使用全部 14 个工具(request_approval、check_request、 permission_prompt、notify、create_endpoint、list_endpoints、wait_for_event、schedule_wakeup、 list_wakeups、cancel_wakeup、kv_get、kv_set、kv_delete、whoami),工具名称为 mcp__pendnt__<tool>。不过,Claude Code 会在 permission_prompt 被指定为 --permission-prompt-tool 后,将其从自身显示的工具列表中移除(见下文),因为它应该由 CLI 自身调用,而不是由模型调用。
  • hooks/hooks.json — 配置三个钩子(结构与 settings.json 的 hooks 键一致,参见 INTEGRATIONS.md §1d):
    • PermissionRequest → hooks/permission-request.mjs。在每次工具调用提示前触发。将工具调用摘要 POST 到 POST /v1/requests(kind: "approval"、wait_s: 25、 timeout_s: $PENDNT_APPROVAL_TIMEOUT_S),然后反复轮询 GET /v1/requests/:id?wait_s=25,直到请求得到答复或总计的 PENDNT_APPROVAL_TIMEOUT_S 时限耗尽。按照 INTEGRATIONS.md §1b 中的 PermissionRequest 约定,精确输出一个 JSON 对象:
      { "hookSpecificOutput": { "hookEventName": "PermissionRequest", "decision": { "behavior": "allow", "updatedInput": {} } } }
      
      或 {"behavior": "deny", "message": "..."}。遇到任何错误都默认拒绝(缺少 API 密钥、网络故障、操作员拒绝、请求过期、超时)——只有明确批准才能获得 allow。即使请求的 kind: "approval",回答页面也始终显示自由文本输入框;只有当操作员输入的文本以 yes/y/allow/approve/ok 开头时,才视为批准,否则会以该文本作为拒绝原因。
    • Notification → hooks/notify.mjs。将 notification_type/message 转发到 POST /v1/notify。根据钩子自身的语义,它无法阻止 Claude Code,也不会尝试阻止——始终以 0 退出。
    • Stop → hooks/stop.mjs。在每轮结束时,将 "run finished" 消息转发到 POST /v1/notify。绝不返回 {"decision":"block"}——它只发送通知,不会让 Agent 继续运行。
  • lib/ — 三个钩子脚本的共用部分:config.mjs(环境变量和 PRODUCT_NAME 常量)、client.mjs(针对 /v1/requests 和 /v1/notify 的轻量 fetch 封装)、stdin.mjs(解析钩子标准输入中的 JSON)。没有 npm 依赖——只需纯 Node 18+(fetch、AbortController)即可运行。

--permission-prompt-tool 路径(§1a)

你可以将 Claude Code 专用的权限提示机制直接指向此插件的 .mcp.json 注册的 permission_prompt MCP 工具,而不是(或除了——两者都适用时,Claude Code 优先使用 --permission-prompt-tool 而非 hooks)使用 PermissionRequest hook。该工具是此服务中专为此标志打造的工具(完整契约请参见 /app/README.md 的 permission_prompt 部分):

export PENDNT_API_KEY=aio_...
export PENDNT_URL=https://api.pendnt.dev   # or http://localhost:8787 for local dev
export MCP_TOOL_TIMEOUT=600000              # ms — must exceed PERMISSION_PROMPT_WAIT_S (default 540s)

claude -p --permission-prompt-tool mcp__pendnt__permission_prompt "deploy to prod"

依赖此路径前,有三点值得了解:

  • 在 pendnt MCP 服务连接之前,Claude Code 会阻塞第一个回合,等待时间上限由 MCP_TIMEOUT 控制(默认 30s,环境变量,单位为毫秒)——如果网络较慢,请调高该值:export MCP_TIMEOUT=60000(摘自 INTEGRATIONS.md §1a)。
  • 从 CLI ≥2.1.199 开始,对于标记了 _meta["anthropic/requiresUserInteraction"] 的任何 MCP 工具调用,--permission-prompt-tool 返回的 allow 会被转换为 deny——无论操作人员如何作答,此提示工具都无法直接批准这类调用(同样摘自 INTEGRATIONS.md §1a)。
  • permission_prompt 会在服务端保持 MCP 工具调用处于打开状态,最长等待 PERMISSION_PROMPT_WAIT_S(/app 上的环境变量,默认 540s = 9 min),等待操作人员响应;与此不同,其他工具的 wait_s 均不超过 25s。Claude Code 自身的 MCP_TOOL_TIMEOUT(每次工具调用的超时时间,单位为毫秒,默认 30000)必须设置得更长,否则 CLI 会先放弃等待——因此上面设置了 export MCP_TOOL_TIMEOUT=600000。

不同于 request_approval,permission_prompt 会原生返回 Claude Code 的确切 {behavior, updatedInput, updatedPermissions, interrupt} / {behavior:"deny", message, interrupt} 契约——allow 会将原始 input 回传为 updatedInput,deny(或等待超时仍未收到响应)会包含面向用户的 message。这与下文的 PermissionRequest hook 为其自身的 hook 形式契约手动完成的转换相同;permission_prompt 则直接通过 MCP 工具结果完成该转换,而这正是 --permission-prompt-tool 实际读取的内容。

无头模式示例

export PENDNT_API_KEY=aio_...
export PENDNT_URL=https://api.pendnt.dev
export MCP_TOOL_TIMEOUT=600000

claude -p --permission-prompt-tool mcp__pendnt__permission_prompt \
  "review open PRs and merge the ones that pass CI"

或者,让 PermissionRequest hook 来处理(安装插件后无需额外标志):

export PENDNT_API_KEY=aio_...
export PENDNT_URL=https://api.pendnt.dev

claude -p "review open PRs and merge the ones that pass CI"

无论哪种方式,每次工具使用提示现在都会创建一个持久的审批请求,而不是阻塞在并不存在的终端上——查看已配置的渠道(电子邮件/网页收件箱——要了解当前实际实现的渠道,请参见 /app/README.md 的“Channels”部分),然后用手机作答,Agent 就会继续运行。

在本地针对 wrangler dev 运行 hook

在 /app 中:

cd ../app
npm install
npm run db:migrate:local
npm run dev   # http://localhost:8787

在另一个终端中,初始化工作区和 API 密钥(参见 /app/README.md),并将插件的环境变量指向该环境:

BOOT=$(curl -s -X POST http://localhost:8787/dev/bootstrap -d '{}')
export PENDNT_API_KEY=$(echo "$BOOT" | jq -r .api_key)
export PENDNT_URL=http://localhost:8787

然后,可以直接运行 hook 脚本,并通过 stdin 输入真实 Claude Code hook 调用会发送的 JSON(适合在不启动完整 Claude Code 会话的情况下迭代调试 hook):

echo '{"session_id":"s1","cwd":"'"$PWD"'","tool_name":"Bash","tool_use_id":"toolu_1","tool_input":{"command":"deploy prod"}}' \
  | PENDNT_APPROVAL_TIMEOUT_S=60 node hooks/permission-request.mjs

……或者在本地安装插件(在 Claude Code 中运行 /plugin marketplace add Pendnt/pendnt-plugin,参见安装)并启动真实会话——只要在 Claude Code 运行的 shell 中导出 PENDNT_URL/PENDNT_API_KEY,每次工具使用提示都会经由本地 wrangler dev 实例往返处理。按照 /app/README.md 中的 curl 操作示例来响应请求:自行计算 HMAC 签名(它是请求 id 和 SIGNING_SECRET 的纯函数),然后 POST /a/<id>/<sig>;或者,在接入真实渠道后,从 wrangler dev 中查看 log 投递渠道的控制台输出,获取答复链接。

注意事项

  • 按设计不依赖 npm(仅使用 fetch/AbortController)——每个 hook 脚本都通过纯 node hooks/*.mjs 运行,插件本身无需执行 npm install。
  • PermissionRequest hook 的默认失败关闭行为(缺少密钥、网络错误、超时 → 拒绝)是有意为之的安全选择,并非需要设法绕过的限制——没有人可以询问的无头 Agent 默认不应继续执行。
  • hooks/hooks.json 的 Notification 匹配器没有限定具体的 notification_type——每条通知(包括与权限提示无关的通知)都会被转发。如果觉得这比预期更吵闹,可以缩小匹配范围,或在 hooks/notify.mjs 内进行过滤。

指南

关于如何在无人值守的情况下运行 Agent 的实用指南,见 pendnt.dev/guides: --dangerously-skip-permissions 的替代方案 · 定时任务中的 claude -p · --permission-prompt-tool 契约 · 用于无人值守运行的 hooks · 退出代码:重试还是保持终止

评论

支持 Markdown

第一次接触 MCP?

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

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