fix: Add checks and better error messages on server object for mcp run (#297)

This commit is contained in:
john0312
2025-05-14 01:27:10 +08:00
committed by GitHub
parent 8b5838675c
commit 37b54b4c03
2 changed files with 43 additions and 2 deletions

View File

@@ -387,6 +387,8 @@ python server.py
mcp run 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 ### Streamable HTTP Transport
> **Note**: Streamable HTTP transport is superseding SSE transport for production deployments. > **Note**: Streamable HTTP transport is superseding SSE transport for production deployments.
@@ -694,6 +696,8 @@ if __name__ == "__main__":
asyncio.run(run()) asyncio.run(run())
``` ```
Caution: The `mcp run` and `mcp dev` tool doesn't support low-level server.
### Writing MCP Clients ### 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): 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):

View File

@@ -6,7 +6,10 @@ import os
import subprocess import subprocess
import sys import sys
from pathlib import Path 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: try:
import typer import typer
@@ -141,17 +144,48 @@ def _import_server(file: Path, server_object: str | None = None):
module = importlib.util.module_from_spec(spec) module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module) 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 no object specified, try common server names
if not server_object: if not server_object:
# Look for the most common server object names # Look for the most common server object names
for name in ["mcp", "server", "app"]: for name in ["mcp", "server", "app"]:
if hasattr(module, name): 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) return getattr(module, name)
logger.error( logger.error(
f"No server object found in {file}. Please either:\n" f"No server object found in {file}. Please either:\n"
"1. Use a standard variable name (mcp, server, or app)\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)}, extra={"file": str(file)},
) )
sys.exit(1) sys.exit(1)
@@ -179,6 +213,9 @@ def _import_server(file: Path, server_object: str | None = None):
) )
sys.exit(1) sys.exit(1)
if not _check_server_object(server, server_object):
sys.exit(1)
return server return server