nahook-mcp
OfficialThe nahook-mcp server lets AI assistants manage webhook deliveries, endpoints, and event triggers on the Nahook platform via the Nahook CLI. Here's what you can do:
Check authentication (
whoami): Verify local CLI credentials, workspace, region, token ID, and expiry — reads local config without hitting the network.List/get endpoints (
list_endpoints,get_endpoint): Retrieve all endpoints or fetch full details of a specific one (status, URL, type, last delivery timestamp).Create an endpoint (
create_endpoint): Set up a new webhook endpoint with a destination URL, optional description, type (webhook or Slack), and target environment.Update an endpoint (
update_endpoint): Pause/resume an endpoint, change its URL, or update its description. (Deletion is not supported.)List environments (
list_environments): View all environments (e.g., production, staging) in your workspace.List/get deliveries (
list_deliveries,get_delivery): Page through an endpoint's delivery history with optional status filtering; fetch a single delivery's details, including the original payload body for debugging.List attempts (
list_attempts): See every HTTP attempt for a delivery — response codes, times, and error messages — useful for diagnosing failures.Retry a delivery (
retry_delivery): Re-enqueue a failed or dead-lettered delivery for another attempt.Trigger an event (
trigger_event): Fire a named event type that fans out to all subscribed endpoints simultaneously.Send directly to an endpoint (
send_to_endpoint): Push a webhook payload to one specific endpoint, bypassing event fan-out. Supports idempotency keys for safe retries.
nahook-mcp
The official Model Context Protocol server for Nahook — drive webhook deliveries, endpoints, and event triggers from Claude Desktop, Cursor, Cline, and any other MCP-compatible AI assistant.
The MCP server ships as a subcommand of the
nahookCLI. One binary, one credentials file, one install path.
What it does
Once installed and authenticated, your AI assistant can:
Inspect endpoints, deliveries, and per-attempt logs to debug failed webhooks.
Retry failed or dead-lettered deliveries.
Trigger events and fan them out to every subscribed endpoint.
Send webhooks directly to a single endpoint.
Manage endpoints (create, update, pause, resume) — never delete, by design.
Write operations are tagged with the MCP destructiveHint/readOnlyHint annotations so MCP clients surface a per-call human-approval prompt before anything mutates state.
Related MCP server: shipmail-mcp
Security guardrails
Webhook payloads are third-party data, so the server treats everything that flows back into the model's context as a potential prompt-injection channel:
Untrusted content is fenced. Every producer- or receiver-authored value that reaches the model — webhook payloads (
get_deliverywithinclude_payload), delivery idempotency keys, and receiver error messages (list_attempts) — is wrapped in explicit<<<UNTRUSTED CONTENT ...>>>delimiters with embedded fence markers neutralized, and the server instructions tell the model to treat fenced content as inert data, never as instructions.Payloads are capped. Bodies over 256 KB are truncated (flagged via
payload_truncated) so a hostile producer can't stuff the model's context. Tune the cap withNAHOOK_MCP_PAYLOAD_CAP=<bytes>in the MCP client's environment.No delete tools, by design. Nothing in the tool surface can destroy data.
update_endpointis marked destructive. It overwrites live endpoint config (repointing its URL is the primitive an injection would target), so itsdestructiveHintistrueand clients surface a prominent approval prompt.Write tools rely on human approval. Per the MCP spec, annotations are advisory hints, not access control — the security boundary is the client's per-call approval prompt, which applies to every non-read tool. The additive write tools (
create_endpoint,send_to_endpoint,trigger_event) are annotateddestructiveHint: falseper their spec semantics; keep human-in-the-loop approval enabled in your MCP client and don't blanket-allow them. If you want a hard guarantee of no writes, run the server without an ingestion key (disables sending) and treat management tools as approval-gated.Secrets never reach the model. Endpoint signing secrets and auth tokens are omitted from every tool output;
whoamireturns only the token's public id.Split credentials. Sending (
trigger_event,send_to_endpoint) requires a separate ingestion key — omit it and the server is management/read-only for ingestion.
Client-side measures can't make prompt injection impossible — pair them with your MCP client's tool-approval prompts.
Install
The MCP server is a subcommand of the nahook CLI. Install the CLI, then add it to your AI client.
1. Install the CLI
macOS / Linux (Homebrew):
brew install getnahook/tap/nahookLinux / macOS (install script):
curl -fsSL https://cli.nahook.com/install.sh | shSee getnahook/nahook-cli for other install options.
2. Log in once
nahook loginThis opens your browser, walks you through device-grant authentication, and writes credentials to ~/.nahook/config.toml.
3. Wire the MCP server into your AI client
Claude Desktop & Claude Code CLI:
claude mcp add nahook -- nahook mcp serveCursor — edit ~/.cursor/mcp.json:
{
"mcpServers": {
"nahook": {
"command": "nahook",
"args": ["mcp", "serve"]
}
}
}Cline (VS Code) — Cline → Settings → MCP Servers → add:
{
"nahook": {
"command": "nahook",
"args": ["mcp", "serve"]
}
}Zed — add to settings.json:
{
"assistant": {
"mcp_servers": {
"nahook": {
"command": "nahook",
"args": ["mcp", "serve"]
}
}
}
}Other MCP-compatible clients (Continue, Windsurf, Goose, …) follow the same command + args shape.
Tools
Tool | What it does |
| Local config sanity check — workspace, region, token id, expiry. |
| List every endpoint in the current workspace. |
| Fetch one endpoint by |
| Create a new endpoint. Defaults to the workspace's default environment; also accepts slugs like |
| Partial patch — pause/resume, change URL, update description. |
| List every environment in the workspace. |
| Page through an endpoint's deliveries, newest-first. |
| Fetch one delivery by |
| List every attempt against a delivery (useful for debugging failures). |
| Re-enqueue a failed or dead-lettered delivery. |
| Fire an event by type — the backend fans it out to every subscriber. |
| Send a webhook directly to one endpoint. |
Authentication model
The MCP server uses two separate credentials:
CLI login token (
nhc_…) — written bynahook login. Powers read tools and management operations on endpoints / deliveries / environments.Ingestion key (
nhk_…) — the same key your SDKs use. Powerstrigger_eventandsend_to_endpoint. Set it viaNAHOOK_INGESTION_KEY=nhk_...in the MCP client's environment, or addingestion_key = "nhk_..."to~/.nahook/config.toml. The server fails loudly if a write tool is called without one configured.
Permissions are evaluated per request against your workspace role — the MCP token has exactly the permissions you have in the dashboard, nothing more.
Where the code lives
The MCP server implementation is part of the nahook CLI source tree. This repo exists as a discoverability surface — README, MCP directory entries, and packaging metadata. There is no separate codebase to maintain.
If you want to file a bug, request a tool, or contribute: please open the issue at getnahook/nahook-cli.
License
MIT — same as the CLI.
Available Tools
12 toolscreate_endpointA
Create a new endpoint in the current workspace. If environment_id is omitted, the workspace's default environment is used. environment_id accepts either an env_xxx id or a slug like "production"/"staging". Returns the created endpoint with its newly-generated public id. Example: user says "create a webhook for https://example.com/hook" → call with url="https://example.com/hook". If the user explicitly names an environment ("in staging"), pass it; otherwise omit and the default is used. For the full endpoint schema, see resource nahook://schemas/endpoint.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | destination URL the endpoint POSTs webhooks to | |
| type | No | webhook (default) or slack | |
| description | No | optional human-readable description | |
| environment_id | No | environment public id (env_xxx) or slug. If omitted, the workspace's default environment is used. Call list_environments to discover available environments. |
Output Schema
| Name | Required | Description |
|---|---|---|
| endpoint | Yes | the endpoint |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate non-destructive and open-world behavior. The description adds that the tool returns the created endpoint with its new public id, and explains the default environment fallback. This provides useful context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, moderately-sized paragraph that front-loads the core purpose. It is concise but could be more structured (e.g., bullet points). Still, every sentence adds value without excessive redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity and the presence of a detailed output schema reference, the description covers key aspects: creation behavior, environment handling, and an example. It is complete enough for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds value by clarifying that environment_id accepts slugs (e.g., 'production') and that omission uses the default. It also provides an example mapping user input to parameters, which aids correct invocation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Create a new endpoint') and the resource ('in the current workspace'). It specifies the verb and resource, and distinguishes from siblings like list_endpoints and update_endpoint by focusing on creation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear guidance on when to include vs omit environment_id: if the user explicitly names an environment, pass it; otherwise omit. It also gives an example mapping user request to parameters. However, it does not explicitly exclude usage for non-creation tasks (e.g., listing or updating).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_deliveryARead-onlyIdempotent
Fetch a single delivery by its public id (del_xxx). Returns status, attempt count, timestamps. Pass include_payload=true to also fetch the original webhook body — critical for debugging why a delivery failed. Adds one extra HTTP round-trip. Example: "why did del_xyz fail?" → call with delivery_id="del_xyz", include_payload=true to see the body the producer sent, then follow up with list_attempts to see what each HTTP attempt returned. For the full delivery schema and status value meanings, see resources nahook://schemas/delivery and nahook://schemas/delivery-statuses.
| Name | Required | Description | Default |
|---|---|---|---|
| delivery_id | Yes | the delivery's public id (del_xxx) | |
| include_payload | No | when true, also fetch the original webhook body the producer sent. Adds one HTTP round-trip. |
Output Schema
| Name | Required | Description |
|---|---|---|
| delivery | Yes | the delivery |
| payload | No | the original webhook body, present only when include_payload was true. Shape matches whatever the producer sent (object, array, etc.) |
| payload_processing | No | true when the backend says the payload is still being uploaded to storage. Retry shortly. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, destructiveHint, idempotentHint, and openWorldHint. The description adds the performance impact of include_payload (extra HTTP round-trip) and returns useful context, exceeding what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences: first states purpose, second explains optional parameter, third gives concrete example. No fluff, front-loaded, and well-organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given high schema coverage, presence of output schema, and rich annotations, the description is fully adequate. It covers purpose, key parameter usage, and references external schemas for completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds meaningful context: include_payload is for debugging and adds a round-trip, delivery_id is the public ID format. Provides more than just schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool fetches a single delivery by its public ID, listing the returned fields (status, attempt count, timestamps). It distinguishes from siblings like list_deliveries and list_attempts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance: when to use include_payload (critical for debugging failures), an example use case, and suggests following up with list_attempts for further debugging. No misleading instructions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_endpointARead-onlyIdempotent
Fetch a single endpoint by its public id (ep_xxx). Example: user says "show me ep_abc" or "details of ep_abc". If the user references an endpoint without naming a specific ep_xxx id, call list_endpoints first to discover ids. For the full endpoint schema, see resource nahook://schemas/endpoint.
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint_id | Yes | the endpoint's public id (ep_xxx) |
Output Schema
| Name | Required | Description |
|---|---|---|
| endpoint | Yes | the endpoint |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover safety (readOnly, idempotent). Description adds context about the id pattern and references a full schema resource, but no additional behavioral traits beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: first states purpose, second gives usage guidance and schema reference. No redundant text.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given output schema exists externally, description covers purpose, parameter format, and when to use alternative. Complete for a simple get-by-ID tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema already describes endpoint_id as 'the endpoint's public id (ep_xxx)'. Description adds concrete example ('ep_abc') and confirms the pattern, providing slight extra value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'Fetch a single endpoint by its public id (ep_xxx)' with example phrasing. Distinguishes from sibling list_endpoints by specifying singular retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises to call list_endpoints first when no specific ep_xxx id is provided, providing clear when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_attemptsARead-onlyIdempotent
List every recorded attempt for a delivery, oldest first. Useful for debugging why a delivery failed. Example: "why did del_xyz fail?" → pair this with get_delivery (include_payload=true). get_delivery shows what the producer sent; list_attempts shows what each receiver attempt returned. Together they tell you whether the failure was producer-side (bad payload) or receiver-side (5xx, timeout).
| Name | Required | Description | Default |
|---|---|---|---|
| delivery_id | Yes | the delivery's public id (del_xxx) |
Output Schema
| Name | Required | Description |
|---|---|---|
| attempts | Yes | every recorded attempt for this delivery, oldest first |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, idempotentHint=true. The description adds behavioral context by specifying the ordering (oldest first) and the type of data returned (what each receiver attempt returned). No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is four sentences, front-loading the core purpose, then adding usage context, example, and deeper explanation. Every sentence adds value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple tool (one parameter, read-only, output schema exists), the description is complete. It explains when to use, how to combine with another tool, and what the response reveals about the failure cause.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage with a clear description for delivery_id. The description does not add technical parameter details but provides usage context (pairing with get_delivery). Baseline is 3 due to high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists recorded attempts for a delivery, ordered oldest first. It distinguishes itself from siblings by explicitly pairing with get_delivery for debugging, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states the tool is useful for debugging delivery failures and provides a concrete example pairing with get_delivery. It explains how to interpret results (producer-side vs receiver-side), giving clear when-to-use context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_deliveriesARead-onlyIdempotent
List deliveries for an endpoint, newest-first. Paginate by passing next_cursor back as cursor on subsequent calls. Returns up to 200 per page (default 50). Example: "show me failed deliveries for ep_acme" → endpoint_id="ep_acme", status="failed". Requires an endpoint_id — if the user names a specific delivery (del_xxx) instead, use get_delivery. Valid status filters: pending, delivering, delivered, failed, scheduled_retry, dead_letter. For the full delivery schema and status value meanings, see resources nahook://schemas/delivery and nahook://schemas/delivery-statuses.
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint_id | Yes | endpoint public id (ep_xxx) whose deliveries to list | |
| limit | No | page size, 1-200 (default 50) | |
| cursor | No | opaque cursor from a previous response's next_cursor; omit for first page | |
| status | No | filter by status: pending, delivering, delivered, failed, scheduled_retry, or dead_letter |
Output Schema
| Name | Required | Description |
|---|---|---|
| deliveries | Yes | the page of deliveries, newest first |
| next_cursor | No | pass back as cursor to get the next page; absent on the last page |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true. Description adds pagination behavior (cursor-based, up to 200 per page, default 50), ordering (newest-first), and references to external schemas for full details. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Efficiently structured in a few sentences: core purpose, pagination, example, sibling distinction, valid filters, and references. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers all necessary aspects for agent usage: purpose, when to use, parameters, behavior, and references to output schema via external resources. Output schema exists, so return values need not be explained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but description adds value beyond schema: example for endpoint_id and status, cursor usage explanation, limit default and range, and emphasis on required endpoint_id.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'List deliveries for an endpoint, newest-first.' Uses specific verb (list) and resource (deliveries for an endpoint). Distinguishes from sibling get_delivery by noting when to use that instead.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use this tool vs get_delivery: 'if the user names a specific delivery (del_xxx) instead, use get_delivery.' Provides example query mapping and valid status filters. Also explains pagination usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_endpointsARead-onlyIdempotent
List every endpoint in the current workspace. Returns id, type, url, status (active/paused), is_active, created_at, and last_delivery_at for each. Example: user says "show me my webhooks" or "list my endpoints" → call with no args. This is the natural first call whenever the user names operations on an endpoint without giving a specific ep_xxx id — use the returned ids in follow-up calls. For the full endpoint schema, see resource nahook://schemas/endpoint.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| endpoints | Yes | the workspace's endpoints, newest first |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint, destructiveHint, idempotentHint, openWorldHint. The description adds behavioral details: returns all endpoints in workspace with given fields, and an example user query. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences: purpose, example, and usage guidance. Every sentence adds unique value. Front-loaded with core functionality.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters, comprehensive annotations, and mention of output schema, the description is fully adequate. It covers return fields, usage context, and example interaction.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist, and schema description coverage is 100%. The description correctly implies no arguments needed via example 'call with no args'. Baseline 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'List every endpoint in the current workspace' with specific return fields (id, type, url, status, etc.). It distinguishes itself from sibling tools like get_endpoint by being the list variant.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit usage guidance: 'natural first call whenever the user names operations on an endpoint without giving a specific ep_xxx id'. It tells the agent to use returned ids in follow-up calls, implicitly contrasting with get_endpoint for specific ids.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_environmentsARead-onlyIdempotent
List every environment in the current workspace. Use the returned id (env_xxx) or slug as environment_id when creating endpoints. Example: user says "what environments do I have". Most workspaces have a single default environment — only call this when the user mentions environments explicitly or you need to disambiguate where a new endpoint should land.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| environments | Yes | every environment in the workspace |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, destructiveHint, idempotentHint. Description adds behavioral context on using returned id/slug as environment_id and typical deployment patterns.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences, front-loaded with purpose. Each sentence adds essential information: what it does, how output is used, when to call.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Fully adequate for a zero-parameter tool with output schema and comprehensive annotations. Covers purpose, usage guidance, and output usage without redundancy.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters. Baseline 4 applies. Description adds no parameter info but mentions output format (id, slug) which is handled by output schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'List every environment in the current workspace' with specific verb and resource. Distinguishes from siblings like list_endpoints by focusing on environments.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises when to call: only when environments mentioned or for disambiguation. Also notes most workspaces have single default environment, guiding against unnecessary calls.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
retry_deliveryA
Re-enqueue a failed or dead-lettered delivery. The backend returns 409 if the delivery is in any other state. Returns the updated delivery row. Example: "retry del_xyz" → call with delivery_id="del_xyz". Only works when the delivery's status is failed or dead_letter — calling on delivered, pending, delivering, or scheduled_retry returns 409. Check status with get_delivery first if uncertain. For which statuses accept retry and which don't, see resource nahook://schemas/delivery-statuses.
| Name | Required | Description | Default |
|---|---|---|---|
| delivery_id | Yes | the delivery's public id (del_xxx) |
Output Schema
| Name | Required | Description |
|---|---|---|
| delivery | Yes | the delivery |
| payload | No | the original webhook body, present only when include_payload was true. Shape matches whatever the producer sent (object, array, etc.) |
| payload_processing | No | true when the backend says the payload is still being uploaded to storage. Retry shortly. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate non-destructive (destructiveHint: false). The description adds the critical behavior of returning 409 on invalid states and the return format (updated delivery row). It also references a schema resource for statuses.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four well-structured sentences: purpose, condition/error, recommendation, example. No redundancy. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a single parameter, clear annotations, and an output schema present, the description covers all necessary context: what, when, when not, error handling, and example. No gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds concrete meaning by specifying the delivery's public id format (del_xyz) and gives an example usage, going beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Re-enqueue a failed or dead-lettered delivery,' specifying the verb and resource. However, it does not explicitly differentiate from sibling tools like get_delivery or send_to_endpoint, though the unique behavior (re-enqueue) is implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use (only on failed or dead_letter status), when not to use (other statuses return 409), and recommends checking status first with get_delivery. Provides an example invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_to_endpointAIdempotent
Send a webhook directly to one endpoint (skips event-type fan-out). Pass idempotency_key for safe retries — duplicate keys return the original delivery id. Example: "send a test webhook to ep_abc with payload {...}" → endpoint_id="ep_abc", payload={...}. Use this when the user names a specific endpoint to target; use trigger_event when the user names an event type that should fan out to all subscribers.
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint_id | Yes | target endpoint public id (ep_xxx) | |
| payload | Yes | the webhook body as a JSON object | |
| idempotency_key | No | optional dedupe key — same key + same endpoint returns the original deliveryId |
Output Schema
| Name | Required | Description |
|---|---|---|
| delivery_id | Yes | public id of the created delivery (del_xxx) |
| idempotency_key | Yes | the key the backend recorded (caller-provided or server-generated) |
| status | Yes | backend acceptance status (typically 'accepted') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare idempotentHint true and destructiveHint false. The description adds concrete behavior: duplicate idempotency keys return original delivery id, and it skips fan-out. Could mention error handling for missing endpoints, but output schema likely covers that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences plus an example and usage guidance. Front-loaded with core purpose, no wasted words, and efficiently uses example to demonstrate parameter usage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (3 params, output schema exists), the description is complete: purpose, usage distinction, idempotency behavior, and example. The output schema covers return details, so no need to describe them.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers all parameters with descriptions. The description adds value by explaining idempotency_key behavior (duplicate key returns original delivery id) and providing an example usage that clarifies how to pass endpoint_id and payload.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool sends a webhook directly to one endpoint, skipping event-type fan-out. Distinguishes from sibling trigger_event by specifying direct endpoint targeting vs event fan-out.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use this tool (user names a specific endpoint) and when to use trigger_event (event type fan-out). Also advises using idempotency_key for safe retries.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
trigger_eventA
Fire an event by event type — the backend fans it out to every endpoint subscribed to that type. Returns one delivery id per subscriber (empty if no subscribers). Use send_to_endpoint when you want to target one specific endpoint instead. Example: "fire an order.created event with order_id=ord_123" → event_type="order.created", payload={"order_id": "ord_123"}. An empty delivery_ids array means no endpoint subscribes to that event type — inspect subscriptions with list_endpoints if the user expected a non-empty result.
| Name | Required | Description | Default |
|---|---|---|---|
| event_type | Yes | the event type to fan out (e.g. order.created) | |
| payload | Yes | the event body as a JSON object — passed verbatim to every subscribed endpoint |
Output Schema
| Name | Required | Description |
|---|---|---|
| event_type_id | Yes | echoes the event type that was triggered |
| delivery_ids | Yes | one delivery id per subscribed endpoint. Empty means the event has no subscribers. |
| status | Yes | backend acceptance status (typically 'accepted') |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=false and openWorldHint=true. The description adds context about fan-out behavior, return values (delivery IDs per subscriber), and implications of an empty result, but could further detail side effects or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise yet comprehensive, with two clear sentences and an example, all front-loaded with the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (2 required parameters, nested object, no enums, and existing output schema), the description fully covers usage, behavior, parameter semantics, and edge cases (empty result).
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Both parameters have schema descriptions (100% coverage). The description adds value with concrete examples (e.g., event_type='order.created', payload={'order_id':'ord_123'}) and explains that payload is passed verbatim, which is not in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('fire') and resource ('event'), and explicitly distinguishes from the sibling tool 'send_to_endpoint' by stating the fan-out behavior.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly provides when to use this tool ('fire an event by event type') and when not to, recommending 'send_to_endpoint' for targeting a specific endpoint. It also advises using 'list_endpoints' if the result is empty.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_endpointAIdempotent
Patch an existing endpoint. Only fields explicitly set in the input are sent to the API; omit a field to leave it unchanged. Common uses: pause/resume via is_active, redirect via url. Example: "pause ep_abc" / "disable ep_abc" → endpoint_id="ep_abc", is_active=false. "resume ep_abc" / "enable ep_abc" → is_active=true. "point ep_abc at https://new.com" → endpoint_id="ep_abc", url="https://new.com". PATCH semantics matter: passing url="" would clear the URL, so don't include fields the user didn't ask to change. For the full endpoint schema, see resource nahook://schemas/endpoint.
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint_id | Yes | the endpoint's public id (ep_xxx) | |
| url | No | new destination URL | |
| description | No | new description text | |
| is_active | No | set false to pause the endpoint, true to resume |
Output Schema
| Name | Required | Description |
|---|---|---|
| endpoint | Yes | the endpoint |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (destructiveHint=false, idempotentHint=true, openWorldHint=true), the description explains the partial update behavior, which is critical for correct usage. It adds context about how the API handles omitted fields, aligning with idempotentHint=true. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: purpose statement, semantics explanation, examples, and warning. Every sentence adds value. No repetition or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of PATCH semantics, the description fully covers what an agent needs to know: how partial updates work, common use cases, and potential pitfalls. References a schema resource for more details. The presence of an output schema does not reduce completeness need.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% (baseline 3). The description adds semantic value by tying parameters to use cases (is_active with pause/resume, url with redirect) and warns about clearing with empty string. This goes beyond the schema's descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with 'Patch an existing endpoint', clearly stating the verb and resource. It distinguishes from siblings like create_endpoint and get_endpoint, and provides common use cases (pause/resume, redirect).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly explains PATCH semantics: only fields set in input are sent, omit to leave unchanged. It gives concrete examples for pause/resume and redirect, and warns against including fields the user didn't ask to change (e.g., passing url='' would clear it). This provides clear when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
whoamiARead-onlyIdempotent
Return the workspace, region, and token id the local Nahook CLI is logged into. Use this as a first call to confirm credentials are in place. Reads ~/.nahook/config.toml; never hits the network. Example: "am I logged in?", "what workspace am I in?". Also worth calling defensively before other tools if you suspect credentials might be missing — it tells you whether nahook login has run.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| logged_in | Yes | true when a CLI token is present in the local config |
| workspace | No | the workspace public id the token is scoped to |
| region | No | the region the token routes to (us, eu, or ap) |
| token_id | No | the token's public id (clitok_xxx), surfaced in the dashboard's active tokens list |
| machine | No | the machine name recorded at login time |
| expires_at | No | RFC3339 timestamp when the token expires |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true, destructiveHint=false, idempotentHint=true. The description adds that it reads ~/.nahook/config.toml and never hits the network, which is valuable behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each with a clear purpose: returns data, usage as first call, defensive use. It is front-loaded and every sentence adds value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters and an output schema exists, the description fully covers what the tool does, when to use it, and its behavioral characteristics (local file read, no network). It is complete for agent understanding.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has no parameters, so the description does not need to add parameter info. Schema coverage is 100%, and the description implicitly conveys the lack of inputs. Baseline for zero parameters is 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns workspace, region, and token id, which is a specific verb+resource. It is distinct from sibling tools like create_endpoint or list_deliveries, which focus on different resources.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly advises using this as a first call to confirm credentials and defensively before other tools if credentials are suspected missing. It does not mention alternatives but provides strong context for when to use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
12 tool updates
v1.0.0- First observed
create_endpoint - First observed
get_delivery - First observed
get_endpoint - First observed
list_attempts - First observed
list_deliveries - First observed
list_endpoints - First observed
list_environments - First observed
retry_delivery - First observed
send_to_endpoint - First observed
trigger_event - First observed
update_endpoint - First observed
whoami
TDQS
Scored across 12 tools
Each tool targets a distinct resource and action. There is no ambiguity between tools like create_endpoint vs update_endpoint, or list_deliveries vs list_attempts. send_to_endpoint and trigger_event are clearly differentiated by direct vs fan-out behavior.
Tools consistently use verb_noun naming in snake_case. The only outlier is 'whoami', which follows a common convention but deviates from the pattern. Overall, the naming is predictable and readable.
12 tools provide a well-scoped set for managing webhook endpoints, deliveries, and events. The count is neither too small nor too large, covering essential operations without being overwhelming.
The tool set is missing critical operations such as deleting an endpoint and managing subscriptions (which are implied by trigger_event). There is no way to list, add, or remove event subscriptions, which would be necessary for a complete webhook management system.
Maintenance
Related MCP Connectors
- mcpOAuthnet.todoist
Official Todoist MCP server for AI assistants to manage tasks, projects, and workflows.
Remote MCP server to read and manage your Atako AI agents, messages, files, and integrations.
Official MCP server for subfeed.app — the cloud for agents. 15+ tools for AI agents to register, build, and deploy other agents. Zero human required. Start here: subfeed.app/skill.md
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
Related MCP Servers
- AlicenseBqualityAmaintenanceMCP Server for full Easypanel control via Claude Code, Cursor, and Claude Desktop. Provides 37 tools for deploy, logs, env vars, domains, databases, and monitoring with built-in safety guards.5716 npm3MIT
- AlicenseBqualityAmaintenanceOfficial MCP server for Shipmail, enabling agents to manage domains, mailboxes, messages, threads, webhooks, and suppressions via natural language.100259 npm1MIT
- AlicenseBqualityCmaintenanceMCP server for the Inngest Cloud REST API to inspect functions, runs, and events in production from Claude Code, Cursor, or any MCP client.817 npm1MIT
- AlicenseNot gradedqualityAmaintenanceA webhook management and delivery service with MCP tools for endpoints, deliveries, relay, and incoming webhooks, enabling autonomous agents to send, track, and relay webhooks.MIT