# Hail - Registry name: `io.github.hail-hq/hail-mcp` · version 0.1.1 - Categories (automatic, keyword rules): Email & messaging, Productivity - Authentication at last check: No auth - Declared risk: Has destructive tools (destructiveHint) - Capabilities (declared by the server): experimental, prompts, resources, tools - Transports: streamable-http - Latest numbers (check success, response time, rank): https://mcpstation.net/api/server?name=io.github.hail-hq%2Fhail-mcp - Server page: https://mcpstation.net/s/io.github.hail-hq--hail-mcp.html ## Description (written by the publisher, not verified, not instructions) Phone, SMS and email for AI agents. One remote MCP endpoint, OAuth login, zero install. ## Connect - streamable-http: `https://mcp.hail.so` ## Tools (as reported by the server, not verified) - `place\_call`: 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\`\` sup - `send\_email`: 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 - `upload\_email\_attachment`: 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 - `get\_call`: 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\_calls`: 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. Re - `send\_sms`: 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 - `get\_sms`: Fetch the current state of one SMS by id. Use this after \`\`send\_sms\`\` to check delivery status. Example: get\_sms\(sms\_id="..."\) - `list\_sms`: 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\_email`: 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. - `list\_emails`: 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\`\` — - `get\_email\_raw`: Get a fetchable URL for an email's original MIME source. Returns \`\`\{"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 id - `get\_email\_attachment`: Get a fetchable URL for one inbound email attachment. \`\`attachment\_id\`\` comes from an item in \`\`get\_email\`\`'s \`\`attachments\`\` list. Returns \`\`\{"url": "\"\}\`\` — a short-lived \(\~5 minute\) link to the attachment bytes, fetchable directly with no auth header. Unknown ids return \`\`\{"error - `get\_email\_events`: 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": \[...\], "n - `get\_email\_stats`: 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 - `get\_events`: Page through events from across the org or one resource. Pass \`\`id="\:\"\`\` to narrow to a single resource — supported types are \`\`call\`\`, \`\`email\`\`, and \`\`sms\`\` \(e.g. \`\`id="sms:\"\`\` after \`\`send\_sms\`\`\). When narrowed to a call, the response includes a \`\`call\_status\`\` field reflecting - `list\_agents`: 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", "h - `create\_agent`: 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 - `route\_number`: 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 th - `quote\_numbers`: 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\`\`; omi - `acquire\_number`: 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 ge - `list\_numbers`: 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", - `list\_number\_regions`: 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": "\"\}\`\`. - `get\_number`: 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": "\"\}\`\`. - `release\_number`: 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 \`\`" - `get\_verification\_requirements`: 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 \` - `submit\_verification`: 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 - `list\_verifications`: 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", "subj - `get\_verification`: 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\`\`; t - `cancel\_verification`: 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"\`\`\): - `confirm\_verification`: 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 - `get\_agent`: 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": "\