Skip to content

Commit d615cd1

Browse files
github-actions[bot]markbackman
authored andcommitted
docs: update MCPClient for persistent session requirement
Updates MCPClient documentation to reflect changes from pipecat PR #4034: - Added async context manager requirement to Overview - Updated all usage examples to use async with MCPClient(...) as mcp: - Added documentation for start() and close() methods - Updated method descriptions to reflect persistent session behavior
1 parent e9b7189 commit d615cd1

1 file changed

Lines changed: 91 additions & 70 deletions

File tree

  • api-reference/server/utilities/mcp

api-reference/server/utilities/mcp/mcp.mdx

Lines changed: 91 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ description: "Service to connect to MCP (Model Context Protocol) servers"
77

88
MCP is an open standard for enabling AI agents to interact with external data and tools. `MCPClient` provides a way to access and call tools via MCP. For example, instead of writing bespoke function call implementations for an external API, you may use an MCP server that provides a bridge to the API. _Be aware there may be security implications._ See [MCP documenation](https://github.com/modelcontextprotocol) for more details.
99

10+
The client maintains a persistent connection to the MCP server and must be used as an async context manager or explicitly started and closed:
11+
12+
```python
13+
async with MCPClient(server_params=...) as mcp:
14+
tools = await mcp.register_tools(llm)
15+
```
16+
1017
## Installation
1118

1219
To use `MCPClient`, install the required dependencies:
@@ -105,27 +112,26 @@ from pipecat.services.mcp_service import MCPClient
105112
llm = ...
106113

107114
# Initialize and configure MCPClient with server parameters
108-
mcp = MCPClient(
115+
async with MCPClient(
109116
server_params=StdioServerParameters(
110117
command=shutil.which("npx"),
111118
args=["-y", "@name/mcp-server-name@latest"],
112119
env={"ENV_API_KEY": "<env_api_key>"},
113120
)
114-
)
115-
116-
# Create tools schema from the MCP server and register them with llm
117-
tools = await mcp.register_tools(llm)
118-
119-
# Create context with system message and tools
120-
context = LLMContext(
121-
messages=[
122-
{
123-
"role": "system",
124-
"content": "You are a helpful assistant in a voice conversation. You have access to MCP tools. Keep responses concise."
125-
}
126-
],
127-
tools=tools
128-
)
121+
) as mcp:
122+
# Create tools schema from the MCP server and register them with llm
123+
tools = await mcp.register_tools(llm)
124+
125+
# Create context with system message and tools
126+
context = LLMContext(
127+
messages=[
128+
{
129+
"role": "system",
130+
"content": "You are a helpful assistant in a voice conversation. You have access to MCP tools. Keep responses concise."
131+
}
132+
],
133+
tools=tools
134+
)
129135
```
130136

131137
### MCP SSE Transport
@@ -138,25 +144,24 @@ from pipecat.services.mcp_service import MCPClient
138144
llm = ...
139145

140146
# Initialize and configure MCPClient with SSE server parameters
141-
mcp = MCPClient(
147+
async with MCPClient(
142148
server_params=SseServerParameters(
143149
url="https://your.mcp.server/sse",
144150
)
145-
)
146-
147-
# Create tools schema from the MCP server and register them with llm
148-
tools = await mcp.register_tools(llm)
149-
150-
# Create context with system message and tools
151-
context = LLMContext(
152-
messages=[
153-
{
154-
"role": "system",
155-
"content": "You are a helpful assistant in a voice conversation. You have access to MCP tools. Keep responses concise."
156-
}
157-
],
158-
tools=tools
159-
)
151+
) as mcp:
152+
# Create tools schema from the MCP server and register them with llm
153+
tools = await mcp.register_tools(llm)
154+
155+
# Create context with system message and tools
156+
context = LLMContext(
157+
messages=[
158+
{
159+
"role": "system",
160+
"content": "You are a helpful assistant in a voice conversation. You have access to MCP tools. Keep responses concise."
161+
}
162+
],
163+
tools=tools
164+
)
160165
```
161166

162167
### MCP Streamable HTTP Transport
@@ -171,18 +176,17 @@ from pipecat.services.mcp_service import MCPClient
171176
llm = ...
172177

173178
# Initialize and configure MCPClient with Streamable HTTP parameters
174-
mcp = MCPClient(
179+
async with MCPClient(
175180
server_params=StreamableHttpParameters(
176181
url="https://api.githubcopilot.com/mcp/",
177182
headers={"Authorization": f"Bearer {os.getenv('GITHUB_PERSONAL_ACCESS_TOKEN')}"},
178183
)
179-
)
180-
181-
# Create tools schema from the MCP server and register them with llm
182-
tools = await mcp.register_tools(llm)
184+
) as mcp:
185+
# Create tools schema from the MCP server and register them with llm
186+
tools = await mcp.register_tools(llm)
183187

184-
# Create context with tools
185-
context = LLMContext(tools=tools)
188+
# Create context with tools
189+
context = LLMContext(tools=tools)
186190
```
187191

188192
### Two-Step Registration
@@ -194,25 +198,24 @@ from mcp.client.session_group import StreamableHttpParameters
194198
from pipecat.services.mcp_service import MCPClient
195199

196200
# Initialize MCPClient
197-
mcp = MCPClient(
201+
async with MCPClient(
198202
server_params=StreamableHttpParameters(
199203
url="https://api.githubcopilot.com/mcp/",
200204
headers={"Authorization": f"Bearer {os.getenv('GITHUB_PERSONAL_ACCESS_TOKEN')}"},
201205
)
202-
)
203-
204-
# Step 1: Get tools schema without registering
205-
tools = await mcp.get_tools_schema()
206-
207-
# Step 2: Create LLM with tools
208-
llm = GeminiLiveLLMService(
209-
api_key=os.getenv("GOOGLE_API_KEY"),
210-
system_instruction="You are a helpful assistant.",
211-
tools=tools,
212-
)
206+
) as mcp:
207+
# Step 1: Get tools schema without registering
208+
tools = await mcp.get_tools_schema()
209+
210+
# Step 2: Create LLM with tools
211+
llm = GeminiLiveLLMService(
212+
api_key=os.getenv("GOOGLE_API_KEY"),
213+
system_instruction="You are a helpful assistant.",
214+
tools=tools,
215+
)
213216

214-
# Step 3: Register tool handlers with the LLM
215-
await mcp.register_tools_schema(tools, llm)
217+
# Step 3: Register tool handlers with the LLM
218+
await mcp.register_tools_schema(tools, llm)
216219
```
217220

218221
### Multiple MCP Servers
@@ -229,50 +232,68 @@ from pipecat.services.mcp_service import MCPClient
229232
llm = ...
230233

231234
# Set up multiple MCP clients
232-
server_a = MCPClient(
235+
async with MCPClient(
233236
server_params=StdioServerParameters(
234237
command=shutil.which("npx"),
235238
args=["-y", "mcp-server-a"],
236239
env={"API_KEY": os.getenv("SERVER_A_API_KEY")},
237240
)
238-
)
239-
240-
server_b = MCPClient(
241+
) as server_a, MCPClient(
241242
server_params=StreamableHttpParameters(
242243
url="https://api.githubcopilot.com/mcp/",
243244
headers={"Authorization": f"Bearer {os.getenv('GITHUB_PERSONAL_ACCESS_TOKEN')}"},
244245
)
245-
)
246+
) as server_b:
247+
# Register tools from each server
248+
tools_a = await server_a.register_tools(llm)
249+
tools_b = await server_b.register_tools(llm)
250+
251+
# Merge tools into a single schema
252+
all_tools = ToolsSchema(
253+
standard_tools=tools_a.standard_tools + tools_b.standard_tools
254+
)
246255

247-
# Register tools from each server
248-
tools_a = await server_a.register_tools(llm)
249-
tools_b = await server_b.register_tools(llm)
256+
# Create context with combined tools
257+
context = LLMContext(tools=all_tools)
258+
```
250259

251-
# Merge tools into a single schema
252-
all_tools = ToolsSchema(
253-
standard_tools=tools_a.standard_tools + tools_b.standard_tools
254-
)
260+
## Methods
261+
262+
<ResponseField name="start" type="async method">
263+
Opens a persistent connection to the MCP server and initializes the session.
264+
The session is reused for all subsequent tool calls until `close()` is called.
265+
Can also be used via async context manager instead of calling this directly.
266+
</ResponseField>
255267

256-
# Create context with combined tools
257-
context = LLMContext(tools=all_tools)
268+
```python
269+
async def start(self) -> None
258270
```
259271

260-
## Methods
272+
<ResponseField name="close" type="async method">
273+
Closes the persistent MCP connection. Safe to call multiple times or without
274+
having called `start()`.
275+
</ResponseField>
276+
277+
```python
278+
async def close(self) -> None
279+
```
261280

262281
<ResponseField name="register_tools" type="async method">
263-
Connects to the MCP server, discovers available tools, converts their schemas
282+
Discovers available tools from the active session, converts their schemas
264283
to Pipecat format, and registers them with the LLM service. This is equivalent
265284
to calling `get_tools_schema()` followed by `register_tools_schema()`.
285+
Requires the client to be started via `start()` or async context manager.
266286
</ResponseField>
267287

268288
```python
269289
async def register_tools(self, llm: LLMService | LLMSwitcher) -> ToolsSchema
270290
```
271291

272292
<ResponseField name="get_tools_schema" type="async method">
273-
Connects to the MCP server, discovers available tools, and converts their
293+
Discovers available tools from the active session and converts their
274294
schemas to Pipecat format — without registering them with an LLM. Use this
275295
when you need the tools schema before the LLM is created.
296+
Requires the client to be started via `start()` or async context manager.
276297
</ResponseField>
277298

278299
```python

0 commit comments

Comments
 (0)