Skip to content

MCP servers

MailKey serves two Model Context Protocol (MCP) servers over Streamable HTTP. They are separate doors for separate people:

Door Endpoint
Business: a business’s AI voice agent taking a key over the phone. Signs in with the business’s API key. https://mcp.mkey.ai/business
Staging: https://mcp-staging.mkey.ai/business
Personal assistant: a person’s own AI assistant. Signs in with OAuth, approved by the person. https://mcp.mkey.ai/mcp
Staging: https://mcp-staging.mkey.ai/mcp

Neither door serves SSE; choose Streamable HTTP in your client.

The business door gives a voice agent the same lookup, read-back and claim flow a phone rep uses. A voice agent is treated like a rep: its reading of the masked preview and the caller’s yes are the read-back, and its claims follow the same approval rules as any other claim from your business.

Send your business’s API key, the same mk_live_... key the REST API takes, as Authorization: Bearer mk_live_.... A bare mk_live_... without Bearer is accepted too. There is no OAuth on this door. The key only works for a business in production; a business in demo mode gets 403.

Every tool forwards to the matching route under /v1/voice, documented in the API reference under Voice agents, so the two behave the same way.

Tool Input Returns
decode_key transcript, exactly what the caller said (at most 500 characters) Up to five valid keys it could mean, best first, each with spoken, the key read in NATO words, group by group. Looks nothing up.
preview_key key, call_id preview_id, say (for example “Zoë v. in Washington, District of Columbia”), expires_at, previews_left
claim_key preview_id, call_id, optional external_ref The name and address with a say sentence, or a pending answer while the person approves the claim
get_grant grant id The grant and, while it is active, the name and address

call_id is the phone call’s id from your voice platform. A preview belongs to the call that made it, each call gets 3 lookups, and a claim must come inside your business’s claim window. When a tool refuses, its error text is worded for the agent to act on, such as “Look the key up again and read the preview back.”

ElevenLabs Agents is the reference integration. Field names below were checked against the ElevenLabs documentation; confirm them in the ElevenLabs UI, which can change.

Before you start. Make sure your business is in production, then create an API key named ElevenLabs in the business console and copy the secret. Build on staging first: https://mcp-staging.mkey.ai/business with a staging key.

Create the agent.

  1. In ElevenLabs, Agents, create a blank agent.
  2. First message: Hi, you've reached <business>. I'm an AI assistant and this call may be recorded. Do you have your MailKey handy? Your business is responsible for AI disclosure and recording consent on its calls.
  3. System prompt: paste the prompt below.
  4. Pick a voice and an LLM. Reliable tool calling matters more than voice quality here.

Add MailKey as an MCP server. MCP servers are off by default in ElevenLabs; turn them on for the workspace first. They are not available in Zero Retention Mode or HIPAA workspaces.

  1. Integrations (MCP servers), Add custom MCP server:
    • Name: MailKey
    • Description: Look up, read back and claim a caller's MailKey.
    • Server URL: https://mcp.mkey.ai/business (staging: https://mcp-staging.mkey.ai/business)
    • Transport: Streamable HTTP
    • Secret Token: a workspace secret holding the bare mk_live_... key. ElevenLabs adds Bearer itself, so a secret that already starts with Bearer fails to connect.
    • HTTP headers: none. The call id travels in the call_id argument.
  2. Add the integration. ElevenLabs tests the connection and lists decode_key, preview_key, claim_key and get_grant. A 401 means a wrong key; a 403 means the business is still in demo mode.
  3. Tool approval: choose fine-grained approval and set all four tools to run without asking. An approval prompt would stop the call mid-sentence with no one to answer it.
  4. Attach the integration to the agent.

Or use webhook tools. If you cannot use MCP, add four Webhook tools on the agent instead, calling POST /v1/voice/decode, POST /v1/voice/previews, POST /v1/voice/grants and GET /v1/voice/grants/{id} on https://api.mkey.ai. Give each an Authorization header from a secret holding Bearer mk_live_... (with the Bearer prefix this time; the HTTP routes refuse a bare key) and an X-Call-Id header set to {{system__conversation_id}}.

Connect a phone number. In Phone Numbers, import your Twilio number (or a SIP trunk) and assign the agent to it.

{{system__conversation_id}} is filled in by ElevenLabs. Replace {{business_name}} with your business’s name if your agent does not set that variable.

You answer phone calls for {{business_name}}. You can save a caller's exact name
and mailing address with MailKey, using the 10-character key from their MailKey
app. This call's id is {{system__conversation_id}}; when a MailKey tool takes
call_id, pass exactly that value.
Getting the key:
- Ask the caller to read their key in its three groups: three, three, then four
characters, such as "K 7 M, X Q Q, D 9 R A".
- Read each group back with NATO words ("Kilo Seven Mike") and ask the caller to
confirm it before moving on.
- If you are unsure of any character, call decode_key with exactly what you heard
and read the first candidate's "spoken" text back, group by group. If the caller
says no, try the next candidate or ask them to read the key again.
- If preview_key says the key is not valid, do not ask the caller to repeat it
yet: call decode_key with exactly what the caller said, read the first
candidate's "spoken" text back, and preview that key once the caller agrees.
- Never ask the caller to type the key on the keypad.
Reading back and claiming:
- Call preview_key with the key. Read its "say" sentence to the caller word for
word, such as "Zoë v. in Washington, District of Columbia", and ask "Is that you?"
- Only after a clear yes, call claim_key with that preview_id. If the caller says
no, ask them to read the key again and look it up again.
- Tell the caller the "say" sentence claim_key returns.
- Each call allows 3 lookups. If the tools say the lookups are used up, ask the
caller to check their key in the MailKey app and call back.
- If a tool says the time ran out or the preview came from another call, look the
key up again and read the preview back again.
- Do not read the full address aloud; the masked preview is the confirmation.
- Names come exactly as the person typed them; never change their spelling.

There is no keypad entry: phone keypads cannot type a key’s letters.

  1. Call the number, read a staging key, and check the agent reads back the masked name and city. Say yes; the grant appears in the business console’s grant list.
  2. Call again and read the key with one character wrong. The agent should call decode_key, read back the right key and recover.

The /mcp door lets a person connect their own AI assistant, such as a chat app that supports remote MCP servers, so it can address an envelope or fill in a shipping form without asking them to type their address.

Add https://mcp.mkey.ai/mcp as a custom connector or remote MCP server in the assistant. The server is an OAuth 2.1 authorization server and protected resource:

  • Discovery: /.well-known/oauth-protected-resource/mcp names the authorization server, and an unauthenticated call answers 401 with a resource_metadata challenge.
  • Clients register themselves through dynamic client registration (/register) or a client ID metadata document.
  • The one scope is address.

The person signs in to MailKey and sees a consent screen naming the assistant, whether its name is verified (by its published domain) or self-registered, and where the access goes. They choose whose addresses it may read: their own, and those of other adults whose MailKey they manage. Then they allow or deny.

Tool What it does
get_mailing_address Returns the exact name, as typed, with a ready-made display name for the envelope, and the current standardized address of the person who connected it. With person_id, another adult they chose. Every answer lists the people it may ask for.
create_one_time_key Makes a one-time MailKey for the person, to hand to a business or friend. It ends at its first use or after 1h, 24h or 7d (default 24h).
list_address_book Lists the names and addresses friends shared with the person. Works only after the person turns on address-book access for that assistant.

The server tells the assistant to ask for the address each time it needs it rather than keep a copy, because the address changes when the person moves.

  • Every read shows in the person’s Address Leases, where they can disconnect the assistant at any time. A disconnected assistant’s tokens stop working at once.
  • A move or key replacement that leaves the assistant out also disconnects it.
  • Children’s addresses are never shared with assistants.
  • An assistant cannot read the address book unless the person turns that on.