Jeremiah Lowin commited on
Commit
da46698
·
1 Parent(s): a01a818

Add documentation for config-based clients

Browse files
docs/clients/{features.mdx → advanced-features.mdx} RENAMED
File without changes
docs/clients/client.mdx CHANGED
@@ -43,7 +43,8 @@ The following inference rules are used to determine the appropriate `ClientTrans
43
  * If it ends with `.js`: Creates a `NodeStdioTransport` to run the script using `node`.
44
  4. **`AnyUrl` or `str` pointing to a URL that begins with `http://` or `https://`**:
45
  * Creates a `StreamableHttpTransport`
46
- 5. **Other**: Raises a `ValueError` if the type cannot be inferred.
 
47
 
48
  ```python
49
  import asyncio
@@ -76,6 +77,65 @@ print(client_stdio.transport)
76
  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.
77
  </Tip>
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  ## Client Usage
80
 
81
  ### Connection Lifecycle
 
43
  * If it ends with `.js`: Creates a `NodeStdioTransport` to run the script using `node`.
44
  4. **`AnyUrl` or `str` pointing to a URL that begins with `http://` or `https://`**:
45
  * Creates a `StreamableHttpTransport`
46
+ 5. **`MCPConfig` or dictionary matching MCPConfig schema**: Creates a client that connects to one or more MCP servers specified in the config.
47
+ 6. **Other**: Raises a `ValueError` if the type cannot be inferred.
48
 
49
  ```python
50
  import asyncio
 
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.3.6" />
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
+ from fastmcp.utilities.mcp_config import MCPConfig
99
+
100
+ # Create a standard MCP configuration with multiple servers
101
+ config = {
102
+ "mcpServers": {
103
+ # A remote HTTP server
104
+ "weather": {
105
+ "url": "https://weather-api.example.com/mcp",
106
+ "transport": "streamable-http"
107
+ },
108
+ # A local server running via stdio
109
+ "assistant": {
110
+ "command": "python",
111
+ "args": ["./my_assistant_server.py"],
112
+ "env": {"DEBUG": "true"}
113
+ }
114
+ }
115
+ }
116
+
117
+ # Create a client that connects to both servers
118
+ client = Client(config)
119
+
120
+ async def main():
121
+ async with client:
122
+ # Access tools from different servers with prefixes
123
+ weather_data = await client.call_tool("weather_get_forecast", {"city": "London"})
124
+ response = await client.call_tool("assistant_answer_question", {"question": "What's the capital of France?"})
125
+
126
+ # Access resources with prefixed URIs
127
+ weather_icons = await client.read_resource("weather://weather/icons/sunny")
128
+ templates = await client.read_resource("resource://assistant/templates/list")
129
+
130
+ print(f"Weather: {weather_data}")
131
+ print(f"Assistant: {response}")
132
+
133
+ if __name__ == "__main__":
134
+ asyncio.run(main())
135
+ ```
136
+
137
+ If your configuration has only a single server, FastMCP will create a direct client to that server without any prefixing.
138
+
139
  ## Client Usage
140
 
141
  ### Connection Lifecycle
docs/clients/transports.mdx CHANGED
@@ -317,4 +317,65 @@ async def main():
317
  asyncio.run(main())
318
  ```
319
 
320
- Communication happens through efficient in-memory queues, making it very fast and ideal for unit testing.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
  asyncio.run(main())
318
  ```
319
 
320
+ Communication happens through efficient in-memory queues, making it very fast and ideal for unit testing.
321
+
322
+ ## Configuration-Based Transports
323
+
324
+ ### MCPConfig Transport
325
+
326
+ <VersionBadge version="2.3.6" />
327
+
328
+ - **Class:** `fastmcp.client.transports.MCPConfigTransport`
329
+ - **Inferred From:** An instance of `MCPConfig` or a dictionary matching the MCPConfig schema
330
+ - **Use Case:** Connecting to one or more MCP servers defined in a configuration object
331
+
332
+ MCPConfig follows an emerging standard for MCP server configuration but is subject to change as the specification evolves. The standard supports both local servers (running via stdio) and remote servers (accessed via HTTP).
333
+
334
+ ```python
335
+ from fastmcp import Client
336
+ from fastmcp.utilities.mcp_config import MCPConfig
337
+
338
+ # Configuration for multiple MCP servers (both local and remote)
339
+ config = {
340
+ "mcpServers": {
341
+ # Remote HTTP server
342
+ "weather": {
343
+ "url": "https://weather-api.example.com/mcp",
344
+ "transport": "streamable-http"
345
+ },
346
+ # Local stdio server
347
+ "assistant": {
348
+ "command": "python",
349
+ "args": ["./assistant_server.py"],
350
+ "env": {"DEBUG": "true"}
351
+ },
352
+ # Another remote server
353
+ "calendar": {
354
+ "url": "https://calendar-api.example.com/mcp",
355
+ "transport": "streamable-http"
356
+ }
357
+ }
358
+ }
359
+
360
+ # Create a transport from the config (happens automatically with Client)
361
+ client = Client(config)
362
+
363
+ async def main():
364
+ async with client:
365
+ # Tools are accessible with server name prefixes
366
+ weather = await client.call_tool("weather_get_forecast", {"city": "London"})
367
+ answer = await client.call_tool("assistant_answer_question", {"query": "What is MCP?"})
368
+ events = await client.call_tool("calendar_list_events", {"date": "2023-06-01"})
369
+
370
+ # Resources use prefixed URI paths
371
+ icons = await client.read_resource("weather://weather/icons/sunny")
372
+ docs = await client.read_resource("resource://assistant/docs/mcp")
373
+
374
+ asyncio.run(main())
375
+ ```
376
+
377
+ If your configuration has only a single server, the client will connect directly to that server without any prefixing. This makes it convenient to switch between single and multi-server configurations without changing your client code.
378
+
379
+ <Note>
380
+ The MCPConfig format is an emerging standard for MCP server configuration and may change as the MCP ecosystem evolves. While FastMCP aims to maintain compatibility with future versions, be aware that field names or structure might change.
381
+ </Note>
docs/docs.json CHANGED
@@ -67,8 +67,8 @@
67
  "group": "Clients",
68
  "pages": [
69
  "clients/client",
70
- "clients/features",
71
- "clients/transports"
72
  ]
73
  },
74
  {
 
67
  "group": "Clients",
68
  "pages": [
69
  "clients/client",
70
+ "clients/transports",
71
+ "clients/advanced-features"
72
  ]
73
  },
74
  {
docs/servers/composition.mdx CHANGED
@@ -35,6 +35,10 @@ The choice of importing or mounting depends on your use case and requirements.
35
 
36
  FastMCP supports [MCP proxying](/patterns/proxy), which allows you to mirror a local or remote server in a local FastMCP instance. Proxies are fully compatible with both importing and mounting.
37
 
 
 
 
 
38
  ## Importing (Static Composition)
39
 
40
  The `import_server()` method copies all components (tools, resources, templates, prompts) from one `FastMCP` instance (the *subserver*) into another (the *main server*). A `prefix` is added to avoid naming conflicts.
 
35
 
36
  FastMCP supports [MCP proxying](/patterns/proxy), which allows you to mirror a local or remote server in a local FastMCP instance. Proxies are fully compatible with both importing and mounting.
37
 
38
+ <VersionBadge version="2.3.6" />
39
+
40
+ You can also create proxies from configuration dictionaries that follow the MCPConfig schema, which is useful for quickly connecting to one or more remote servers. See the [Proxy Servers documentation](/servers/proxy#configuration-based-proxies) for details on configuration-based proxying. Note that MCPConfig follows an emerging standard and its format may evolve over time.
41
+
42
  ## Importing (Static Composition)
43
 
44
  The `import_server()` method copies all components (tools, resources, templates, prompts) from one `FastMCP` instance (the *subserver*) into another (the *main server*). A `prefix` is added to avoid naming conflicts.
docs/servers/proxy.mdx CHANGED
@@ -104,6 +104,64 @@ proxy = FastMCP.as_proxy(
104
  # requests to original_server
105
  ```
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  ## `FastMCPProxy` Class
108
 
109
  Internally, `FastMCP.as_proxy()` uses the `FastMCPProxy` class. You generally don't need to interact with this class directly, but it's available if needed.
 
104
  # requests to original_server
105
  ```
106
 
107
+ ### Configuration-Based Proxies
108
+
109
+ <VersionBadge version="2.3.6" />
110
+
111
+ You can create a proxy directly from a configuration dictionary that follows the MCPConfig schema. This is useful for quickly setting up proxies to remote servers without manually configuring each connection detail.
112
+
113
+ ```python
114
+ from fastmcp import FastMCP
115
+
116
+ # Create a proxy directly from a config dictionary
117
+ config = {
118
+ "mcpServers": {
119
+ "default": { # For single server configs, 'default' is commonly used
120
+ "url": "https://example.com/mcp",
121
+ "transport": "streamable-http"
122
+ }
123
+ }
124
+ }
125
+
126
+ # Create a proxy to the configured server
127
+ proxy = FastMCP.as_proxy(config, name="Config-Based Proxy")
128
+
129
+ # Run the proxy with stdio transport for local access
130
+ if __name__ == "__main__":
131
+ proxy.run()
132
+ ```
133
+
134
+ <Note>
135
+ The MCPConfig format follows an emerging standard for MCP server configuration and may evolve as the specification matures. While FastMCP aims to maintain compatibility with future versions, be aware that field names or structure might change.
136
+ </Note>
137
+
138
+ You can also use MCPConfig to create a proxy to multiple servers. When multiple servers are specified, they are automatically mounted with their config names as prefixes, providing a unified interface to all servers:
139
+
140
+ ```python
141
+ from fastmcp import FastMCP
142
+
143
+ # Multi-server configuration
144
+ config = {
145
+ "mcpServers": {
146
+ "weather": {
147
+ "url": "https://weather-api.example.com/mcp",
148
+ "transport": "streamable-http"
149
+ },
150
+ "calendar": {
151
+ "url": "https://calendar-api.example.com/mcp",
152
+ "transport": "streamable-http"
153
+ }
154
+ }
155
+ }
156
+
157
+ # Create a proxy to multiple servers
158
+ composite_proxy = FastMCP.as_proxy(config, name="Composite Proxy")
159
+
160
+ # Tools and resources are accessible with prefixes:
161
+ # - weather_get_forecast, calendar_add_event
162
+ # - weather://weather/icons/sunny, calendar://calendar/events/today
163
+ ```
164
+
165
  ## `FastMCPProxy` Class
166
 
167
  Internally, `FastMCP.as_proxy()` uses the `FastMCPProxy` class. You generally don't need to interact with this class directly, but it's available if needed.
src/fastmcp/client/transports.py CHANGED
@@ -474,7 +474,52 @@ class FastMCPTransport(ClientTransport):
474
 
475
 
476
  class MCPConfigTransport(ClientTransport):
477
- """Transport for running MCPConfig."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
 
479
  def __init__(self, config: MCPConfig | dict):
480
  from fastmcp.client.client import Client
@@ -526,7 +571,38 @@ def infer_transport(
526
  argument, handling various input types and converting them to the appropriate
527
  ClientTransport subclass.
528
 
 
 
 
 
 
 
 
529
  For HTTP URLs, they are assumed to be Streamable HTTP URLs unless they end in `/sse`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
530
  """
531
  from fastmcp.utilities.mcp_config import MCPConfig
532
 
 
474
 
475
 
476
  class MCPConfigTransport(ClientTransport):
477
+ """Transport for connecting to one or more MCP servers defined in an MCPConfig.
478
+
479
+ This transport provides a unified interface to multiple MCP servers defined in an MCPConfig
480
+ object or dictionary matching the MCPConfig schema. It supports two key scenarios:
481
+
482
+ 1. If the MCPConfig contains exactly one server, it creates a direct transport to that server.
483
+ 2. If the MCPConfig contains multiple servers, it creates a composite client by mounting
484
+ all servers on a single FastMCP instance, with each server's name used as its mounting prefix.
485
+
486
+ In the multi-server case, tools are accessible with the prefix pattern `{server_name}_{tool_name}`
487
+ and resources with the pattern `protocol://{server_name}/path/to/resource`.
488
+
489
+ This is particularly useful for creating clients that need to interact with multiple specialized
490
+ MCP servers through a single interface, simplifying client code.
491
+
492
+ Examples:
493
+ ```python
494
+ from fastmcp import Client
495
+ from fastmcp.utilities.mcp_config import MCPConfig
496
+
497
+ # Create a config with multiple servers
498
+ config = {
499
+ "mcpServers": {
500
+ "weather": {
501
+ "url": "https://weather-api.example.com/mcp",
502
+ "transport": "streamable-http"
503
+ },
504
+ "calendar": {
505
+ "url": "https://calendar-api.example.com/mcp",
506
+ "transport": "streamable-http"
507
+ }
508
+ }
509
+ }
510
+
511
+ # Create a client with the config
512
+ client = Client(config)
513
+
514
+ async with client:
515
+ # Access tools with prefixes
516
+ weather = await client.call_tool("weather_get_forecast", {"city": "London"})
517
+ events = await client.call_tool("calendar_list_events", {"date": "2023-06-01"})
518
+
519
+ # Access resources with prefixed URIs
520
+ icons = await client.read_resource("weather://weather/icons/sunny")
521
+ ```
522
+ """
523
 
524
  def __init__(self, config: MCPConfig | dict):
525
  from fastmcp.client.client import Client
 
571
  argument, handling various input types and converting them to the appropriate
572
  ClientTransport subclass.
573
 
574
+ The function supports these input types:
575
+ - ClientTransport: Used directly without modification
576
+ - FastMCPServer: Creates an in-memory FastMCPTransport
577
+ - Path or str (file path): Creates PythonStdioTransport (.py) or NodeStdioTransport (.js)
578
+ - AnyUrl or str (URL): Creates StreamableHttpTransport (default) or SSETransport (for /sse endpoints)
579
+ - MCPConfig or dict: Creates MCPConfigTransport, potentially connecting to multiple servers
580
+
581
  For HTTP URLs, they are assumed to be Streamable HTTP URLs unless they end in `/sse`.
582
+
583
+ For MCPConfig with multiple servers, a composite client is created where each server
584
+ is mounted with its name as prefix. This allows accessing tools and resources from multiple
585
+ servers through a single unified client interface, using naming patterns like
586
+ `servername_toolname` for tools and `protocol://servername/path` for resources.
587
+ If the MCPConfig contains only one server, a direct connection is established without prefixing.
588
+
589
+ Examples:
590
+ ```python
591
+ # Connect to a local Python script
592
+ transport = infer_transport("my_script.py")
593
+
594
+ # Connect to a remote server via HTTP
595
+ transport = infer_transport("http://example.com/mcp")
596
+
597
+ # Connect to multiple servers using MCPConfig
598
+ config = {
599
+ "mcpServers": {
600
+ "weather": {"url": "http://weather.example.com/mcp"},
601
+ "calendar": {"url": "http://calendar.example.com/mcp"}
602
+ }
603
+ }
604
+ transport = infer_transport(config)
605
+ ```
606
  """
607
  from fastmcp.utilities.mcp_config import MCPConfig
608