Jeremiah Lowin commited on
Commit
7c60ea8
·
unverified ·
2 Parent(s): 3892c4ba266504

Merge pull request #912 from jlowin/client-docs

Browse files
docs/clients/advanced-features.mdx DELETED
@@ -1,152 +0,0 @@
1
- ---
2
- title: Advanced Features
3
- sidebarTitle: Advanced Features
4
- description: Learn about the advanced features of the FastMCP Client.
5
- icon: stars
6
- ---
7
-
8
- import { VersionBadge } from '/snippets/version-badge.mdx'
9
-
10
- In addition to basic server interaction, FastMCP clients can also handle more advanced features and server interaction patterns. The `Client` constructor accepts additional configuration to handle these server requests.
11
-
12
- <Tip>
13
- To enable many of these features, you must provide an appropriate handler or callback function. For example. In most cases, if you do not provide a handler, FastMCP's default handler will emit a `DEBUG` level log.
14
- </Tip>
15
-
16
- ## Logging and Notifications
17
-
18
- <VersionBadge version="2.0.0" />
19
- MCP servers can emit logs to clients. To process these logs, you can provide a `log_handler` to the client.
20
-
21
- The `log_handler` must be an async function that accepts a single argument, which is an instance of `fastmcp.client.logging.LogMessage`. This has attributes like `level`, `logger`, and `data`.
22
-
23
- ```python {2, 12}
24
- from fastmcp import Client
25
- from fastmcp.client.logging import LogMessage
26
-
27
- async def log_handler(message: LogMessage):
28
- level = message.level.upper()
29
- logger = message.logger or 'default'
30
- data = message.data
31
- print(f"[Server Log - {level}] {logger}: {data}")
32
-
33
- client_with_logging = Client(
34
- ...,
35
- log_handler=log_handler,
36
- )
37
- ```
38
- ## Progress Monitoring
39
-
40
- <VersionBadge version="2.3.5" />
41
-
42
- MCP servers can report progress during long-running operations. The client can set a progress handler to receive and process these updates.
43
-
44
- ```python {2, 13}
45
- from fastmcp import Client
46
- from fastmcp.client.progress import ProgressHandler
47
-
48
- async def my_progress_handler(
49
- progress: float,
50
- total: float | None,
51
- message: str | None
52
- ) -> None:
53
- print(f"Progress: {progress} / {total} ({message})")
54
-
55
- client = Client(
56
- ...,
57
- progress_handler=my_progress_handler
58
- )
59
- ```
60
-
61
- By default, FastMCP uses a handler that logs progress updates at the debug level. This default handler properly handles cases where `total` or `message` might be None.
62
-
63
- You can override the progress handler for specific tool calls:
64
-
65
- ```python
66
- # Client uses the default debug logger for progress
67
- client = Client(...)
68
-
69
- async with client:
70
- # Use default progress handler (debug logging)
71
- result1 = await client.call_tool("long_task", {"param": "value"})
72
-
73
- # Override with custom progress handler just for this call
74
- result2 = await client.call_tool(
75
- "another_task",
76
- {"param": "value"},
77
- progress_handler=my_progress_handler
78
- )
79
- ```
80
-
81
- A typical progress update includes:
82
- - Current progress value (e.g., 2 of 5 steps completed)
83
- - Total expected value (may be None)
84
- - Status message (may be None)
85
-
86
- ## LLM Sampling
87
-
88
- <VersionBadge version="2.0.0" />
89
-
90
- MCP Servers can request LLM completions from clients. The client can provide a `sampling_handler` to handle these requests. The sampling handler receives a list of messages and other parameters from the server, and should return a string completion.
91
-
92
- The following example uses the `marvin` library to generate a completion:
93
-
94
- ```python {8-17, 21}
95
- import marvin
96
- from fastmcp import Client
97
- from fastmcp.client.sampling import (
98
- SamplingMessage,
99
- SamplingParams,
100
- RequestContext,
101
- )
102
-
103
- async def sampling_handler(
104
- messages: list[SamplingMessage],
105
- params: SamplingParams,
106
- context: RequestContext
107
- ) -> str:
108
- return await marvin.say_async(
109
- message=[m.content.text for m in messages],
110
- instructions=params.systemPrompt,
111
- )
112
-
113
- client = Client(
114
- ...,
115
- sampling_handler=sampling_handler,
116
- )
117
- ```
118
-
119
-
120
- ## Roots
121
-
122
- <VersionBadge version="2.0.0" />
123
-
124
- Roots are a way for clients to inform servers about the resources they have access to or certain boundaries on their access. The server can use this information to adjust behavior or provide more accurate responses.
125
-
126
- Servers can request roots from clients, and clients can notify servers when their roots change.
127
-
128
- To set the roots when creating a client, users can either provide a list of roots (which can be a list of strings) or an async function that returns a list of roots.
129
-
130
- <CodeGroup>
131
- ```python Static Roots {5}
132
- from fastmcp import Client
133
-
134
- client = Client(
135
- ...,
136
- roots=["/path/to/root1", "/path/to/root2"],
137
- )
138
- ```
139
- ```python Dynamic Roots Callback {4-6, 10}
140
- from fastmcp import Client
141
- from fastmcp.client.roots import RequestContext
142
-
143
- async def roots_callback(context: RequestContext) -> list[str]:
144
- print(f"Server requested roots (Request ID: {context.request_id})")
145
- return ["/path/to/root1", "/path/to/root2"]
146
-
147
- client = Client(
148
- ...,
149
- roots=roots_callback,
150
- )
151
- ```
152
- </CodeGroup>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
docs/clients/client.mdx CHANGED
@@ -1,7 +1,7 @@
1
  ---
2
- title: Client Overview
3
  sidebarTitle: Overview
4
- description: Learn how to use the FastMCP Client to interact with MCP servers.
5
  icon: user-robot
6
  ---
7
 
@@ -9,294 +9,213 @@ import { VersionBadge } from '/snippets/version-badge.mdx'
9
 
10
  <VersionBadge version="2.0.0" />
11
 
12
- The `fastmcp.Client` provides a high-level, asynchronous interface for interacting with any Model Context Protocol (MCP) server, whether it's built with FastMCP or another implementation. It simplifies communication by handling protocol details and connection management.
13
 
14
- ## FastMCP Client
15
 
16
- The FastMCP Client architecture separates the protocol logic (`Client`) from the connection mechanism (`Transport`).
 
 
17
 
18
- - **`Client`**: Handles sending MCP requests (like `tools/call`, `resources/read`), receiving responses, and managing callbacks.
19
- - **`Transport`**: Responsible for establishing and maintaining the connection to the server (e.g., via WebSockets, SSE, Stdio, or in-memory).
20
 
21
- ### Transports
22
 
23
- Clients must be initialized with a `transport`. You can either provide an already instantiated transport object, or provide a transport source and let FastMCP attempt to infer the correct transport to use.
 
 
24
 
25
- The following inference rules are used to determine the appropriate `ClientTransport` based on the input type:
26
 
27
- 1. **`ClientTransport` Instance**: If you provide an already instantiated transport object, it's used directly.
28
- 2. **`FastMCP` Instance**: Creates a `FastMCPTransport` for efficient in-memory communication (ideal for testing). This also works with a **FastMCP 1.0 server** created via `mcp.server.fastmcp.FastMCP`.
29
- 3. **`Path` or `str` pointing to an existing file**:
30
- * If it ends with `.py`: Creates a `PythonStdioTransport` to run the script using `python`.
31
- * If it ends with `.js`: Creates a `NodeStdioTransport` to run the script using `node`.
32
- 4. **`AnyUrl` or `str` pointing to a URL that begins with `http://` or `https://`**:
33
- * Creates a `StreamableHttpTransport`
34
- 5. **`MCPConfig` or dictionary matching MCPConfig schema**: Creates a client that connects to one or more MCP servers specified in the config.
35
- 6. **Other**: Raises a `ValueError` if the type cannot be inferred.
36
 
37
  ```python
38
  import asyncio
39
  from fastmcp import Client, FastMCP
40
 
41
- # Example transports (more details in Transports page)
42
- server_instance = FastMCP(name="TestServer") # In-memory server
43
- http_url = "https://example.com/mcp" # HTTP server URL
44
- server_script = "my_mcp_server.py" # Path to a Python server file
45
 
46
- # Client automatically infers the transport type
47
- client_in_memory = Client(server_instance)
48
- client_http = Client(http_url)
49
 
50
- client_stdio = Client(server_script)
 
51
 
52
- print(client_in_memory.transport)
53
- print(client_http.transport)
54
- print(client_stdio.transport)
 
 
 
 
 
 
 
 
 
 
55
 
56
- # Expected Output (types may vary slightly based on environment):
57
- # <FastMCP(server='TestServer')>
58
- # <StreamableHttp(url='https://example.com/mcp')>
59
- # <PythonStdioTransport(command='python', args=['/path/to/your/my_mcp_server.py'])>
60
  ```
61
 
62
- You can also initialize a client from an MCP configuration dictionary or `MCPConfig` file:
63
 
64
- ```python
65
- from fastmcp import Client
66
 
67
- config = {
68
- "mcpServers": {
69
- "local": {"command": "python", "args": ["local_server.py"]},
70
- "remote": {"url": "https://example.com/mcp"},
71
- }
72
- }
 
 
 
 
 
 
 
 
 
73
 
74
- client_config = Client(config)
 
 
 
75
  ```
 
76
  <Tip>
77
- For more control over connection details (like headers for SSE, environment variables for Stdio), you can instantiate the specific `ClientTransport` class yourself and pass it to the `Client`. See the [Transports](/clients/transports) page for details.
78
  </Tip>
79
 
80
- ### Multi-Server Clients
81
 
82
  <VersionBadge version="2.4.0" />
83
 
84
- FastMCP supports creating clients that connect to multiple MCP servers through a single client interface using a standard MCP configuration format (`MCPConfig`). This configuration approach makes it easy to connect to multiple specialized servers or create composable systems with a simple, declarative syntax.
85
-
86
- <Note>
87
- The MCP configuration format follows an emerging standard and may evolve as the specification matures. FastMCP will strive to maintain compatibility with future versions, but be aware that field names or structure might change.
88
- </Note>
89
-
90
- When you create a client with an `MCPConfig` containing multiple servers:
91
 
92
- 1. FastMCP creates a composite client that internally mounts all servers using their config names as prefixes
93
- 2. Tools and resources from each server are accessible with appropriate prefixes in the format `servername_toolname` and `protocol://servername/resource/path`
94
- 3. You interact with this as a single unified client, with requests automatically routed to the appropriate server
95
 
96
  ```python
97
- from fastmcp import Client
98
-
99
- # Create a standard MCP configuration with multiple servers
100
  config = {
101
  "mcpServers": {
102
- # A remote HTTP server
103
- "weather": {
104
- "url": "https://weather-api.example.com/mcp",
105
- "transport": "streamable-http"
 
 
106
  },
107
- # A local server running via stdio
108
- "assistant": {
 
109
  "command": "python",
110
- "args": ["./my_assistant_server.py"],
111
- "env": {"DEBUG": "true"}
 
112
  }
113
  }
114
  }
115
-
116
- # Create a client that connects to both servers
117
- client = Client(config)
118
-
119
- async def main():
120
- async with client:
121
- # Access tools from different servers with prefixes
122
- weather_data = await client.call_tool("weather_get_forecast", {"city": "London"})
123
- response = await client.call_tool("assistant_answer_question", {"question": "What's the capital of France?"})
124
-
125
- # Access resources with prefixed URIs
126
- weather_icons = await client.read_resource("weather://weather/icons/sunny")
127
- templates = await client.read_resource("resource://assistant/templates/list")
128
-
129
- print(f"Weather: {weather_data}")
130
- print(f"Assistant: {response}")
131
-
132
- if __name__ == "__main__":
133
- asyncio.run(main())
134
  ```
135
 
136
- If your configuration has only a single server, FastMCP will create a direct client to that server without any prefixing.
137
 
138
- ## Client Usage
 
 
 
 
 
 
139
 
140
- ### Connection Lifecycle
141
 
142
- The client operates asynchronously and must be used within an `async with` block. This context manager handles establishing the connection, initializing the MCP session, and cleaning up resources upon exit.
 
 
 
 
 
 
 
 
143
 
144
- ```python
145
- import asyncio
146
- from fastmcp import Client
147
 
148
- client = Client("my_mcp_server.py") # Assumes my_mcp_server.py exists
149
 
150
- async def main():
151
- # Connection is established here
 
 
 
152
  async with client:
153
- print(f"Client connected: {client.is_connected()}")
154
-
155
- # Make MCP calls within the context
156
  tools = await client.list_tools()
157
- print(f"Available tools: {tools}")
158
-
159
- if any(tool.name == "greet" for tool in tools):
160
- result = await client.call_tool("greet", {"name": "World"})
161
- print(f"Greet result: {result}")
162
-
163
- # Connection is closed automatically here
164
- print(f"Client connected: {client.is_connected()}")
165
-
166
- if __name__ == "__main__":
167
- asyncio.run(main())
168
  ```
169
 
170
- You can make multiple calls to the server within the same `async with` block using the established session.
171
 
172
- ### Client Methods
173
 
174
- The `Client` provides methods corresponding to standard MCP requests:
175
 
176
- <Warning>
177
- The standard client methods return user-friendly representations that may change as the protocol evolves. For consistent access to the complete data structure, use the `*_mcp` methods described later.
178
- </Warning>
179
 
180
- #### Tool Operations
181
-
182
- * **`list_tools()`**: Retrieves a list of tools available on the server.
183
- ```python
184
  tools = await client.list_tools()
185
- # tools -> list[mcp.types.Tool]
186
- ```
187
- * **`call_tool(name: str, arguments: dict[str, Any] | None = None, timeout: float | None = None, progress_handler: ProgressHandler | None = None)`**: Executes a tool on the server.
188
- ```python
189
- result = await client.call_tool("add", {"a": 5, "b": 3})
190
- # result -> list[mcp.types.TextContent | mcp.types.ImageContent | ...]
191
- print(result[0].text) # Assuming TextContent, e.g., '8'
192
 
193
- # With timeout (aborts if execution takes longer than 2 seconds)
194
- result = await client.call_tool("long_running_task", {"param": "value"}, timeout=2.0)
195
-
196
- # With progress handler (to track execution progress)
197
- result = await client.call_tool(
198
- "long_running_task",
199
- {"param": "value"},
200
- progress_handler=my_progress_handler
201
- )
202
- ```
203
- * Arguments are passed as a dictionary. FastMCP servers automatically handle JSON string parsing for complex types if needed.
204
- * Returns a list of content objects (usually `TextContent` or `ImageContent`).
205
- * The optional `timeout` parameter limits the maximum execution time (in seconds) for this specific call, overriding any client-level timeout.
206
- * The optional `progress_handler` parameter receives progress updates during execution, overriding any client-level progress handler.
207
-
208
- #### Resource Operations
209
-
210
- * **`list_resources()`**: Retrieves a list of static resources.
211
- ```python
212
- resources = await client.list_resources()
213
- # resources -> list[mcp.types.Resource]
214
- ```
215
- * **`list_resource_templates()`**: Retrieves a list of resource templates.
216
- ```python
217
- templates = await client.list_resource_templates()
218
- # templates -> list[mcp.types.ResourceTemplate]
219
- ```
220
- * **`read_resource(uri: str | AnyUrl)`**: Reads the content of a resource or a resolved template.
221
- ```python
222
- # Read a static resource
223
- readme_content = await client.read_resource("file:///path/to/README.md")
224
- # readme_content -> list[mcp.types.TextResourceContents | mcp.types.BlobResourceContents]
225
- print(readme_content[0].text) # Assuming text
226
-
227
- # Read a resource generated from a template
228
- weather_content = await client.read_resource("data://weather/london")
229
- print(weather_content[0].text) # Assuming text JSON
230
- ```
231
-
232
- #### Prompt Operations
233
-
234
- * **`list_prompts()`**: Retrieves available prompt templates.
235
- * **`get_prompt(name: str, arguments: dict[str, Any] | None = None)`**: Retrieves a rendered prompt message list.
236
-
237
- <VersionBadge version="2.9.0" />
238
-
239
- **Automatic Argument Serialization**: When calling prompts with complex arguments, the FastMCP client automatically serializes non-string values to JSON strings as required by the MCP specification. This allows you to pass typed objects directly while maintaining protocol compliance.
240
 
241
- ```python
242
- from dataclasses import dataclass
 
243
 
244
- @dataclass
245
- class UserData:
246
- name: str
247
- age: int
248
 
 
249
  async with client:
250
- # You can pass complex objects directly
251
- result = await client.get_prompt("analyze_user", {
252
- "user": UserData(name="Alice", age=30), # Automatically serialized to JSON
253
- "preferences": {"theme": "dark"}, # Dict serialized to JSON string
254
- "scores": [85, 92, 78], # List serialized to JSON string
255
- "simple_name": "Bob" # Strings passed through unchanged
256
- })
257
  ```
258
 
259
- The client handles the serialization automatically using `pydantic_core.to_json()` for consistent formatting, while the server can deserialize these JSON strings back to the expected types if using FastMCP's server-side type conversion.
260
-
261
- ### Raw MCP Protocol Objects
262
 
263
- <VersionBadge version="2.2.7" />
264
 
265
- The FastMCP client attempts to provide a "friendly" interface to the MCP protocol, but sometimes you may need access to the raw MCP protocol objects. Each of the main client methods that returns data has a corresponding `*_mcp` method that returns the raw MCP protocol objects directly.
266
-
267
- <Warning>
268
- The standard client methods (without `_mcp`) return user-friendly representations of MCP data, while `*_mcp` methods will always return the complete MCP protocol objects. As the protocol evolves, changes to these user-friendly representations may occur and could potentially be breaking. If you need consistent, stable access to the full data structure, prefer using the `*_mcp` methods.
269
- </Warning>
270
 
271
  ```python
272
- # Standard method - returns just the list of tools
273
- tools = await client.list_tools()
274
- # tools -> list[mcp.types.Tool]
275
-
276
- # Raw MCP method - returns the full protocol object
277
- result = await client.list_tools_mcp()
278
- # result -> mcp.types.ListToolsResult
279
- tools = result.tools
280
  ```
281
 
282
- Available raw MCP methods:
283
-
284
- * **`list_tools_mcp()`**: Returns `mcp.types.ListToolsResult`
285
- * **`call_tool_mcp(name, arguments)`**: Returns `mcp.types.CallToolResult`
286
- * **`list_resources_mcp()`**: Returns `mcp.types.ListResourcesResult`
287
- * **`list_resource_templates_mcp()`**: Returns `mcp.types.ListResourceTemplatesResult`
288
- * **`read_resource_mcp(uri)`**: Returns `mcp.types.ReadResourceResult`
289
- * **`list_prompts_mcp()`**: Returns `mcp.types.ListPromptsResult`
290
- * **`get_prompt_mcp(name, arguments)`**: Returns `mcp.types.GetPromptResult`
291
- * **`complete_mcp(ref, argument)`**: Returns `mcp.types.CompleteResult`
292
-
293
- These methods are especially useful for debugging or when you need to access metadata or fields that aren't exposed by the simplified methods.
294
-
295
- ### Additional Features
296
 
297
- #### Pinging the Server
298
 
299
- The client can be used to ping the server to verify connectivity.
300
 
301
  ```python
302
  async with client:
@@ -304,93 +223,69 @@ async with client:
304
  print("Server is reachable")
305
  ```
306
 
307
- #### Session Management
308
 
309
- When using stdio transports, clients support a `keep_alive` feature (enabled by default) that maintains subprocess sessions between connection contexts. You can manually control this behavior using the client's `close()` method.
310
 
311
- When `keep_alive=False`, the client will automatically close the session when the context manager exits.
 
 
312
 
313
  ```python
314
  from fastmcp import Client
 
315
 
316
- client = Client("my_mcp_server.py") # keep_alive=True by default
 
317
 
318
- async def example():
319
- async with client:
320
- await client.ping()
321
-
322
- async with client:
323
- await client.ping() # Same subprocess as above
324
- ```
325
 
326
- <Note>
327
- For detailed examples and configuration options, see [Session Management in Transports](/clients/transports#session-management).
328
- </Note>
329
-
330
- #### Timeouts
331
 
332
- <VersionBadge version="2.3.4" />
333
-
334
- You can control request timeouts at both the client level and individual request level:
335
-
336
- ```python
337
- from fastmcp import Client
338
- from fastmcp.exceptions import McpError
339
-
340
- # Client with a global 5-second timeout for all requests
341
  client = Client(
342
- my_mcp_server,
343
- timeout=5.0 # Default timeout in seconds
 
 
 
344
  )
345
-
346
- async with client:
347
- # This uses the global 5-second timeout
348
- result1 = await client.call_tool("quick_task", {"param": "value"})
349
-
350
- # This specifies a 10-second timeout for this specific call
351
- result2 = await client.call_tool("slow_task", {"param": "value"}, timeout=10.0)
352
-
353
- try:
354
- # This will likely timeout
355
- result3 = await client.call_tool("medium_task", {"param": "value"}, timeout=0.01)
356
- except McpError as e:
357
- # Handle timeout error
358
- print(f"The task timed out: {e}")
359
  ```
360
 
361
- <Warning>
362
- Timeout behavior varies between transport types:
363
 
364
- - With **SSE** transport, the per-request (tool call) timeout **always** takes precedence, regardless of which is lower.
365
- - With **HTTP** transport, the **lower** of the two timeouts (client or tool call) takes precedence.
 
 
 
 
366
 
367
- For consistent behavior across all transports, we recommend explicitly setting timeouts at the individual tool call level when needed, rather than relying on client-level timeouts.
368
- </Warning>
369
 
370
- #### Error Handling
371
 
372
- When a `call_tool` request results in an error on the server (e.g., the tool function raised an exception), the `client.call_tool()` method will raise a `fastmcp.exceptions.ClientError`.
373
 
374
- ```python
375
- async def safe_call_tool():
376
- async with client:
377
- try:
378
- # Assume 'divide' tool exists and might raise ZeroDivisionError
379
- result = await client.call_tool("divide", {"a": 10, "b": 0})
380
- print(f"Result: {result}")
381
- except ClientError as e:
382
- print(f"Tool call failed: {e}")
383
- except ConnectionError as e:
384
- print(f"Connection failed: {e}")
385
- except Exception as e:
386
- print(f"An unexpected error occurred: {e}")
387
-
388
- # Example Output if division by zero occurs:
389
- # Tool call failed: Division by zero is not allowed.
390
- ```
391
 
392
- Other errors, like connection failures, will raise standard Python exceptions (e.g., `ConnectionError`, `TimeoutError`).
 
 
 
 
 
 
 
 
 
 
 
 
 
393
 
394
  <Tip>
395
- The client transport often has its own error-handling mechanisms, so you can not always trap errors like those raised by `call_tool` outside of the `async with` block. Instead, you can use `call_tool_mcp()` to get the raw `mcp.types.CallToolResult` object and handle errors yourself by checking its `isError` attribute.
396
- </Tip>
 
1
  ---
2
+ title: The FastMCP Client
3
  sidebarTitle: Overview
4
+ description: Programmatic client for interacting with MCP servers through a well-typed, Pythonic interface.
5
  icon: user-robot
6
  ---
7
 
 
9
 
10
  <VersionBadge version="2.0.0" />
11
 
12
+ The central piece of MCP client applications is the `fastmcp.Client` class. This class provides a **programmatic interface** for interacting with any Model Context Protocol (MCP) server, handling protocol details and connection management automatically.
13
 
14
+ The FastMCP Client is designed for deterministic, controlled interactions rather than autonomous behavior, making it ideal for:
15
 
16
+ - **Testing MCP servers** during development
17
+ - **Building deterministic applications** that need reliable MCP interactions
18
+ - **Creating the foundation for agentic or LLM-based clients** with structured, type-safe operations
19
 
20
+ All client operations require using the `async with` context manager for proper connection lifecycle management.
 
21
 
 
22
 
23
+ <Note>
24
+ This is not an agentic client - it requires explicit function calls and provides direct control over all MCP operations. Use it as a building block for higher-level systems.
25
+ </Note>
26
 
27
+ ## Creating a Client
28
 
29
+ Creating a client is straightforward. You provide a server source and the client automatically infers the appropriate transport mechanism.
 
 
 
 
 
 
 
 
30
 
31
  ```python
32
  import asyncio
33
  from fastmcp import Client, FastMCP
34
 
35
+ # In-memory server (ideal for testing)
36
+ server = FastMCP("TestServer")
37
+ client = Client(server)
 
38
 
39
+ # HTTP server
40
+ client = Client("https://example.com/mcp")
 
41
 
42
+ # Local Python script
43
+ client = Client("my_mcp_server.py")
44
 
45
+ async def main():
46
+ async with client:
47
+ # Basic server interaction
48
+ await client.ping()
49
+
50
+ # List available operations
51
+ tools = await client.list_tools()
52
+ resources = await client.list_resources()
53
+ prompts = await client.list_prompts()
54
+
55
+ # Execute operations
56
+ result = await client.call_tool("example_tool", {"param": "value"})
57
+ print(result)
58
 
59
+ asyncio.run(main())
 
 
 
60
  ```
61
 
62
+ ## Client-Transport Architecture
63
 
64
+ The FastMCP Client separates concerns between protocol and connection:
 
65
 
66
+ - **`Client`**: Handles MCP protocol operations (tools, resources, prompts) and manages callbacks
67
+ - **`Transport`**: Establishes and maintains the connection (WebSockets, HTTP, Stdio, in-memory)
68
+
69
+ ### Transport Inference
70
+
71
+ The client automatically infers the appropriate transport based on the input:
72
+
73
+ 1. **`FastMCP` instance** → In-memory transport (perfect for testing)
74
+ 2. **File path ending in `.py`** → Python Stdio transport
75
+ 3. **File path ending in `.js`** → Node.js Stdio transport
76
+ 4. **URL starting with `http://` or `https://`** → HTTP transport
77
+ 5. **`MCPConfig` dictionary** → Multi-server client
78
+
79
+ ```python
80
+ from fastmcp import Client, FastMCP
81
 
82
+ # Examples of transport inference
83
+ client_memory = Client(FastMCP("TestServer"))
84
+ client_script = Client("./server.py")
85
+ client_http = Client("https://api.example.com/mcp")
86
  ```
87
+
88
  <Tip>
89
+ For testing and development, always prefer the in-memory transport by passing a `FastMCP` server directly to the client. This eliminates network complexity and separate processes.
90
  </Tip>
91
 
92
+ ## Configuration-Based Clients
93
 
94
  <VersionBadge version="2.4.0" />
95
 
96
+ Create clients from MCP configuration dictionaries, which can include multiple servers. While there is no official standard for MCP configuration format, FastMCP follows established conventions used by tools like Claude Desktop.
 
 
 
 
 
 
97
 
98
+ ### Configuration Format
 
 
99
 
100
  ```python
 
 
 
101
  config = {
102
  "mcpServers": {
103
+ "server_name": {
104
+ # Remote HTTP/SSE server
105
+ "transport": "streamable-http", # or "sse"
106
+ "url": "https://api.example.com/mcp",
107
+ "headers": {"Authorization": "Bearer token"},
108
+ "auth": "oauth" # or bearer token string
109
  },
110
+ "local_server": {
111
+ # Local stdio server
112
+ "transport": "stdio"
113
  "command": "python",
114
+ "args": ["./server.py", "--verbose"],
115
+ "env": {"DEBUG": "true"},
116
+ "cwd": "/path/to/server",
117
  }
118
  }
119
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  ```
121
 
122
+ ### Multi-Server Example
123
 
124
+ ```python
125
+ config = {
126
+ "mcpServers": {
127
+ "weather": {"url": "https://weather-api.example.com/mcp"},
128
+ "assistant": {"command": "python", "args": ["./assistant_server.py"]}
129
+ }
130
+ }
131
 
132
+ client = Client(config)
133
 
134
+ async with client:
135
+ # Tools are prefixed with server names
136
+ weather_data = await client.call_tool("weather_get_forecast", {"city": "London"})
137
+ response = await client.call_tool("assistant_answer_question", {"question": "What's the capital of France?"})
138
+
139
+ # Resources use prefixed URIs
140
+ icons = await client.read_resource("weather://weather/icons/sunny")
141
+ templates = await client.read_resource("resource://assistant/templates/list")
142
+ ```
143
 
144
+ ## Connection Lifecycle
 
 
145
 
146
+ The client operates asynchronously and uses context managers for connection management:
147
 
148
+ ```python
149
+ async def example():
150
+ client = Client("my_mcp_server.py")
151
+
152
+ # Connection established here
153
  async with client:
154
+ print(f"Connected: {client.is_connected()}")
155
+
156
+ # Make multiple calls within the same session
157
  tools = await client.list_tools()
158
+ result = await client.call_tool("greet", {"name": "World"})
159
+
160
+ # Connection closed automatically here
161
+ print(f"Connected: {client.is_connected()}")
 
 
 
 
 
 
 
162
  ```
163
 
164
+ ## Operations
165
 
166
+ FastMCP clients can interact with several types of server components:
167
 
168
+ ### Tools
169
 
170
+ Tools are server-side functions that the client can execute with arguments.
 
 
171
 
172
+ ```python
173
+ async with client:
174
+ # List available tools
 
175
  tools = await client.list_tools()
 
 
 
 
 
 
 
176
 
177
+ # Execute a tool
178
+ result = await client.call_tool("multiply", {"a": 5, "b": 3})
179
+ print(result[0].text) # "15"
180
+ ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
 
182
+ See [Tools](/clients/tools) for detailed documentation.
183
+
184
+ ### Resources
185
 
186
+ Resources are data sources that the client can read, either static or templated.
 
 
 
187
 
188
+ ```python
189
  async with client:
190
+ # List available resources
191
+ resources = await client.list_resources()
192
+
193
+ # Read a resource
194
+ content = await client.read_resource("file:///config/settings.json")
195
+ print(content[0].text)
 
196
  ```
197
 
198
+ See [Resources](/clients/resources) for detailed documentation.
 
 
199
 
200
+ ### Prompts
201
 
202
+ Prompts are reusable message templates that can accept arguments.
 
 
 
 
203
 
204
  ```python
205
+ async with client:
206
+ # List available prompts
207
+ prompts = await client.list_prompts()
208
+
209
+ # Get a rendered prompt
210
+ messages = await client.get_prompt("analyze_data", {"data": [1, 2, 3]})
211
+ print(messages.messages)
 
212
  ```
213
 
214
+ See [Prompts](/clients/prompts) for detailed documentation.
 
 
 
 
 
 
 
 
 
 
 
 
 
215
 
216
+ ### Server Connectivity
217
 
218
+ Use `ping()` to verify the server is reachable:
219
 
220
  ```python
221
  async with client:
 
223
  print("Server is reachable")
224
  ```
225
 
226
+ ## Client Configuration
227
 
228
+ Clients can be configured with additional handlers and settings for specialized use cases.
229
 
230
+ ### Callback Handlers
231
+
232
+ The client supports several callback handlers for advanced server interactions:
233
 
234
  ```python
235
  from fastmcp import Client
236
+ from fastmcp.client.logging import LogMessage
237
 
238
+ async def log_handler(message: LogMessage):
239
+ print(f"Server log: {message.data}")
240
 
241
+ async def progress_handler(progress: float, total: float | None, message: str | None):
242
+ print(f"Progress: {progress}/{total} - {message}")
 
 
 
 
 
243
 
244
+ async def sampling_handler(messages, params, context):
245
+ # Integrate with your LLM service here
246
+ return "Generated response"
 
 
247
 
 
 
 
 
 
 
 
 
 
248
  client = Client(
249
+ "my_mcp_server.py",
250
+ log_handler=log_handler,
251
+ progress_handler=progress_handler,
252
+ sampling_handler=sampling_handler,
253
+ timeout=30.0
254
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  ```
256
 
257
+ The `Client` constructor accepts several configuration options:
 
258
 
259
+ - `transport`: Transport instance or source for automatic inference
260
+ - `log_handler`: Handle server log messages
261
+ - `progress_handler`: Monitor long-running operations
262
+ - `sampling_handler`: Respond to server LLM requests
263
+ - `roots`: Provide local context to servers
264
+ - `timeout`: Default timeout for requests (in seconds)
265
 
266
+ ### Transport Configuration
 
267
 
268
+ For detailed transport configuration (headers, authentication, environment variables), see the [Transports](/clients/transports) documentation.
269
 
270
+ ## Next Steps
271
 
272
+ Explore the detailed documentation for each operation type:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
 
274
+ ### Core Operations
275
+ - **[Tools](/clients/tools)** - Execute server-side functions and handle results
276
+ - **[Resources](/clients/resources)** - Access static and templated resources
277
+ - **[Prompts](/clients/prompts)** - Work with message templates and argument serialization
278
+
279
+ ### Advanced Features
280
+ - **[Logging](/clients/logging)** - Handle server log messages
281
+ - **[Progress](/clients/progress)** - Monitor long-running operations
282
+ - **[Sampling](/clients/sampling)** - Respond to server LLM requests
283
+ - **[Roots](/clients/roots)** - Provide local context to servers
284
+
285
+ ### Connection Details
286
+ - **[Transports](/clients/transports)** - Configure connection methods and parameters
287
+ - **[Authentication](/clients/auth/oauth)** - Set up OAuth and bearer token authentication
288
 
289
  <Tip>
290
+ The FastMCP Client is designed as a foundational tool. Use it directly for deterministic operations, or build higher-level agentic systems on top of its reliable, type-safe interface.
291
+ </Tip>
docs/clients/logging.mdx ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Server Logging
3
+ sidebarTitle: Logging
4
+ description: Receive and handle log messages from MCP servers.
5
+ icon: receipt
6
+ ---
7
+
8
+ import { VersionBadge } from '/snippets/version-badge.mdx'
9
+
10
+ <VersionBadge version="2.0.0" />
11
+
12
+ MCP servers can emit log messages to clients. The client can handle these logs through a log handler callback.
13
+
14
+ ## Setting Up Log Handling
15
+
16
+ Provide a `log_handler` function when creating the client:
17
+
18
+ ```python
19
+ from fastmcp import Client
20
+ from fastmcp.client.logging import LogMessage
21
+
22
+ async def log_handler(message: LogMessage):
23
+ level = message.level.upper()
24
+ logger = message.logger or 'server'
25
+ data = message.data
26
+ print(f"[{level}] {logger}: {data}")
27
+
28
+ client = Client(
29
+ "my_mcp_server.py",
30
+ log_handler=log_handler,
31
+ )
32
+ ```
33
+
34
+ ## LogMessage Structure
35
+
36
+ The `log_handler` receives a `LogMessage` object with:
37
+
38
+ - **`level`**: Log level (e.g., "debug", "info", "warning", "error")
39
+ - **`logger`**: Logger name (optional, may be None)
40
+ - **`data`**: The actual log message content
41
+
42
+ ```python
43
+ async def detailed_log_handler(message: LogMessage):
44
+ if message.level == "error":
45
+ print(f"ERROR: {message.data}")
46
+ elif message.level == "warning":
47
+ print(f"WARNING: {message.data}")
48
+ else:
49
+ print(f"{message.level.upper()}: {message.data}")
50
+ ```
51
+
52
+ ## Default Log Handling
53
+
54
+ If you don't provide a custom `log_handler`, FastMCP uses a default handler that emits DEBUG level logs:
55
+
56
+ ```python
57
+ # Without custom handler - uses default DEBUG logging
58
+ client = Client("my_mcp_server.py")
59
+
60
+ async with client:
61
+ # Server logs will be emitted at DEBUG level
62
+ await client.call_tool("some_tool")
63
+ ```
docs/clients/progress.mdx ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Progress Monitoring
3
+ sidebarTitle: Progress
4
+ description: Handle progress notifications from long-running server operations.
5
+ icon: bars-progress
6
+ ---
7
+
8
+ import { VersionBadge } from '/snippets/version-badge.mdx'
9
+
10
+ <VersionBadge version="2.3.5" />
11
+
12
+ MCP servers can report progress during long-running operations. The client can receive these updates through a progress handler.
13
+
14
+ ## Setting Up Progress Handling
15
+
16
+ Set a progress handler when creating the client:
17
+
18
+ ```python
19
+ from fastmcp import Client
20
+
21
+ async def my_progress_handler(
22
+ progress: float,
23
+ total: float | None,
24
+ message: str | None
25
+ ) -> None:
26
+ if total is not None:
27
+ percentage = (progress / total) * 100
28
+ print(f"Progress: {percentage:.1f}% - {message or ''}")
29
+ else:
30
+ print(f"Progress: {progress} - {message or ''}")
31
+
32
+ client = Client(
33
+ "my_mcp_server.py",
34
+ progress_handler=my_progress_handler
35
+ )
36
+ ```
37
+
38
+ ## Per-Call Progress Handler
39
+
40
+ Override the progress handler for specific tool calls:
41
+
42
+ ```python
43
+ async with client:
44
+ # Override with specific progress handler for this call
45
+ result = await client.call_tool(
46
+ "long_running_task",
47
+ {"param": "value"},
48
+ progress_handler=my_progress_handler
49
+ )
50
+ ```
51
+
52
+ ## Handler Parameters
53
+
54
+ The progress handler receives:
55
+
56
+ - **`progress`** (float): Current progress value
57
+ - **`total`** (float | None): Expected total value (may be None)
58
+ - **`message`** (str | None): Optional status message (may be None)
59
+
docs/clients/prompts.mdx ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Prompts
3
+ sidebarTitle: Prompts
4
+ description: Use server-side prompt templates with automatic argument serialization.
5
+ icon: message-lines
6
+ ---
7
+
8
+ import { VersionBadge } from '/snippets/version-badge.mdx'
9
+
10
+ <VersionBadge version="2.0.0" />
11
+
12
+ Prompts are reusable message templates exposed by MCP servers. They can accept arguments to generate personalized message sequences for LLM interactions.
13
+
14
+ ## Listing Prompts
15
+
16
+ Use `list_prompts()` to retrieve all available prompt templates:
17
+
18
+ ```python
19
+ async with client:
20
+ prompts = await client.list_prompts()
21
+ # prompts -> list[mcp.types.Prompt]
22
+
23
+ for prompt in prompts:
24
+ print(f"Prompt: {prompt.name}")
25
+ print(f"Description: {prompt.description}")
26
+ if prompt.arguments:
27
+ print(f"Arguments: {[arg.name for arg in prompt.arguments]}")
28
+ ```
29
+
30
+ ## Using Prompts
31
+
32
+ ### Basic Usage
33
+
34
+ Request a rendered prompt using `get_prompt()` with the prompt name and arguments:
35
+
36
+ ```python
37
+ async with client:
38
+ # Simple prompt without arguments
39
+ result = await client.get_prompt("welcome_message")
40
+ # result -> mcp.types.GetPromptResult
41
+
42
+ # Access the generated messages
43
+ for message in result.messages:
44
+ print(f"Role: {message.role}")
45
+ print(f"Content: {message.content}")
46
+ ```
47
+
48
+ ### Prompts with Arguments
49
+
50
+ Pass arguments as a dictionary to customize the prompt:
51
+
52
+ ```python
53
+ async with client:
54
+ # Prompt with simple arguments
55
+ result = await client.get_prompt("user_greeting", {
56
+ "name": "Alice",
57
+ "role": "administrator"
58
+ })
59
+
60
+ # Access the personalized messages
61
+ for message in result.messages:
62
+ print(f"Generated message: {message.content}")
63
+ ```
64
+
65
+ ## Automatic Argument Serialization
66
+
67
+ <VersionBadge version="2.9.0" />
68
+
69
+ FastMCP automatically serializes complex arguments to JSON strings as required by the MCP specification. This allows you to pass typed objects directly:
70
+
71
+ ```python
72
+ from dataclasses import dataclass
73
+
74
+ @dataclass
75
+ class UserData:
76
+ name: str
77
+ age: int
78
+
79
+ async with client:
80
+ # Complex arguments are automatically serialized
81
+ result = await client.get_prompt("analyze_user", {
82
+ "user": UserData(name="Alice", age=30), # Automatically serialized to JSON
83
+ "preferences": {"theme": "dark"}, # Dict serialized to JSON string
84
+ "scores": [85, 92, 78], # List serialized to JSON string
85
+ "simple_name": "Bob" # Strings passed through unchanged
86
+ })
87
+ ```
88
+
89
+ The client handles serialization using `pydantic_core.to_json()` for consistent formatting. FastMCP servers can automatically deserialize these JSON strings back to the expected types.
90
+
91
+ ### Serialization Examples
92
+
93
+ ```python
94
+ async with client:
95
+ result = await client.get_prompt("data_analysis", {
96
+ # These will be automatically serialized to JSON strings:
97
+ "config": {
98
+ "format": "csv",
99
+ "include_headers": True,
100
+ "delimiter": ","
101
+ },
102
+ "filters": [
103
+ {"field": "age", "operator": ">", "value": 18},
104
+ {"field": "status", "operator": "==", "value": "active"}
105
+ ],
106
+ # This remains a string:
107
+ "report_title": "Monthly Analytics Report"
108
+ })
109
+ ```
110
+
111
+ ## Working with Prompt Results
112
+
113
+ The `get_prompt()` method returns a `GetPromptResult` object containing a list of messages:
114
+
115
+ ```python
116
+ async with client:
117
+ result = await client.get_prompt("conversation_starter", {"topic": "climate"})
118
+
119
+ # Access individual messages
120
+ for i, message in enumerate(result.messages):
121
+ print(f"Message {i + 1}:")
122
+ print(f" Role: {message.role}")
123
+ print(f" Content: {message.content.text if hasattr(message.content, 'text') else message.content}")
124
+ ```
125
+
126
+ ## Raw MCP Protocol Access
127
+
128
+ For access to the complete MCP protocol objects, use the `*_mcp` methods:
129
+
130
+ ```python
131
+ async with client:
132
+ # Raw MCP method returns full protocol object
133
+ prompts_result = await client.list_prompts_mcp()
134
+ # prompts_result -> mcp.types.ListPromptsResult
135
+
136
+ prompt_result = await client.get_prompt_mcp("example_prompt", {"arg": "value"})
137
+ # prompt_result -> mcp.types.GetPromptResult
138
+ ```
139
+
140
+ ## Multi-Server Clients
141
+
142
+ When using multi-server clients, prompts are accessible without prefixing (unlike tools):
143
+
144
+ ```python
145
+ async with client: # Multi-server client
146
+ # Prompts from any server are directly accessible
147
+ result1 = await client.get_prompt("weather_prompt", {"city": "London"})
148
+ result2 = await client.get_prompt("assistant_prompt", {"query": "help"})
149
+ ```
150
+
151
+ ## Common Prompt Patterns
152
+
153
+ ### System Messages
154
+
155
+ Many prompts generate system messages for LLM configuration:
156
+
157
+ ```python
158
+ async with client:
159
+ result = await client.get_prompt("system_configuration", {
160
+ "role": "helpful assistant",
161
+ "expertise": "python programming"
162
+ })
163
+
164
+ # Typically returns messages with role="system"
165
+ system_message = result.messages[0]
166
+ print(f"System prompt: {system_message.content}")
167
+ ```
168
+
169
+ ### Conversation Templates
170
+
171
+ Prompts can generate multi-turn conversation templates:
172
+
173
+ ```python
174
+ async with client:
175
+ result = await client.get_prompt("interview_template", {
176
+ "candidate_name": "Alice",
177
+ "position": "Senior Developer"
178
+ })
179
+
180
+ # Multiple messages for a conversation flow
181
+ for message in result.messages:
182
+ print(f"{message.role}: {message.content}")
183
+ ```
184
+
185
+ <Tip>
186
+ Prompt arguments and their expected types depend on the specific prompt implementation. Check the server's documentation or use `list_prompts()` to see available arguments for each prompt.
187
+ </Tip>
docs/clients/resources.mdx ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Resource Operations
3
+ sidebarTitle: Resources
4
+ description: Access static and templated resources from MCP servers.
5
+ icon: folder-open
6
+ ---
7
+
8
+ import { VersionBadge } from '/snippets/version-badge.mdx'
9
+
10
+ <VersionBadge version="2.0.0" />
11
+
12
+ Resources are data sources exposed by MCP servers. They can be static files or dynamic templates that generate content based on parameters.
13
+
14
+ ## Types of Resources
15
+
16
+ MCP servers expose two types of resources:
17
+
18
+ - **Static Resources**: Fixed content accessible via URI (e.g., configuration files, documentation)
19
+ - **Resource Templates**: Dynamic resources that accept parameters to generate content (e.g., API endpoints, database queries)
20
+
21
+ ## Listing Resources
22
+
23
+ ### Static Resources
24
+
25
+ Use `list_resources()` to retrieve all static resources available on the server:
26
+
27
+ ```python
28
+ async with client:
29
+ resources = await client.list_resources()
30
+ # resources -> list[mcp.types.Resource]
31
+
32
+ for resource in resources:
33
+ print(f"Resource URI: {resource.uri}")
34
+ print(f"Name: {resource.name}")
35
+ print(f"Description: {resource.description}")
36
+ print(f"MIME Type: {resource.mimeType}")
37
+ ```
38
+
39
+ ### Resource Templates
40
+
41
+ Use `list_resource_templates()` to retrieve available resource templates:
42
+
43
+ ```python
44
+ async with client:
45
+ templates = await client.list_resource_templates()
46
+ # templates -> list[mcp.types.ResourceTemplate]
47
+
48
+ for template in templates:
49
+ print(f"Template URI: {template.uriTemplate}")
50
+ print(f"Name: {template.name}")
51
+ print(f"Description: {template.description}")
52
+ ```
53
+
54
+ ## Reading Resources
55
+
56
+ ### Static Resources
57
+
58
+ Read a static resource using its URI:
59
+
60
+ ```python
61
+ async with client:
62
+ # Read a static resource
63
+ content = await client.read_resource("file:///path/to/README.md")
64
+ # content -> list[mcp.types.TextResourceContents | mcp.types.BlobResourceContents]
65
+
66
+ # Access text content
67
+ if hasattr(content[0], 'text'):
68
+ print(content[0].text)
69
+
70
+ # Access binary content
71
+ if hasattr(content[0], 'blob'):
72
+ print(f"Binary data: {len(content[0].blob)} bytes")
73
+ ```
74
+
75
+ ### Resource Templates
76
+
77
+ Read from a resource template by providing the URI with parameters:
78
+
79
+ ```python
80
+ async with client:
81
+ # Read a resource generated from a template
82
+ # For example, a template like "weather://{{city}}/current"
83
+ weather_content = await client.read_resource("weather://london/current")
84
+
85
+ # Access the generated content
86
+ print(weather_content[0].text) # Assuming text JSON response
87
+ ```
88
+
89
+ ## Content Types
90
+
91
+ Resources can return different content types:
92
+
93
+ ### Text Resources
94
+
95
+ ```python
96
+ async with client:
97
+ content = await client.read_resource("resource://config/settings.json")
98
+
99
+ for item in content:
100
+ if hasattr(item, 'text'):
101
+ print(f"Text content: {item.text}")
102
+ print(f"MIME type: {item.mimeType}")
103
+ ```
104
+
105
+ ### Binary Resources
106
+
107
+ ```python
108
+ async with client:
109
+ content = await client.read_resource("resource://images/logo.png")
110
+
111
+ for item in content:
112
+ if hasattr(item, 'blob'):
113
+ print(f"Binary content: {len(item.blob)} bytes")
114
+ print(f"MIME type: {item.mimeType}")
115
+
116
+ # Save to file
117
+ with open("downloaded_logo.png", "wb") as f:
118
+ f.write(item.blob)
119
+ ```
120
+
121
+ ## Working with Multi-Server Clients
122
+
123
+ When using multi-server clients, resource URIs are automatically prefixed with the server name:
124
+
125
+ ```python
126
+ async with client: # Multi-server client
127
+ # Access resources from different servers
128
+ weather_icons = await client.read_resource("weather://weather/icons/sunny")
129
+ templates = await client.read_resource("resource://assistant/templates/list")
130
+
131
+ print(f"Weather icon: {weather_icons[0].blob}")
132
+ print(f"Templates: {templates[0].text}")
133
+ ```
134
+
135
+ ## Raw MCP Protocol Access
136
+
137
+ For access to the complete MCP protocol objects, use the `*_mcp` methods:
138
+
139
+ ```python
140
+ async with client:
141
+ # Raw MCP methods return full protocol objects
142
+ resources_result = await client.list_resources_mcp()
143
+ # resources_result -> mcp.types.ListResourcesResult
144
+
145
+ templates_result = await client.list_resource_templates_mcp()
146
+ # templates_result -> mcp.types.ListResourceTemplatesResult
147
+
148
+ content_result = await client.read_resource_mcp("resource://example")
149
+ # content_result -> mcp.types.ReadResourceResult
150
+ ```
151
+
152
+ ## Common Resource URI Patterns
153
+
154
+ Different MCP servers may use various URI schemes:
155
+
156
+ ```python
157
+ # File system resources
158
+ "file:///path/to/file.txt"
159
+
160
+ # Custom protocol resources
161
+ "weather://london/current"
162
+ "database://users/123"
163
+
164
+ # Generic resource protocol
165
+ "resource://config/settings"
166
+ "resource://templates/email"
167
+ ```
168
+
169
+ <Tip>
170
+ Resource URIs and their formats depend on the specific MCP server implementation. Check the server's documentation for available resources and their URI patterns.
171
+ </Tip>
docs/clients/roots.mdx ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Client Roots
3
+ sidebarTitle: Roots
4
+ description: Provide local context and resource boundaries to MCP servers.
5
+ icon: folder-tree
6
+ ---
7
+
8
+ import { VersionBadge } from '/snippets/version-badge.mdx'
9
+
10
+ <VersionBadge version="2.0.0" />
11
+
12
+ Roots are a way for clients to inform servers about the resources they have access to. Servers can use this information to adjust behavior or provide more relevant responses.
13
+
14
+ ## Setting Static Roots
15
+
16
+ Provide a list of roots when creating the client:
17
+
18
+ <CodeGroup>
19
+ ```python Static Roots
20
+ from fastmcp import Client
21
+
22
+ client = Client(
23
+ "my_mcp_server.py",
24
+ roots=["/path/to/root1", "/path/to/root2"]
25
+ )
26
+ ```
27
+
28
+ ```python Dynamic Roots Callback
29
+ from fastmcp import Client
30
+ from fastmcp.client.roots import RequestContext
31
+
32
+ async def roots_callback(context: RequestContext) -> list[str]:
33
+ print(f"Server requested roots (Request ID: {context.request_id})")
34
+ return ["/path/to/root1", "/path/to/root2"]
35
+
36
+ client = Client(
37
+ "my_mcp_server.py",
38
+ roots=roots_callback
39
+ )
40
+ ```
41
+ </CodeGroup>
42
+
docs/clients/sampling.mdx ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: LLM Sampling
3
+ sidebarTitle: Sampling
4
+ description: Handle server-initiated LLM sampling requests.
5
+ icon: robot
6
+ ---
7
+
8
+ import { VersionBadge } from '/snippets/version-badge.mdx'
9
+
10
+ <VersionBadge version="2.0.0" />
11
+
12
+ MCP servers can request LLM completions from clients. The client handles these requests through a sampling handler callback.
13
+
14
+ ## Setting Up Sampling Handling
15
+
16
+ Provide a `sampling_handler` function when creating the client:
17
+
18
+ ```python
19
+ from fastmcp import Client
20
+ from fastmcp.client.sampling import (
21
+ SamplingMessage,
22
+ SamplingParams,
23
+ RequestContext,
24
+ )
25
+
26
+ async def sampling_handler(
27
+ messages: list[SamplingMessage],
28
+ params: SamplingParams,
29
+ context: RequestContext
30
+ ) -> str:
31
+ # Your LLM integration logic here
32
+ # Extract text from messages and generate a response
33
+ return "Generated response based on the messages"
34
+
35
+ client = Client(
36
+ "my_mcp_server.py",
37
+ sampling_handler=sampling_handler,
38
+ )
39
+ ```
40
+
41
+ ## Handler Parameters
42
+
43
+ The sampling handler receives three parameters:
44
+
45
+ ### SamplingMessage
46
+
47
+ - **`role`**: Message role (e.g., "user", "assistant", "system")
48
+ - **`content`**: Message content (usually has `.text` attribute)
49
+
50
+ ### SamplingParams
51
+
52
+ - **`systemPrompt`**: System prompt string (optional)
53
+ - **`maxTokens`**: Maximum tokens to generate (optional)
54
+ - **`temperature`**: Sampling temperature (optional)
55
+ - **`topP`**: Top-p sampling parameter (optional)
56
+ - **`stopSequences`**: List of stop sequences (optional)
57
+
58
+ ### RequestContext
59
+
60
+ - **`request_id`**: Unique identifier for the sampling request
61
+
62
+ ## Basic Example
63
+
64
+ ```python
65
+ from fastmcp import Client
66
+ from fastmcp.client.sampling import SamplingMessage, SamplingParams, RequestContext
67
+
68
+ async def basic_sampling_handler(
69
+ messages: list[SamplingMessage],
70
+ params: SamplingParams,
71
+ context: RequestContext
72
+ ) -> str:
73
+ # Extract message content
74
+ conversation = []
75
+ for message in messages:
76
+ content = message.content.text if hasattr(message.content, 'text') else str(message.content)
77
+ conversation.append(f"{message.role}: {content}")
78
+
79
+ # Use the system prompt if provided
80
+ system_prompt = params.systemPrompt or "You are a helpful assistant."
81
+
82
+ # Here you would integrate with your preferred LLM service
83
+ # This is just a placeholder response
84
+ return f"Response based on conversation: {' | '.join(conversation)}"
85
+
86
+ client = Client(
87
+ "my_mcp_server.py",
88
+ sampling_handler=basic_sampling_handler
89
+ )
90
+ ```
91
+
docs/clients/tools.mdx ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Tool Operations
3
+ sidebarTitle: Tools
4
+ description: Discover and execute server-side tools with the FastMCP client.
5
+ icon: wrench
6
+ ---
7
+
8
+ import { VersionBadge } from '/snippets/version-badge.mdx'
9
+
10
+ <VersionBadge version="2.0.0" />
11
+
12
+ Tools are executable functions exposed by MCP servers. The FastMCP client provides methods to discover available tools and execute them with arguments.
13
+
14
+ ## Discovering Tools
15
+
16
+ Use `list_tools()` to retrieve all tools available on the server:
17
+
18
+ ```python
19
+ async with client:
20
+ tools = await client.list_tools()
21
+ # tools -> list[mcp.types.Tool]
22
+
23
+ for tool in tools:
24
+ print(f"Tool: {tool.name}")
25
+ print(f"Description: {tool.description}")
26
+ if tool.inputSchema:
27
+ print(f"Parameters: {tool.inputSchema}")
28
+ ```
29
+
30
+ ## Executing Tools
31
+
32
+ ### Basic Execution
33
+
34
+ Execute a tool using `call_tool()` with the tool name and arguments:
35
+
36
+ ```python
37
+ async with client:
38
+ # Simple tool call
39
+ result = await client.call_tool("add", {"a": 5, "b": 3})
40
+ # result -> list[mcp.types.TextContent | mcp.types.ImageContent | ...]
41
+
42
+ # Access the result content
43
+ print(result[0].text) # Assuming TextContent, e.g., '8'
44
+ ```
45
+
46
+ ### Advanced Execution Options
47
+
48
+ The `call_tool()` method supports additional parameters for timeout control and progress monitoring:
49
+
50
+ ```python
51
+ async with client:
52
+ # With timeout (aborts if execution takes longer than 2 seconds)
53
+ result = await client.call_tool(
54
+ "long_running_task",
55
+ {"param": "value"},
56
+ timeout=2.0
57
+ )
58
+
59
+ # With progress handler (to track execution progress)
60
+ result = await client.call_tool(
61
+ "long_running_task",
62
+ {"param": "value"},
63
+ progress_handler=my_progress_handler
64
+ )
65
+ ```
66
+
67
+ **Parameters:**
68
+ - `name`: The tool name (string)
69
+ - `arguments`: Dictionary of arguments to pass to the tool (optional)
70
+ - `timeout`: Maximum execution time in seconds (optional, overrides client-level timeout)
71
+ - `progress_handler`: Progress callback function (optional, overrides client-level handler)
72
+
73
+ ## Handling Results
74
+
75
+ Tool execution returns a list of content objects. The most common types are:
76
+
77
+ - **`TextContent`**: Text-based results with a `.text` attribute
78
+ - **`ImageContent`**: Image data with image-specific attributes
79
+ - **`BlobContent`**: Binary data content
80
+
81
+ ```python
82
+ async with client:
83
+ result = await client.call_tool("get_weather", {"city": "London"})
84
+
85
+ for content in result:
86
+ if hasattr(content, 'text'):
87
+ print(f"Text result: {content.text}")
88
+ elif hasattr(content, 'data'):
89
+ print(f"Binary data: {len(content.data)} bytes")
90
+ ```
91
+
92
+ ## Error Handling
93
+
94
+ ### Exception-Based Error Handling
95
+
96
+ By default, `call_tool()` raises a `ToolError` if the tool execution fails:
97
+
98
+ ```python
99
+ from fastmcp.exceptions import ToolError
100
+
101
+ async with client:
102
+ try:
103
+ result = await client.call_tool("potentially_failing_tool", {"param": "value"})
104
+ print("Tool succeeded:", result)
105
+ except ToolError as e:
106
+ print(f"Tool failed: {e}")
107
+ ```
108
+
109
+ ### Manual Error Checking
110
+
111
+ For more granular control, use `call_tool_mcp()` which returns the raw MCP protocol object with an `isError` flag:
112
+
113
+ ```python
114
+ async with client:
115
+ result = await client.call_tool_mcp("potentially_failing_tool", {"param": "value"})
116
+ # result -> mcp.types.CallToolResult
117
+
118
+ if result.isError:
119
+ print(f"Tool failed: {result.content}")
120
+ else:
121
+ print(f"Tool succeeded: {result.content}")
122
+ ```
123
+
124
+ ## Argument Handling
125
+
126
+ Arguments are passed as a dictionary to the tool:
127
+
128
+ ```python
129
+ async with client:
130
+ # Simple arguments
131
+ result = await client.call_tool("greet", {"name": "World"})
132
+
133
+ # Complex arguments
134
+ result = await client.call_tool("process_data", {
135
+ "config": {"format": "json", "validate": True},
136
+ "items": [1, 2, 3, 4, 5],
137
+ "metadata": {"source": "api", "version": "1.0"}
138
+ })
139
+ ```
140
+
141
+ <Tip>
142
+ For multi-server clients, tool names are automatically prefixed with the server name (e.g., `weather_get_forecast` for a tool named `get_forecast` on the `weather` server).
143
+ </Tip>
docs/docs.json CHANGED
@@ -63,7 +63,7 @@
63
  {
64
  "group": "Servers",
65
  "pages": [
66
- "servers/fastmcp",
67
  {
68
  "group": "Core Components",
69
  "icon": "toolbox",
@@ -94,13 +94,31 @@
94
  "group": "Clients",
95
  "pages": [
96
  "clients/client",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  "clients/transports",
98
  {
99
  "group": "Authentication",
100
  "icon": "user-shield",
101
  "pages": ["clients/auth/oauth", "clients/auth/bearer"]
102
- },
103
- "clients/advanced-features"
104
  ]
105
  },
106
  {
 
63
  {
64
  "group": "Servers",
65
  "pages": [
66
+ "servers/server",
67
  {
68
  "group": "Core Components",
69
  "icon": "toolbox",
 
94
  "group": "Clients",
95
  "pages": [
96
  "clients/client",
97
+ {
98
+ "group": "Core Operations",
99
+ "icon": "handshake",
100
+ "pages": [
101
+ "clients/tools",
102
+ "clients/resources",
103
+ "clients/prompts"
104
+ ]
105
+ },
106
+ {
107
+ "group": "Advanced Features",
108
+ "icon": "stars",
109
+ "pages": [
110
+ "clients/logging",
111
+ "clients/progress",
112
+ "clients/sampling",
113
+ "clients/roots"
114
+ ]
115
+ },
116
  "clients/transports",
117
  {
118
  "group": "Authentication",
119
  "icon": "user-shield",
120
  "pages": ["clients/auth/oauth", "clients/auth/bearer"]
121
+ }
 
122
  ]
123
  },
124
  {
docs/servers/resources.mdx CHANGED
@@ -2,7 +2,7 @@
2
  title: Resources & Templates
3
  sidebarTitle: Resources
4
  description: Expose data sources and dynamic content generators to your MCP client.
5
- icon: database
6
  ---
7
 
8
  import { VersionBadge } from "/snippets/version-badge.mdx"
 
2
  title: Resources & Templates
3
  sidebarTitle: Resources
4
  description: Expose data sources and dynamic content generators to your MCP client.
5
+ icon: folder-open
6
  ---
7
 
8
  import { VersionBadge } from "/snippets/version-badge.mdx"
docs/servers/{fastmcp.mdx → server.mdx} RENAMED
@@ -1,7 +1,7 @@
1
  ---
2
  title: The FastMCP Server
3
- sidebarTitle: FastMCP Servers
4
- description: Learn about the core FastMCP server class and how to run it.
5
  icon: server
6
  ---
7
 
 
1
  ---
2
  title: The FastMCP Server
3
+ sidebarTitle: Overview
4
+ description: The core FastMCP server class for building MCP applications with tools, resources, and prompts.
5
  icon: server
6
  ---
7
 
justfile CHANGED
@@ -24,4 +24,7 @@ api-ref *MODULES:
24
 
25
  # Clean up API reference documentation
26
  api-ref-clean:
27
- rm -rf docs/python-sdk
 
 
 
 
24
 
25
  # Clean up API reference documentation
26
  api-ref-clean:
27
+ rm -rf docs/python-sdk
28
+
29
+ copy-context:
30
+ uvx --with-editable . --refresh-package copychat copychat@latest src/ docs/ -x changelog.mdx -x python-sdk/ -v