Using MCP Server Tools in Voice Live - Differences from Function Calling and Parallel Tool Calls
- Azure
- MicrosoftFoundry
- VoiceLiveAPI
- MCP
- AI
Trying MCP Server Tools in Voice Live
I wanted a voice-conversation agent to be able to look things up using external tools, so I tried it with the Voice Live API.
The Voice Live API is an API for building agents that converse using voice. There are two ways to make the model use tools:
- function calling: The client defines the tools and executes them in response to calls from the model
- MCP server: An MCP (Model Context Protocol) server is registered with the session, and the Voice Live service calls the tools
This article describes how MCP server tools differ from function calling, the setup, and what happened when I actually ran it and how I addressed it. It also describes parallel tool calls, where multiple tools are used to answer a single question. This is the third installment in the Voice Live feature explanation series.
List of articles in the series (SDK 1.2.0 / API 2026-07-15)
- Changes in Voice Live SDK 1.2.0 and API 2026-07-15 GA
Classifying Features That Lack Types in the SDK - Handling Conversation “Pauses” with the Voice Live API
Speak first, wait for hesitation, interrupt, and speak during wait times -
Improving Voice Live Audio Input Quality
Choosing Noise Suppression, Echo Cancellation, and Live-Reference AEC - Using MCP Server Tools in Voice Live (This Article)
Differences from Function Calling and Parallel Tool Calls -
Calling a Foundry Agent as a Tool in Voice Live
How to use the chat-supervisor pattern and choose the model for the preceding stage -
Making a Microsoft Foundry Agent Speak with a “Voice of Your Own” Created from 30 Seconds of Audio
From Applying for Personal Voice to Implementation -
Choosing Among Voice Live API Avatars
Configuring and implementing standard, custom photo, and custom video -
Receiving Voice Live avatar video over WebSocket
Differences from WebRTC and video formats
Bonus episode: Connecting to Voice Live's WebRTC audio connection with SIPSorcery for .NET
A record of comparing the SDP line by line
The code used for validation is available here.
This article reflects information as of October 2026. It applies to Voice Live API 2026-07-15 (GA) and the .NET SDK Azure.AI.VoiceLive 1.2.0.
Preparation
You can get set up by following the official quickstart from resource creation through running your first voice conversation in C#. See the Voice Live overview page for supported regions.
When trying the content of this article in the quickstart environment, note the following points.
-
When using MCP, set the API version to 2026-04-10 or later
- The parallel tool calls setting (parallel_tool_calls) is available with API version 2026-06-01-preview or later
- Use the Azure.AI.VoiceLive 1.2.0 .NET SDK
How tools are invoked in Voice Live
In function calling and MCP, tools are executed in different places.
| function calling | MCP server | |
|---|---|---|
| Tool definition | Passed by the client in session.update | The client registers the MCP server, and the service retrieves the list of tools |
| Tool execution | Client | Voice Live service |
| What is sent to the client | function_call (tool name and arguments) | Execution notification (such as response.mcp_call.completed) |
| Tool result | Sent by the client via function_call_output | Used as-is by the service |
| Request for a response using the result | The client sends response.create | The client sends response.create |
The last line is the same for either approach. To respond using the tool result, the client sends response.create. Voice Live rejects overlapping responses, so this request must be sent only once. MCP Issue 1, introduced later, and parallel tool calls both relate to this rule.
The pattern in which the client declares tools (function calling, MCP) pertains to the Model session. In an Agent session, tools are managed and executed by the agent (on the cloud side).
MCP server registration
With SDK 1.2.0, it can be written using types.
To use MCP, API version 2026-04-10 or later is required.
The default value for require_approval is always. If omitted, an mcp_approval_request is sent to the client every time a tool is called, and the tool is not executed until the client returns mcp_approval_response (approve=true). If approval handling is not implemented, the conversation stops there. To have it run automatically, explicitly specify never. You can also separate them by tool, such as {"never": [...], "always": [...]}.
Issues encountered when running MCP
The sample uses deepwiki, a public MCP server (which answers questions about GitHub repository wikis), asks about the configuration of microsoft/vscode, and confirms that the tool is executed on the server side. During this process, the following occurred.
Issue 1: No response is generated after the tool is executed
MCP tools are executed on the server, but it is the client's role to send response.create using those results to generate a response.In Voice Live, MCP is treated as one form of tool, and, just like function calling, it does not automatically begin a response even when all tool results are in (the last row of the table mentioned above). In Foundry agents as well, MCP is configured as one of the tools, alongside functions, web search, and so on. The OpenAI Realtime API has the same behavior, and the official guide states that it "does not continue automatically."
After receiving response.mcp_call.completed, confirm that the response that invoked the tool (response 1) has closed, and then the client requests the next response (the sample in the official how-to guide is structured the same way).
An MCP call can complete while the response that invoked it is still open. Because responses cannot overlap, the sample tracks whether a response is in progress and, if it is, waits for response.done before making a request.
Solution: Send the response request only once
In actual testing, response.done → response.mcp_call.completed sometimes arrive in that order, so the order cannot be relied upon. The sample keeps a count of "responses that should be requested," and makes only one request, regardless of which arrives later.
Issue 2: Answering from its own knowledge without calling a tool
This may be a common occurrence in the world of agents. Even when an MCP server is registered, the model will often answer using its own knowledge without calling a tool. It is difficult to distinguish this at a glance from the MCP configuration being broken. In particular, because we were also checking the operation this time, the MCP server we used may not have been well suited to the task.
Solution: Guide the model to use tools through instructions
The sample explicitly states in the session instructions, “Always use tools for questions about repositories.”
You can verify whether the tools were actually called by checking for MCP call entries in response.output_item.done. If they do not appear there, the model answered on its own.
Challenge 3: The tool result is large
deepwiki has a tool called read_wiki_contents that returns the full text of the wiki. When called, it returned a result of approximately 620KB. Since this becomes the input for the spoken answer as-is, I think it is unsuitable for answering via voice.
Solution: Restrict the tools that are used
The sample uses instructions to guide the model to use ask_question for short answers. To reliably restrict them, limit the tools that may be used with allowed_tools in the server definition (AllowedTools in the SDK).
Challenge 4: The items are empty when they are created
The MCP tool list and tool invocation entries are empty at the point of conversation.item.created (both the tool list and the invocation arguments and results). Their contents are populated only after mcp_list_tools.completed or response.output_item.done.
Solution: Display them after their contents have been populated
Displaying them at conversation.item.created results in the incorrect display of “0 tools” and “No results,” so display and record them at mcp_list_tools.completed or response.output_item.done.
Parallel tool calls
When a single question requires multiple tools (for example, “What is the weather and time in Tokyo?”), the model calls multiple tools within a single turn. This is parallel tool calling. In function calling, multiple function_call entries arrive within a single response.
The default value of parallel_tool_calls is true. If set to false, the model can call tools one at a time in sequence. In SDK 1.2.0, this can be configured with VoiceLiveSessionOptions.AllowParallelToolCalls.
The important point is that you send all tool results and then send response.create only once. If you send response.create every time you send a result, the response will be triggered twice, resulting in an error.
| How to send it | Result |
|---|---|
| response.create for each result | Error because it attempts to respond twice |
| Once, after sending all results | get_weather / get_time are each called once, with no errors |
As with MCP Issue 1, if you keep track of the “number of responses that should be requested” and request a response only once at the end, this can be used for both function calling and MCP. Note that parallel calls were confirmed only with function tools in the sample.
Summary
- With function calling, the client executes the tools; with MCP, the Voice Live service executes the tools.
- With either method, the client sends the request for a response using the tool results.
- Because responses cannot overlap, send the response request only once.
- The default value of require_approval is always, so specify never if you want it to execute automatically.
- When the model does not call a tool, use instructions to guide it to the tool.
- Use allowed_tools to prevent tools with large results from being used.
- For parallel tool calls, send all results and then send response.create once.
Reference links
Go to list of users who liked
Go to list of comments
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme


