Jeremiah Lowin commited on
Commit
3f47e4c
·
unverified ·
2 Parent(s): b896869484479b

Merge pull request #118 from jlowin/readme

Browse files
Files changed (1) hide show
  1. README.md +179 -88
README.md CHANGED
@@ -52,16 +52,12 @@ FastMCP handles the complex protocol details and server management, letting you
52
 
53
  ---
54
 
55
- ### FastMCP v1 and v2
56
 
57
- FastMCP v1's core approach of using the `@tool`, `@resource`, `@prompt` decorators with the `FastMCP` class proved so successful that it became part of the official Model Context Protocol Python SDK! For basic server creation, you can use the upstream version by importing `mcp.server.fastmcp.FastMCP`.
58
 
59
- 👉 The **MCP Python SDK** can be found at [github.com/modelcontextprotocol/python-sdk](https://github.com/modelcontextprotocol/python-sdk)
60
 
61
- **FastMCP v2 builds upon v1's foundation** and adds the advanced features listed above (Client, Proxy, Mounting, API Generation, and more).
62
-
63
- * **Need just the basics?** Use FastMCP v1 (the official SDK).
64
- * **Need advanced features like clients, proxies, or composing servers?** Use FastMCP v2 (this library).
65
 
66
  ---
67
 
@@ -69,24 +65,26 @@ FastMCP v1's core approach of using the `@tool`, `@resource`, `@prompt` decorato
69
  ## Table of Contents
70
 
71
  - [Key Features:](#key-features)
72
- - [FastMCP v1 and v2](#fastmcp-v1-and-v2)
73
  - [Installation](#installation)
74
  - [Quickstart](#quickstart)
75
  - [What is MCP?](#what-is-mcp)
76
- - [Core Concepts (The Foundation)](#core-concepts-the-foundation)
77
  - [The `FastMCP` Server](#the-fastmcp-server)
78
  - [Tools](#tools)
79
  - [Resources](#resources)
80
  - [Prompts](#prompts)
81
  - [Context](#context)
82
  - [Images](#images)
 
 
 
 
 
83
  - [Advanced Features](#advanced-features)
84
  - [Proxy Servers](#proxy-servers)
85
  - [Composing MCP Servers](#composing-mcp-servers)
86
  - [OpenAPI \& FastAPI Generation](#openapi--fastapi-generation)
87
- - [MCP Client](#mcp-client)
88
- - [LLM Sampling](#llm-sampling)
89
- - [Roots Access](#roots-access)
90
  - [Running Your Server](#running-your-server)
91
  - [Development Mode (Recommended for Building \& Testing)](#development-mode-recommended-for-building--testing)
92
  - [Claude Desktop Integration (For Regular Use)](#claude-desktop-integration-for-regular-use)
@@ -166,7 +164,7 @@ The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) lets you bui
166
 
167
  FastMCP provides a high-level, Pythonic interface for building and interacting with these servers.
168
 
169
- ## Core Concepts (The Foundation)
170
 
171
  These are the building blocks for creating MCP servers, using the familiar decorator-based approach.
172
 
@@ -339,6 +337,174 @@ def load_image_from_disk(path: str) -> Image:
339
  ```
340
  FastMCP handles the conversion to/from the base64-encoded format required by the MCP protocol.
341
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
  ## Advanced Features
343
 
344
  Building on the core concepts, FastMCP v2 introduces powerful features for more complex scenarios:
@@ -479,81 +645,6 @@ mcp_server = FastMCP.from_openapi(openapi_spec, client=http_client)
479
  if __name__ == "__main__":
480
  mcp_server.run()
481
  ```
482
-
483
- ### MCP Client
484
-
485
- The `Client` class lets you interact with any MCP server (not just FastMCP ones) from Python code:
486
-
487
- ```python
488
- from fastmcp import Client
489
-
490
- async with Client("path/to/server") as client:
491
- # Call a tool
492
- result = await client.call_tool("weather", {"location": "San Francisco"})
493
- print(result)
494
-
495
- # Read a resource
496
- res = await client.read_resource("db://users/123/profile")
497
- print(res)
498
- ```
499
-
500
- You can connect to servers using any supported transport protocol (Stdio, SSE, FastMCP, etc.). If you don't specify a transport, the `Client` class automatically attempts to detect an appropriate one from your connection string or server object.
501
-
502
- #### LLM Sampling
503
-
504
- Sampling is an MCP feature that allows a server to request a completion from the client LLM, enabling sophisticated use cases while maintaining security and privacy on the server.
505
-
506
- ```python
507
- import marvin # Or any other LLM client
508
- from fastmcp import Client, Context, FastMCP
509
- from fastmcp.client.sampling import RequestContext, SamplingMessage, SamplingParams
510
-
511
- # -- Create a server that requests LLM completions from the client
512
-
513
- mcp = FastMCP("Sampling Example")
514
-
515
- @mcp.tool()
516
- async def generate_poem(topic: str, context: Context) -> str:
517
- """Generate a short poem about the given topic."""
518
- response = await context.sample(
519
- f"Write a short poem about {topic}",
520
- system_prompt="You are a talented poet who writes concise, evocative verses."
521
- )
522
- return response.text
523
-
524
- # -- Create a client that handles the sampling requests
525
-
526
- async def sampling_handler(
527
- messages: list[SamplingMessage],
528
- params: SamplingParams,
529
- ctx: RequestContext,
530
- ) -> str:
531
- # Use your preferred LLM client to generate completions
532
- return await marvin.say_async(
533
- message=[m.content.text for m in messages if m.content.type == "text"],
534
- instructions=params.systemPrompt,
535
- )
536
-
537
- # Connect them together
538
- async with Client(mcp, sampling_handler=sampling_handler) as client:
539
- result = await client.call_tool("generate_poem", {"topic": "autumn leaves"})
540
- print(result.content[0].text)
541
- ```
542
-
543
- #### Roots Access
544
-
545
- FastMCP exposes the MCP roots functionality, allowing clients to specify which file system roots they can access. This creates a secure boundary for tools that need to work with files. Note that the server must account for client roots explicitly.
546
-
547
- ```python
548
- from fastmcp import Client, RootsList
549
-
550
- # Specify file roots that the client can access
551
- roots = ["file:///path/to/allowed/directory"]
552
-
553
- async with Client(mcp_server, roots=roots) as client:
554
- # Now tools in the MCP server can access files in the specified roots
555
- await client.call_tool("process_file", {"filename": "data.csv"})
556
- ```
557
  ## Running Your Server
558
 
559
  Choose the method that best suits your needs:
 
52
 
53
  ---
54
 
55
+ ### What's New in v2?
56
 
57
+ FastMCP 1.0 made it so easy to build MCP servers that it's now part of the [official Model Context Protocol Python SDK](https://github.com/modelcontextprotocol/python-sdk)! For basic use cases, you can use the upstream version by importing `mcp.server.fastmcp.FastMCP` (or installing `fastmcp=1.0`).
58
 
59
+ Based on how the MCP ecosystem is evolving, FastMCP 2.0 builds on that foundation to introduce a variety of new features (and more experimental ideas). It adds advanced features like proxying and composing MCP servers, as well as automatically generating them from OpenAPI specs or FastAPI objects. FastMCP 2.0 also introduces new client-side functionality like LLM sampling.
60
 
 
 
 
 
61
 
62
  ---
63
 
 
65
  ## Table of Contents
66
 
67
  - [Key Features:](#key-features)
68
+ - [What's New in v2?](#whats-new-in-v2)
69
  - [Installation](#installation)
70
  - [Quickstart](#quickstart)
71
  - [What is MCP?](#what-is-mcp)
72
+ - [Core Concepts](#core-concepts)
73
  - [The `FastMCP` Server](#the-fastmcp-server)
74
  - [Tools](#tools)
75
  - [Resources](#resources)
76
  - [Prompts](#prompts)
77
  - [Context](#context)
78
  - [Images](#images)
79
+ - [MCP Clients](#mcp-clients)
80
+ - [Client Methods](#client-methods)
81
+ - [Transport Options](#transport-options)
82
+ - [LLM Sampling](#llm-sampling)
83
+ - [Roots Access](#roots-access)
84
  - [Advanced Features](#advanced-features)
85
  - [Proxy Servers](#proxy-servers)
86
  - [Composing MCP Servers](#composing-mcp-servers)
87
  - [OpenAPI \& FastAPI Generation](#openapi--fastapi-generation)
 
 
 
88
  - [Running Your Server](#running-your-server)
89
  - [Development Mode (Recommended for Building \& Testing)](#development-mode-recommended-for-building--testing)
90
  - [Claude Desktop Integration (For Regular Use)](#claude-desktop-integration-for-regular-use)
 
164
 
165
  FastMCP provides a high-level, Pythonic interface for building and interacting with these servers.
166
 
167
+ ## Core Concepts
168
 
169
  These are the building blocks for creating MCP servers, using the familiar decorator-based approach.
170
 
 
337
  ```
338
  FastMCP handles the conversion to/from the base64-encoded format required by the MCP protocol.
339
 
340
+
341
+ ### MCP Clients
342
+
343
+ The `Client` class lets you interact with any MCP server (not just FastMCP ones) from Python code:
344
+
345
+ ```python
346
+ from fastmcp import Client
347
+
348
+ async with Client("path/to/server") as client:
349
+ # Call a tool
350
+ result = await client.call_tool("weather", {"location": "San Francisco"})
351
+ print(result)
352
+
353
+ # Read a resource
354
+ res = await client.read_resource("db://users/123/profile")
355
+ print(res)
356
+ ```
357
+
358
+ You can connect to servers using any supported transport protocol (Stdio, SSE, FastMCP, etc.). If you don't specify a transport, the `Client` class automatically attempts to detect an appropriate one from your connection string or server object.
359
+
360
+ #### Client Methods
361
+
362
+ The `Client` class exposes several methods for interacting with MCP servers.
363
+
364
+ ```python
365
+ async with Client("path/to/server") as client:
366
+ # List available tools
367
+ tools = await client.list_tools()
368
+
369
+ # List available resources
370
+ resources = await client.list_resources()
371
+
372
+ # Call a tool with arguments
373
+ result = await client.call_tool("generate_report", {"user_id": 123})
374
+
375
+ # Read a resource
376
+ user_data = await client.read_resource("db://users/123/profile")
377
+
378
+ # Get a prompt
379
+ greeting = await client.get_prompt("welcome", {"name": "Alice"})
380
+
381
+ # Send progress updates
382
+ await client.progress("task-123", 50, 100) # 50% complete
383
+
384
+ # Basic connectivity testing
385
+ await client.ping()
386
+ ```
387
+
388
+ These methods correspond directly to MCP protocol operations, making it easy to interact with any MCP-compatible server (not just FastMCP ones).
389
+
390
+ #### Transport Options
391
+
392
+ FastMCP supports various transport protocols for connecting to MCP servers:
393
+
394
+ ```python
395
+ from fastmcp import Client
396
+ from fastmcp.client.transports import (
397
+ SSETransport,
398
+ PythonStdioTransport,
399
+ FastMCPTransport
400
+ )
401
+
402
+ # Connect to a server over SSE (common for web-based MCP servers)
403
+ async with Client(SSETransport("http://localhost:8000/mcp")) as client:
404
+ # Use client here...
405
+
406
+ # Connect to a Python script using stdio (useful for local tools)
407
+ async with Client(PythonStdioTransport("path/to/script.py")) as client:
408
+ # Use client here...
409
+
410
+ # Connect directly to a FastMCP server object in the same process
411
+ from your_app import mcp_server
412
+ async with Client(FastMCPTransport(mcp_server)) as client:
413
+ # Use client here...
414
+ ```
415
+
416
+ Common transport options include:
417
+ - `SSETransport`: Connect to a server via Server-Sent Events (HTTP)
418
+ - `PythonStdioTransport`: Run a Python script and communicate via stdio
419
+ - `FastMCPTransport`: Connect directly to a FastMCP server object
420
+ - `WSTransport`: Connect via WebSockets
421
+
422
+ In addition, if you pass a connection string or `FastMCP` server object to the `Client` constructor, it will try to automatically detect the appropriate transport.
423
+
424
+ #### LLM Sampling
425
+
426
+ Sampling is an MCP feature that allows a server to request a completion from the client LLM, enabling sophisticated use cases while maintaining security and privacy on the server.
427
+
428
+ ```python
429
+ import marvin # Or any other LLM client
430
+ from fastmcp import Client, Context, FastMCP
431
+ from fastmcp.client.sampling import RequestContext, SamplingMessage, SamplingParams
432
+
433
+ # -- SERVER SIDE --
434
+ # Create a server that requests LLM completions from the client
435
+
436
+ mcp = FastMCP("Sampling Example")
437
+
438
+ @mcp.tool()
439
+ async def generate_poem(topic: str, context: Context) -> str:
440
+ """Generate a short poem about the given topic."""
441
+ # The server requests a completion from the client LLM
442
+ response = await context.sample(
443
+ f"Write a short poem about {topic}",
444
+ system_prompt="You are a talented poet who writes concise, evocative verses."
445
+ )
446
+ return response.text
447
+
448
+ @mcp.tool()
449
+ async def summarize_document(document_uri: str, context: Context) -> str:
450
+ """Summarize a document using client-side LLM capabilities."""
451
+ # First read the document as a resource
452
+ doc_resource = await context.read_resource(document_uri)
453
+ doc_content = doc_resource[0].content # Assuming single text content
454
+
455
+ # Then ask the client LLM to summarize it
456
+ response = await context.sample(
457
+ f"Summarize the following document:\n\n{doc_content}",
458
+ system_prompt="You are an expert summarizer. Create a concise summary."
459
+ )
460
+ return response.text
461
+
462
+ # -- CLIENT SIDE --
463
+ # Create a client that handles the sampling requests
464
+
465
+ async def sampling_handler(
466
+ messages: list[SamplingMessage],
467
+ params: SamplingParams,
468
+ ctx: RequestContext,
469
+ ) -> str:
470
+ """Handle sampling requests from the server using your preferred LLM."""
471
+ # Extract the messages and system prompt
472
+ prompt = [m.content.text for m in messages if m.content.type == "text"]
473
+ system_instruction = params.systemPrompt or "You are a helpful assistant."
474
+
475
+ # Use your preferred LLM client to generate completions
476
+ return await marvin.say_async(
477
+ message=prompt,
478
+ instructions=system_instruction,
479
+ )
480
+
481
+ # Connect them together
482
+ async with Client(mcp, sampling_handler=sampling_handler) as client:
483
+ result = await client.call_tool("generate_poem", {"topic": "autumn leaves"})
484
+ print(result.content[0].text)
485
+ ```
486
+
487
+ This pattern is powerful because:
488
+ 1. The server can delegate text generation to the client LLM
489
+ 2. The server remains focused on business logic and data handling
490
+ 3. The client maintains control over which LLM is used and how requests are handled
491
+ 4. No sensitive data needs to be sent to external APIs
492
+
493
+ #### Roots Access
494
+
495
+ FastMCP exposes the MCP roots functionality, allowing clients to specify which file system roots they can access. This creates a secure boundary for tools that need to work with files. Note that the server must account for client roots explicitly.
496
+
497
+ ```python
498
+ from fastmcp import Client, RootsList
499
+
500
+ # Specify file roots that the client can access
501
+ roots = ["file:///path/to/allowed/directory"]
502
+
503
+ async with Client(mcp_server, roots=roots) as client:
504
+ # Now tools in the MCP server can access files in the specified roots
505
+ await client.call_tool("process_file", {"filename": "data.csv"})
506
+ ```
507
+
508
  ## Advanced Features
509
 
510
  Building on the core concepts, FastMCP v2 introduces powerful features for more complex scenarios:
 
645
  if __name__ == "__main__":
646
  mcp_server.run()
647
  ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
648
  ## Running Your Server
649
 
650
  Choose the method that best suits your needs: