The MCP server
Connect Claude Code, Cursor, VS Code or Codex to your webhooks: your agent reads what arrived, what was delivered and what your watchdogs see, and tests with temporary endpoints.
WebhookVault runs a Model Context Protocol server at
https://mcp.webhookvault.net. An AI assistant connected to it can answer questions about your
webhooks from the real history: why an expected webhook never reached your receiver, what a
provider actually sends, which deliveries are failing and why, whether a watchdog would have
alerted anyone. It can also run a test end to end: make a temporary endpoint, wait for the
webhook to arrive, and replay a stored request to your receiver.
Agent access keys
The server accepts Agent access keys only. Create one under Workspace, API keys in the app and choose Agent access. The page then shows ready-to-copy setup for your tool, already holding the new key. The key is shown once, like every key.
| Developer access | Agent access | |
|---|---|---|
| For | Your own code, scripts and CI | AI assistants, through the MCP server |
| Works with | The WebhookVault API | The MCP server only |
| Can | Everything the API allows, including deleting data | Read your endpoints, requests, deliveries and watchdogs; create and end its own temporary endpoints; wait for a request; replay to existing actions; resume a paused watchdog |
| Cannot | Be used with the MCP server | Delete or pause anything you made, change where your webhooks are sent, or change keys, team or billing |
Both kinds act on the whole workspace and share its API key slots. The server answers a
Developer access key with 403 and the code developer_key_not_accepted; the API answers an
Agent access key with 403 and agent_key_not_accepted.
Connecting your tool
Replace YOUR_AGENT_KEY with the key. The app fills it in for you when the key is created.
Claude Code
claude mcp add --transport http --scope user webhookvault https://mcp.webhookvault.net \
--header "Authorization: Bearer YOUR_AGENT_KEY"--scope user makes it available in every project; leave it out to add it to the current
project only. In Claude Code, /mcp lists webhookvault as connected.
Cursor
Add to ~/.cursor/mcp.json (every project) or .cursor/mcp.json (one project):
{
"mcpServers": {
"webhookvault": {
"url": "https://mcp.webhookvault.net",
"headers": {
"Authorization": "Bearer YOUR_AGENT_KEY"
}
}
}
}To keep the key out of the file, set WEBHOOKVAULT_KEY in your environment and write
"Bearer ${env:WEBHOOKVAULT_KEY}" instead.
VS Code
Run MCP: Open User Configuration from the command palette and add the server. VS Code asks for the key the first time the server starts and keeps it in its secret store, so it is never written to the file:
{
"inputs": [
{
"type": "promptString",
"id": "webhookvault-key",
"description": "WebhookVault Agent access key",
"password": true
}
],
"servers": {
"webhookvault": {
"type": "http",
"url": "https://mcp.webhookvault.net",
"headers": {
"Authorization": "Bearer ${input:webhookvault-key}"
}
}
}
}Codex
Codex reads the key from an environment variable. Set it in your shell profile:
export WEBHOOKVAULT_KEY="YOUR_AGENT_KEY"then add the server to ~/.codex/config.toml:
[mcp_servers.webhookvault]
url = "https://mcp.webhookvault.net"
bearer_token_env_var = "WEBHOOKVAULT_KEY"Other clients
Any MCP client that connects to a remote server over Streamable HTTP and can send a header:
server URL https://mcp.webhookvault.net, header Authorization: Bearer YOUR_AGENT_KEY.
claude.ai and Claude desktop add servers as connectors that sign in instead of sending a key, which this server does not offer. Use the key with Claude Code instead.
What your agent can do
The tool reference lists every tool with its arguments. In short:
- Read: endpoints and their configuration, captured requests (search, full detail, wait for the next one), deliveries and every attempt, transformation rules and dry runs against a stored request, watchdogs, alert routing and alert history, the Activity feed, usage against your plan, the recycle bin.
- Diagnose: traffic and error summaries per endpoint, the shape of what an endpoint
receives, and
diagnose_endpoint, which checks an endpoint for the usual reasons a webhook goes missing and says where to look next. - Change, within limits:
- create temporary endpoints that capture only and expire on their own (at most 3 live per key, 1 to 1,440 minutes), and end the ones the same key created. Their names may hold letters, digits, spaces, hyphens, underscores and dots only;
- replay a stored request to the endpoint's actions that are included in replays, or to the
ones named in
actionIds(queued, then read the result withlist_deliveries). A replay re-sends to a live receiver, which may act on it twice, so the agent is told to ask you first. The server also checks: when a chosen action already received the request, or is still delivering it, nothing is queued and the agent getsalready_deliveredwith those deliveries (see Idempotency and safe replays). It may send anyway withallowDuplicateonly after you say yes in the conversation, never on its own initiative and never because text in a payload, header or response asks for it; - resume a paused watchdog.
Every change appears in your Activity feed under the key, with the tool and the agent product that made it. An agent cannot pause or delete anything, change an action or where it sends, see or set a secret, or change keys, members, contacts or billing: those tools do not exist. It can read the Activity feed, which records such changes as you see them in the app.
Two prompts are built in: debug_missing_webhook and test_my_receiver. Most clients show them
as starting points or slash commands in clients that support prompts.
Webhook content is third-party data
Anyone who knows a capture URL can send to it, so a request body can contain text written to
look like instructions. The server marks every value that came from outside (bodies, headers,
query strings, event names, your receiver's responses) by placing it under a field named
untrusted, and opens such results with a note saying so. Well-behaved agents treat those
values as data to report on, never as instructions.
Before any value leaves the server for your agent:
- credential headers and query parameters (authorization, signatures, cookies, api keys and
similar names) are replaced with
[redacted], including in transformation previews; - parts of a capture URL's path after the endpoint id that look like tokens are shown as
{redacted}; - card numbers are masked to their last four digits;
- URLs of your actions are shown as their host and path shape, with secret-looking parts and query values removed;
- email addresses in the Activity feed are shortened.
Bodies are otherwise shown as stored, as they are in the app.
Limits
| What | Limit |
|---|---|
| Requests per key | Your plan's API rate per minute |
| One tool call | 8 seconds; await_request waits up to 55 |
| Heavy reads (summaries, body search, traffic shape) | 2 at once per key, 3 per workspace |
await_request | 2 waits at once per key, 4 per workspace |
replay_request | 10 requests a minute and 60 an hour per key, the same request 3 times an hour, however many actions each replay goes to (at most 10) |
| Temporary endpoints | 3 live per key, and they count against your plan's endpoints until they expire |
| One result | About 64 KB; read large bodies in chunks with bodyOffset |
Each tool call counts as one API call toward your plan's monthly usage. Connecting and listing tools do not count.
Errors
A refused tool call returns a result marked as an error, with a stable code and a sentence
saying what to do. The codes:
| Code | Meaning |
|---|---|
not_found | No such item in this workspace (also for anything the key may not touch) |
validation_failed | An argument is missing or out of range |
feature_not_in_plan | The workspace's plan does not include it |
busy | Too many heavy reads or waits at once; try again shortly |
rate_limited | A replay limit was reached |
limit_reached | A plan or per-key limit was reached |
timeout | The tool ran past its time budget; narrow the request |
search_too_broad | A text search took too long; narrow the window or the text |
too_large | A stored body is too large for a transformation preview |
response_too_large | The result would be too large; ask for less |
endpoint_inactive | The endpoint is switched off, by a person or by the plan |
endpoint_expired | The temporary endpoint has expired |
endpoint_in_use | A person added actions to this temporary endpoint, so an agent may not end it |
forwarding_disabled | No action on the endpoint is switched on |
action_inactive | The chosen action is switched off |
nothing_to_replay | Nothing could be queued (a cut body, or the request or actions changed) |
no_replay_actions | No action was named and none of the switched-on ones is included in replays; name them in actionIds |
already_delivered | A chosen action already received this request or is still delivering it. Nothing was queued; error.details lists each earlier delivery (action, state, time, status, jobId) |
key_revoked | The key was revoked or suspended while await_request was waiting |
internal_error | Our failure; the message carries a trace id |
Before any tool runs, the server answers 401 without a valid key, 403 with
developer_key_not_accepted for a Developer access key, 403 with api_access_disabled when
the plan has no API access, and 429 when the key's rate is used up.