How to Give Your AI Coding Assistant Access to Your Webhooks via MCP
You're deep in a debugging session. Your AI coding assistant is helping you trace a payment flow bug. It asks what the last Stripe webhook payload looked like. So you leave your editor, open the Hooklistener dashboard, find the endpoint, locate the request, copy the JSON body, and paste it back into your conversation.
The whole thing takes 30 seconds, but it breaks your focus completely. And you do it dozens of times a day.
There's a better way. The Model Context Protocol (MCP) lets your coding assistant talk directly to Hooklistener's MCP server. No tab-switching. No copy-pasting. Just ask "show me the last webhook on my Stripe endpoint" and get the answer inline. This guide shows you how to set it up in under two minutes.
What we cover:Connecting Hooklistener's MCP server to Claude Code, Cursor, and OpenAI Codex CLI. What you can do with it, and the gotchas we ran into while building it. We won't cover building your own MCP server from scratch—just using ours.
What is MCP, and Why Should You Care?
Think of MCP as a USB-C port for AI assistants. Before USB-C, every device had its own charger. Before MCP, every AI tool needed custom integrations to access external data.
MCP standardizes how AI assistants discover and use external tools. Here's the mental model:
- MCP Server = a service that exposes "tools" (functions the AI can call). Hooklistener runs one at
app.hooklistener.com/api/mcp. - MCP Client = your AI assistant (Claude Code, Cursor, etc.). It connects to the server, discovers the tools, and calls them when relevant.
- Tools = specific actions like "list endpoints", "get a captured request", or "create an uptime monitor". The AI decides when to call them based on your conversation.
The AI doesn't just fetch raw data—it understands the tool schemas, picks the right one, formats the arguments, and presents the result in context. You ask a question in plain English; it handles the plumbing.
Prerequisites
You need exactly one thing: a Hooklistener account. That's it.
The MCP server uses OAuth 2.0 for authentication. When you add the server, your client opens a browser, you sign in to Hooklistener, and you're connected. Under the hood it's the full modern OAuth stack—server discovery, dynamic client registration, and PKCE—but you never see any of that. No tokens to copy, no secrets to store in config files.
If your MCP client doesn't support OAuth, there's a legacy fallback: an API key generated from Organization Settings > API Keys (keys start with hklst_). API-key auth is deprecated—tool responses include a deprecation notice nudging you to reconnect with OAuth—but it still works.
If you do use an API key:Never commit it to version control. Each developer should use their own key, stored in an environment variable. Better yet, use OAuth and skip the problem entirely.
Setup: Claude Code
Claude Code has first-class MCP support. One command, and you're connected.
# OAuth 2.0 (recommended) — signs in via browser automatically
claude mcp add --transport http hooklistener https://app.hooklistener.com/api/mcpRun /mcp, pick "hooklistener", and choose authenticate. Your browser opens, you sign in, and the connection is live. This registers the server for the current project. Use --scope user to make it available across all your projects, or --scope project to write it to .mcp.json so your whole team gets it—each teammate signs in with their own account, so there's nothing secret in the file.
Verify it's working by typing /mcp in Claude Code. You should see "hooklistener" listed with 67 tools.
Legacy: API key
If you can't use the browser flow, pass an API key as a bearer header instead. This is deprecated—tool responses will include a notice asking you to reconnect with OAuth—but it works:
claude mcp add --transport http hooklistener \
https://app.hooklistener.com/api/mcp \
--header "Authorization: Bearer hklst_your_api_key_here"Manual alternative
If you prefer editing config files directly, add this to .mcp.json (project-level) or ~/.claude.json (user scope). No headers needed—Claude Code handles the OAuth sign-in when you first connect:
{
"mcpServers": {
"hooklistener": {
"type": "http",
"url": "https://app.hooklistener.com/api/mcp"
}
}
}Pitfall:If you add the server while Claude Code is running, you need to restart it. The MCP connection is established at startup. A common frustration is editing the config and wondering why nothing changed.
Setup: Cursor
Cursor supports OAuth for streamable HTTP servers, so the config is just a URL. Add this to .cursor/mcp.json in your project root:
{
"mcpServers": {
"hooklistener": {
"url": "https://app.hooklistener.com/api/mcp"
}
}
}Restart Cursor or reload MCP servers from the settings panel, then complete the browser sign-in when prompted. The tools will appear in Cursor's agent mode. If you need the legacy API-key route instead, add a "headers" object with "Authorization": "Bearer hklst_your_api_key_here".
Setup: OpenAI Codex
Codex supports OAuth for streamable HTTP servers. Add the server, then sign in with your browser:
codex mcp add hooklistener \
--url https://app.hooklistener.com/api/mcp \
--oauth-resource https://app.hooklistener.com/api/mcp
codex mcp login hooklistener --scopes full_accessUse --scopes read_only if the agent should only inspect traffic: it can search, wait, diff, and diagnose, but not create, delete, or replay anything. Or add the server manually to ~/.codex/config.toml and run the same login command:
[mcp_servers.hooklistener]
url = "https://app.hooklistener.com/api/mcp"
oauth_resource = "https://app.hooklistener.com/api/mcp"If you can't use OAuth, keep an API key in an environment variable and reference it with bearer_token_env_var = "HOOKLISTENER_API_KEY" instead of oauth_resource.
What You Can Actually Do With It
Once connected, your AI assistant has access to 67 tools in 7 toolsets. A new workspace lists 26 of them (the webhook tools plus each product's create tool); the rest appear after you start using that product and reconnect. The server launched with 8 tools and has grown with every release (see the changelog). You don't call these tools directly—the assistant picks the right one based on what you ask.
We won't describe all 67 here. Instead, here are the tools worth knowing about, then a map of the full surface.
The standouts
wait_for_request — waits until a webhook actually arrives on an endpoint, optionally filtered by event type, path, headers, or body (up to 60 seconds, or a timeout of 0 to just check for existing requests). By default it returns a durable task receipt right away and the assistant follows the task (hooklistener://tasks/{task_id}) until it succeeds or times out; the receipt survives across turns and client timeouts. Pass blocking: true to hold the call open until the request lands instead. This is the tool that turns your assistant from a viewer into a tester: it can trigger an action in your app, wait for the resulting webhook, and verify the payload—a real end-to-end test, driven by the agent.
wait_for_email — the same wait pattern for email (task receipt by default, blocking: true optional). Pair it with create_inbox and your assistant can test an entire signup flow: create an inbox, register a user with the generated address, and wait for the confirmation email to land.
diagnose_request — analyzes a captured request's response status, body, mock rules, and every forwarding attempt, then returns a health verdict with findings and suggestions. "Why did this webhook fail?" gets a structured answer instead of a guess.
compare_requests — AI-assisted comparison of 2–5 captured requests on the same endpoint. Useful for "this one worked, that one didn't—what changed?" Requires a paid plan.
verify_request_signature and replay_request — check a Stripe, GitHub, or Slack signature against your stored secret, then replay the webhook to localhost with an edited body, re-signed so your handler accepts it.
save_request_case and run_endpoint_cases — turn real captured webhooks into a replay suite and rerun it against localhost or staging after every fix, with a pass/fail report per case.
create_realtime_endpoint and wait_for_realtime_message — a hosted WebSocket, Socket.IO, MQTT, or SSE endpoint for your client, plus a blocking wait on the message you expect it to send.
The full map
| Category | What's in it |
|---|---|
| Webhooks | create_endpoint, wait_for_request, list_requests, verify_request_signature, replay_request, diagnose_request, list_endpoints, get_endpoint, update_endpoint, delete_endpoint, get_request, delete_request, investigate_request_retries, validate_request, diff_requests, compare_requests, list_request_forwards, list_secrets, create_secret, delete_secret, cancel_task |
| Rules, threads and alerts | create_response_rule, test_response_rules, set_thread_rule, list_endpoint_anomalies, update_response_rule, delete_response_rule, list_request_threads, list_thread_requests, delete_thread_rule, set_endpoint_alerts |
| Replay cases and suites | save_request_case, run_endpoint_cases, wait_for_case_run, list_endpoint_cases, update_request_case, delete_request_case, replay_request_case, list_endpoint_case_suites, create_endpoint_case_suite, update_case_suite, delete_case_suite, add_case_to_suite, remove_case_from_suite, list_endpoint_case_runs, get_case_run |
| Real-time: WebSocket, Socket.IO, MQTT, SSE | create_realtime_endpoint, wait_for_realtime_message, send_realtime_message, manage_realtime_rules, list_realtime_endpoints, list_realtime_sessions, get_realtime_messages |
| Email inboxes | create_inbox, wait_for_email, get_email, list_inboxes, list_emails |
| Uptime monitors | create_monitor, get_monitor_status, list_monitors, update_monitor, delete_monitor |
| Localhost tunnels | plan_tunnel_action, replay_tunnel_capture, read_tunnel_capture_sensitive, add_tunnel_case_capture |
The full reference with every parameter schema lives in the MCP tools documentation.
Real Workflow Examples
Here's where it clicks. These aren't hypothetical—they're the workflows that made us build this in the first place.
"Create a debug endpoint for Stripe and give me the URL"
The assistant calls create_endpoint with the name "Stripe Webhooks" and hands you the public URL. You paste it into Stripe's dashboard. No context switch, no clicking around. Ten seconds.
"Show me the last webhook that came in on my Stripe endpoint"
It calls list_endpoints to find your Stripe endpoint, then list_requests to grab the most recent capture, then get_request to fetch the full payload. You see the headers, body, and metadata right in your conversation. If the body contains a checkout.session.completed event, the assistant can immediately help you write the handler.
"Is my production API healthy? What's the uptime this month?"
The assistant calls get_monitor_status and reports back: "99.95% uptime over the last 30 days, average response time 125ms. The last check was 2 minutes ago, status 200." If something looks off, you're already in the right context to investigate.
"Set up a health check for our new staging environment"
It calls create_monitor with the URL, a 5-minute check interval, and a 30-second timeout. Done. You didn't leave your terminal.
"Trigger a test checkout and verify the webhook fires"
The assistant runs your test script, then calls wait_for_request on the endpoint, filtered to the checkout event. It gets a task receipt back and follows the task until the webhook lands (or the wait times out after up to 60 seconds) — no polling the request list, no sleeping. When it arrives, the assistant inspects the payload and confirms the event type and fields match what your handler expects. That's an end-to-end webhook test with zero manual steps.
"Why did the last webhook on this endpoint fail?"
It calls diagnose_request and gets back a health verdict with concrete findings: a 500 response, an invalid JSON body, a forward to localhost that timed out. Instead of you eyeballing logs, the assistant reads the diagnosis and proposes the fix.
How It Works Under the Hood
You don't need to understand the protocol to use it, but knowing the basics helps when things go wrong.
Hooklistener's MCP server uses the Streamable HTTP transport. Your AI assistant communicates with it via JSON-RPC 2.0 over plain HTTP POST requests to a single endpoint: /api/mcp.
The flow looks like this:
- Your assistant sends an
initializerequest with its client info - The server responds with its capabilities (what tools it supports)
- The assistant calls
tools/listto discover available tools and their parameter schemas - When you ask a question, the assistant picks the right tool and calls
tools/callwith the arguments - The server validates your credentials, runs the query, and returns the result
Every request after initialize includes an mcp-session-id header to maintain session context. Authentication works one of two ways. With OAuth (the default), you sign in once via browser and your client attaches a short-lived access token to every request—discovery, dynamic client registration, and PKCE all happen automatically. With a legacy API key, the key rides along as an Authorization: Bearer header on every call instead.
Testing It Manually (For the Curious)
If you want to see what your AI assistant is doing behind the scenes, you can hit the MCP server directly with curl. This is also useful for debugging connection issues. These examples use an API key because curl can't do a browser OAuth dance—it's the one place the legacy auth still earns its keep.
Initialize a session
curl -X POST https://app.hooklistener.com/api/mcp \
-H "Authorization: Bearer hklst_your_key" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": {
"name": "my-test",
"version": "1.0"
}
}
}'Grab the mcp-session-id from the response headers, then list tools:
List available tools
curl -X POST https://app.hooklistener.com/api/mcp \
-H "Authorization: Bearer hklst_your_key" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "mcp-session-id: SESSION_ID_FROM_ABOVE" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}'You'll see all 67 tools with their names, descriptions, and parameter schemas. This is exactly what your AI assistant sees when it connects.
Troubleshooting
"Authentication required" error
On OAuth: your access token has probably expired and the client failed to refresh it. Re-run the sign-in from your client—in Claude Code, type /mcp, select hooklistener, and choose authenticate. The browser flow takes a few seconds.
On a legacy API key: the key is missing or invalid. Double-check that it starts with hklst_ and that the Authorization header is formatted as Bearer hklst_... with a space after "Bearer". Generate a fresh key from Organization Settings if needed—or take the hint and switch to OAuth.
Server not showing up in your assistant
Most MCP clients only load servers at startup. Restart your editor or CLI after editing the config. In Claude Code, run /mcp to check the connection status. Verify your config file is valid JSON—a trailing comma will silently break it.
Tools appear but calls fail
This usually means your plan doesn't include the feature you're trying to use. Debug endpoints and request inspection are available on all plans. The free plan includes 1 email inbox, 1 uptime monitor, and 3 saved replay cases; stored signing secrets, Slack or webhook alerts, and AI request comparison (compare_requests) need a paid plan. If you're hitting a quota (e.g., max endpoints or inboxes), the error message will tell you exactly that.
A Note on Security
Every tool call is authenticated and scoped to your organization. There's no way to access another organization's data through the MCP server—every database query is filtered by your organization ID.
OAuth is the safer default, and it's why we made it the primary flow. Access tokens are short-lived (one hour, with a 30-day refresh token), so a leaked token expires on its own. And because the client handles the token exchange, there are no secrets sitting in your config files—a committed .mcp.json contains nothing but a URL.
If you're still on a legacy API key: it's hashed with SHA-256 before storage—we never store it in plaintext. When you make a request, we match on a prefix, then verify the full hash. But API-key auth for MCP is deprecated, and every tool response includes a deprecation notice asking you to reconnect with OAuth.
For team environments still using keys, avoid putting them directly in .mcp.json if it's committed to version control. Use environment variables or keep the key in a local config file that's gitignored. Codex CLI's bearer-token-env-var pattern is a good example. Or, again: OAuth makes the whole problem disappear.
What This Unlocks
The real value isn't any single tool call. It's the compound effect of your AI assistant having live context about your webhooks while it helps you write code.
When you're writing a Stripe webhook handler and the assistant can see the actual payload that just came in, it writes better code. When you're debugging a failed integration and the assistant can inspect the headers and body—or just call diagnose_request—it finds the bug faster. When it can trigger a flow and wait on wait_for_request until the webhook lands, it verifies its own work.
The setup takes two minutes: claude mcp add, sign in, done. If you want the high-level overview of everything the server exposes, the MCP server page has it. The time you save compounds every day.
Related Reading
Hooklistener MCP Server
The full overview: every tool category, setup snippets for each client, and FAQs.
What Is an MCP Server?
The protocol from first principles: servers, clients, tools, and why the standard matters.
Agentic Webhook Testing
How wait tools like wait_for_request let AI agents run real end-to-end webhook tests.