Skip to main content
Glama
hail

hail

Official

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
HAIL_API_KEYYes
HAIL_API_URLYes
HAIL_AUTH_URLNo

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
place_callA

Originate an outbound phone call.

    Provide ``system_prompt`` (mode A — Hail's bundled fallback LLM
    uses this prompt) or ``llm`` (mode B — bring your own
    OpenAI-compatible endpoint as
    ``{"base_url": ..., "api_key": ..., "model": ...}``), or both, or
    ``agent_id`` (a saved agent from ``list_agents`` supplies the
    prompt, first message, AI line, voice and tools; fields you pass
    here win). At least one is required. Passing both runs your prompt on your
    own endpoint: it receives Hail's voice preamble plus your prompt
    as the leading system message.

    ``to`` must be E.164 (e.g. ``+14155551234``). ``from_`` is
    optional and defaults to the first active number on your org.
    ``first_message`` is spoken verbatim on pickup; omit it to let
    the agent open the conversation itself — it reacts to how the
    call was answered, or introduces itself after silence.
    ``language`` sets the call's spoken language for speech-to-text,
    text-to-speech, and turn detection, as a lowercase ISO 639-1 code
    (e.g. ``"da"``); 39 languages are supported (server rejects others
    with 422); omit for English. STT provider selection is
    console-BYO-only (no per-call override); configure it on the
    organization to pin a provider.
    ``ai_disclosure=False`` skips the spoken "this is an AI
    assistant" line at the start of the call. Leave enabled unless
    the user has verified it is not required for this call — US
    artificial-voice calls (47 CFR 64.1200(b)(1)) and several AI
    bot-disclosure laws require it, and Hail does not verify this.
    The agent still identifies itself as an AI if asked.
    ``recording_enabled``: omit it to follow the agent, then the
    workspace recording setting. ``true`` records this call and
    ``false`` does not, whatever the workspace setting. Pass it only
    when the user asked for or against a recording.
    ``metadata`` is free-form JSON attached to the call record.
    ``tools`` are the agent tools to allow on this call. Omit for all
    available; pass ``[]`` to disable.

    ``recipient_consent`` is required and must be the JSON boolean
    ``true`` (strings and numbers are refused): attest that you (the caller
    triggering this request) have obtained the lawful consent needed
    to contact this recipient. The API rejects the request (422) if
    this is not ``true`` — Hail does not verify consent for you, you
    are responsible for having a lawful basis (TCPA / ePrivacy / GDPR
    as applicable). Set ``message_type="marketing"`` for promotional
    calls (this additionally requires a non-empty ``consent_source``
    describing how/where consent was obtained) — leave as the default
    ``"informational"`` for transactional/service calls.

    ``idempotency_key`` defaults to a fresh UUID per invocation
    and is returned in the response under ``idempotency_key`` — to
    retry *this* exact request (rather than dispatch a second call),
    pass the value back on the retry. A new key is a new call.

    Example:
        place_call(to="+14155551234",
                   recipient_consent=True,
                   system_prompt="You are scheduling a haircut.",
                   first_message="Hi, I'm calling on behalf of Alex.")

    Returns the API's ``CallResponse`` as a dict (id, status,
    from_e164, to_e164, ...). On failure returns
    ``{"error": "<message>"}`` instead.
    
send_emailA

Send an outbound email through your configured SES sender.

    ``to`` is a non-empty list of RFC-style email addresses. At
    least one of ``body_text`` / ``body_html`` is required (both
    is fine — multipart-alternative). Prefer including
    ``body_html``: open and click tracking only works for emails
    with an HTML body. A plain-text-only email still gets sent,
    delivered, and bounce events, but opens and clicks are never
    tracked. ``cc``, ``bcc``, and
    ``reply_to`` are optional and follow the usual mail
    conventions. Hail sets no ``reply_to`` of its own — to have
    replies reach the human running this session, call ``whoami``
    and pass their ``email``.

    ``recipient_consent`` is required and must be the JSON boolean
    ``true`` (strings and numbers are refused): attest that you (the caller
    triggering this request) have obtained the lawful consent needed
    to email this recipient. The API rejects the request (422) if
    this is not ``true`` — Hail does not verify consent for you. Set
    ``message_type="marketing"`` for promotional email (this
    additionally requires a non-empty ``consent_source`` describing
    how/where consent was obtained) — leave as the default
    ``"informational"`` for transactional/service email.

    ``from_`` is optional only while the workspace has one verified
    sender identity. With several, omitting it returns 422 listing
    them — call ``list_email_domains`` and pass one. With none, the
    server auto-mints a per-org hail-mail address of the form
    ``<user>+<org>@<base>`` if the operator configured
    ``HAIL_MAIL_BASE_DOMAIN`` (the ``<org>`` part is derived from your
    organization id; the ``<user>`` part comes from ``HAIL_MAIL_FROM``
    / ``HAIL_MAIL_DEFAULT_USER_PREFIX``, or an explicit row created
    via ``POST /email-domains``). When supplied, ``from_`` must match
    a verified row already in ``email_domains`` (register one with
    the website console or ``POST /email-domains``).

    ``from_name`` is an optional display name rendered on the
    From: header ("Acme Billing <billing@acme.com>"). Control
    characters are rejected.

    ``metadata`` is free-form JSON attached to the email record.

    ``idempotency_key`` defaults to a fresh UUID and is returned
    in the response under ``idempotency_key`` — pass the same
    value on a retry to replay rather than re-send. A new key
    is a new message.

    ``attachment_ids`` are ids returned by ``upload_email_attachment``
    — upload a file first, then pass its id(s) here to attach it.

    Example:
        send_email(to=["alice@example.com"],
                   subject="Welcome",
                   recipient_consent=True,
                   body_text="Thanks for signing up.")

    Returns the ``EmailResponse`` dict (id, status, from_address,
    to_addresses, sent_at, provider_message_id, ...). On failure
    returns ``{"error": "<message>"}`` instead.
    
upload_email_attachmentA

Upload a file to attach to a future outbound email.

    ``content_base64`` is the file's raw bytes, base64-encoded.
    Returns ``{"id": ..., "filename": ..., "content_type": ...,
    "size_bytes": ...}`` — pass ``id`` in ``send_email``'s
    ``attachment_ids`` list. The id is reusable across many sends
    and expires in 24h if never used. Files over 25MB (combined
    with the message body and any other attachments, per send) are
    rejected — host large files externally and link to them in the
    body instead.
    
get_callA

Fetch the current state of one call by id.

    Use this after ``place_call`` (or to check on any prior call)
    to read the call's latest ``status`` and timing fields.

    Returns the API's ``CallResponse`` as a dict, or
    ``{"error": "call not found"}`` for an unknown id.
    
list_callsA

List recent calls in your organization, newest first.

    Cursor-paginated: pass the previous response's ``next_cursor``
    to fetch the next page. ``status`` (one of queued, dialing,
    ringing, in_progress, completed, failed, busy, no_answer,
    canceled) and ``to`` (E.164) are optional server-side filters.

    Returns a dict ``{"items": [...], "next_cursor": <str|None>}``.
    
send_smsA

Send an outbound SMS.

    ``to`` must be E.164 (e.g. ``+14155551234``). ``body`` is the
    message text. With no ``from_``: destinations where the sender-ID
    carrier delivers a dynamic alphanumeric sender ID unchanged (about
    110 countries, see core/hailhq/core/sender_id_corridors.py) use
    your organization's sender ID
    (or ``HAIL``, the platform default); Australia (+61) may use
    ``HAIL`` instead; every other destination,
    including the US and Canada,
    uses your organization's oldest active SMS-capable number and the
    API returns 422 when there is none.
    SMS never uses the shared voice-call pool.

    ``recipient_consent`` is required and must be the JSON boolean
    ``true`` (strings and numbers are refused): attest that you (the caller
    triggering this request) have obtained the lawful consent needed
    to text this recipient. The API rejects the request (422) if
    this is not ``true`` — Hail does not verify consent for you. Set
    ``message_type="marketing"`` for promotional texts (this
    additionally requires a non-empty ``consent_source``) — leave as
    the default ``"informational"`` for transactional/service texts.

    ``idempotency_key`` defaults to a fresh UUID and is returned in
    the response under ``idempotency_key`` — pass the same value on
    a retry to replay rather than re-send.

    Example:
        send_sms(to="+14155551234", body="Your order shipped!",
                 recipient_consent=True)

    Returns the ``SmsResponse`` dict (id, status, from_e164,
    to_e164, segment_count, ...). On failure returns
    ``{"error": "<message>"}`` instead.
    
get_smsA

Fetch the current state of one SMS by id.

    Use this after ``send_sms`` to check delivery status.

    Example:
        get_sms(sms_id="...")
    
list_smsA

Page through recent SMS messages for your organization.

    ``status`` filters to one of: queued, sent, delivered, failed,
    undelivered, received. ``to`` filters to messages sent to a
    specific E.164 number. Paginate with the returned
    ``next_cursor``.
    
get_emailA

Fetch the full record of one email by id.

    Returns the complete row — including ``body_text`` / ``body_html``
    and (for inbound mail) the ``in_reply_to`` / ``message_id`` headers
    and ``spam``/``virus``/``spf``/``dkim``/``dmarc`` verdicts. Use this
    after ``list_emails`` to read a received reply's body.

    Returns the API's ``EmailResponse`` as a dict, or
    ``{"error": "resource not found"}`` for an unknown id.
    
list_emailsA

List emails in your organization, newest first.

    Cursor-paginated: pass the previous response's ``next_cursor`` to
    fetch the next page. Two optional server-side filters:

    * ``direction`` — ``outbound`` or ``inbound``. Pass
      ``direction="inbound"`` to read replies and other received mail.
    * ``status`` — one of ``queued``, ``sent``, ``failed``,
      ``bounced``, ``complained``, ``received``.

    Items are trimmed summaries (no message body). Call ``get_email``
    with an item's ``id`` to read the full body.

    Example:
        list_emails(direction="inbound")

    Returns ``{"items": [...], "next_cursor": <str|None>}`` on success,
    or ``{"error": "<message>"}`` instead.
    
get_email_rawA

Get a fetchable URL for an email's original MIME source.

    Returns ``{"url": "<presigned-s3-url>"}`` — a short-lived
    (~5 minute) link to the full raw RFC822 message. Fetch the URL
    directly to read the complete original; it needs no auth header.
    Raw source exists for **inbound** mail only — outbound ids return
    ``{"error": "resource not found"}``.
    
get_email_attachmentA

Get a fetchable URL for one inbound email attachment.

    ``attachment_id`` comes from an item in ``get_email``'s
    ``attachments`` list. Returns ``{"url": "<presigned-s3-url>"}`` —
    a short-lived (~5 minute) link to the attachment bytes, fetchable
    directly with no auth header. Unknown ids return
    ``{"error": "resource not found"}``.
    
get_email_eventsA

Delivery/engagement timeline (sent→delivered→opened…) for one email.

    Chronological lifecycle events for a single email — use this to see
    exactly what happened to one message (bounced? opened? clicked?)
    rather than the account-wide aggregates ``get_email_stats`` returns.

    Returns ``{"items": [...], "next_cursor": ...}`` where each item has
    ``kind`` (one of sent, delivered, delivery_delayed, bounced,
    complained, rejected, opened, clicked), ``payload``, and
    ``occurred_at``. ``opened`` and ``clicked`` only occur for emails
    sent with an HTML body. A plain-text-only email still gets sent,
    delivered, and bounce events, but opens and clicks are never
    tracked. Pass ``cursor`` from a previous ``next_cursor`` to
    page (``limit`` 1..1000, default 100). On failure returns
    ``{"error": "resource not found"}`` for an unknown id.
    
get_email_statsA

Account-level email deliverability stats (counts, rates, time series).

    Aggregates across your whole organization's outbound mail over a
    window — use this for "how's deliverability doing" rather than
    one message's history (``get_email_events`` covers that).

    ``from_`` / ``to`` are ISO 8601 timestamps (defaults: last 7 days
    ending now). ``bucket`` is ``"day"`` (default) or ``"hour"`` —
    ``"hour"`` is limited to an 8-day span; any range is capped at 92
    days.

    Returns ``{"from": ..., "to": ..., "bucket": ..., "totals": {...},
    "rates": {...}, "series": [...]}`` — ``totals``/each ``series``
    bucket carry counts (sent, delivered, bounced, opened, ...) and
    ``rates`` carries derived ratios (delivery, bounce, open, click),
    each ``None`` when ``totals.sent`` is 0. Open and click numbers
    only count HTML emails. Plain-text-only emails are never tracked
    for opens or clicks, so they lower those rates. On failure returns
    ``{"error": "<message>"}`` instead.
    
get_eventsA

Page through events from across the org or one resource.

    Pass ``id="<type>:<uuid>"`` to narrow to a single resource —
    supported types are ``call``, ``email``, and ``sms`` (e.g.
    ``id="sms:<uuid>"`` after ``send_sms``). When narrowed to a
    call, the response includes a ``call_status`` field reflecting
    the call's current state. Without ``id``, returns events from
    across the whole org. ``kind`` filters server-side by event kind
    (``state_change``, ``agent_turn``, ``user_turn``, ``tool_call``,
    ``error``, ...).

    This is **not** a streaming subscription — the call returns
    whatever events exist now plus a ``next_cursor`` if more pages
    remain. To follow a call to completion, loop: pass the previous
    response's ``next_cursor`` until ``next_cursor`` is null and,
    when narrowed to a call, ``call_status`` is one of
    ``completed``, ``failed``, ``busy``, ``no_answer``, ``canceled``
    (the terminal set).

    Example:
        get_events(id="call:0c2f...-...", limit=200)

    Returns ``{"items": [...], "next_cursor": <str|None>,
    "call_status": <str|None>}`` on success, or
    ``{"error": ...}`` on a malformed ``id`` or upstream failure.
    
list_agentsA

List the workspace's saved agents: the brains that answer calls and texts on its numbers, and that place_call can use via agent_id.

    Returns ``{"items": [{"id", "name", "system_prompt", "first_message",
    "ai_disclosure", "ai_disclosure_line", "voice_config", "tools",
    "max_duration_seconds", "handover_max_duration_seconds", "voice_enabled",
    "sms_enabled", "status", "handover_contacts"}, ...]}``.
    
create_agentA

Save an agent. Then call route_number so a number answers with it, or pass its id as agent_id to place_call.

    ``system_prompt`` is what the agent follows. ``first_message`` is
    spoken after the AI line; omit it to let the caller speak first.
    ``ai_disclosure_line`` replaces the workspace AI line for this
    agent; ``{org}`` becomes the organization name. ``language`` is a
    lowercase ISO 639-1 code. ``max_duration_seconds`` is 60..3600.
    ``handover_max_duration_seconds`` (60..3600, default 1800) is the
    call limit once a handover contact answers.
    ``handover_contacts``: People the agent may hand a live call to:
    ``[{contact_id, note}]`` (max 10; ``note`` 1-200 chars says when to
    hand over). ``contact_id`` is an id from ``list_contacts``: a
    contact's uuid, or ``member:<user id>`` for a team member. The
    person needs a phone number. The agent never sees it.

    Returns the API's ``AgentResponse`` as a dict, or
    ``{"error": "<message>"}``.
    
route_numberA

Choose which agent answers a number's calls and texts.

    ``voice_agent_id`` makes the number answer calls with that agent
    (Hail registers it for inbound at the carrier and LiveKit);
    ``clear_voice=True`` stops answering calls. ``sms_agent_id`` makes
    the agent reply to texts; ``clear_sms=True`` stops that. A field
    left out keeps its value. ``number_id`` comes from GET /numbers.

    Returns the updated ``PhoneNumberResponse`` as a dict, or
    ``{"error": "<message>"}``.
    
quote_numbersA

Compare live phone-number offers from the carriers. Read-only: it buys nothing and charges nothing.

    ``country_code`` is an ISO alpha-2 code such as ``"US"``.
    ``capabilities`` is ``["voice"]``, ``["sms"]`` or both (default).
    ``number_type`` is ``local``, ``mobile``, ``national`` or
    ``toll_free``; omit it to compare all types.
    ``area_code`` is an area code or the first digits of the number, as
    dialed in the country: ``"020"`` (London), ``"480"`` (Arizona).
    ``city`` is a city name such as ``"London"``. Each offer has
    ``locality`` and ``region`` (such as ``"Phoenix"``, ``"AZ"``): check
    them, since city names repeat across states. ``region`` (optional,
    with ``city``) is a US/CA state code; list_number_regions lists them.
    Omit all three to search the whole country.

    Returns ``{"offers": [...], "recommended_quote_id", "expires_at"}``.
    Each offer has ``e164``, ``number_type``,
    ``capabilities``, ``monthly_cents``, ``setup_cents``, ``readiness``,
    ``requirements``, ``subject_types``, ``verifications`` and
    ``quote_id``. Money fields are cents (USD).
    Quotes expire in 10 minutes (``expires_at``); quote again after that.

    ``subject_types`` says who may verify for the number: ``person``
    (the user), ``business`` (the user's company), or both; empty when no
    verification is needed. ``verifications`` lists the verifications
    the offer can be bought with (``id``, ``state``, ``subject_type``,
    ``subject_name``), approved first: those of an accepted subject type
    still under review, and the approved ones the carrier still accepts
    for the offer. ``subject_name`` is the person's or company's name from the
    verification form. When several are approved, show the user the
    names and ask which one buys the number; pass its ``id`` as
    ``verification_id`` to acquire_number.

    An offer with ``readiness == "verification_required"`` cannot be
    bought until the organization is verified. Ask the user "you or your
    company?" to pick the ``subject_type`` (one of ``subject_types``).
    Call get_verification_requirements, ask the user for the details,
    then submit_verification, both with the offer's ``quote_id`` and that
    ``subject_type``, and poll get_verification (review takes business
    days). ``requirements``
    lists what the carrier needs. Prefer an offer whose
    ``readiness`` is ``"ready"``; ``recommended_quote_id`` points at the
    best one, or is null if none is ready.

    An offer with ``by_request: true`` has no ``e164``: support orders
    that number by hand. acquire_number refuses it; tell the user to ask
    support. Its ``quote_id`` still works for verification.

    Errors come back as ``{"error": "<message>"}``.
acquire_numberA

Buys a real phone number. It charges the setup fee and the first month now and renews monthly. Call quote_numbers first. Pass the offer's quote_id, country_code, number_type, and confirm_total_cents = monthly_cents + setup_cents from that offer. If the quote expired or the price changed (409) you get an error: quote again. Only buy when your user asked for this number. After buying, call route_number to point it at an agent.

    A quote buys at most one number. After a timeout, retry with the same
    quote_id and idempotency_key, or check list_numbers. Never request a
    new quote after a timeout.

    ``idempotency_key`` is optional; to retry after a timeout or a
    5xx, pass the ``idempotency_key`` that result returned, so the number
    is bought once. A 4xx error returns no key: the API remembers that
    failure under it, so drop it and quote again.

    ``verification_id`` picks which approved verification buys a number
    that needs one: the ``id`` of an approved entry in the offer's
    ``verifications``. Pass it when more than one is approved: show the
    user each ``subject_name`` (the person's or company's name) and ask
    which. With one approved, it is used. ``subject_type`` (``person`` or
    ``business``) is optional: it keeps only that kind. A 422 on
    ``verification_id`` means several are approved and none was picked,
    or the id is not an approved verification for this number.

    Returns the number (``id``, ``e164``, ``provisioning_state``,
    ``verification_id``, ``subject_name``, ...)
    plus ``idempotency_key``, or ``{"error": "<message>",
    "idempotency_key": ...}``.
list_numbersA

List the workspace's dedicated phone numbers, newest first.

    ``limit`` is 1..200 (default 50). Pass the returned ``next_cursor``
    as ``cursor`` for the next page.

    Returns ``{"items": [{"id", "e164", "country_code",
    "number_type", "capabilities", "provisioning_state", "voice_agent_id",
    "sms_agent_id", ...}], "next_cursor"}``, or ``{"error": "<message>"}``.
list_number_regionsA

List the US state and Canadian province codes that quote_numbers accepts as region (optional, with city).

    Returns ``{"regions": [{"country_code", "code", "name"}]}``, such as
    ``{"country_code": "US", "code": "AZ", "name": "Arizona"}``, or
    ``{"error": "<message>"}``.
get_numberA

Fetch one dedicated number by id: its state, capabilities and which agents answer its calls and texts. number_id comes from list_numbers.

    Returns the ``PhoneNumberResponse`` as a dict, or
    ``{"error": "<message>"}``.
release_numberA

Release a phone number. DESTRUCTIVE and permanent.

    Calls and texts to the number stop. This month's fee and any earlier
    months are still billed. There is no refund. The number may not be
    recoverable.
    Ask the user before calling this.

    ``confirm_e164`` must equal the number's ``e164`` (for example
    ``"+14155550100"``). The tool reads the number first and refuses with
    ``{"error": ...}`` on a mismatch, without releasing anything. A number
    whose order is still pending cannot be released (409). A number whose
    order failed was never bought: the call only hides it from the list
    and returns ``{"dismissed": true, "number_id", "e164"}``.

    Returns ``{"released": true, "number_id", "e164"}``, or
    ``{"error": "<message>"}``.
get_verification_requirementsA

Read what the carrier needs to verify the organization before it can buy a number. Call this when quote_numbers shows an offer with readiness == "verification_required". Read-only.

    ``country_code`` is ISO alpha-2 (for example ``"GB"``). ``number_type``
    is ``local``, ``mobile``, ``national`` or ``toll_free``.
    ``subject_type`` is required: ``person`` (the user) or ``business``
    (the user's company). Never guess it: ask the user "you or your
    company?". The result's ``subject_types`` lists what the carrier
    accepts. The organization may hold one verification of each. ``quote_id`` is the
    offer's ``quote_id`` from quote_numbers. It is required for
    ``purpose='number'``: the form is the one for that offer.

    ``purpose`` is ``number`` (default, to buy a number) or ``sms``.
    ``purpose='sms'`` registers the organization to text US numbers from a
    US number (country_code US, number_type local). Fees are charged from
    credit per step: when the details are submitted, when the carriers
    start their review, then monthly after approval. If the error says to pass
    ``number_id``, pass the ``id`` of one of the organization's US numbers
    from list_numbers.

    Returns ``required`` (false means no verification is needed and
    submit_verification would fail), ``fields`` (values to collect),
    ``documents`` (slots, each with ``options``), ``address_required``.
    A field of kind ``choices`` takes several of its ``options``: send
    their keys joined by commas (for example
    ``"CUSTOMER_CARE,DELIVERY_NOTIFICATION"``), between ``min_choices``
    and ``max_choices`` of them.
    A field with ``max_length`` takes at most that many characters,
    counted in UTF-16 code units (an emoji counts as 2); a longer value
    is refused (422).
    Skip any document slot whose ``needs_input`` is false: do not send it.

    Ask the USER for every value and every file. Never invent, guess or
    infer personal or company data. Never reuse data from another task.

    Errors come back as ``{"error": "<message>"}``.
submit_verificationA

Send the user's personal or company details and identity documents to the carrier for verification. IRREVERSIBLE: once submitted it cannot be cancelled, and the carrier keeps the documents.

    ``attest_authorized``: pass true only if the person or company named
    in these details and documents asked for this submission and gave you
    the details and files in this conversation. Never invent, guess, infer
    or reuse personal data or documents. Anything else: pass false (the
    call then sends nothing).

    ``purpose`` is ``number`` (default) or ``sms``. ``purpose='sms'``
    registers the organization to text US numbers from a US number
    (country_code US, number_type local). The carrier fee is debited from
    credit at filing. Pass the same ``purpose`` to
    get_verification_requirements. For ``purpose='number'``, pass the
    same ``quote_id`` you passed to get_verification_requirements. For
    ``purpose='sms'``, pass the same ``number_id`` if you passed one.

    ``subject_type`` is required: ``person`` (the user) or ``business``
    (the user's company), the same one passed to
    get_verification_requirements. Never guess it: ask the user "you or
    your company?".

    The verification is named after the person or company in the form
    (for example the business name, or the first and last name); it
    comes back as ``subject_name``. The organization may hold several
    verifications of one subject type (several people or companies).

    Steps: 1) call get_verification_requirements. 2) Ask the user for each
    field and file. 3) Call this once. Do not submit twice: a 409 means
    one with the same subject type and name already exists (see
    list_verifications).

    Arguments, as listed by get_verification_requirements:
    ``fields`` is ``{field name: value}``. ``address`` is
    ``{"customer_name", "street", "city", "region", "postal_code",
    "country_code"}`` (all required when ``address_required``).
    ``documents`` is ``{slot: {"option": <option key>, "fields": {...}}}``
    for each slot with ``needs_input``. ``files`` is a list of
    ``{"slot", "content_type", "content_base64"}``, one per slot that
    needs a file; ``slot`` must be a key in ``documents``
    and match letters, digits, - and _ (at most 64).
    ``content_type`` is ``image/jpeg``, ``image/png`` or
    ``application/pdf``. Limits: 10 MiB per file, 29 MiB in total, at
    most 20 files and 20 fields. Compress images to JPG or PNG under about
    7 MiB so the call stays small.

    Returns the verification: ``id``, ``state`` and ``subject_name``.
    Review takes business days and nothing notifies you: poll
    get_verification. If the carrier finds a problem you get
    ``{"error", "problems": [{"loc", "msg"}]}`` and nothing is stored:
    ask the user to fix it, then submit again. After a timeout call
    list_verifications before trying again.
list_verificationsA

List the organization's carrier verifications, newest first.

    ``purpose`` is ``number`` or ``sms``; only that kind is listed.
    Omit to see every registration. ``purpose='sms'`` lists the
    registrations to text US numbers from a US number.

    Returns ``{"items": [{"id", "country_code", "number_type",
    "subject_type", "subject_name", "purpose", "state",
    "rejection_reason", "created_at",
    "updated_at", "submitted_at", "approved_at", "confirmation",
    "step", "identity_confirmed"}]}``. ``step`` says where a US texting
    filing in progress is: ``confirm_identity``, ``filing`` or
    ``carrier_review``. ``identity_confirmed`` on a person's newest
    filing, when cancelled or rejected: the next one with the same person
    needs no code. Dismiss a rejected filing first.
    ``state`` is ``awaiting_review``, ``submitting``, ``submitted``,
    ``approved``, ``rejected`` or ``cancelled``. Use it to check whether a
    submission already exists before submitting again. ``confirmation``
    ``code``: call confirm_verification with the code the carrier texted
    the person.

    Errors come back as ``{"error": "<message>"}``.
get_verificationA

Fetch one verification and its state. Use it to poll.

    There is no notification, and review takes business days. Poll every
    few minutes to hours, not every few seconds; the state refreshes from
    the carrier at most once a minute.

    On ``approved``: call quote_numbers again. The offer is now
    ``ready``; then acquire_number. On ``rejected``: read
    ``rejection_reason``, ask the user, dismiss it with
    cancel_verification, then submit a new one. ``verification_id`` comes
    from submit_verification or list_verifications.

    Returns ``{"id", "state", "rejection_reason", ...}`` or
    ``{"error": "<message>"}``.
cancel_verificationA

Cancel a verification that has not been sent for review, or dismiss a rejected one (needed before submitting a new one for the same country and number type). The draft is discarded.

    Works in state ``awaiting_review`` or ``rejected``, and for an
    ``approved`` US SMS registration (``purpose: "sms"``): its numbers
    leave the campaign, US-to-US texts from them fail again, and its
    monthly fee stops after the current month. Some registrations bill at
    least 3 monthly fees from approval, so cancelling sooner can still
    charge 3 months. Ask the user first. A
    ``submitting`` or ``submitted`` verification is under review and
    cannot be cancelled (409): wait for the result with get_verification.

    Returns the verification with ``state: "cancelled"``, or
    ``{"error": "<message>"}``.
confirm_verificationA

When a registration shows confirmation 'code', ask the person for the code the carrier texted and submit it here.

    ``verification_id`` comes from submit_verification or
    list_verifications. ``code`` is 4 to 10 characters. A wrong or expired
    code is an error naming ``code``; the carrier sends a new one after a
    day. On success the registration moves on; poll get_verification
    until ``approved``. A ``confirmation`` of ``reply`` means the person
    answers the carrier's text instead; nothing is entered here.

    Returns the verification or ``{"error": "<message>"}``.
get_agentA

Fetch one saved agent by id. agent_id comes from list_agents or create_agent.

    Returns the ``AgentResponse`` as a dict (``name``, ``system_prompt``,
    ``first_message``, ``ai_disclosure``, ``voice_config``, ``tools``,
    ``voice_enabled``, ``sms_enabled``, ``status``, ...), or
    ``{"error": "<message>"}``.
update_agentA

Change a saved agent. Safe to repeat: the same call gives the same result.

    Only the fields you pass change; a field left out keeps its value.
    ``status`` is ``"live"`` or ``"paused"``; a paused agent does not
    answer. ``language`` is a lowercase ISO 639-1 code. Pass ``language``
    or ``voice_id`` alone: the other value is kept. ``max_duration_seconds``
    and ``handover_max_duration_seconds`` are 60..3600.
    ``handover_contacts`` replaces the whole list: ``[{contact_id, note}]``
    (max 10) as in ``create_agent``; ``[]`` removes every contact.

    To remove a value, list its name in ``clear_fields``. Allowed:
    ``first_message`` (the agent waits for the caller),
    ``ai_disclosure_line`` (back to the workspace line), ``tools``
    (back to all tools), ``max_duration_seconds`` (back to the workspace
    limit), ``handover_max_duration_seconds`` (back to 1800). Any other
    name is refused. Do not set and clear one field.

    Live calls keep the settings they started with. The change applies
    to the next call or text.

    Returns the updated ``AgentResponse`` as a dict, or
    ``{"error": "<message>"}``.
delete_agentA

Delete a saved agent. DESTRUCTIVE. Ask the user before calling this.

    Numbers that used the agent stop answering with it: calls ring out
    and texts reach webhooks only. Reroute them first with
    ``route_number`` if that matters.

    ``confirm_name`` must equal the agent's ``name``. The tool reads the
    agent first and refuses with ``{"error": ...}`` on a mismatch,
    without deleting anything. To stop an agent without deleting it, use
    ``update_agent`` with ``status="paused"``.

    Returns ``{"deleted": true, "agent_id", "name"}``, or
    ``{"error": "<message>"}``.
list_contactsA

List the workspace's contacts: org members (with their phone/email) plus manually saved contacts. Use lookup_contact for name searches.

    ``q`` optionally filters server-side (matches name/email/phone).
    ``limit`` caps the page (server default 100, max 500).

    Returns ``{"items": [{"id", "kind", "name", "phone_e164", "email",
    "role"}, ...]}`` — ``kind`` is ``"member"`` (id ``member:<user_id>``,
    ``role`` set) or ``"manual"`` (id is the contact's UUID, ``role``
    null).
    
lookup_contactA

Find a contact by name, email, or phone fragment. Resolve a person to their phone_e164/email BEFORE calling place_call, send_sms, or send_email — do not guess a contact's number.

    Returns up to 10 matches, same item shape as ``list_contacts``.

    Example:
        lookup_contact(query="maya")
    
list_email_domainsA

List the addresses this workspace can send email from. Call this BEFORE send_email when you do not already know the from_ address — do not guess a domain.

    Returns ``{"items": [...], "next_cursor": ..., "default_from": ...}``.
    Each item carries ``domain``, ``kind`` (``"custom"`` or
    ``"hail_mail"``) and ``verification_status``; only ``"verified"``
    rows can send. A ``custom`` item's ``domain`` is a bare DNS name
    that accepts any local-part (``sales@acme.com``); a ``hail_mail``
    item's ``domain`` is already a full address.

    ``default_from`` is the address a ``send_email`` with no ``from_``
    goes out as. It is null when the workspace has several verified
    identities — then ``send_email`` rejects a missing ``from_`` and you
    must pass one from ``items``.

    Example:
        list_email_domains()
    
whoamiA

Identify the human whose credentials this session runs under.

    Use it to sign or route mail as that person: pass their address as
    ``send_email(reply_to=...)`` so replies reach them rather than the
    sending domain, which is often an unattended ``noreply@``.

    Returns ``{"auth_kind", "organization_id", "user_id", "email",
    "name"}``. ``user_id``/``email``/``name`` are null when the server
    runs on a shared operator key (``auth_kind="shared"``) — there is no
    human behind it, so send without a ``reply_to``.

    Example:
        whoami()
    
create_contactA

Save a new contact for the workspace. Provide at least one of phone_e164 (E.164, e.g. +14155551234) or email — the API rejects (422) a contact with neither. A duplicate phone or email on an existing contact returns 409.

    Example:
        create_contact(name="Maya Chen", phone_e164="+14155551234")

    Returns the created contact entry as a dict. On failure returns
    ``{"error": "<message>"}`` instead.
    

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

A3.9/5.0

Scored across 38 tools

Disambiguation4/5

Most tools target a clearly distinct resource and action, and the detailed descriptions help separate calls, SMS, email, numbers, agents, and verification. A few overlaps remain, especially get_email_events versus get_events narrowed to an email, and lookup_contact versus list_contacts with a query filter.

Naming Consistency4/5

The set is overwhelmingly snake_case with predictable verb_noun naming such as list_calls, send_email, get_agent, and route_number. The main deviations are whoami, which does not follow the pattern, and some domain-specific verbs like quote_numbers and lookup_contact.

Tool Count2/5

The surface is broad, covering telephony, SMS, email, agents, numbers, contacts, and verifications, but 38 tools is heavy for a single MCP server. A set this large increases selection burden and could reasonably be split by domain.

Completeness4/5

Core lifecycle coverage is strong: calls, SMS, email, numbers, agents, and carrier verifications all have create/read/list/update or state-management operations where appropriate. Minor gaps exist, such as no update/delete contact tools and only listing email domains rather than managing them through the MCP surface.

Maintenance

ActivityActive
ResponsivenessSyncing