MCP tools reference
One remote MCP server, Streamable HTTP transport, at
https://api.pendnt.dev/mcp. Every call is authenticated the same way as the REST
API: Authorization: Bearer <api_key>, scoped to that key's workspace.
Connecting
The server is stateless: no Mcp-Session-Id handshake, no
server-side session state between calls — every request is self-contained, so it works cleanly
behind Workers without needing sticky sessions. All actual state (requests, endpoints, events,
wakeups, KV) lives server-side, addressed by your workspace, exactly like the REST routes.
Claude Code
claude mcp add --transport http pendnt https://api.pendnt.dev/mcp \
--header "Authorization: Bearer $PENDNT_API_KEY"
.mcp.json
{
"mcpServers": {
"pendnt": {
"type": "http",
"url": "https://api.pendnt.dev/mcp",
"headers": {
"Authorization": "Bearer YOUR_PENDNT_API_KEY"
}
}
}
}
See Claude Code integration and Claude Agent SDK integration for full setup, including the permission-flow hook.
Tools
Every tool returns its result as a single JSON-encoded text content block. Tools that error (e.g. an unknown id) return an MCP tool error rather than a JSON error body.
request_approval
Ask a human operator to approve/deny an action, or answer a question, before the agent
proceeds. Delivers to the operator's configured channels (email, web inbox, etc). Blocks for up
to wait_s seconds (0–25; longer is clamped) waiting for an answer; if it returns
still pending, call check_request with the returned id to keep polling
— the request itself stays open (durable) for timeout_s seconds (default 86400 =
24h) regardless of how long this call waited.
| Arg | Type | Notes |
|---|---|---|
title | string, required | Short summary shown to the human, e.g. "Deploy to prod?" |
details | string, optional | Longer context shown below the title |
kind | "approval" | "question", optional | "approval" (default) shows Approve/Deny. "question" shows options (if given) plus free text. |
options | string[], optional | For kind: "question": fixed choices offered as buttons, in addition to free text |
timeout_s | number, optional | How long the request stays open before auto-expiring (default 86400) |
wait_s | number, optional | Long-poll duration before returning; capped at 25 |
Returns: { "id", "status", "answer" }
check_request
Poll the status of a request previously created by request_approval (or
POST /v1/requests). Optionally long-polls up to wait_s seconds (max 25)
if it's still pending.
| Arg | Type | Notes |
|---|---|---|
id | string, required | The request id returned by request_approval |
wait_s | number, optional | Long-poll duration, 0–25 |
Returns: { "id", "status", "answer" }. Errors not_found if the id
doesn't exist.
notify
Fire-and-forget message to the operator's configured channels. Does not block or expect a
reply — use request_approval instead if the agent needs to wait for a human
response.
| Arg | Type | Notes |
|---|---|---|
message | string, required | The notification text |
level | "info" | "warning" | "error", optional | Severity hint for channel formatting (default "info") |
Returns: { "id", "status": "answered" }
create_endpoint
Provisions a new https://.../in/<slug> URL that stores any HTTP request sent
to it (e.g. a GitHub webhook, a Stripe event, or an OAuth callback). Use wait_for_event
to retrieve what arrives at it.
| Arg | Type | Notes |
|---|---|---|
name | string, optional | A human-readable label, e.g. "gh-webhook" |
require_token | boolean, optional | If true, incoming requests need ?token=<secret> or X-Endpoint-Token, or are rejected 403 |
Returns: { id, name, slug, url, secret, require_token, created_at }
list_endpoints
Lists all inbound webhook endpoints created for this workspace. No arguments. Returns:
{ "endpoints": [...] }
wait_for_event
Long-polls (up to wait_s seconds, max 25) for new events — inbound webhook
deliveries and fired wakeups — with seq > since_seq. Pass the returned
last_seq back in as since_seq on the next call so you don't re-read the
same events.
| Arg | Type | Notes |
|---|---|---|
endpoint_id | string, optional | Restrict to events from one endpoint (id from create_endpoint); omit for all events in the workspace |
since_seq | number, optional | Only return events with seq greater than this (default 0) |
wait_s | number, optional | Long-poll duration if nothing is available yet, 0–25 |
Returns: { "events": [...], "last_seq" }
schedule_wakeup
Schedules a future event (delivered via wait_for_event, kind: "wakeup")
— useful to resume a paused or deferred agent later. Provide exactly one of at
(absolute ISO 8601 timestamp) or in_s (seconds from now).
| Arg | Type | Notes |
|---|---|---|
at | string, optional | Absolute ISO 8601 timestamp, e.g. "2026-09-01T00:00:00Z" |
in_s | number, optional | Seconds from now to fire at |
payload | any, optional | Arbitrary JSON attached to the wakeup event |
Returns: { "id", "fire_at" }
list_wakeups
Lists scheduled, fired, and cancelled wakeups for this workspace. No arguments. Returns:
{ "wakeups": [{ id, fire_at, payload, status, created_at }] }
cancel_wakeup
Cancels a scheduled wakeup before it fires. No effect if it has already fired or been cancelled.
| Arg | Type | Notes |
|---|---|---|
id | string, required | The wakeup id returned by schedule_wakeup |
Returns: { "ok": true }. Errors not_found if the id doesn't exist.
kv_get
Reads a value previously written with kv_set from this workspace's small
per-workspace KV scratchpad.
| Arg | Type | Notes |
|---|---|---|
key | string, required |
Returns: { "key", "value", "updated_at" }. Errors not_found if unset.
kv_set
Writes a string value (<= 64KB) to this workspace's KV scratchpad, keyed by
key. Overwrites any existing value.
| Arg | Type | Notes |
|---|---|---|
key | string, required | |
value | string, required | <= 64KB |
Returns: { "key", "value", "updated_at" }
kv_delete
Deletes a value from the KV scratchpad. No-op if the key doesn't exist.
| Arg | Type | Notes |
|---|---|---|
key | string, required |
Returns: { "ok": true }
whoami
Returns the workspace id, plan, plan limits, and API base URL for the workspace this API key belongs to — useful to sanity-check which workspace/environment the agent is talking to before doing anything else. No arguments.