Merge branch 'main' into feature/apps-merge-main

This commit is contained in:
Jeremiah Lowin 2026-02-13 23:00:32 -05:00
commit ae82aa511e
No known key found for this signature in database
5 changed files with 40 additions and 27 deletions

View file

@ -988,9 +988,9 @@ Implementation (`src/fastmcp/cli/run.py`):
- stdio: Full MCP features including elicitation
- HTTP: Limited bidirectional features during reload
Also available with `fastmcp dev`:
Also available with `fastmcp dev inspector`:
```bash
fastmcp dev server.py # Includes --reload by default
fastmcp dev inspector server.py # Includes --reload by default
```
---

View file

@ -345,10 +345,14 @@ This will run all the servers defined in the file.
## `fastmcp dev`
The `dev` command group contains development tools for MCP servers.
### `fastmcp dev inspector`
Run a MCP server with the [MCP Inspector](https://github.com/modelcontextprotocol/inspector) for testing. Auto-reload is enabled by default, so your server automatically restarts when you save changes to source files.
```bash
fastmcp dev server.py
fastmcp dev inspector server.py
```
<Tip>
@ -361,7 +365,7 @@ When using `fastmcp.json`, the dev command automatically uses the configured dep
</Tip>
<Warning>
The `dev` command is a shortcut for testing a server over STDIO only. When the Inspector launches, you may need to:
The `dev inspector` command is a shortcut for testing a server over STDIO only. When the Inspector launches, you may need to:
1. Select "STDIO" from the transport dropdown
2. Connect manually
@ -377,7 +381,7 @@ This command does not support HTTP testing. To test a server over Streamable HTT
2. Open the MCP Inspector separately and connect to your running server
</Warning>
### Options
#### Options
| Option | Flag | Description |
| ------ | ---- | ----------- |
@ -392,39 +396,39 @@ This command does not support HTTP testing. To test a server over Streamable HTT
| Project Directory | `--project` | Run the command within the given project directory |
| Requirements File | `--with-requirements` | Requirements file to install dependencies from |
### Entrypoints
#### Entrypoints
The `dev` command supports local FastMCP server files and configuration:
The `dev inspector` command supports local FastMCP server files and configuration:
1. **Inferred server instance**: `server.py` - imports the module and looks for a FastMCP server instance named `mcp`, `server`, or `app`. Errors if no such object is found.
2. **Explicit server entrypoint**: `server.py:custom_name` - imports and uses the specified server entrypoint
2. **Explicit server entrypoint**: `server.py:custom_name` - imports and uses the specified server entrypoint
3. **Factory function**: `server.py:create_server` - calls the specified function (sync or async) to create a server instance
4. **FastMCP configuration**: `fastmcp.json` - uses FastMCP's declarative configuration (auto-detects in current directory)
<Warning>
The `dev` command **only supports local files and fastmcp.json** - no URLs, remote servers, or standard MCP configuration files.
The `dev inspector` command **only supports local files and fastmcp.json** - no URLs, remote servers, or standard MCP configuration files.
</Warning>
**Examples**
```bash
# Run dev server with editable mode and additional packages
fastmcp dev server.py -e . --with pandas --with matplotlib
fastmcp dev inspector server.py -e . --with pandas --with matplotlib
# Run dev server with fastmcp.json configuration (auto-detects)
fastmcp dev
fastmcp dev inspector
# Run dev server with explicit fastmcp.json file
fastmcp dev dev.fastmcp.json
fastmcp dev inspector dev.fastmcp.json
# Run dev server with specific Python version
fastmcp dev server.py --python 3.11
fastmcp dev inspector server.py --python 3.11
# Run dev server with requirements file
fastmcp dev server.py --with-requirements requirements.txt
fastmcp dev inspector server.py --with-requirements requirements.txt
# Run dev server within a specific project directory
fastmcp dev server.py --project /path/to/project
fastmcp dev inspector server.py --project /path/to/project
```
## `fastmcp install`

View file

@ -37,10 +37,10 @@ version()
Display version information and platform details.
### `dev` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L138" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `inspector` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L142" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
dev(server_spec: str | None = None) -> None
inspector(server_spec: str | None = None) -> None
```
@ -50,7 +50,7 @@ Run an MCP server with the MCP Inspector for development.
- `server_spec`: Python file to run, optionally with \:object suffix, or None to auto-detect fastmcp.json
### `run` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L318" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `run` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L322" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run(server_spec: str | None = None, *server_args: str) -> None
@ -74,7 +74,7 @@ fastmcp run server.py -- --config config.json --debug
- `server_spec`: Python file, object specification (file\:obj), config file, URL, or None to auto-detect
### `inspect` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L620" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `inspect` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L624" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
inspect(server_spec: str | None = None) -> None
@ -105,7 +105,7 @@ fastmcp inspect # auto-detect fastmcp.json
- `server_spec`: Python file to inspect, optionally with \:object suffix, or fastmcp.json
### `prepare` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L862" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `prepare` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L866" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prepare(config_path: Annotated[str | None, cyclopts.Parameter(help='Path to fastmcp.json configuration file')] = None, output_dir: Annotated[str | None, cyclopts.Parameter(help='Directory to create the persistent environment in')] = None, skip_source: Annotated[bool, cyclopts.Parameter(help='Skip source preparation (e.g., git clone)')] = False) -> None

View file

@ -134,8 +134,12 @@ def version(
console.print("[dim]Run: pip install --upgrade fastmcp[/dim]")
@app.command
async def dev(
# Create dev subcommand group
dev_app = cyclopts.App(name="dev", help="Development tools for MCP servers")
@dev_app.command
async def inspector(
server_spec: str | None = None,
*,
with_editable: Annotated[
@ -946,6 +950,9 @@ async def prepare(
sys.exit(1)
# Add dev subcommand group
app.command(dev_app)
# Add project subcommand group
app.command(project_app)

View file

@ -91,10 +91,10 @@ class TestVersionCommand:
class TestDevCommand:
"""Test the dev command."""
def test_dev_command_parsing(self):
"""Test that dev command can be parsed with various options."""
def test_dev_inspector_command_parsing(self):
"""Test that dev inspector command can be parsed with various options."""
# Test basic parsing
command, bound, _ = app.parse_args(["dev", "server.py"])
command, bound, _ = app.parse_args(["dev", "inspector", "server.py"])
assert command is not None
assert bound.arguments["server_spec"] == "server.py"
@ -102,6 +102,7 @@ class TestDevCommand:
command, bound, _ = app.parse_args(
[
"dev",
"inspector",
"server.py",
"--with",
"package1",
@ -115,11 +116,12 @@ class TestDevCommand:
assert bound.arguments["inspector_version"] == "1.0.0"
assert bound.arguments["ui_port"] == 3000
def test_dev_command_parsing_with_new_options(self):
"""Test dev command parsing with new uv options."""
def test_dev_inspector_command_parsing_with_new_options(self):
"""Test dev inspector command parsing with new uv options."""
command, bound, _ = app.parse_args(
[
"dev",
"inspector",
"server.py",
"--python",
"3.10",