Skip to content

Commit 8fd1a8c

Browse files
committed
Enhance FastMCP server with port override functionality during run method
1 parent d0443a1 commit 8fd1a8c

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,17 @@ from mcp.server.fastmcp import FastMCP
502502
mcp = FastMCP("My App")
503503

504504
if __name__ == "__main__":
505+
# Run with default settings
505506
mcp.run()
507+
508+
# Override port
509+
mcp.run(port=3000)
510+
511+
# Specify transport and port
512+
mcp.run(transport="streamable-http", port=8080)
513+
514+
# SSE with custom mount path and port
515+
mcp.run(transport="sse", mount_path="/api", port=9000)
506516
```
507517

508518
Run it with:
@@ -512,8 +522,12 @@ python server.py
512522
mcp run server.py
513523
```
514524

515-
Note that `mcp run` or `mcp dev` only supports server using FastMCP and not the low-level server variant.
525+
The `run()` method accepts these parameters:
526+
- `transport`: Transport protocol ("stdio", "sse", or "streamable-http")
527+
- `mount_path`: Optional mount path for SSE transport
528+
- `port`: Optional port override (defaults to settings.port or 8000)
516529

530+
Note that `mcp run` or `mcp dev` only supports server using FastMCP and not the low-level server variant.
517531
### Streamable HTTP Transport
518532

519533
> **Note**: Streamable HTTP transport is superseding SSE transport for production deployments.

src/mcp/server/fastmcp/server.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,14 +206,18 @@ def run(
206206
self,
207207
transport: Literal["stdio", "sse", "streamable-http"] = "stdio",
208208
mount_path: str | None = None,
209+
port: int | None = None,
209210
) -> None:
210211
"""Run the FastMCP server. Note this is a synchronous function.
211212
212213
Args:
213214
transport: Transport protocol to use ("stdio", "sse", or "streamable-http")
214215
mount_path: Optional mount path for SSE transport
216+
port: Optional port to run the server on
215217
"""
216218
TRANSPORTS = Literal["stdio", "sse", "streamable-http"]
219+
if port is not None:
220+
self.settings.port = port # override port if provided
217221
if transport not in TRANSPORTS.__args__: # type: ignore
218222
raise ValueError(f"Unknown transport: {transport}")
219223

tests/server/fastmcp/test_server.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,3 +850,36 @@ def prompt_fn(name: str) -> str:
850850
async with client_session(mcp._mcp_server) as client:
851851
with pytest.raises(McpError, match="Missing required arguments"):
852852
await client.get_prompt("prompt_fn")
853+
854+
855+
@pytest.fixture
856+
def server_port() -> int:
857+
import socket
858+
859+
with socket.socket() as s:
860+
s.bind(("127.0.0.1", 0))
861+
return s.getsockname()[1]
862+
863+
864+
class TestServerTransports:
865+
"""Test port overrides during run."""
866+
867+
@pytest.mark.anyio
868+
async def test_port_override_default_port(self, server_port):
869+
"""Test that the port argument overrides default port."""
870+
mcp = FastMCP()
871+
872+
with patch("anyio.run") as mock_anyio_run:
873+
mcp.run(port=server_port)
874+
assert mcp.settings.port == server_port
875+
mock_anyio_run.assert_called_once_with(mcp.run_stdio_async)
876+
877+
@pytest.mark.anyio
878+
async def test_port_inheritance_without_override(self, server_port):
879+
"""Test that existing settings.port is preserved when no port override is provided."""
880+
mcp = FastMCP(port=server_port)
881+
882+
with patch("anyio.run") as mock_anyio_run:
883+
mcp.run()
884+
assert mcp.settings.port == server_port
885+
mock_anyio_run.assert_called_once_with(mcp.run_stdio_async)

0 commit comments

Comments
 (0)