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.
Inputs: url (required), type, description, environment_id. Returns: endpoint
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.
Inputs: delivery_id (required), include_payload. Returns: delivery, payload, payload_processing
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.
Inputs: endpoint_id (required). Returns: endpoint
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).
Inputs: delivery_id (required). Returns: attempts
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.
Inputs: endpoint_id (required), limit, cursor, status. Returns: deliveries, next_cursor
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.
Returns: endpoints
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.
Returns: environments
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.
Inputs: delivery_id (required). Returns: delivery, payload, payload_processing
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.
Inputs: endpoint_id (required), payload (required), idempotency_key. Returns: delivery_id, idempotency_key, status
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.
Inputs: event_type (required), payload (required). Returns: event_type_id, delivery_ids, status
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.
Inputs: endpoint_id (required), url, description, is_active. Returns: endpoint
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.
Returns: logged_in, workspace, region, token_id, +2 more
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
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
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Official Duck Framework MCP server for AI-assisted development and project scaffolding.
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
- AlicenseBqualityCmaintenanceMCP 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.57309 npm4MIT
- AlicenseBqualityBmaintenanceOfficial MCP server for Shipmail, enabling agents to manage domains, mailboxes, messages, threads, webhooks, and suppressions via natural language.100837 npm1MIT
- AlicenseBqualityDmaintenanceMCP server for the Inngest Cloud REST API to inspect functions, runs, and events in production from Claude Code, Cursor, or any MCP client.825 npm1MIT
- AlicenseNot gradedqualityCmaintenanceA 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