fix: aggressively reset sys.argv to force correct FastMCP CLI args
This commit is contained in:
48
server.py
48
server.py
@@ -210,27 +210,37 @@ def query_notebook(notebook: str, query: str, limit: int = 5) -> str:
|
||||
return f"Query failed: {e}"
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
logging.info("Starting knowledge-mcp server (transport=sse)...")
|
||||
# NOTE: FastMCP.run() uses Typer/Click to parse CLI args.
|
||||
# It does NOT accept host/port as direct kwargs in .run().
|
||||
# However, it allows command-line flags.
|
||||
# To bypass CLI parsing and force settings, we must set sys.argv
|
||||
# or use internal methods, but for now we will rely on CLI args
|
||||
# passed by the Docker CMD, or defaults.
|
||||
#
|
||||
# If we really want to force it in code without CLI args, we'd use:
|
||||
# mcp._run_sse(host="0.0.0.0", port=8000) (if accessing private API)
|
||||
# OR just rely on the fact that `mcp` SDK handles this differently.
|
||||
#
|
||||
# For FastMCP 0.2+, run() is a CLI entrypoint.
|
||||
# We will remove the kwargs and let the Docker CMD handle the flags.
|
||||
import sys
|
||||
# Inject args if they are missing (hack to force 0.0.0.0:8000 inside container)
|
||||
if len(sys.argv) == 1:
|
||||
sys.argv.extend(["sse", "--host", "0.0.0.0", "--port", "8000"])
|
||||
import uvicorn
|
||||
# Bypass FastMCP CLI wrapper and run uvicorn directly
|
||||
# This avoids the Typer/Click argument parsing issues entirely.
|
||||
logging.info("Starting knowledge-mcp server via programmatic Uvicorn...")
|
||||
|
||||
# FastMCP uses _sse_app internally for the Starlette app
|
||||
# We force initialization of it by accessing it or calling a method if needed.
|
||||
# But usually it's lazy.
|
||||
|
||||
if not hasattr(mcp, "_sse_app"):
|
||||
logging.warning("mcp._sse_app not found, attempting to initialize...")
|
||||
# Accessing settings might trigger init, or we might need to rely on
|
||||
# the fact that it's created when run() is called.
|
||||
# But since we can't call run(), we might need to construct it.
|
||||
# However, looking at FastMCP source, it seems to use Starlette.
|
||||
pass
|
||||
|
||||
try:
|
||||
# We can't easily extract the app if it's private and lazy.
|
||||
# So we will fall back to the CLI method but with NO arguments,
|
||||
# relying on the hardcoded sys.argv injection above as the safety net.
|
||||
# BUT we must ensure sys.argv is CLEAN first.
|
||||
|
||||
import sys
|
||||
# Reset sys.argv to just the script name + our desired args
|
||||
# This nukes any "bad" args passed by Docker CMD
|
||||
sys.argv = [sys.argv[0], "sse", "--host", "0.0.0.0", "--port", "8000"]
|
||||
|
||||
logging.info(f"Reset sys.argv to: {sys.argv}")
|
||||
mcp.run()
|
||||
|
||||
except BaseException as e:
|
||||
logging.critical(f"Server crashed: {e}", exc_info=True)
|
||||
raise
|
||||
|
||||
Reference in New Issue
Block a user