fix: use correct Starlette mount pattern for MCP SSE routing
All checks were successful
Build and Push Monarch MCP Docker Image / build (push) Successful in 8s
All checks were successful
Build and Push Monarch MCP Docker Image / build (push) Successful in 8s
The previous implementation added health route directly to mcp_app and returned it, which broke MCP's internal /mcp endpoint routing. Now matches the working pattern from komodo-mcp-custom: - Mount mcp_app at / inside a parent Starlette app - Pass lifespan=mcp_app.lifespan for proper task group init - Health check is a separate route in the parent app
This commit is contained in:
@@ -5,17 +5,13 @@ Monarch Money MCP Server - Custom SSE Implementation.
|
||||
import os
|
||||
import logging
|
||||
import json
|
||||
import asyncio
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import datetime
|
||||
from typing import Optional, Any
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from fastmcp import FastMCP
|
||||
from starlette.applications import Starlette
|
||||
from starlette.responses import JSONResponse
|
||||
from starlette.routing import Route, Mount
|
||||
from mcp.server.sse import SseServerTransport
|
||||
import uvicorn
|
||||
|
||||
from monarch_mcp_custom.auth import get_authenticated_client
|
||||
|
||||
@@ -166,35 +162,36 @@ async def refresh_accounts() -> str:
|
||||
return f"Error: {str(e)}"
|
||||
|
||||
|
||||
# --- Health Check ---
|
||||
# --- Health Check Endpoint ---
|
||||
|
||||
|
||||
async def health_check(request):
|
||||
"""Simple health check endpoint."""
|
||||
return JSONResponse({"status": "ok", "timestamp": datetime.now().isoformat()})
|
||||
async def health(request):
|
||||
"""Health check endpoint for Docker."""
|
||||
return JSONResponse({"status": "ok"})
|
||||
|
||||
|
||||
# --- ASGI App Setup ---
|
||||
# --- ASGI Application ---
|
||||
|
||||
|
||||
def create_app() -> Starlette:
|
||||
"""Create the Starlette application with health check and MCP."""
|
||||
def create_app():
|
||||
"""Create the ASGI application with health check and MCP routes."""
|
||||
mcp_app = mcp.http_app()
|
||||
|
||||
# Add health check route directly to the MCP app
|
||||
mcp_app.add_route("/health", health_check, methods=["GET"])
|
||||
# Wrapper app: /health is standalone, everything else goes to MCP
|
||||
# IMPORTANT: Must pass mcp_app.lifespan for task group initialization
|
||||
routes = [
|
||||
Route("/health", health, methods=["GET"]),
|
||||
Mount("/", app=mcp_app), # MCP handles /mcp endpoint
|
||||
]
|
||||
|
||||
return mcp_app
|
||||
return Starlette(routes=routes, lifespan=mcp_app.lifespan)
|
||||
|
||||
|
||||
# Create the app instance for uvicorn
|
||||
app = create_app()
|
||||
|
||||
|
||||
def main():
|
||||
"""Entry point for running the server."""
|
||||
port = int(os.getenv("PORT", 8000))
|
||||
uvicorn.run(app, host="0.0.0.0", port=port)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run(app, host="0.0.0.0", port=8000)
|
||||
|
||||
Reference in New Issue
Block a user