Skip to main content
Glama

Nofax

CI License: MIT Node.js >=20 MCP

Human-in-the-loop approvals and notifications for AI coding agents, without running a Nofax SaaS.

Nofax is a small open-source bridge between an agent and a human. Local mode can pause an AI workflow, notify your phone, and return an explicit decision. An optional self-deployed Cloudflare Worker exposes a deliberately narrower remote MCP surface for one-way notifications and safe request inspection.

No Nofax account. No paid model API. No inbound port on your machine. MIT licensed.

Current status: local Nofax is on the stable 0.2.x line. The optional Cloudflare Worker is the upcoming 0.3.0 remote surface and is developed alongside the local package.

Why Nofax

Agent workflows increasingly need a clean answer to one question: when automation reaches a human decision boundary, how does it ask without pretending that silence means approval?

Nofax keeps that boundary explicit:

  • pending is never approval;

  • timeout and transport failure fail closed;

  • the first accepted terminal response wins;

  • agent-specific hook schemas stay isolated in adapters;

  • remote access is intentionally narrower than local access;

  • Nofax does not grant authority the calling agent did not already have.

Related MCP server: Relay

Two operating modes

Capability

Local Nofax 0.2

Remote Worker 0.3

Transport

stdio / CLI hooks

MCP Streamable HTTP

One-way notification

Yes

Yes

Allow / Deny

Yes

No

Explicit choices

Yes

No

Free-text refinement

Yes

No

Wait for human response

Yes

No

Read request metadata

Yes

Yes

Durable state

Local files

Existing SQLite Durable Object rows

Hosted by Nofax

No

No — self-deployed Worker

Remote authentication

Local process boundary

Private bearer key

The remote Worker is not a hosted remote-approval service. It can send an informational notification and inspect existing request state, but it has no approval callback, choice, refinement, wait, webhook, or arbitrary remote-write endpoint.

Quick start

1. Install

npm install -g nofax

Requires Node.js 20 or newer.

2. Initialize

nofax init

Nofax creates ~/.nofax/config.json and generates a high-entropy notification topic. With the default transport, subscribe to the displayed topic in the ntfy mobile app.

3. Test

nofax test

4. Use it

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"

An approval resolves to stable terminal JSON:

{"decision":"allow"}

or:

{"decision":"deny"}

If the request is still pending, times out, disconnects, or hits a transport error, Nofax never converts that condition into approval.

MCP

Start the local stdio MCP server:

nofax mcp

Local MCP exposes:

  • nofax_notify

  • nofax_request_approval

  • nofax_request_choice

  • nofax_request_refinement

  • nofax_wait_for_response

  • nofax_get_request

  • nofax_list_pending

Interactive requests return a durable request ID. nofax_wait_for_response performs a bounded wait; callers must repeat the wait while the request remains pending rather than infer approval.

Agent integrations

Claude Code

Use Nofax as a local PermissionRequest hook in ~/.claude/settings.json:

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

Codex

Codex hooks are enabled by default. Configure ~/.codex/hooks.json:

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

Restart Codex, run /hooks, and review/trust the exact Nofax hook definition before relying on it. Codex skips non-managed hooks until they are trusted, and a changed hook definition must be reviewed again. If an administrator or local policy has explicitly disabled hooks, re-enable them with [features] hooks = true in ~/.codex/config.toml.

Codex currently evaluates PermissionRequest hooks before its configured approval reviewer. A terminal Nofax Allow/Deny therefore resolves the request before Codex can route it to approvals_reviewer = "auto_review" (or the legacy guardian_subagent value). If you want Nofax to be the human approval surface, use approvals_reviewer = "user"; do not combine this Nofax approval hook with Auto-review/Guardian expecting both reviewers to run. Current Codex hook input does not expose the effective reviewer, so Nofax cannot safely distinguish a user-routed approval from one that Codex intended to auto-review.

PermissionRequest hooks are also serial with Codex's native approval UI: while Nofax is waiting, the normal Codex approval prompt is not simultaneously available. If Nofax returns no decision (for example after timeout or transport failure), Codex falls back to its normal approval flow. Nofax never converts that fallback condition into approval.

Gemini CLI

Current Gemini CLI builds expose a synchronous BeforeTool hook that can allow or deny a tool call. Route selected tools through Nofax in ~/.gemini/settings.json:

{
  "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 waits for an explicit Nofax Allow/Deny result. A Nofax timeout or transport failure returns Gemini's ask decision, forcing the native interactive confirmation instead of allowing an auto-approval policy to treat the missing Nofax decision as permission. The Notification hook remains advisory and is forwarded only as a phone notification.

Adjust the matcher to the tools you want Nofax to gate. Keep the hook timeout longer than Nofax's configured approval timeout (timeoutSeconds, 300 seconds by default).

Optional remote Cloudflare Worker

The worker/ package provides a private, self-deployed MCP endpoint:

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

It exposes exactly three tools:

  • nofax_notify — one-way notification only;

  • nofax_get_request — read one safe request projection;

  • nofax_list_pending — read unresolved, unexpired request projections.

Deploy from 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

Preferred MCP connection:

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

Clients that cannot attach a static authorization header can use the compatibility capability path:

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

Treat the complete capability URL like a password.

See docs/remote-mcp.md for deployment, threat boundaries, and qualification details.

Important: public ntfy + serverless egress

The default public ntfy.sh service applies publisher quotas. Serverless platforms such as Cloudflare Workers may use shared outbound IP space, so a Worker can receive an ntfy 42908 daily-quota response even when that individual Worker has sent very little traffic. That limit is imposed by ntfy, not by the Cloudflare Workers request quota.

For reliability-sensitive deployments, use a notification provider whose quota is tied to your own authenticated account/identity, or operate a trusted self-hosted transport. Do not build a critical workflow around anonymous public-topic quota assumptions.

Security model

Nofax is a transport and human-interaction component, not an authorization policy engine.

Local mode:

  • pending, timeout, disconnect, malformed state, and network failure never mean approval;

  • the first valid terminal response wins;

  • notification topics and one-time response topics are capabilities;

  • public ntfy is not end-to-end encrypted from the provider;

  • redaction is best-effort and cannot reliably identify secrets embedded in arbitrary free-form text.

Remote mode:

  • only explicit nofax_notify performs an external messaging side effect;

  • request-inspection operations are read-only and do not perform hidden cleanup writes;

  • remote approval, callback, webhook, refinement, choice, and wait surfaces are absent;

  • NOFAX_REMOTE_KEY is a bearer credential;

  • remote projections omit callback capabilities, prompt/message text, and internal allowed-decision lists.

Read SECURITY.md before using Nofax with sensitive information.

Configuration

Default local config lives at ~/.nofax/config.json:

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

Override the home directory with NOFAX_HOME:

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

Use another ntfy-compatible server with:

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

Development

Local package:

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

Remote Worker:

cd worker
npm ci
npm run check

CI qualifies Node.js 20, 22, and 24 for the local package. The Worker gate runs TypeScript, Vitest, a production-dependency audit, and a Wrangler deployment dry-run.

Project docs

Non-goals

Nofax deliberately does not provide:

  • a Nofax-operated approval SaaS;

  • a paid model API dependency;

  • persistent always approve policy;

  • an arbitrary remote shell endpoint;

  • a public multi-user Worker behind one shared deployment key;

  • a claim that MCP annotations themselves are a security boundary.

License

MIT © Tomi Šeregi. See LICENSE.

Available Tools

7 tools
nofax_get_requestGet Nofax requestA
Read-onlyIdempotent

Inspect safe metadata and terminal state for one known durable requestId without waiting. Use nofax_wait_for_response when the caller must wait for a human decision, or nofax_list_pending to recover requestIds after interruption. Secret response topics are never returned.

ParametersJSON Schema
NameRequiredDescriptionDefault
requestIdYesDurable Nofax request handle to inspect without exposing its secret response topic.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesThe durable request was read successfully.
requestYesSafe request metadata and terminal state; secret response topics are omitted.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive behavior. The description adds meaningful extra context: the call does not wait, reports terminal state, and never returns secret response topics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences front-load the behavior, then provide sibling routing and a security note. Every sentence earns its place with no redundant wording.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with annotations, rich schema coverage, and an output schema, the description covers behavior, alternatives, and the one critical restriction (never returning secret topics). Nothing needed for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single requestId parameter is already well-documented as a durable handle with a hidden secret topic. The description reinforces this but does not add substantially new parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description opens with a specific verb ('Inspect') and clear object: safe metadata and terminal state for one known durable requestId. It explicitly contrasts with waiting and listing siblings, making the tool's scope unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Names nofax_wait_for_response for when a caller must wait for a human decision and nofax_list_pending for recovery after interruption. This is explicit routing guidance with no ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nofax_list_pendingList pending Nofax requestsA
Read-onlyIdempotent

List a bounded set of unresolved Nofax request handles for recovery after client or conversation interruption. Secret response topics are never returned.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of unresolved requests to return; defaults to 20.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesThe pending-request scan completed successfully.
requestsYesBounded unresolved request projections with no secret response topics.

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnlyHint, idempotentHint, and destructiveHint, but the description adds valuable behavioral context: it returns a bounded set and never returns secret response topics. This goes beyond the schema and annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is only two sentences and every clause earns its place. The main purpose and the critical security exclusion are both front-loaded without wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only list operation with one optional parameter Roy and a rich output schema, the description covers the essential context. It explains why the tool exists and the sensitive exclusion, though it could slightly enhance guidance on when to prefer this over get_request.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the single 'limit' parameter is already fully documented. The description's mention of a 'bounded set' loosely ties to the limit but does not add specific syntax, defaults, or edge-case guidance beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description has a specific verb ('List'), a clear resource (pending Nofax request handles), and a purpose ('recovery after client or conversation interruption'). It also distinguishes itself from siblings like get_request by focusing on pending handles rather than retrieving a single request.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description conveys a clear usage context: use this tool after client or conversation interruption to recover unresolved handles. It does not explicitly name alternatives or exclusions, but the purpose statement is specific enough to guide selection among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nofax_notifySend Nofax notificationA

Send a one-way phone notification. This tool is informational and does not create a human-response wait. Notification transport success never counts as approval.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleNoOptional notification title shown to the human; defaults to "Nofax".
messageYesNotification body shown to the human.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesThe notification transport call completed successfully; this is never approval.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds significant behavioral context beyond annotations: the one-way nature, absence of a human-response wait, and the critical warning that transport success never equals approval. This prevents a dangerous misinterpretation that annotations alone would not cover.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, the purpose is front-loaded, and the essential non-approval caveat is included without any redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter tool with complete schema descriptions and an output schema present, the description covers all key semantic distinctions (one-way, no wait, no approval) needed for correct invocation. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with clear descriptions for both 'message' and 'title'. The tool description adds no additional parameter-level meaning, so the baseline 3 applies as the schema already does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Send'), a resource ('one-way phone notification'), and explicitly says the tool is informational. This differentiates it from sibling request/approval tools by emphasizing the one-way nature and lack of a response wait.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly communicates when to use (informational, no response wait) and when not to rely on it ('never counts as approval'). It doesn't explicitly name alternative tools, but the when-not guidance is strong enough to route an agent correctly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nofax_request_approvalRequest human approvalA

Send Allow/Deny to the phone and return a durable pending requestId. IMPORTANT: after this tool returns pending, call nofax_wait_for_response and repeat while it remains pending. Never continue the guarded action without a terminal Allow response. Set allowRefine when the human should also be able to send refinement text.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleNoOptional approval prompt title shown to the human; defaults to "Nofax approval".
messageYesGuarded action or decision context shown to the human.
allowRefineNoWhen true, also let the human return free-text refinement instead of only Allow or Deny.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesThe request is unresolved and must not be treated as approval.
mustWaitYesSignals that the caller must keep waiting for a terminal human response.
requestIdYesDurable Nofax request handle.
instructionYesFail-closed next-step instruction for the caller.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate this is not read-only, not idempotent, and not destructive. The description adds valuable behavior beyond those: it returns a durable pending requestId, uses an asynchronous polling pattern, and requires a terminal Allow before proceeding, which is not captured by the annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with no filler. The critical async workflow is front-loaded with 'IMPORTANT', the terminal-Allow warning is prominent, and the optional flag guidance is placed at the end without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has a nontrivial asynchronous approval flow, and the description covers the complete calling pattern: send request, poll with nofax_wait_for_response, repeat while pending, and do not proceed without a terminal Allow. Since an output schema exists, return-value detail is not needed. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all three parameters. The description reinforces allowRefine ('Set allowRefine when the human should also be able to send refinement text') but does not add substantial new meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Send Allow/Deny to the phone and return a durable pending requestId'. It clarifies the outcome and distinguishes this from siblings like nofax_request_choice and nofax_request_refinement by mentioning 'allowRefine' and the wait-for-response flow.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit instructions: 'after this tool returns pending, call nofax_wait_for_response and repeat while it remains pending' and 'Never continue the guarded action without a terminal Allow response'. It also states when to set allowRefine, giving the agent clear conditions and workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nofax_request_choiceRequest human choiceA

Send up to three explicit options to the phone and return a durable pending requestId. IMPORTANT: call nofax_wait_for_response and repeat while pending; do not choose on the human's behalf.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleNoOptional choice prompt title shown to the human; defaults to "Nofax choice".
messageYesQuestion or decision context shown to the human.
optionsYesOne to three explicit choices to present to the human.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesThe request is unresolved and must not be treated as approval.
mustWaitYesSignals that the caller must keep waiting for a terminal human response.
requestIdYesDurable Nofax request handle.
instructionYesFail-closed next-step instruction for the caller.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description adds that the returned requestId is durable, that the request remains pending, and that the caller must poll rather than assume a terminal answer. It also explicitly forbids deciding for the human, which is useful behavioral guidance. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with no filler. The core behavior and return value come first, followed by a high-value usage warning. The 'IMPORTANT' note earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with a fully documented schema and output schema, the description covers the critical workflow details: send options, receive pending requestId, poll with wait_for_response, and avoid self-serving decisions. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description only reinforces the 'up to three options' constraint and does not add meaning beyond what the schema already documents for message, title, and options.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action: send up to three explicit options to the phone and return a durable pending requestId. This distinguishes it from the sibling tools, especially nofax_notify, nofax_request_approval, and nofax_request_refinement.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides a clear operational protocol: call nofax_wait_for_response and repeat while pending, and do not choose on the human's behalf. It does not formally enumerate when to use this versus the other request-type siblings, but the context is sufficiently clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nofax_request_refinementRequest human refinementA

Ask the human for free-text refinement through the configured Nofax Refine iOS Shortcut. Use this when free-text edits are needed; use nofax_request_approval for Allow/Deny or nofax_request_choice for predefined options. Returns a durable pending requestId; call nofax_wait_for_response and repeat while pending.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleNoOptional refinement prompt title shown to the human; defaults to "Nofax refinement".
messageYesContext or draft the human should refine with free text.

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYesThe request is unresolved and must not be treated as approval.
mustWaitYesSignals that the caller must keep waiting for a terminal human response.
requestIdYesDurable Nofax request handle.
instructionYesFail-closed next-step instruction for the caller.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate mutation (readOnlyHint false) but description adds the asynchronous nature (durable pending requestId, polling via wait_for_response) and external shortcut prerequisite. It doesn't cover cancellation or timeout, but the key behaviors are disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with the primary action front-loaded and no filler; every sentence earns its place by adding purpose, usage, or follow-up guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple 2-parameter tool with an output schema, the description covers purpose, usage, alternatives, and the pending/waiting workflow. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema covers both parameters fully (100% coverage) with clear descriptions, so the description adds little beyond reinforcing that 'message' is the free-text context. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states a specific verb ('Ask') and resource ('the human for free-text refinement') and explicitly names sibling tools with their use cases, making it easy to distinguish from nofax_request_approval and nofax_request_choice.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use ('when free-text edits are needed') and when-not-to-use alternatives (Allow/Deny vs predefined options), plus follow-up instruction to call nofax_wait_for_response and repeat while pending.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

nofax_wait_for_responseWait for Nofax human responseA
Idempotent

Long-poll a durable Nofax request for up to 240 seconds. If the result is pending, you MUST call this tool again with the same requestId. Repeat indefinitely until a terminal response is returned or the user explicitly changes/cancels the goal. Do not continue the guarded action while pending.

ParametersJSON Schema
NameRequiredDescriptionDefault
requestIdYesDurable request handle returned by a nofax_request_* tool.
waitSecondsNoMaximum seconds to long-poll during this call; defaults to 240. A timeout still returns pending, never approval.

Output Schema

ParametersJSON Schema
NameRequiredDescription
textNoHuman free-text refinement when the terminal decision is refine.
statusYesWhether the human request is still pending or has reached a terminal response.
decisionNoTerminal human decision when resolved, such as allow, deny, refine, or an explicit choice value.
mustWaitNoPresent and true while the request remains pending.
requestIdYesDurable Nofax request handle.
instructionYesSafety-preserving instruction describing what the caller may do next.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false, and the description adds critical behavioral details: the long-poll mechanism, the 240-second cap, the guarantee that a timeout still returns pending (never approval), and the requirement to re-invoke. This goes beyond what annotations provide, though it does not disclose every edge case (e.g., behavior on request cancellation), but that is adequately covered by openWorldHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact but includes all essential operational instructions (repeat behavior, do-not-continue) without redundancy. It is front-loaded with the purpose and then explains the required pattern. Slightly more detail could be trimmed, but it is well-structured and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema (which would describe terminal responses) and annotations covering idempotence and non-destructiveness, the description is sufficient for an agent to call this tool correctly. It covers the polling loop, timeout behavior, and when to stop. The only omission is how to handle cancellation, but that is covered by the user-facing directive in the description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already fully described in the input schema. The description adds the 'durable' qualifier for requestId and reiterates the timeout semantics for waitSeconds, but does not significantly enrich the meaning beyond the schema, which is the baseline for high coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('long-poll') and resource ('durable Nofax request'), and clearly distinguishes from sibling tools like nofax_get_request by emphasizing the blocking wait behavior. It is not a tautology and leaves no ambiguity about the tool's core function.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit, actionable usage rules: it instructs the agent to call the tool again with the same requestId when pending, repeat indefinitely until terminal response, and avoid continuing the guarded action while pending. This is precise guidance on when and how to use the tool, including an explicit stop condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.3/5.0

Scored across 7 tools

Disambiguation4/5

The three request tools are clearly differentiated by response type (choice, refinement, approval), and wait/get/list separate polling, inspection, and recovery. Minor overlap exists between get_request and wait_for_response, but the descriptions explicitly state when each is appropriate.

Naming Consistency4/5

All tools share the nofax_ snake_case prefix and mostly follow a nofax_<verb>_<object> pattern. The request_* group is consistent, but list_pending is vaguer than list_pending_requests, and wait_for_response versus get_request mixes slightly different verb styles.

Tool Count5/5

Seven tools fit the narrow human-approval domain well, covering request creation variants, polling, inspection, pending recovery, and one-way notification. There is no redundancy or excessive granularity.

Completeness4/5

The set covers creation of three request types, long-poll waiting, non-blocking status inspection, pending recovery, and one-way notification. A slight gap is the lack of an explicit cancel or expire tool for pending requests, but the core human-in-the-loop workflow is otherwise well covered.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Human-in-the-Loop authorization gateway for AI Agents. Securely pause MCP workflows and route high-risk actions to human approvers via Slack or Email.
    52 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Adds a human-in-the-loop checkpoint to MCP-capable AI coding agents, enabling them to pause and request user feedback before executing actions.
    11 npm
    71
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Provides tools to retrieve the GodPrompt universal system prompt and its components (core skill, protocols, gates, anti-patterns) for AI software development, plus task classification. Designed for progressive context usage.
    7
    1,904 npm
    1
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to request human decisions for subjective or high-stakes choices through MCP tools like ask_human and provision_api_key.
    -