Jeremiah Lowin commited on
Commit
9b4ba17
·
1 Parent(s): 11e3870

add client docs

Browse files
docs/clients/overview.mdx ADDED
@@ -0,0 +1,252 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
8
+ 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.
9
+
10
+ ## FastMCP Client
11
+
12
+ The FastMCP Client architecture separates the protocol logic (`Client`) from the connection mechanism (`Transport`).
13
+
14
+ - **`Client`**: Handles sending MCP requests (like `tools/call`, `resources/read`), receiving responses, and managing callbacks.
15
+ - **`Transport`**: Responsible for establishing and maintaining the connection to the server (e.g., via WebSockets, SSE, Stdio, or in-memory).
16
+
17
+
18
+ ### Transports
19
+
20
+ 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.
21
+
22
+ The following inference rules are used to determine the appropriate `ClientTransport` based on the input type:
23
+
24
+ 1. **`ClientTransport` Instance**: If you provide an already instantiated transport object, it's used directly.
25
+ 2. **`FastMCP` Instance**: Creates a `FastMCPTransport` for efficient in-memory communication (ideal for testing).
26
+ 3. **`Path` or `str` pointing to an existing file**:
27
+ * If it ends with `.py`: Creates a `PythonStdioTransport` to run the script using `python`.
28
+ * If it ends with `.js`: Creates a `NodeStdioTransport` to run the script using `node`.
29
+ 4. **`AnyUrl` or `str` pointing to a URL**:
30
+ * If it starts with `http://` or `https://`: Creates an `SSETransport`.
31
+ * If it starts with `ws://` or `wss://`: Creates a `WSTransport`.
32
+ 5. **Other**: Raises a `ValueError` if the type cannot be inferred.
33
+
34
+ ```python
35
+ import asyncio
36
+ from fastmcp import Client, FastMCP
37
+
38
+ # Example transports (more details in Transports page)
39
+ server_instance = FastMCP(name="TestServer") # In-memory server
40
+ sse_url = "http://localhost:8000/sse" # SSE server URL
41
+ ws_url = "ws://localhost:9000" # WebSocket server URL
42
+ server_script = "my_mcp_server.py" # Path to a Python server file
43
+
44
+ # Client automatically infers the transport type
45
+ client_in_memory = Client(server_instance)
46
+ client_sse = Client(sse_url)
47
+ client_ws = Client(ws_url)
48
+ client_stdio = Client(server_script)
49
+
50
+ print(client_in_memory.transport)
51
+ print(client_sse.transport)
52
+ print(client_ws.transport)
53
+ print(client_stdio.transport)
54
+
55
+ # Expected Output (types may vary slightly based on environment):
56
+ # <FastMCP(server='TestServer')>
57
+ # <SSE(url='http://localhost:8000/sse')>
58
+ # <WebSocket(url='ws://localhost:9000')>
59
+ # <PythonStdioTransport(command='python', args=['/path/to/your/my_mcp_server.py'])>
60
+ ```
61
+ <Tip>
62
+ 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.
63
+ </Tip>
64
+
65
+ ## Client Usage
66
+
67
+ ### Connection Lifecycle
68
+
69
+ 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.
70
+
71
+ ```python
72
+ import asyncio
73
+ from fastmcp import Client
74
+
75
+ client = Client("my_mcp_server.py") # Assumes my_mcp_server.py exists
76
+
77
+ async def main():
78
+ # Connection is established here
79
+ async with client:
80
+ print(f"Client connected: {client.is_connected()}")
81
+
82
+ # Make MCP calls within the context
83
+ tools = await client.list_tools()
84
+ print(f"Available tools: {tools}")
85
+
86
+ if any(tool.name == "greet" for tool in tools):
87
+ result = await client.call_tool("greet", {"name": "World"})
88
+ print(f"Greet result: {result}")
89
+
90
+ # Connection is closed automatically here
91
+ print(f"Client connected: {client.is_connected()}")
92
+
93
+ if __name__ == "__main__":
94
+ asyncio.run(main())
95
+ ```
96
+
97
+ You can make multiple calls to the server within the same `async with` block using the established session.
98
+
99
+ ### Client Methods
100
+
101
+ The `Client` provides methods corresponding to standard MCP requests:
102
+
103
+ #### Tool Operations
104
+
105
+ * **`list_tools()`**: Retrieves a list of tools available on the server.
106
+ ```python
107
+ tools = await client.list_tools()
108
+ # tools -> list[mcp.types.Tool]
109
+ ```
110
+ * **`call_tool(name: str, arguments: dict[str, Any] | None = None)`**: Executes a tool on the server.
111
+ ```python
112
+ result = await client.call_tool("add", {"a": 5, "b": 3})
113
+ # result -> list[mcp.types.TextContent | mcp.types.ImageContent | ...]
114
+ print(result[0].text) # Assuming TextContent, e.g., '8'
115
+ ```
116
+ * Arguments are passed as a dictionary. FastMCP servers automatically handle JSON string parsing for complex types if needed.
117
+ * Returns a list of content objects (usually `TextContent` or `ImageContent`).
118
+
119
+ #### Resource Operations
120
+
121
+ * **`list_resources()`**: Retrieves a list of static resources.
122
+ ```python
123
+ resources = await client.list_resources()
124
+ # resources -> list[mcp.types.Resource]
125
+ ```
126
+ * **`list_resource_templates()`**: Retrieves a list of resource templates.
127
+ ```python
128
+ templates = await client.list_resource_templates()
129
+ # templates -> list[mcp.types.ResourceTemplate]
130
+ ```
131
+ * **`read_resource(uri: str | AnyUrl)`**: Reads the content of a resource or a resolved template.
132
+ ```python
133
+ # Read a static resource
134
+ readme_content = await client.read_resource("file:///path/to/README.md")
135
+ # readme_content -> list[mcp.types.TextResourceContents | mcp.types.BlobResourceContents]
136
+ print(readme_content[0].text) # Assuming text
137
+
138
+ # Read a resource generated from a template
139
+ weather_content = await client.read_resource("data://weather/london")
140
+ print(weather_content[0].text) # Assuming text JSON
141
+ ```
142
+
143
+ #### Prompt Operations
144
+
145
+ * **`list_prompts()`**: Retrieves available prompt templates.
146
+ * **`get_prompt(name: str, arguments: dict[str, Any] | None = None)`**: Retrieves a rendered prompt message list.
147
+
148
+ ### Callbacks
149
+
150
+ MCP allows servers to make requests *back* to the client for certain capabilities. The `Client` constructor accepts callback functions to handle these server requests:
151
+
152
+ #### Roots
153
+
154
+ * **`roots: RootsList | RootsHandler | None`**: Provides the server with a list of root directories the client grants access to. This can be a static list or a function that dynamically determines roots.
155
+ ```python
156
+ from pathlib import Path
157
+ from fastmcp.client.roots import RootsHandler, RootsList
158
+ from mcp.shared.context import RequestContext # For type hint
159
+
160
+ # Option 1: Static list
161
+ static_roots: RootsList = [str(Path.home() / "Documents")]
162
+
163
+ # Option 2: Dynamic function
164
+ def dynamic_roots_handler(context: RequestContext) -> RootsList:
165
+ # Logic to determine accessible roots based on context
166
+ print(f"Server requested roots (Request ID: {context.request_id})")
167
+ return [str(Path.home() / "Downloads")]
168
+
169
+ client_with_roots = Client(
170
+ "my_server.py",
171
+ roots=dynamic_roots_handler # or roots=static_roots
172
+ )
173
+
174
+ # Tell the server the roots might have changed (if needed)
175
+ # async with client_with_roots:
176
+ # await client_with_roots.send_roots_list_changed()
177
+ ```
178
+ See `fastmcp.client.roots` for helpers.
179
+
180
+ #### LLM Sampling
181
+
182
+ * **`sampling_handler: SamplingHandler | None`**: Handles `sampling/createMessage` requests from the server. This callback receives messages from the server and should return an LLM completion.
183
+ ```python
184
+ from fastmcp.client.sampling import SamplingHandler, MessageResult
185
+ from mcp.types import SamplingMessage, SamplingParams, TextContent
186
+ from mcp.shared.context import RequestContext # For type hint
187
+
188
+ async def my_llm_handler(
189
+ messages: list[SamplingMessage],
190
+ params: SamplingParams,
191
+ context: RequestContext
192
+ ) -> str | MessageResult:
193
+ print(f"Server requested sampling (Request ID: {context.request_id})")
194
+ # In a real scenario, call your LLM API here
195
+ last_user_message = next((m for m in reversed(messages) if m.role == 'user'), None)
196
+ prompt = last_user_message.content.text if last_user_message and isinstance(last_user_message.content, TextContent) else "Default prompt"
197
+
198
+ # Simulate LLM response
199
+ response_text = f"LLM processed: {prompt[:50]}..."
200
+ # Return simple string (becomes TextContent) or a MessageResult object
201
+ return response_text
202
+
203
+ client_with_sampling = Client(
204
+ "my_server.py",
205
+ sampling_handler=my_llm_handler
206
+ )
207
+ ```
208
+ See `fastmcp.client.sampling` for helpers.
209
+
210
+ #### Logging
211
+
212
+ * **`log_handler: LoggingFnT | None`**: Receives log messages sent from the server (`ctx.info`, `ctx.error`, etc.).
213
+ ```python
214
+ from mcp.client.session import LoggingFnT, LogLevel
215
+
216
+ def my_log_handler(level: LogLevel, message: str, logger_name: str | None):
217
+ print(f"[Server Log - {level.upper()}] {logger_name or 'default'}: {message}")
218
+
219
+ client_with_logging = Client(
220
+ "my_server.py",
221
+ log_handler=my_log_handler
222
+ )
223
+ ```
224
+
225
+
226
+ ### Error Handling
227
+
228
+ 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.client.ClientError`.
229
+
230
+ ```python
231
+ async def safe_call_tool():
232
+ async with client:
233
+ try:
234
+ # Assume 'divide' tool exists and might raise ZeroDivisionError
235
+ result = await client.call_tool("divide", {"a": 10, "b": 0})
236
+ print(f"Result: {result}")
237
+ except ClientError as e:
238
+ print(f"Tool call failed: {e}")
239
+ except ConnectionError as e:
240
+ print(f"Connection failed: {e}")
241
+ except Exception as e:
242
+ print(f"An unexpected error occurred: {e}")
243
+
244
+ # Example Output if division by zero occurs:
245
+ # Tool call failed: Division by zero is not allowed.
246
+ ```
247
+
248
+ Other errors, like connection failures, will raise standard Python exceptions (e.g., `ConnectionError`, `TimeoutError`).
249
+
250
+ <Tip>
251
+ 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 call `call_tools(..., return_raw_result=True)` to get the raw result object and handle errors yourself by checking its `isError` attribute.
252
+ </Tip>
docs/clients/transports.mdx ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Client Transports
3
+ sidebarTitle: Transports
4
+ description: Understand the different ways FastMCP Clients can connect to servers.
5
+ icon: link
6
+ ---
7
+
8
+ The FastMCP `Client` relies on a `ClientTransport` object to handle the specifics of connecting to and communicating with an MCP server. FastMCP provides several built-in transport implementations for common connection methods.
9
+
10
+ While the `Client` often infers the correct transport automatically (see [Client Overview](/clients/overview#transport-inference)), you can also instantiate transports explicitly for more control.
11
+
12
+
13
+ ## Stdio Transports
14
+
15
+ These transports manage an MCP server running as a subprocess, communicating with it via standard input (stdin) and standard output (stdout). This is the standard mechanism used by clients like Claude Desktop.
16
+
17
+ ### Python Stdio
18
+
19
+ * **Class:** `fastmcp.client.transports.PythonStdioTransport`
20
+ * **Inferred From:** Paths to `.py` files.
21
+ * **Use Case:** Running a Python-based MCP server script (like one using FastMCP or the base `mcp` library) in a subprocess.
22
+
23
+ This is the most common way to interact with local FastMCP servers during development or when integrating with tools that expect to launch a server script.
24
+
25
+ ```python
26
+ from fastmcp import Client
27
+ from fastmcp.client.transports import PythonStdioTransport
28
+
29
+ server_script = "my_mcp_server.py" # Assumes this file exists and runs mcp.run()
30
+
31
+ # Option 1: Inferred transport
32
+ client_inferred = Client(server_script)
33
+
34
+ # Option 2: Explicit transport (e.g., to use a specific python executable or add args)
35
+ transport_explicit = PythonStdioTransport(
36
+ script_path=server_script,
37
+ python_cmd="/usr/bin/python3.11", # Specify python version
38
+ # args=["--some-server-arg"], # Pass args to the script
39
+ # env={"MY_VAR": "value"}, # Set environment variables
40
+ # cwd="/path/to/run/in" # Set working directory
41
+ )
42
+ client_explicit = Client(transport_explicit)
43
+
44
+ async def use_stdio_client(client):
45
+ async with client:
46
+ tools = await client.list_tools()
47
+ print(f"Connected via Python Stdio, found tools: {tools}")
48
+
49
+ # asyncio.run(use_stdio_client(client_inferred))
50
+ # asyncio.run(use_stdio_client(client_explicit))
51
+ ```
52
+
53
+ <Warning>
54
+ The server script (`my_mcp_server.py` in the example) *must* include logic to start the MCP server and listen on stdio, typically via `mcp.run()` or `fastmcp.server.run()`. The `Client` only launches the script; it doesn't inject the server logic.
55
+ </Warning>
56
+
57
+ ### Node.js Stdio
58
+
59
+ * **Class:** `fastmcp.client.transports.NodeStdioTransport`
60
+ * **Inferred From:** Paths to `.js` files.
61
+ * **Use Case:** Running a Node.js-based MCP server script in a subprocess.
62
+
63
+ Similar to the Python transport, but for JavaScript servers.
64
+
65
+ ```python
66
+ from fastmcp import Client
67
+ from fastmcp.client.transports import NodeStdioTransport
68
+
69
+ node_server_script = "my_mcp_server.js" # Assumes this JS file starts an MCP server on stdio
70
+
71
+ # Option 1: Inferred transport
72
+ client_inferred = Client(node_server_script)
73
+
74
+ # Option 2: Explicit transport
75
+ transport_explicit = NodeStdioTransport(
76
+ script_path=node_server_script,
77
+ node_cmd="node" # Or specify path to Node executable
78
+ )
79
+ client_explicit = Client(transport_explicit)
80
+
81
+ # Usage is the same as other clients
82
+ # async with client_explicit:
83
+ # tools = await client_explicit.list_tools()
84
+ ```
85
+
86
+ ### UVX Stdio (Experimental)
87
+
88
+ * **Class:** `fastmcp.client.transports.UvxStdioTransport`
89
+ * **Inferred From:** Not automatically inferred. Must be instantiated explicitly.
90
+ * **Use Case:** Running an MCP server packaged as a Python tool using [`uvx`](https://docs.astral.sh/uv/reference/cli/#uvx) (part of the `uv` toolchain). This allows running tools without explicitly installing them into the current environment.
91
+
92
+ This is useful for executing MCP servers distributed as command-line tools or packages.
93
+
94
+ ```python
95
+ from fastmcp.client.transports import UvxStdioTransport
96
+
97
+ # Example: Run a hypothetical 'cloud-analyzer-mcp' tool via uvx
98
+ # Assume this tool, when run, starts an MCP server on stdio
99
+ transport = UvxStdioTransport(
100
+ tool_name="cloud-analyzer-mcp",
101
+ # from_package="cloud-analyzer-cli", # Optionally specify package if tool name differs
102
+ # with_packages=["boto3", "requests"], # Add dependencies if needed
103
+ # tool_args=["--config", "prod.yaml"] # Pass args to the tool itself
104
+ )
105
+ client = Client(transport)
106
+
107
+ # async with client:
108
+ # analysis = await client.call_tool("analyze_bucket", {"name": "my-data"})
109
+ ```
110
+
111
+ ### NPX Stdio (Experimental)
112
+
113
+ * **Class:** `fastmcp.client.transports.NpxStdioTransport`
114
+ * **Inferred From:** Not automatically inferred. Must be instantiated explicitly.
115
+ * **Use Case:** Running an MCP server packaged as an NPM package using `npx`.
116
+
117
+ Similar to `UvxStdioTransport`, but for the Node.js ecosystem.
118
+
119
+ ```python
120
+ from fastmcp.client.transports import NpxStdioTransport
121
+
122
+ # Example: Run a hypothetical 'npm-mcp-server-package' via npx
123
+ transport = NpxStdioTransport(
124
+ package="npm-mcp-server-package",
125
+ # args=["--port", "stdio"] # Args passed to the package script
126
+ )
127
+ client = Client(transport)
128
+
129
+ # async with client:
130
+ # response = await client.call_tool("get_npm_data", {})
131
+ ```
132
+ ## Network Transports
133
+
134
+ These transports connect to servers running over a network, typically long-running services accessible via URLs.
135
+
136
+ ### SSE (Server-Sent Events)
137
+
138
+ * **Class:** `fastmcp.client.transports.SSETransport`
139
+ * **Inferred From:** `http://` or `https://` URLs
140
+ * **Use Case:** Connecting to persistent MCP servers exposed over HTTP/S, often using FastMCP's `mcp.run(transport="sse")` mode.
141
+
142
+ SSE is a simple, unidirectional protocol where the server pushes messages to the client over a standard HTTP connection.
143
+
144
+ ```python
145
+ from fastmcp import Client
146
+ from fastmcp.client.transports import SSETransport
147
+
148
+ sse_url = "http://localhost:8000/sse"
149
+
150
+ # Option 1: Inferred transport
151
+ client_inferred = Client(sse_url)
152
+
153
+ # Option 2: Explicit transport (e.g., to add custom headers)
154
+ headers = {"Authorization": "Bearer mytoken"}
155
+ transport_explicit = SSETransport(url=sse_url, headers=headers)
156
+ client_explicit = Client(transport_explicit)
157
+
158
+ async def use_sse_client(client):
159
+ async with client:
160
+ tools = await client.list_tools()
161
+ print(f"Connected via SSE, found tools: {tools}")
162
+
163
+ # asyncio.run(use_sse_client(client_inferred))
164
+ # asyncio.run(use_sse_client(client_explicit))
165
+ ```
166
+
167
+ ### WebSocket
168
+
169
+ * **Class:** `fastmcp.client.transports.WSTransport`
170
+ * **Inferred From:** `ws://` or `wss://` URLs
171
+ * **Use Case:** Connecting to MCP servers using the WebSocket protocol for bidirectional communication.
172
+
173
+ WebSockets provide a persistent, full-duplex connection between client and server.
174
+
175
+ ```python
176
+ from fastmcp import Client
177
+ from fastmcp.client.transports import WSTransport
178
+
179
+ ws_url = "ws://localhost:9000"
180
+
181
+ # Option 1: Inferred transport
182
+ client_inferred = Client(ws_url)
183
+
184
+ # Option 2: Explicit transport
185
+ transport_explicit = WSTransport(url=ws_url)
186
+ client_explicit = Client(transport_explicit)
187
+
188
+ async def use_ws_client(client):
189
+ async with client:
190
+ tools = await client.list_tools()
191
+ print(f"Connected via WebSocket, found tools: {tools}")
192
+
193
+ # asyncio.run(use_ws_client(client_inferred))
194
+ # asyncio.run(use_ws_client(client_explicit))
195
+ ```
196
+
197
+ ## In-Memory Transports
198
+
199
+ ### FastMCP Transport
200
+
201
+ * **Class:** `fastmcp.client.transports.FastMCPTransport`
202
+ * **Inferred From:** An instance of `fastmcp.server.FastMCP`.
203
+ * **Use Case:** Connecting directly to a `FastMCP` server instance running in the *same Python process*.
204
+
205
+ This is extremely useful for:
206
+ * **Testing:** Writing unit or integration tests for your FastMCP server without needing subprocesses or network connections.
207
+ * **Embedding:** Using an MCP server as a component within a larger application.
208
+
209
+ ```python
210
+ from fastmcp import FastMCP, Client
211
+ from fastmcp.client.transports import FastMCPTransport
212
+
213
+ # 1. Create your FastMCP server instance
214
+ server = FastMCP(name="InMemoryServer")
215
+ @server.tool()
216
+ def ping(): return "pong"
217
+
218
+ # 2. Create a client pointing directly to the server instance
219
+ # Option A: Inferred
220
+ client_inferred = Client(server)
221
+
222
+ # Option B: Explicit
223
+ transport_explicit = FastMCPTransport(mcp=server)
224
+ client_explicit = Client(transport_explicit)
225
+
226
+ # 3. Use the client (no subprocess or network involved)
227
+ async def test_in_memory():
228
+ async with client_inferred: # Or client_explicit
229
+ result = await client_inferred.call_tool("ping")
230
+ print(f"In-memory call result: {result[0].text}") # Output: pong
231
+
232
+ # asyncio.run(test_in_memory())
233
+ ```
234
+ Communication happens through efficient in-memory queues, making it very fast.
235
+
236
+ ## Choosing a Transport
237
+
238
+ * **Local Development/Testing:** Use `PythonStdioTransport` (inferred from `.py` files) or `FastMCPTransport` (for same-process testing).
239
+ * **Connecting to Remote/Persistent Servers:** Use `SSETransport` (for `http/s`) or `WSTransport` (for `ws/s`).
240
+ * **Running Packaged Tools:** Use `UvxStdioTransport` (Python/uv) or `NpxStdioTransport` (Node/npm) if you need to run MCP servers without local installation.
241
+ * **Integrating with Claude Desktop (or similar):** These tools typically expect to run a Python script, so your server should be runnable via `python your_server.py`, making `PythonStdioTransport` the relevant mechanism on the client side.
docs/docs.json CHANGED
@@ -15,7 +15,9 @@
15
  "description": "The fast, Pythonic way to build MCP servers.",
16
  "footer": {
17
  "socials": {
18
- "github": "https://github.com/jlowin/fastmcp"
 
 
19
  }
20
  },
21
  "name": "FastMCP",
@@ -47,7 +49,10 @@
47
  },
48
  {
49
  "group": "Clients",
50
- "pages": []
 
 
 
51
  },
52
  {
53
  "group": "Deployment",
 
15
  "description": "The fast, Pythonic way to build MCP servers.",
16
  "footer": {
17
  "socials": {
18
+ "bluesky": "https://bsky.app/profile/jlowin.dev",
19
+ "github": "https://github.com/jlowin/fastmcp",
20
+ "x": "https://x.com/jlowin"
21
  }
22
  },
23
  "name": "FastMCP",
 
49
  },
50
  {
51
  "group": "Clients",
52
+ "pages": [
53
+ "clients/overview",
54
+ "clients/transports"
55
+ ]
56
  },
57
  {
58
  "group": "Deployment",
docs/style.css CHANGED
@@ -1,13 +1,13 @@
1
- /* Target inline code elements with higher specificity */
2
- p code,
3
- table code,
4
- li code,
5
- h1 code,
6
- h2 code,
7
- h3 code,
8
- h4 code,
9
- h5 code,
10
- h6 code {
11
  color: #f72585 !important;
12
  background-color: #ea54551a !important;
13
  }
 
1
+ /* Target only inline code elements, not code blocks */
2
+ p code:not(pre code),
3
+ table code:not(pre code),
4
+ li code:not(pre code),
5
+ h1 code:not(pre code),
6
+ h2 code:not(pre code),
7
+ h3 code:not(pre code),
8
+ h4 code:not(pre code),
9
+ h5 code:not(pre code),
10
+ h6 code:not(pre code) {
11
  color: #f72585 !important;
12
  background-color: #ea54551a !important;
13
  }