fix: run via fastmcp CLI and remove direct mcp.run()
This commit is contained in:
@@ -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"]
|
||||||
|
|||||||
57
server.py
57
server.py
@@ -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
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user