From 8fd1a8c702aa0d1b7b6d9d616cf62edf4755846f Mon Sep 17 00:00:00 2001 From: yeoyujie Date: Sat, 21 Jun 2025 01:31:02 +0800 Subject: [PATCH 1/2] Enhance FastMCP server with port override functionality during run method --- README.md | 16 +++++++++++++- src/mcp/server/fastmcp/server.py | 4 ++++ tests/server/fastmcp/test_server.py | 33 +++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d8a2db2b6..88aa2eceb 100644 --- a/README.md +++ b/README.md @@ -502,7 +502,17 @@ from mcp.server.fastmcp import FastMCP mcp = FastMCP("My App") if __name__ == "__main__": + # Run with default settings mcp.run() + + # Override port + mcp.run(port=3000) + + # Specify transport and port + mcp.run(transport="streamable-http", port=8080) + + # SSE with custom mount path and port + mcp.run(transport="sse", mount_path="/api", port=9000) ``` Run it with: @@ -512,8 +522,12 @@ python server.py mcp run server.py ``` -Note that `mcp run` or `mcp dev` only supports server using FastMCP and not the low-level server variant. +The `run()` method accepts these parameters: +- `transport`: Transport protocol ("stdio", "sse", or "streamable-http") +- `mount_path`: Optional mount path for SSE transport +- `port`: Optional port override (defaults to settings.port or 8000) +Note that `mcp run` or `mcp dev` only supports server using FastMCP and not the low-level server variant. ### Streamable HTTP Transport > **Note**: Streamable HTTP transport is superseding SSE transport for production deployments. diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index 1b761e917..ac61fd5d2 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -206,14 +206,18 @@ def run( self, transport: Literal["stdio", "sse", "streamable-http"] = "stdio", mount_path: str | None = None, + port: int | None = None, ) -> None: """Run the FastMCP server. Note this is a synchronous function. Args: transport: Transport protocol to use ("stdio", "sse", or "streamable-http") mount_path: Optional mount path for SSE transport + port: Optional port to run the server on """ TRANSPORTS = Literal["stdio", "sse", "streamable-http"] + if port is not None: + self.settings.port = port # override port if provided if transport not in TRANSPORTS.__args__: # type: ignore raise ValueError(f"Unknown transport: {transport}") diff --git a/tests/server/fastmcp/test_server.py b/tests/server/fastmcp/test_server.py index 8719b78d5..9d1bfeb67 100644 --- a/tests/server/fastmcp/test_server.py +++ b/tests/server/fastmcp/test_server.py @@ -850,3 +850,36 @@ def prompt_fn(name: str) -> str: async with client_session(mcp._mcp_server) as client: with pytest.raises(McpError, match="Missing required arguments"): await client.get_prompt("prompt_fn") + + +@pytest.fixture +def server_port() -> int: + import socket + + with socket.socket() as s: + s.bind(("127.0.0.1", 0)) + return s.getsockname()[1] + + +class TestServerTransports: + """Test port overrides during run.""" + + @pytest.mark.anyio + async def test_port_override_default_port(self, server_port): + """Test that the port argument overrides default port.""" + mcp = FastMCP() + + with patch("anyio.run") as mock_anyio_run: + mcp.run(port=server_port) + assert mcp.settings.port == server_port + mock_anyio_run.assert_called_once_with(mcp.run_stdio_async) + + @pytest.mark.anyio + async def test_port_inheritance_without_override(self, server_port): + """Test that existing settings.port is preserved when no port override is provided.""" + mcp = FastMCP(port=server_port) + + with patch("anyio.run") as mock_anyio_run: + mcp.run() + assert mcp.settings.port == server_port + mock_anyio_run.assert_called_once_with(mcp.run_stdio_async) From 796e67ebd0a7dbe78f49948a418517d1b8f0f19b Mon Sep 17 00:00:00 2001 From: yeoyujie Date: Sat, 21 Jun 2025 01:39:41 +0800 Subject: [PATCH 2/2] Remove unnecessary comment --- src/mcp/server/fastmcp/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mcp/server/fastmcp/server.py b/src/mcp/server/fastmcp/server.py index ac61fd5d2..dbcb85c8f 100644 --- a/src/mcp/server/fastmcp/server.py +++ b/src/mcp/server/fastmcp/server.py @@ -217,7 +217,7 @@ def run( """ TRANSPORTS = Literal["stdio", "sse", "streamable-http"] if port is not None: - self.settings.port = port # override port if provided + self.settings.port = port if transport not in TRANSPORTS.__args__: # type: ignore raise ValueError(f"Unknown transport: {transport}")