Model Context Protocol

Give your AI a phone number

WebhookPush speaks MCP, the standard way an AI client connects to an outside service. Connect it once and your agent can push a notification to your phone — and, the part nothing else does, stop and wait for your actual answer before it carries on.

What MCP is, in one minute

An AI model can only write text. MCP is the protocol that lets it do things: a client (Claude, ChatGPT, an agent you wrote) connects to an MCP server, asks what tools it has, and calls them. The server does the work and hands back a result the model can reason about.

WebhookPush is one of those servers. Its tools are the things you would otherwise do by hand — send yourself a notification, read the events a webhook received, create or delete a webhook — plus one that has no equivalent anywhere else: ask you a question and wait.

Your AI client
Claude · ChatGPT
WebhookPush MCP
tools + your grant
Your phone
push · a question · your answer

You are not sending your data to us to be trained on, and the agent is not given your password. It gets a token you granted, for the scopes you approved, which you can revoke.

The point: an agent that can ask

Most "send a notification" integrations are fire-and-forget: the agent pushes a message and carries on guessing. ask_user does the opposite — it stops the agent, buzzes your phone, and resumes with the decision you actually made, tapped from the lock screen.

ask_user(
  question: "Migration will drop 3 unused columns. Proceed?",
  detail:   "users.legacy_id, users.temp_flag, orders.old_ref — no reads in 90 days.",
  choices:  ["Proceed", "Skip those", "Stop"],
  wait_seconds: 600
)

Your phone shows the question with up to four tappable buttons, or a box to type a reply. The first tap wins — answers are single-use. Timing out is not a failure: the question stays live on your phone, and the agent can pick the answer up later with check_answer or carry on and tell you what it assumed.

Two ways to connect

Both give you the same tools. Which one you want depends on whether a process can run on your own machine.

1. Hosted connector — Claude and ChatGPT, anywhere

One URL, no key to copy. Your client registers itself, sends you here to approve it, and that is the whole setup.

https://webhook.sp33c.tech/mcp
  1. Open your client's connector settings
    In Claude: Settings → Connectors → Add custom connector. In ChatGPT: Settings → Connectors → Add.
  2. Paste the URL above
    Give it a name you will recognise later — "WebhookPush" is a fine one.
  3. Approve the connection
    You will be sent to WebhookPush, asked to sign in if you are not already, and shown exactly what the client is asking for.
  4. Check it worked
    Ask your assistant to "send me a test notification with WebhookPush". Your phone should buzz.

The consent screen names the client and lists what it is asking for: reading your inbox and webhooks, and — separately — sending notifications and changing things. Approving both is the default. You can revoke either at any time in settings, and the next call the client makes will fail until you approve it again.

From Claude Code, the same connector is one command — no key, no header:

claude mcp add --transport http webhookpush https://webhook.sp33c.tech/mcp

Then run /mcp inside Claude Code, pick webhookpush and sign in. Claude Code registers itself and goes through the same consent screen as any other client.

Nothing to install, and no device of yours has to stay awake — the connector runs on our servers. If your client has no "custom connector" option, it does not support remote MCP yet; use the local server below.

2. Local server — Claude Code, Claude Desktop

Runs on your own machine as a normal command. Sign in once through your browser; no key to paste. Needs Node 18 or newer.

npx -y @sp33c/webhookpush-mcp login        # opens your browser
claude mcp add webhookpush -- npx -y @sp33c/webhookpush-mcp

For Claude Desktop and other clients, in mcpServers:

{
  "mcpServers": {
    "webhookpush": {
      "command": "npx",
      "args": ["-y", "@sp33c/webhookpush-mcp"]
    }
  }
}

For CI or a headless box, create an API key at settings → keys and set WEBHOOKPUSH_API_KEY. It never expires — which is what makes it right for a machine and wrong as your own default.

Which one should you use?

Local, wherever you can. This is the reverse of the usual advice, and there is a concrete reason: a local process can hold a question open for up to an hour, because the only limit is the one you asked for. A hosted request has to answer before the platform times it out, so on the connector ask_user waits under a minute and then returns "not answered yet" with the id to check later. The question still reaches your phone and still waits for you either way — only the agent's ability to sit and wait changes.

LocalHosted connector
Where it runsYour machineOur servers
Sign-inBrowser, onceOAuth + consent screen
ask_user waits up to1 hourunder a minute, then resumable
Works inClaude Code, Claude DesktopClaude web & mobile, Claude Code, ChatGPT

What it can do

Nineteen tools, each annotated so your client can show you which ones only read and which ones change something.

Reaching you

notify_userPush a notification. Progress, completions, things needing eventual attention.
ask_userAsk a question and block until you answer. Up to 4 buttons, or a typed reply.
check_answerPick up an answer to an earlier question that timed out.

Webhooks

list_webhooks · get_webhookEvery webhook, its state, and the URL to call it.
create_webhookCreate one — returns the URL, the secret (once) and a runnable curl.
update_webhookRename, retag, change notification templates.
disable_webhook ⚠Stop it accepting events, or turn it back on.
rotate_webhook_secret ⚠New secret. Every existing caller breaks.
delete_webhook ⚠Permanent. Optionally purges its messages.
test_webhook ⚠Fires a real event — your phone buzzes and it costs a daily call.
webhook_statsAverage events per day, over 1 day to 1 year.

Inbox

list_messagesThe events your webhooks received. Filter by webhook, time or unread.
get_messageOne message in full, including the raw payload.
mark_message_read · archive_messageTidy up. Archiving keeps a message forever.
delete_message ⚠Permanent.

Account

whoami · account_usageWhich account, which plan, and what is left today.

⚠ marks a tool that changes something irreversibly. On the hosted connector, ChatGPT's search and fetch are also served — thin aliases over the inbox tools, because its connector path expects those names.

Safety — what it can't do

An agent using this reads webhook payloads, and a payload is written by whoever calls your webhook. That is the one place text somebody else composed enters the model's context, so the design starts there.

  • Destructive tools fail closed. Deleting, disabling, rotating or test-firing a webhook requires echoing that webhook's exact current name. Text arriving inside a payload does not know the name, so it cannot compose a valid destructive call even if it talks the model into trying.
  • Payload text is fenced and labelled as data. It comes back wrapped, attributed to the webhook it arrived on, and capped — with the truncation marker inside the fence, so you can tell nothing was hidden.
  • An agent cannot answer its own question. There is no tool that replies to a message. If there were, ask_user would be theatre.
  • Some settings are not reachable at all. No tool can set a webhook's callback URL or turn its secret requirement off — those are an exfiltration primitive and an authentication-disabling primitive. Change them in the dashboard.
  • Read-only is a real boundary. Grant only the read scope — or set WEBHOOKPUSH_READONLY=1 locally — and the writing tools are never registered. Not "refuses when called": absent from the list, so it cannot be called.

More on the controls behind the account itself on the security page.

Privacy and revoking access

A connector acts as you, limited to the scopes you approved. It can reach the same things you can in the app: your webhooks, your inbox and its payloads, your plan usage. It never sees your password, and it cannot mint a permanent API key or delete your account — those need you, signed in, in our own UI.

Revoke a connection in settings; the next call it makes fails and it has to ask again. Full detail in the privacy policy.

Questions, or something behaving oddly? Tell us.