-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathmain_stdio.py
More file actions
122 lines (89 loc) · 3.73 KB
/
main_stdio.py
File metadata and controls
122 lines (89 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/env python3
"""
Common Chronicle MCP Server - With Progress Reporting
This version implements FastMCP best practices for long-running tasks
using the official progress reporting mechanism.
"""
import asyncio
import sys
# Add this block to switch asyncio event loop policy on Windows
if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
from contextlib import asynccontextmanager
from fastapi import FastAPI
from app.services.mcp.mcp_tools import mcp
from app.utils.logger import setup_logger
logger = setup_logger("main_stdio")
# Global variables for lazy initialization
_services_initialized = False
_llm_clients_initialized = False
_db_initialized = False
async def ensure_services_initialized():
"""Initialize services only when needed (lazy loading)"""
global _services_initialized, _llm_clients_initialized, _db_initialized
if not _services_initialized:
logger.info("Initializing services on demand...")
# Initialize LLM clients only when needed
if not _llm_clients_initialized:
try:
from app.services.llm_service import initialize_all_llm_clients
initialize_all_llm_clients()
_llm_clients_initialized = True
logger.info("LLM clients initialized")
except Exception as e:
logger.warning(f"LLM client initialization failed: {e}")
# Initialize database only when needed
if not _db_initialized:
try:
from app.db import check_db_connection, init_db
await init_db()
if await check_db_connection():
_db_initialized = True
logger.info("Database initialized")
else:
logger.warning("Database connectivity check failed")
except Exception as e:
logger.warning(f"Database initialization failed: {e}")
_services_initialized = True
logger.info("Services initialization completed")
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Lightweight lifespan - minimal initialization"""
logger.info("MCP STDIO Server with Progress Reporting startup...")
# Only do minimal initialization here
logger.info("Minimal initialization complete - services will be loaded on demand")
logger.info("Progress reporting enabled for long-running tasks")
yield
logger.info("MCP STDIO Server shutdown...")
# Cleanup only if services were actually initialized
if _llm_clients_initialized:
try:
from app.services.llm_service import close_all_llm_clients
await close_all_llm_clients()
logger.info("LLM clients closed")
except Exception as e:
logger.warning(f"Error closing LLM clients: {e}")
logger.info("Shutdown complete.")
def create_app():
"""
Create FastAPI application for MCP STDIO with progress reporting
"""
app = FastAPI(
title="Common Chronicle MCP Server (With Progress)",
description="Timeline generation service via MCP - with progress reporting for long tasks",
lifespan=lifespan,
)
return app
def main():
"""Main entry point for MCP server with progress reporting"""
logger.info("Starting Common Chronicle MCP Server (With Progress Reporting)")
# Show available tools
logger.info(
"MCP server ready with progress reporting - services will initialize on first use"
)
logger.info("Long-running tasks will provide real-time progress updates")
# Run MCP server with STDIO transport
logger.info("Running MCP server with STDIO transport...")
mcp.run(transport="stdio")
if __name__ == "__main__":
main()