fix: run via fastmcp CLI and remove direct mcp.run()

This commit is contained in:
Clawdbot
2026-02-12 12:40:22 +11:00
parent 15908f95e3
commit 75a9c979b3
2 changed files with 8 additions and 53 deletions

View File

@@ -22,5 +22,5 @@ USER appuser
# Expose the SSE port # Expose the SSE port
EXPOSE 8000 EXPOSE 8000
# Run in SSE mode # Run via FastMCP CLI in SSE mode
CMD ["python", "server.py", "sse", "--host", "0.0.0.0", "--port", "8000"] CMD ["fastmcp", "run", "server.py:mcp", "--transport", "sse", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -209,55 +209,10 @@ def query_notebook(notebook: str, query: str, limit: int = 5) -> str:
except Exception as e: except Exception as e:
return f"Query failed: {e}" return f"Query failed: {e}"
if __name__ == "__main__": # NOTE:
import uvicorn # We intentionally do NOT call mcp.run() here.
# Bypass FastMCP CLI wrapper and run uvicorn directly # This module is meant to be run via the FastMCP CLI:
# This avoids the Typer/Click argument parsing issues entirely. # fastmcp run server.py:mcp --transport sse --host 0.0.0.0 --port 8000
logging.info("Starting knowledge-mcp server via programmatic Uvicorn...") # The CLI handles proper server startup; calling mcp.run() directly has been
# exiting cleanly (exit code 0) under this container setup.
# 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
# Expose as ASGI app for uvicorn to pick up if run directly (uvicorn server:app)
# This bypasses the Typer CLI entirely.
app = mcp._sse_app if hasattr(mcp, "_sse_app") else None
if app is None:
# Fallback if _sse_app isn't pre-initialized or private
try:
from starlette.applications import Starlette
from mcp.server.sse import SseServerTransport
# We need to construct the app manually if FastMCP hides it
# But FastMCP typically creates it on demand.
# Let's try to find it or create a wrapper.
pass
except ImportError:
pass