Overview
LiveKit Agents has first-class support for Model Context Protocol (MCP) servers.
To use MCP, install the optional dependencies:
uv add livekit-agents[mcp]~=1.5
Wrap an MCP server in an MCPToolset and pass it to the agent's tools parameter:
from livekit.agents import Agent, mcpclass MyAgent(Agent):def __init__(self):super().__init__(instructions="You are a helpful assistant.",tools=[mcp.MCPToolset(id="my-mcp-server",mcp_server=mcp.MCPServerHTTP("https://your-mcp-server.com/mcp"),)],)
The mcp_servers parameter on AgentSession and Agent is deprecated and will be removed in a future version. Use MCPToolset in the tools parameter instead. When mcp_servers is used, the SDK auto-generates toolset IDs that aren't stable across sessions, so switching to explicit MCPToolset gives you predictable IDs.
HTTP servers
Use MCPServerHTTP to connect to a remote MCP server over HTTP:
from livekit.agents import AgentSession, mcpsession = AgentSession(# ... other arguments ...tools=[mcp.MCPToolset(id="my-api",mcp_server=mcp.MCPServerHTTP("https://your-mcp-server.com/tools",transport_type="streamable_http",),)],)
The transport type is auto-detected from the URL path: URLs ending in /mcp use streamable HTTP transport, and URLs ending in /sse use Server-Sent Events transport. To override auto-detection, pass transport_type explicitly as shown above.
Local servers (stdio)
Use MCPServerStdio to launch a local MCP server process and communicate over stdin/stdout. This is useful for MCP servers distributed as CLI tools:
from livekit.agents import AgentSession, mcpsession = AgentSession(# ... other arguments ...tools=[mcp.MCPToolset(id="filesystem",mcp_server=mcp.MCPServerStdio(command="npx",args=["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"],),)],)
The env and cwd parameters let you customize the child process environment and working directory.
Authentication
Pass authentication headers to an MCP server with the headers parameter:
import osfrom livekit.agents import AgentSession, mcpsession = AgentSession(# ... other arguments ...tools=[mcp.MCPToolset(id="zapier",mcp_server=mcp.MCPServerHTTP("https://actions.zapier.com/mcp/sse",headers={"Authorization": f"Bearer {os.environ['ZAPIER_API_KEY']}"},),)],)
Filtering tools
Limit which tools from an MCP server are exposed to the LLM. Use server-level filtering when you know the exact tool names, or toolset-level filtering when you need to inspect tools after they load.
Server-level filtering
Use the allowed_tools parameter on the MCP server to filter by tool name. Tools not in the list are excluded.
The following example creates an MCPToolset, wrapping MCPServerHTTP with allowed_tools=["search_products", "get_product_details"]. Only those two tools are available, and everything else the server exposes is excluded.
from livekit.agents import AgentSession, mcpsession = AgentSession(# ... other arguments ...tools=[mcp.MCPToolset(id="products",mcp_server=mcp.MCPServerHTTP("https://your-mcp-server.com/mcp",allowed_tools=["search_products", "get_product_details"],),)],)
Toolset-level filtering
Use MCPToolset.filter_tools() for more control. It accepts a predicate function and filters tools in-place after setup.
The following example creates an MCPToolset, manually calls setup() to connect and fetch tools, then calls filter_tools() with a lambda that only keeps tools with IDs containing "search".
from livekit.agents import mcptoolset = mcp.MCPToolset(id="my-api",mcp_server=mcp.MCPServerHTTP("https://your-mcp-server.com/mcp"),)# When using outside of AgentSession, call setup() manuallyawait toolset.setup()toolset.filter_tools(lambda tool: "search" in tool.id)
Transforming tool results
Use the tool_result_resolver parameter to transform MCP tool results before they reach the LLM. The resolver receives an MCPToolResultContext with tool_name, arguments, and result. It can be sync or async.
By default, the SDK serializes content items to JSON. This example truncates large results instead:
import jsonfrom livekit.agents import mcpMAX_CHARS = 4000async def truncating_resolver(ctx: mcp.MCPToolResultContext) -> str:"""Truncate large MCP tool results to avoid excessive LLM context usage."""if len(ctx.result.content) == 1:text = str(ctx.result.content[0].model_dump_json())elif len(ctx.result.content) > 1:text = json.dumps([item.model_dump() for item in ctx.result.content])else:return "Tool returned no content."if len(text) > MAX_CHARS:text = text[:MAX_CHARS] + "\n... [truncated]"return textsession = AgentSession(# ... other arguments ...tools=[mcp.MCPToolset(id="my-api",mcp_server=mcp.MCPServerHTTP("https://your-mcp-server.com/mcp",tool_result_resolver=truncating_resolver,),)],)
The resolver is available on all MCP server types and is only called for successful tool calls. Errors raise a ToolError before the resolver runs.
Multiple servers
Pass multiple MCPToolset instances in the tools list. You can combine different server types, and all servers are initialized in parallel:
from livekit.agents import AgentSession, mcpsession = AgentSession(# ... other arguments ...tools=[mcp.MCPToolset(id="api-server",mcp_server=mcp.MCPServerHTTP("https://api.example.com/mcp"),),mcp.MCPToolset(id="filesystem",mcp_server=mcp.MCPServerStdio(command="npx",args=["-y", "@modelcontextprotocol/server-filesystem", "/data"],),),],)
If an individual server fails to connect, the error is logged but does not prevent the agent from starting.
Combining MCP tools with function tools
Your agent can use both MCP-provided tools and locally defined function tools. Pass them together in the tools list.
In the following example, the LLM can call both the MCP server's tools and the save_note function tool.
from livekit.agents import Agent, function_tool, RunContext, mcpclass MyAgent(Agent):def __init__(self):super().__init__(instructions="You are a helpful assistant with access to a knowledge base and local tools.",tools=[mcp.MCPToolset(id="knowledge-base",mcp_server=mcp.MCPServerHTTP("https://your-mcp-server.com/sse"),)],)@function_tool()async def save_note(self, context: RunContext, text: str) -> str:"""Save a note for the user.Args:text: The note content to save."""# your custom logic herereturn "Note saved successfully."
In this example, the LLM can call both the MCP server's tools and the save_note function tool.
Agent vs AgentSession placement
MCPToolset follows the same tools override pattern as other tools. If an Agent specifies tools, those tools replace (not merge with) any tools set on the AgentSession. The toolset lifecycle depends on where you place it. Agent toolsets close when switching to a different agent, and session toolsets close when the session ends. See Toolsets for details.
Set toolsets on the AgentSession for shared defaults across multiple agents in a workflow. Set toolsets on a specific Agent only when that agent needs a different set of tools. This is the same override pattern used by stt, llm, tts, and other agent properties.