MCP Servers
Give an assistant the tools of an MCP server during a call, such as searching a mailbox or looking up a customer in your CRM, with the headers you choose for authentication.
An MCP server offers tools over the Model Context Protocol. Connect one to an assistant and it can use those tools during a call, the same way it uses your custom tools: search a mailbox while the caller waits, look up an order, check a calendar.
You add the server once to your organization, then attach it to as many assistants as you like.
This page is about MCP servers that your assistants use during a call. To let an AI coding assistant such as Claude Code manage your VoiceDock account, see VoiceDock's own MCP server.
How it works
- You add the server with its URL and the headers it needs, such as an API key.
- You attach it to an assistant with a tool of type
mcp, and choose which of its tools the assistant may use. - When a call comes in, the platform connects to the server and fetches its tools before the call is answered.
- During the call the model calls those tools when it needs them. The platform sends each call to your server and gives the result back to the model.
Add a server
curl -X POST https://api.hmsovereign.com/api/v1/mcp-servers \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Mailbox",
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_SERVER_TOKEN"
}
}'{
"mcp_server": {
"id": "2f1c9a7e-4b3d-4e8a-9c21-6d5f0b7a8e13",
"name": "Mailbox",
"url": "https://mcp.example.com/mcp",
"transport": "streamable_http",
"header_names": ["Authorization"],
"timeout_seconds": 20,
"created_at": "2026-09-29T10:00:00Z",
"updated_at": "2026-09-29T10:00:00Z"
}
}| Field | Notes |
|---|---|
name | Unique within your organization. |
url | Must use https:// and resolve to a public address. Stored in its normalized form, so the API may return it with a lowercase host or a trailing slash. |
transport | streamable_http (default) for current MCP servers; sse only for a server that offers nothing else. |
headers | Sent with every request to the server. Up to 10. |
timeout_seconds | How long the platform waits for the server on each request, including a tool call during a conversation. 5 to 60, default 20. |
You can also add servers in the dashboard, under MCP servers. Open a server there to see the tools it offers right now, which assistants use it and which of its tools they may call, and to replace or remove its headers. On an assistant, you attach a server under MCP servers and tick the tools it may use.
Authentication
The platform authenticates with the headers you give it, and nothing else. There is no sign-in flow to set up: you obtain a token or API key from the server's provider, and pass it as a header.
| Your situation | What to do |
|---|---|
| The server takes a fixed API key | Set it once in headers |
| Your token expires | Renew it yourself and update the server with PATCH /mcp-servers/{id} |
| Each caller has their own token | Pass it per call with mcp_headers, see below |
| The server needs no authentication | Leave headers out |
Header values are write-only. They are stored encrypted and never returned by the API or shown in the dashboard; header_names tells you which are set. To change one, send all headers again in a PATCH: headers replaces the stored set. Send "headers": {} to remove them.
The platform only ever sends your headers to the address you entered. If the server redirects to a different host, the request is refused, so a key meant for one server never reaches another. The same holds when you move a server: a PATCH that points url at a different host must send headers in the same request, or {} if the new host needs none. Without them the request is refused and the stored headers stay where they were.
Put credentials in headers, not in the URL: the URL is returned by the API and shown in the dashboard.
Attach it to an assistant
Add a tool of type mcp to the assistant's llm_config.tools:
{
"llm_config": {
"tools": [
{
"type": "mcp",
"mcp_server_id": "2f1c9a7e-4b3d-4e8a-9c21-6d5f0b7a8e13",
"allowed_tools": ["search_mail", "read_mail"],
"required": true
},
{ "type": "end_call" }
]
}
}| Field | Notes |
|---|---|
mcp_server_id | The id of the server. Attach each server once. |
allowed_tools | Required. The tools the assistant may use, by name, at most 25. The connection test shows the names. |
required | true by default. See when the server cannot be reached. |
You attach a set of tools, not a whole server. The model only sees what you list, a tool the server adds later does not reach your callers until you list it, and every tool you offer is one more option the model weighs on each turn. An assistant can use at most five MCP servers.
A listed tool must not have the name of another tool of the assistant, such as one of your custom tools, and end_call and transfer_call cannot be listed at all: they are the built-in tools. Add those as built-in tools if the assistant needs them.
Test the connection
curl -X POST https://api.hmsovereign.com/api/v1/mcp-servers/2f1c9a7e-4b3d-4e8a-9c21-6d5f0b7a8e13/test \
-H "Authorization: Bearer YOUR_API_KEY"{
"ok": true,
"duration_ms": 412,
"tools": [
{
"name": "search_mail",
"description": "Search the mailbox for messages that match a query",
"input_schema": { "type": "object", "properties": { "query": { "type": "string" } } }
}
]
}The test connects from the platform, the same way a call does, and returns the tools with their exact names for allowed_tools. When the server cannot be reached you get "ok": false and the reason, such as an HTTP 401 that points at the headers.
Headers per call
For a token that belongs to the caller, or one you renew for every call, return mcp_headers from your assistant-request webhook. It maps a server id to its headers for this call:
{
"assistant_id": "80e53f65-fa68-4d6d-afe4-2f8dee19caed",
"mcp_headers": {
"2f1c9a7e-4b3d-4e8a-9c21-6d5f0b7a8e13": {
"Authorization": "Bearer TOKEN_FOR_THIS_CALLER"
}
}
}These headers are merged over the stored ones; a name you send here wins, regardless of letter case. They are used for this call only and are not stored: in the webhook log their values show as [redacted]. mcp_headers works with a saved assistant, a hybrid one and a transient one.
To try a per-call token before you use it, send it in the body of the test: {"headers": {"Authorization": "Bearer ..."}}. It is not stored either.
When the server cannot be reached
The platform connects to the server when a call comes in, before it is answered, and allows four seconds for that.
- With
required: true, a call is rejected when the server cannot be reached or when a tool fromallowed_toolsis missing. The caller hears the error message, and the reason is in the call log and in the status-update webhook. An assistant that promises to look something up and then cannot is worse than a clear message. - With
required: false, the call goes ahead without the server's tools, and the call log says so. Use this when the assistant is useful without the server.
A tool name that clashes with another tool of the assistant always rejects the call, whatever required says.
During the call, a tool call that fails or takes longer than timeout_seconds is reported to the model as a failed tool call, so it can tell the caller. A token that you update with PATCH is used from the next call on; calls in progress keep the connection they opened.
What the model receives
The result of a tool call goes to the model as text. Content a voice model cannot use, such as an image, is replaced by a short note. A result longer than 32,000 characters is cut off, with a note that it was; design tools that return what the caller needs, not everything the server has. The platform asks the server for uncompressed answers. An answer larger than 5 MB, or a compressed one, is not read and counts as a failed tool call.
The model reads that text the way it reads what the caller says, so instructions in an email or a web page that a tool returns can steer its next step. Choose allowed_tools and the other tools of the assistant with that in mind.
Each tool call appears in the call log with the server, the tool, how long it took and whether it succeeded. The arguments and the result are not logged.
Prompting
Tell the assistant in its prompt what the server is for and when to use it: "When the caller asks about an email, search the mailbox with search_mail before you answer." Say what to do while it waits, and what to say when nothing is found.
On GPT-Live, the tools of an MCP server are called by the backend model, like any other tool. Add what the server can do to the delegation block in the system prompt, such as "Search the caller's mailbox.", so the voice model knows which requests to hand over. The GPT-Live page shows that block.
Workflows
An MCP server belongs to the assistant, not to a workflow step. Attached to the assistant, its tools are available in every step of a workflow. A tool of type mcp on a workflow node is rejected.
Related
- Custom Tools — webhook tools and the built-in tools
- Webhooks — the assistant-request webhook and
mcp_headers - OpenAI GPT-Live — tools on a model with a backend
- VoiceDock's own MCP server — manage your account from an AI coding assistant