From 443970f4685db7a55cc05016d82907cc741f7a09 Mon Sep 17 00:00:00 2001 From: John L Chen Date: Sun, 16 Mar 2025 23:07:16 +0800 Subject: [PATCH 1/2] fix: Add checks and better error messages on server object for mcp run/dev mcp run/dev command expects the server object in the python file to be a global variable, and it must be of the FastMCP type and not the low level Server type. The previous error messages may be confusing to users who are not aware of these facts. --- src/mcp/cli/cli.py | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/mcp/cli/cli.py b/src/mcp/cli/cli.py index cb0830600..b2632f1d9 100644 --- a/src/mcp/cli/cli.py +++ b/src/mcp/cli/cli.py @@ -6,7 +6,10 @@ import subprocess import sys from pathlib import Path -from typing import Annotated +from typing import Annotated, Any + +from mcp.server import FastMCP +from mcp.server import Server as LowLevelServer try: import typer @@ -141,17 +144,48 @@ def _import_server(file: Path, server_object: str | None = None): module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) + def _check_server_object(server_object: Any, object_name: str): + """Helper function to check that the server object is supported + + Args: + server_object: The server object to check. + + Returns: + True if it's supported. + """ + if not isinstance(server_object, FastMCP): + logger.error( + f"The server object {object_name} is of type " + f"{type(server_object)} (expecting {FastMCP})." + ) + if isinstance(server_object, LowLevelServer): + logger.warning( + "Note that only FastMCP server is supported. Low level " + "Server class is not yet supported." + ) + return False + return True + # If no object specified, try common server names if not server_object: # Look for the most common server object names for name in ["mcp", "server", "app"]: if hasattr(module, name): + if not _check_server_object(getattr(module, name), f"{file}:{name}"): + logger.error( + f"Ignoring object '{file}:{name}' as it's not a valid " + "server object" + ) + continue return getattr(module, name) logger.error( f"No server object found in {file}. Please either:\n" "1. Use a standard variable name (mcp, server, or app)\n" - "2. Specify the object name with file:object syntax", + "2. Specify the object name with file:object syntax" + "3. If the server creates the FastMCP object within main() " + " or another function, refactor the FastMCP object to be a " + " global variable named mcp, server, or app.", extra={"file": str(file)}, ) sys.exit(1) @@ -179,6 +213,9 @@ def _import_server(file: Path, server_object: str | None = None): ) sys.exit(1) + if not _check_server_object(server, server_object): + sys.exit(1) + return server From 9f6df590ed1ba09609be34b9f6a913a592b9b44b Mon Sep 17 00:00:00 2001 From: John L Chen Date: Sun, 16 Mar 2025 23:20:36 +0800 Subject: [PATCH 2/2] fix: Add documentation on mcp run doesn't support low-level server --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 034b8d4b5..b281b5513 100644 --- a/README.md +++ b/README.md @@ -387,6 +387,8 @@ 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. + ### Streamable HTTP Transport > **Note**: Streamable HTTP transport is superseding SSE transport for production deployments. @@ -694,6 +696,8 @@ if __name__ == "__main__": asyncio.run(run()) ``` +Caution: The `mcp run` and `mcp dev` tool doesn't support low-level server. + ### Writing MCP Clients The SDK provides a high-level client interface for connecting to MCP servers using various [transports](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports):