pendnt について
pendntは、対話型またはヘッドレスのエージェントを運用するチーム向けのClaude Codeプラグインです。権限要求を人間の承認に回し、通知を中継します。承認フックとMCP権限ツールを備え、無人実行でも明示的な判断を待てます。
主な機能
- 01ヘッドレス実行の権限承認
- 02MCP権限プロンプトツール
- 03通知・実行終了フック
- 04永続的な承認リクエスト
- 05エラー時は既定で拒否
活用シーン
- 01無人のClaude Code実行でツール呼び出しを承認
- 02エージェントの実行終了通知を受信
- 03スマートフォンから承認リクエストに対応
MCP 対応
pendntのリモートMCPサーバーと各ツールを登録し、Claude Codeのヘッドレス権限機能向けに`permission_prompt`を提供します。ほかのツールでは承認、通知、Webhook、ウェイクアップ、キー・バリューストレージを扱えます。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://api.pendnt.dev/mcpclaude mcp add --transport http dev-pendnt-pendnt https://api.pendnt.dev/mcp{"mcpServers":{"dev-pendnt-pendnt":{"type":"http","url":"https://api.pendnt.dev/mcp"}}}Cursor で開く{"servers":{"dev-pendnt-pendnt":{"type":"http","url":"https://api.pendnt.dev/mcp"}}}VS Code で開く{"mcpServers":{"dev-pendnt-pendnt":{"type":"http","url":"https://api.pendnt.dev/mcp"}}}{"mcpServers":{"dev-pendnt-pendnt":{"serverUrl":"https://api.pendnt.dev/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
https://api.pendnt.dev/mcp認証が必要ツール
詳細
pendnt(Claude Code プラグイン)
10 秒でお試し — アカウント不要:
curl https://api.pendnt.dev/try?plain=1を実行すると、クイックスタート付きの 72 時間有効なトライアルキー(20 リクエスト)が返されます。
Claude Code のセッション(対話型またはヘッドレス(claude -p))を
pendnt ワークスペースに接続します。これにより、エージェントがターミナルを使わなくても、
永続的な人間による承認、通知、「実行完了」の通知を利用できます。
「pendnt」は仮の製品名です。名前が使われているのは、
lib/config.mjs の PRODUCT_NAME と、
plugin.json、marketplace.json、
.mcp.json の name フィールド、および
/app/src/routes/mcp.ts に登録されている対応する MCP サーバー名だけです。
これらをまとめて変更すれば、関連するすべての箇所で名前が変更されます。
このプラグインには、ヘッドレス環境で権限確認プロンプトに応答する独立した方法が 2 つあります。
どちらか一方、または両方を選んでください。両方を設定した場合は
--permission-prompt-tool が優先されます(詳しくは以下の §1a を参照してください)。
PermissionRequestフック(hooks/permission-request.mjs) — 追加のフラグなしで、通常のclaude -pで動作します。ツール使用のプロンプトが表示されるたびに自動で実行されます。permission_promptMCP ツール(--permission-prompt-tool mcp__pendnt__permission_prompt経由) — ヘッドレス環境での権限確認プロンプトに対応する Claude Code 独自の専用メカニズムです (INTEGRATIONS.md§1a を参照してください)。
さらに、どちらも POST /v1/notify に中継する Notification フックと Stop フックがあります。
詳しくは以下の同梱内容を参照してください。
インストール
ローカルマーケットプレイス(公開前に試す場合)
このリポジトリは独自のローカルマーケットプレイスとしても機能します。
.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>(ローカルでは POST /dev/bootstrap から取得する aio_...、本番環境では実際のワークスペースの API キー)。これが設定されていない場合、PermissionRequest/Notification/Stop フックはセッションにエラーを返すのではなく、安全側に倒してすべて失敗します(拒否/何もしない)。 |
PENDNT_URL | いいえ | https://api.pendnt.dev | pendnt REST API のベース URL。/mcp や /v1 は含めません。ローカル開発で wrangler dev に接続する場合は、http://localhost:8787 を指定します(以下を参照してください)。 |
PENDNT_APPROVAL_TIMEOUT_S | いいえ | 600(10 分) | PermissionRequest フックが再ポーリングを続けてから、諦めて拒否するまでの合計実時間です。個々のポーリングはサーバー側で最大 25 秒(wait_s)に制限されるため、この予算に達するまでフックは GET /v1/requests/:id?wait_s=25 を繰り返します。 |
シェルで設定するか、.claude/settings.json の env に設定してください。
settings.json のドキュメントを参照してください。
.mcp.json の ${PENDNT_URL:-...}/${PENDNT_API_KEY} 構文は、
.mcp.json の値(ヘッダー と URL)に対する Claude Code 独自の環境変数展開機能です。
詳しくは INTEGRATIONS.md §1e を参照してください。
含まれるもの
.mcp.json— リモート MCP サーバーpendnt(${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>として直接利用できます。ただしpermission_promptは、--permission-prompt-toolで指定すると Claude Code が自身の表示ツール一覧から削除します(下記参照)。これは モデルではなく CLI 自体から呼び出すためのツールです。hooks/hooks.json— 3 つのフックを設定します(形式はsettings.jsonのhooksキーと同じです。詳細はINTEGRATIONS.md§1d を参照してください)。PermissionRequest→hooks/permission-request.mjs。ツール使用のプロンプトごとに実行されます。ツール呼び出しの概要をPOST /v1/requests(kind: "approval"、wait_s: 25、timeout_s: $PENDNT_APPROVAL_TIMEOUT_S)に POST し、回答されるか、PENDNT_APPROVAL_TIMEOUT_Sの合計 時間が経過するまでGET /v1/requests/:id?wait_s=25を再度ポーリングします。INTEGRATIONS.md§1b のPermissionRequestコントラクトに従い、JSON オブジェクトを 1 つだけ出力します。
または{ "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"}を返すことはありません。通知するだけで、エージェントの実行を継続させることはありません。
lib/— 3 つのフックスクリプトで共有する部分です。config.mjs(環境変数とPRODUCT_NAME定数)、client.mjs(/v1/requestsと/v1/notify用の薄いfetchラッパー)、stdin.mjs(フックの stdin JSON 解析)が含まれます。npm の依存関係は不要です。Node 18 以降(fetch、AbortController)だけで動作します。
--permission-prompt-tool の経路(§1a)
PermissionRequest フックの代わりに、またはフックに加えて(両方が適用される場合、Claude Code はフックよりも --permission-prompt-tool を優先します)、Claude Code 専用の権限プロンプト機構を、このプラグインの .mcp.json が登録する MCP ツール permission_prompt に直接向けることができます。このサーバーでこのフラグ専用に設計されたツールです(契約の詳細は /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"
この経路を利用する前に、知っておくべきことが3つあります。
pendntMCP サーバーが接続するまで、Claude Code は最初のターンをブロックします。上限はMCP_TIMEOUT(デフォルトは30秒、環境変数、単位はミリ秒)です。ネットワークが遅い場合は値を増やしてください:export MCP_TIMEOUT=60000(INTEGRATIONS.md§1a より)。- CLI ≥2.1.199 以降では、
--permission-prompt-toolによるallowは、_meta["anthropic/requiresUserInteraction"]が設定されたあらゆる MCP ツール呼び出しに対してdenyに変換されます。このプロンプトツールは、オペレーターの回答にかかわらず、それらの呼び出しを承認できません(こちらもINTEGRATIONS.md§1a より)。 permission_promptは、オペレーターの応答を待つ間、MCP ツール呼び出しをサーバー側で最大PERMISSION_PROMPT_WAIT_Sの間オープン状態に保ちます(/appの環境変数、デフォルトは540秒=9分)。これは、他のすべてのツールのwait_sが最大25秒であるのとは異なります。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 フックが独自のフック形式の契約に合わせて手動で行う変換と同じです。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 フックに処理させることもできます(プラグインのインストール後は追加のフラグは不要です)。
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」セクションを参照してください)を確認し、スマートフォンから回答すれば、エージェントが処理を再開します。
wrangler dev に対してフックをローカルで実行する
/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
次に、フックスクリプトを直接実行し、実際の Claude Code のフック呼び出しが標準入力に送る JSON を渡す方法があります(Claude Code のセッション全体を起動せずにフックを試行錯誤するのに便利です)。
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 を実行します。Install を参照)、実際のセッションを実行します。Claude Code を実行するシェルで PENDNT_URL/PENDNT_API_KEY をエクスポートしておけば、ツール使用時の各プロンプトがローカルの wrangler dev インスタンスを経由して往復します。/app/README.md の curl の手順と同じ方法でリクエストに回答します。リクエスト ID と SIGNING_SECRET のみを使う純粋関数として HMAC 署名を計算し、POST /a/<id>/<sig> を実行します。または、実際のチャネルが接続されたら回答リンクが表示されるよう、wrangler dev の log 配信チャネルのコンソール出力を監視します。
注意点
- 設計上、npm の依存関係はありません(
fetch/AbortControllerのみ)。すべてのフックスクリプトはプレーンなnode hooks/*.mjsの下で実行され、プラグイン内でnpm installを実行する必要はありません。 PermissionRequestフックのフェイルクローズのデフォルト動作(キーがない、ネットワークエラー、タイムアウトの場合は拒否)は、 回避すべき制約ではなく、安全性を考慮した意図的な選択です。問い合わせる相手のいないヘッドレスエージェントは、 デフォルトで処理を続行すべきではありません。hooks/hooks.jsonのNotificationマッチャーは、特定のnotification_typeに絞り込まれていません。そのため、 権限プロンプトに関係しないものも含め、すべての通知が中継されます。通知が多すぎる場合は、マッチャーを絞り込むか、hooks/notify.mjs内でフィルタリングしてください。
ガイド
エージェントを無人で実行するための実践的な解説は、pendnt.dev/guides にあります: --dangerously-skip-permissions の代替方法 · cron での claude -p · --permission-prompt-tool の仕様 · 無人実行向けのフック · 終了コード:再試行するか、停止したままにするか
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。