Jeremiah Lowin commited on
Commit
548235b
·
1 Parent(s): 48dfb8a

Begin adding docs

Browse files
docs/docs.json ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "https://mintlify.com/docs.json",
3
+ "background": {
4
+ "color": {
5
+ "dark": "#222831",
6
+ "light": "#EEEEEE"
7
+ },
8
+ "decoration": "windows"
9
+ },
10
+ "colors": {
11
+ "dark": "#EA5455",
12
+ "light": "#EA5455",
13
+ "primary": "#EA5455"
14
+ },
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",
22
+ "navbar": {
23
+ "primary": {
24
+ "href": "https://github.com/jlowin/fastmcp",
25
+ "type": "github"
26
+ }
27
+ },
28
+ "navigation": {
29
+ "groups": [
30
+ {
31
+ "group": "Get Started",
32
+ "pages": [
33
+ "getting-started/welcome",
34
+ "getting-started/installation",
35
+ "getting-started/quickstart"
36
+ ]
37
+ },
38
+ {
39
+ "group": "Servers",
40
+ "pages": []
41
+ },
42
+ {
43
+ "group": "Clients",
44
+ "pages": []
45
+ },
46
+ {
47
+ "group": "Deployment",
48
+ "pages": []
49
+ }
50
+ ]
51
+ },
52
+ "theme": "mint"
53
+ }
docs/getting-started/installation.mdx ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Installation
3
+ icon: arrow-down-to-line
4
+ ---
5
+ ## Install FastMCP
6
+
7
+ We recommend using [uv](https://docs.astral.sh/uv/getting-started/installation/) to install and manage FastMCP.
8
+
9
+ If you plan to use FastMCP in your project, you can add it as a dependency with:
10
+
11
+ ```bash
12
+ uv add fastmcp
13
+ ```
14
+
15
+ Alternatively, you can install it directly with `pip` or `uv pip`:
16
+ <CodeGroup>
17
+ ```bash uv
18
+ uv pip install fastmcp
19
+ ```
20
+
21
+ ```bash pip
22
+ pip install fastmcp
23
+ ```
24
+ </CodeGroup>
25
+
26
+ ## Verify Installation
27
+
28
+ To verify that FastMCP is installed correctly, you can run the following command:
29
+
30
+ ```bash
31
+ fastmcp version
32
+ ```
33
+
34
+ You should see output like the following:
35
+
36
+ ```bash
37
+ $ fastmcp version
38
+
39
+ FastMCP version: 0.4.2.dev41+ga077727.d20250410
40
+ MCP version: 1.6.0
41
+ Python version: 3.12.2
42
+ Platform: macOS-15.3.1-arm64-arm-64bit
43
+ FastMCP root path: ~/Developer/fastmcp
44
+ ```
45
+
46
+ ## Installing for Development
47
+
48
+ If you plan to contribute to FastMCP, you should begin by cloning the repository and using uv to install all dependencies.
49
+
50
+ ```bash
51
+ git clone https://github.com/jlowin/fastmcp.git
52
+ cd fastmcp
53
+ uv sync
54
+ ```
55
+
56
+ This will install all dependencies, including ones for development, and create a virtual environment.
57
+
58
+ To run the tests, use pytest:
59
+
60
+ ```bash
61
+ pytest
62
+ ```
docs/getting-started/quickstart.mdx ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Quickstart
3
+ icon: rocket
4
+ ---
5
+
6
+ Welcome! This guide will help you quickly set up FastMCP and run your first MCP server.
7
+
8
+ If you haven't already installed FastMCP, follow the [installation instructions](/docs/getting-started/installation).
9
+
10
+ ## Creating a FastMCP Server
11
+
12
+ A FastMCP server is a collection of tools, resources, and other MCP components. To create a server, start by instantiating the `FastMCP` class.
13
+
14
+ Create a new file called `my_server.py` and add the following code:
15
+
16
+ ```python my_server.py
17
+ from fastmcp import FastMCP
18
+
19
+ mcp = FastMCP("My MCP Server")
20
+ ```
21
+
22
+
23
+ That's it! You've created a FastMCP server, albeit a very boring one. Let's add a tool to make it more interesting.
24
+
25
+
26
+ ## Adding a Tool
27
+
28
+ To add a tool that returns a simple greeting, write a function and decorate it with `@mcp.tool` to register it with the server:
29
+
30
+ ```python my_server.py {5-7}
31
+ from fastmcp import FastMCP
32
+
33
+ mcp = FastMCP("My MCP Server")
34
+
35
+ @mcp.tool
36
+ def greet(name: str) -> str:
37
+ return f"Hello, {name}!"
38
+ ```
39
+
40
+
41
+ ## Testing the Server
42
+
43
+
44
+ To test the server, create a FastMCP client and point it at the server object.
45
+
46
+ ```python my_server.py {1, 9-16}
47
+ from fastmcp import FastMCP, Client
48
+
49
+ mcp = FastMCP("My MCP Server")
50
+
51
+ @mcp.tool
52
+ def greet(name: str) -> str:
53
+ return f"Hello, {name}!"
54
+
55
+ client = Client(mcp)
56
+
57
+ async def call_tool(name: str):
58
+ async with client:
59
+ result = await client.call_tool("greet", {"name": name})
60
+ print(result)
61
+
62
+ asyncio.run(call_tool("Ford"))
63
+ ```
64
+
65
+ There are a few things to note here:
66
+ - Clients are asynchronous, so we need to use `asyncio.run` to run the client.
67
+ - We must enter a client context (`async with client:`) before using the client. You can make multiple client calls within the same context.
68
+
69
+ ## Running the server
70
+
71
+ In order to run the server with Python, we need to add a `run` statement to the `__main__` block of the server file.
72
+
73
+ ```python my_server.py {9-10}
74
+ from fastmcp import FastMCP, Client
75
+
76
+ mcp = FastMCP("My MCP Server")
77
+
78
+ @mcp.tool
79
+ def greet(name: str) -> str:
80
+ return f"Hello, {name}!"
81
+
82
+ if __name__ == "__main__":
83
+ mcp.run()
84
+ ```
85
+
86
+ This lets us run the server with `python my_server.py`, using the default `stdio` transport, which is the standard way to expose an MCP server to a client.
87
+
88
+ <Tip>
89
+ Why do we need the `if __name__ == "__main__":` block?
90
+
91
+ Within the FastMCP ecosystem, this line may be unecessary. However, including it ensures that your FastMCP server runs for all users and clients in a consistent way and is therefore recommended as best practice.
92
+ </Tip>
93
+
94
+ ### Interacting with the Python server
95
+
96
+ Now that the server can be executed with `python my_server.py`, we can interact with it like any other MCP server.
97
+
98
+ In a new file, create a client and point it at the server file:
99
+
100
+ ```python my_client.py
101
+ from fastmcp import Client
102
+
103
+ client = Client("my_server.py")
104
+
105
+ async def call_tool(name: str):
106
+ async with client:
107
+ result = await client.call_tool("greet", {"name": name})
108
+ print(result)
109
+
110
+ asyncio.run(call_tool("Ford"))
111
+ ```
112
+
113
+
114
+
115
+ ### Using the FastMCP CLI
116
+
117
+ To have FastMCP run the server for us, we can use the `fastmcp run` command. This will start the server and keep it running until it is stopped. By default, it will use the `stdio` transport, which is a simple text-based protocol for interacting with the server.
118
+
119
+ ```bash
120
+ fastmcp run my_server.py:mcp
121
+ ```
122
+
123
+ Note that FastMCP *does not* require the `__main__` block in the server file, and will ignore it if it is present. Instead, it looks for the server object provided in the CLI command (here, `mcp`). If no server object is provided, `fastmcp run` will automatically search for servers called "mcp", "app", or "server" in the file.
124
+
125
+ <Tip>
126
+ We pointed our client at the server file, which is recognized as a Python MCP server and executed with `python my_server.py` by default. This exceutes the `__main__` block of the server file. There are other ways to run the server, which are described in the [server configuration](/docs/getting-started/configuration) guide.
127
+ </Tip>
docs/getting-started/welcome.mdx ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: "Welcome to FastMCP!"
3
+ sidebarTitle: "Welcome!"
4
+ description: The fast, Pythonic way to build MCP servers.
5
+
6
+ icon: hand-wave
7
+ ---
8
+
9
+
10
+ [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) servers are a new, standardized way to provide context and tools to your LLMs, and FastMCP makes building MCP servers simple and intuitive. Create tools, expose resources, define prompts, and more with clean, Pythonic code:
11
+
12
+ ```python {1, 3, 5, 11}
13
+ from fastmcp import FastMCP
14
+
15
+ mcp = FastMCP("Demo 🚀")
16
+
17
+ @mcp.tool()
18
+ def add(a: int, b: int) -> int:
19
+ """Add two numbers"""
20
+ return a + b
21
+
22
+ if __name__ == "__main__":
23
+ mcp.run()
24
+ ```
25
+
26
+
27
+ ## What is MCP?
28
+ The Model Context Protocol (MCP) lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. It is often described as "the USB-C port for AI", providing a uniform way to connect LLMs to resources they can use. It may be easier to think of it as an API, but specifically designed for LLM interactions. MCP servers can:
29
+
30
+ - Expose data through **Resources** (think of these sort of like GET endpoints; they are used to load information into the LLM's context)
31
+ - Provide functionality through **Tools** (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect)
32
+ - Define interaction patterns through **Prompts** (reusable templates for LLM interactions)
33
+ - And more!
34
+
35
+ There is a low-level Python SDK available for implementing the protocol directly, but FastMCP aims to make that easier by providing a high-level, Pythonic interface.
36
+
37
+ <Tip>
38
+ FastMCP 1.0 was so successful that it is now included as part of the official [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)!
39
+ </Tip>
40
+
41
+
42
+
43
+
44
+ ## Why FastMCP?
45
+
46
+ The MCP protocol is powerful but implementing it involves a lot of boilerplate - server setup, protocol handlers, content types, error management. FastMCP handles all the complex protocol details and server management, so you can focus on building great tools. It's designed to be high-level and Pythonic; in most cases, decorating a function is all you need.
47
+
48
+ FastMCP aims to be:
49
+
50
+ - **Fast**: High-level interface means less code and faster development
51
+ - **Simple**: Build MCP servers with minimal boilerplate
52
+ - **Pythonic**: Feels natural to Python developers
53
+ - **Complete**: FastMCP aims to provide a full implementation of the core MCP specification
54
+
55
+ **FastMCP v1** focused on abstracting the most common boilerplate of exposing MCP server functionality, and is now included in the official MCP Python SDK. **FastMCP v2** expands on that foundation to introduce novel functionality mainly focused on simplifying server interactions, including flexible clients, proxying and composition, and deployment.
56
+
docs/style.css ADDED
@@ -0,0 +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: #ea5455 !important;
12
+ background-color: #ea54551a !important;
13
+ }
pyproject.toml CHANGED
@@ -1,7 +1,7 @@
1
  [project]
2
  name = "fastmcp"
3
  dynamic = ["version"]
4
- description = "An ergonomic MCP interface"
5
  authors = [{ name = "Jeremiah Lowin" }]
6
  dependencies = [
7
  "dotenv>=0.9.9",
 
1
  [project]
2
  name = "fastmcp"
3
  dynamic = ["version"]
4
+ description = "The fast, Pythonic way to build MCP servers."
5
  authors = [{ name = "Jeremiah Lowin" }]
6
  dependencies = [
7
  "dotenv>=0.9.9",
src/fastmcp/cli/cli.py CHANGED
@@ -133,6 +133,7 @@ def _import_server(file: Path, server_object: str | None = None):
133
  sys.exit(1)
134
 
135
  module = importlib.util.module_from_spec(spec)
 
136
  spec.loader.exec_module(module)
137
 
138
  # If no object specified, try common server names
@@ -323,6 +324,8 @@ def run(
323
  # Import and get server object
324
  server = _import_server(file, server_object)
325
 
 
 
326
  # Run the server
327
  kwargs = {}
328
  if transport:
 
133
  sys.exit(1)
134
 
135
  module = importlib.util.module_from_spec(spec)
136
+ breakpoint()
137
  spec.loader.exec_module(module)
138
 
139
  # If no object specified, try common server names
 
324
  # Import and get server object
325
  server = _import_server(file, server_object)
326
 
327
+ logger.info(f'Found server "{server.name}" in {file}')
328
+
329
  # Run the server
330
  kwargs = {}
331
  if transport:
src/fastmcp/client/transports.py CHANGED
@@ -208,6 +208,28 @@ class PythonStdioTransport(StdioTransport):
208
  self.script_path = script_path
209
 
210
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  class NodeStdioTransport(StdioTransport):
212
  """Transport for running Node.js scripts."""
213
 
 
208
  self.script_path = script_path
209
 
210
 
211
+ class FastMCPStdioTransport(StdioTransport):
212
+ """Transport for running FastMCP servers using the FastMCP CLI."""
213
+
214
+ def __init__(
215
+ self,
216
+ script_path: str | Path,
217
+ args: list[str] | None = None,
218
+ env: dict[str, str] | None = None,
219
+ cwd: str | None = None,
220
+ ):
221
+ script_path = Path(script_path).resolve()
222
+ if not script_path.is_file():
223
+ raise FileNotFoundError(f"Script not found: {script_path}")
224
+ if not str(script_path).endswith(".py"):
225
+ raise ValueError(f"Not a Python script: {script_path}")
226
+
227
+ super().__init__(
228
+ command="fastmcp", args=["run", str(script_path)], env=env, cwd=cwd
229
+ )
230
+ self.script_path = script_path
231
+
232
+
233
  class NodeStdioTransport(StdioTransport):
234
  """Transport for running Node.js scripts."""
235
 
src/fastmcp/server/server.py CHANGED
@@ -137,6 +137,7 @@ class FastMCP(Generic[LifespanResultT]):
137
  Args:
138
  transport: Transport protocol to use ("stdio" or "sse")
139
  """
 
140
  anyio.run(self.run_async, transport)
141
 
142
  def _setup_handlers(self) -> None:
 
137
  Args:
138
  transport: Transport protocol to use ("stdio" or "sse")
139
  """
140
+ logger.info(f'Starting server "{self.name}"...')
141
  anyio.run(self.run_async, transport)
142
 
143
  def _setup_handlers(self) -> None: