The MCP server
Your agent is about to do something it cannot undo. It asks somebody on WhatsApp, waits, and acts on the answer.
JABEE_API_KEY=jak_... npx @jabee/mcp
Setting it up
Make a key under Management then Approvals in the
dashboard. It starts jak_. Then add the server to your MCP client:
{
"mcpServers": {
"jabee": {
"command": "npx",
"args": ["-y", "@jabee/mcp"],
"env": { "JABEE_API_KEY": "jak_..." }
}
}
}
That is the whole setup. There is no WhatsApp number to register, no Meta developer account and no message template to get approved, because the number and the template are ours and already approved.
The person answering needs a verified phone, which they get by tapping a link in the dashboard and sending one message. Until they do, requests fall back to email.
If your client installs from the official MCP registry rather than from a config file,
the server is listed there as ai.jabee/mcp — the same npm package,
published under our own domain namespace.
The three tools
ask_person
Asks for a decision and waits for it.
| Argument | What it does |
|---|---|
title | The decision, in one line. Required. |
body | Why you are asking, and what they need in order to decide. |
url | A link to the thing being decided. |
allow_amendment | Offer an Edit button that asks for free text. |
external_id | Your own id. Sending the same one twice returns the request you already made, so a retry is safe. |
expires_in_minutes | How long the decision stays useful. Defaults to a day. |
wait_seconds | How long to block before returning. Defaults to 120. Pass 0 to return at once and poll. |
It returns the decision, or the request id if nobody has answered inside
wait_seconds. The default is two minutes because an agent blocked on a tool
call is an agent whose client may time out, and a decision nobody has made in two minutes
usually needs longer than any tool call should take.
check_approval
Reads a request back by id, for when ask_person came back pending. It
also says if the request was withdrawn by whatever asked for it, in which case your
agent should not act on it, and repeats any outcome already recorded against it.
tell_person
One way. A build failed, an order shipped, a job finished. Returns as soon as it is sent and waits for nobody.
The answer is often not yes or no
Set allow_amendment and the person gets an Edit button. Tapping it asks
for text, and what they write comes back to your agent as the answer. That is how a quote
gets changed by 50 dirhams rather than refused outright, and it is the argument for using
a person rather than a confirmation dialog.
The parts that are easy to get wrong
All of these are handled, and all of them are why building this yourself takes a week rather than a weekend.
- Two people tapping at once. Settled in one SQL statement, so exactly one wins and the second is told what already happened. Your agent hears one answer.
- Nobody tapping at all. The request expires at the time you set and says so, rather than leaving your agent waiting on somebody who has gone home.
- Retries. Send the same
external_idagain and you get the request you already made, rather than asking somebody the same question twice. - Rate limits. A per-key limit is waited out once and retried. A daily limit is not, because it cannot be waited out inside a tool call, and the agent is told plainly instead.
Limits
60 API calls a minute per key, and 200 new requests per business in any 24 hours. A
repeated external_id does not count against the daily figure.
The daily limit exists because every request is a message from a number every Jabee business shares, and one number's standing with Meta is everybody's. If you genuinely need more, email us.
If you would rather not use MCP
The same thing is an HTTP API, with a signed webhook instead of a blocking call, and signature verification in Node and Python. The MCP server is a wrapper over it.
Questions
Which clients does this work with?
Anything that speaks MCP over stdio, which includes Claude Code, Claude Desktop and Cursor. It is a standard server with no client-specific behaviour.
Do I need a WhatsApp number?
No. Requests go from Jabee's own number to people who verified a phone with us, so there is nothing to register and no template to get approved.
What happens if my agent stops while a request is pending?
The request carries on and expires on its own. Nothing is left half done on our side. When your agent comes back it can read the answer with check_approval and the id.
Can it message my customers?
No, deliberately. It reaches one phone you have verified. A shared number messaging strangers is what gets numbers banned. To reach customers you connect your own number.
Is the key safe in my MCP configuration?
It is as safe as that file. A key belongs to one business, can only see that business's requests, and is revoked and replaced from the dashboard if it leaks. Give each machine its own.
What does it cost?
$29 a month, flat, with no per-request charge. Notifications are in the same plan.