voip.ms Advanced Tools sandbox POC — webhooks + MCP for AI Voice Agent
DARE.CO.UK · PARKED SKETCH · 2026-06-11
Mirrored from ~/.claude/.../memory/parked_sketch_voipms_advanced_tools_sandbox_poc_2026-06-09.md. This is a design sketch parked for future build — read for context, not as a current deliverable.
voip.ms shipped Beta webhook + MCP for AI Voice Agent (2026-06-09); sandbox.gf.cx/voip/ scaffolded same-day with webhook receiver + MCP info stub + R2 logging — awaiting dan-side portal configuration to fire the first real call event.
voip.ms Advanced Tools sandbox POC (status: SCAFFOLDED 2026-06-09)
What landed (sandbox.gf.cx/voip/)
/api/voip/health→ bind-state probe (no auth) · returns mode=live with both VOIP_SANDBOX_KEY + MEDIA bound/api/voip/webhook(POST/PUT/PATCH) →X-Sandbox-Keygated · writes full payload + headers + cf metadata togf-cx-media/sandbox/voip/calls/<date>/<stamp>-<rand>.json/api/voip/mcp/info→ JSON server-info stub · advertises 4 intended tools but does not yet speak MCP/voip/landing page documents URLs + auth + voip.ms portal config steps
VOIP_SANDBOX_KEY secret bound on sandbox-gf-cx Worker. Source of truth in 1Password at op://Code Shared/voip.ms api/bearer_token — Dan added a bearer_token field to the existing voip.ms api item (co-located with the REST API creds rather than a standalone sandbox item — the path with · middle-dot I’d originally proposed didn’t work anyway because op read rejects that character). Worker re-bound to the op value 2026-06-10 01:45 UTC after Dan saved it. sandbox.gf.cx is NOT a git repo — ships via wrangler-direct from ~/Code/sandbox.gf.cx/ with no commits.
To rotate the secret: update the bearer_token field in 1Password, then cd ~/Code/sandbox.gf.cx && op read 'op://Code Shared/voip.ms api/bearer_token' | op run --env-file=<(echo 'CLOUDFLARE_API_TOKEN=op://Code Shared/Cloudflare gf.cx full access/credential') -- npx wrangler secret put VOIP_SANDBOX_KEY. Re-paste the new value into the voip.ms portal’s webhook + MCP Extension config at the same time or production calls will start 401-ing.
Smoke green: webhook returns 401 without auth; 200 + R2 write with auth; verified via HEAD media.gf.cx/sandbox/voip/calls/2026-06-09/...json → 200 / 2,936 bytes.
Open before this becomes “live”
- Capture the secret into 1Password.
- Pick a throwaway voip.ms DID + agent. Do not use a production DID for the first probe.
- Configure the agent’s Webhook extension to fire on the cheapest call event (
call_ended). - Place a test call. Inspect the R2 write — that’s the moment we learn voip.ms’s real payload shape.
- Once payload shape is known, write v2: actual MCP SSE handler + the four lookup tools (lookup_amazon_order / lookup_open_claim / lookup_contractor / lookup_return) against
pa/substrate.
Original concept (kept for context)
voip.ms quietly shipped Beta-tier Advanced Tools and Integrations on their AI Voice Agent product on/around 2026-06-09. Two mechanisms exposed:
| Mechanism | Direction | Configured under |
|---|---|---|
| Webhooks | Agent → external endpoint, fire-and-forget (per call event) | AI Agent → Extensions → Webhooks |
| MCP Servers | Bidirectional live during call (SSE or HTTP transport, auth-header gated) | AI Agent → Extensions → MCP Servers |
Webhook fields: Name (internal id), Friendly Name, Description (the LLM sees this when deciding whether to fire), Trigger Condition, HTTP Method, URL, Parameters (each can be dynamic / fixed / default-fallback).
MCP Server fields: Name, Transport Type (SSE | HTTP), URL,
Auth Headers (e.g. Authorization: Bearer … or X-API-Key: …).
Why this is interesting for the gf.cx stack
pa/, home-insurance/claims/, pa/amazon/orders/, pa/contractors/* are
already structured JSON + HTML — exactly the shape an MCP server wants to
expose as read-only lookup tools. “Did Jorge finish the french-drain job?”,
“What’s the status of my Hertz return?”, “Has the storm claim been paid?” —
all answerable from existing pa/ substrate without a human pickup.
Webhooks are the cheaper trial: log every inbound-call event into R2, push the AI-generated summary into Fastmail, mirror to dash.gf.cx editorial.
POC home
sandbox.gf.cx/voip/ — matches the existing scaffold pattern
(sandbox.gf.cx/fal/ shipped 2026-06-07; sandbox.gf.cx/transcripts/
sketched 2026-06-09). MCP server lives as a CDN, security layer, and DNS provider sitting in front of dare.co.uk." data-tip="Cloudflare — the CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Worker at
mcp.sandbox.gf.cx or co-located under the sandbox project; webhook
receiver is a /api/voip/webhook/<event> route.
Two routes (ranked by effort)
- Webhook receiver — ~30 min CDN, security layer, and DNS provider sitting in front of dare.co.uk." data-tip="Cloudflare — the CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Worker. Validates a static bearer,
schemas the inbound payload, writes to R2 under
sandbox/voip/calls/<YYYY-MM-DD>/<call_id>.json, optionally fans out to Fastmail. Good first probe — proves voip.ms triggers as documented. - MCP server — half-day. CDN, security layer, and DNS provider sitting in front of dare.co.uk." data-tip="Cloudflare — the CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Worker speaking the MCP protocol (SSE
transport), exposing 3-5 narrowly-scoped lookup tools against pa/
substrate. Per voip.ms doc, auth is whatever
Auth Headerswe set on the agent side — keep it a long randomX-Sandbox-Key. Tools to prototype first: -lookup_amazon_order(order_id)→ status, items, tracking -lookup_open_claim(claim_id)→ status, last correspondence date -lookup_contractor(slug)→ status, last visit, open quote -lookup_return(rma_or_order)→ carrier, tracking, expected refund
Open decisions (gate the build)
- Which DID + agent persona? Personal household, dare.co.uk business, smart.sellars, audreyinc — each implies a different data slice. Likely start with a new throwaway DID on voip.ms specifically for the POC so nothing production-facing is touched.
- Auth boundary on the MCP server. Read-only against pa/, gated by a
static
X-Sandbox-Key. No writes in v1. - Schema for the call event payload — voip.ms doc doesn’t show the default body shape; need to either probe with a webhook.site URL first or check their dev docs.
Triggers to actually build this
- Dan picks the agent + use case and asks to proceed
- voip.ms moves the feature out of Beta and the FAQ tail confirms
- Or a concrete use case arrives (e.g. an actual customer-facing line needing automated order-status answers)
Do NOT build without
- A throwaway DID for the test agent (don’t repoint live numbers)
- A clear auth-header on both webhook and MCP routes
- A documented allowlist of MCP tools (don’t expose pa/ broadly)