diff --git a/docs/development/v3-notes/v3-features.mdx b/docs/development/v3-notes/v3-features.mdx index ae6bfc27d..fb3cb8ad0 100644 --- a/docs/development/v3-notes/v3-features.mdx +++ b/docs/development/v3-notes/v3-features.mdx @@ -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 ``` --- diff --git a/docs/patterns/cli.mdx b/docs/patterns/cli.mdx index 8ccf9d01f..fe32bdd75 100644 --- a/docs/patterns/cli.mdx +++ b/docs/patterns/cli.mdx @@ -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 ``` @@ -361,7 +365,7 @@ When using `fastmcp.json`, the dev command automatically uses the configured dep -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 -### 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) -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. **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` diff --git a/docs/python-sdk/fastmcp-cli-cli.mdx b/docs/python-sdk/fastmcp-cli-cli.mdx index fca179c65..2f6a5e651 100644 --- a/docs/python-sdk/fastmcp-cli-cli.mdx +++ b/docs/python-sdk/fastmcp-cli-cli.mdx @@ -37,10 +37,10 @@ version() Display version information and platform details. -### `dev` +### `inspector` ```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` +### `run` ```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` +### `inspect` ```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` +### `prepare` ```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 diff --git a/src/fastmcp/cli/cli.py b/src/fastmcp/cli/cli.py index 5b9c24e4a..07b2ddb5b 100644 --- a/src/fastmcp/cli/cli.py +++ b/src/fastmcp/cli/cli.py @@ -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) diff --git a/tests/cli/test_cli.py b/tests/cli/test_cli.py index 703771dff..eecc4300c 100644 --- a/tests/cli/test_cli.py +++ b/tests/cli/test_cli.py @@ -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",