Files
hold-slayer/docs/mcp-server.md
Robert Helewka 4a3c14d4af
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 45s
CVE Scan & Docker Build / build-and-push (push) Successful in 1m53s
docs: add Claude AI assistant rules and configuration
Add comprehensive rule documentation for AI-assisted development covering
authentication surfaces, outbound-call safety invariants, and other project
conventions to guide Claude's understanding of critical system behaviors.
2026-07-28 19:01:38 -04:00

6.3 KiB

MCP Server

The MCP (Model Context Protocol) server lets any MCP-compatible AI assistant control the Hold Slayer gateway. Built with FastMCP, it is mounted on the FastAPI app at /mcp/ (trailing slash) over streamable HTTP and authenticates with an owner-minted Personal Access Token (hs_pat_…) — the same owner-only auth as the REST API and WebSocket. Auth is enforced by an ASGI guard (_owner_only_mcp in main.py) that resolves the bearer to the owner; a Casdoor JWT also works, but MCP clients can't refresh one, so a PAT is the intended credential.

Overview

An AI assistant connects to the MCP endpoint and gains access to 15 tools and 3 resources for placing calls, checking status, sending DTMF, getting transcripts, and managing call flows. The assistant can orchestrate an entire call through natural language.

make_call places a real PSTN call that may incur charges; emergency numbers are always refused, and the concurrent-call cap applies.

Tools

make_call

Place an outbound call through the SIP trunk.

Param Type Required Description
number string Yes Phone number to call (E.164 format)
mode string No direct, hold_slayer, or ai_assisted (default: direct)
intent string No What you want to accomplish on the call
call_flow_id string No ID of a stored call flow to follow
device string No Device to transfer to when a human is detected

Returns: call ID and initial status.

get_call_status

Check the current state of a call — status, duration, hold time, current audio classification, recent transcript.

Param Type Required Description
call_id string Yes The call to check

transfer_call

Transfer an active call to a registered device.

Param Type Required Description
call_id string Yes The call to transfer
device string Yes Device ID or type to ring

hangup

Hang up an active call.

Param Type Required Description
call_id string Yes The call to hang up

list_active_calls

List all calls currently in progress. No parameters.

send_dtmf

Send touch-tone digits on an active call (manual IVR navigation).

Param Type Required Description
call_id string Yes The call to send digits on
digits string Yes DTMF digits (e.g., "1", "123#")

get_call_transcript

Get the full transcript of an active call.

Param Type Required Description
call_id string Yes The call to get the transcript for

get_call_recording

Get recording metadata (path, duration) for a persisted call.

Param Type Required Description
call_id string Yes The call to look up

get_call_summary

Stored summary, action items, and sentiment for a persisted call.

Param Type Required Description
call_id string Yes The call to look up

search_call_history

Search past call records.

Param Type Required Description
phone_number string No Filter by phone number (partial match)
intent string No Filter by intent text (partial match)
limit int No Max results (default: 10)

get_call_flow

Look up the stored IVR call flow for a phone number.

Param Type Required Description
phone_number string Yes Number to look up (E.164)

create_call_flow

Store a new IVR call flow by hand.

Param Type Required Description
name string Yes Human-readable name
phone_number string Yes Phone number (E.164)
steps_json string Yes JSON array of call flow steps
notes string No General notes

learn_call_flow

Build (or refine) a reusable IVR call flow from a completed hold-slayer exploration call. Exploration calls record every IVR prompt heard and DTMF sent; this turns those discoveries into a stored flow so the next call navigates directly.

Param Type Required Description
call_id string Yes A completed call that ran in exploration mode
company_name string No Company name for labeling a new flow

list_devices

List registered devices and their online/offline status. No parameters.

gateway_status

Trunk registration, device count, active calls, engine mode. No parameters.

Resources

Resource URI Description
gateway://status Current gateway status — trunk registration, active calls
gateway://call-flows List of all stored call flows
gateway://active-calls All active calls with current status

Connecting an AI Assistant

Claude Code:

claude mcp add hold-slayer --transport http http://localhost:8000/mcp/ \
  --header "Authorization: Bearer hs_pat_..."

Generic MCP client configuration:

{
  "mcpServers": {
    "hold-slayer": {
      "url": "http://localhost:8000/mcp/",
      "headers": {"Authorization": "Bearer hs_pat_..."}
    }
  }
}

Example Conversation

User: "Call Chase Bank and dispute the Amazon charge from December 15th"

Assistant actions:

  1. Calls make_call(number="+18005551234", mode="hold_slayer", intent="dispute Amazon charge Dec 15th", call_flow_id="chase-bank-main")
  2. Receives call_id: "call_abc123"
  3. Polls get_call_status("call_abc123") periodically
  4. Status progression: initiatingringingconnectedon_hold
  5. Tells user: "I'm on hold with Chase Bank. Currently 4 minutes in. I'll let you know when someone picks up."
  6. Status changes to transferring — human detected!
  7. Tells user: "A live agent just picked up. I'm transferring the call to your desk phone now. Pick up!"
  8. After the call, calls learn_call_flow("call_abc123", company_name="Chase Bank") to save the IVR path for next time.