feat(server): integrate MCP queries and investigation messaging
Add project-bound OAuth MCP queries and controlled analysis with scoped evidence, limits, timeouts and a nearby-model spatial query using EPSG:4326 inputs. Default nearby searches to 200 meters and five results. Integrate investigation messaging/presentation, health/readiness and typed history; remove duplicate web search and fix online simulation and compressed baseline writes. Include project migrations 023-025; keep local credentials and demo seeding excluded. Validation: 319 focused pytest checks; real PostGIS temporary-table regression; read-only Jinqian bridge radius comparison; cross-language MCP discovery/calls.
This commit is contained in:
+27
-2
@@ -1,11 +1,12 @@
|
||||
from fastapi import FastAPI
|
||||
from contextlib import asynccontextmanager
|
||||
from contextlib import asynccontextmanager, AsyncExitStack
|
||||
from fastapi.middleware.gzip import GZipMiddleware
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from app.api.problem_details import install_problem_details_handlers
|
||||
from app.api.health import router as health_router
|
||||
from app.api.v1.rest_router import api_router
|
||||
from app.infra.db.dynamic_manager import project_connection_manager
|
||||
from app.infra.db.postgresql.workbench_event_hub import workbench_event_hubs
|
||||
@@ -24,13 +25,21 @@ logger.setLevel(logging.INFO)
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
app.state.startup_complete = False
|
||||
logger.info("**********************************************************")
|
||||
logger.info(str(datetime.now()))
|
||||
logger.info("TJWater CloudService is starting...")
|
||||
logger.info("**********************************************************")
|
||||
|
||||
try:
|
||||
yield
|
||||
async with AsyncExitStack() as stack:
|
||||
if mcp_runtime is not None:
|
||||
await stack.enter_async_context(mcp_runtime.lifespan())
|
||||
app.state.startup_complete = True
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
app.state.startup_complete = False
|
||||
finally:
|
||||
await workbench_event_hubs.close_all()
|
||||
await project_connection_manager.close_all()
|
||||
@@ -40,6 +49,14 @@ async def lifespan(app: FastAPI):
|
||||
logger.info("Database connections closed")
|
||||
|
||||
|
||||
# Disabled deployments do not import the MCP SDK or acquire business credentials.
|
||||
from app.mcp.config import McpSettings
|
||||
mcp_settings = McpSettings()
|
||||
mcp_runtime = None
|
||||
if mcp_settings.enabled:
|
||||
from app.mcp.application import McpQueryApplication
|
||||
mcp_runtime = McpQueryApplication(mcp_settings)
|
||||
|
||||
# 根据环境配置决定是否启用文档
|
||||
is_production = settings.ENVIRONMENT.lower() == "production"
|
||||
|
||||
@@ -56,8 +73,13 @@ app = FastAPI(
|
||||
|
||||
|
||||
# Include Routers
|
||||
app.state.startup_complete = False
|
||||
app.include_router(health_router)
|
||||
app.include_router(api_router, prefix="/api/v1")
|
||||
install_problem_details_handlers(app)
|
||||
from app.api.v1.endpoints.mcp_queries import router as mcp_context_router
|
||||
app.state.mcp_runtime = mcp_runtime
|
||||
app.include_router(mcp_context_router, prefix="/api/v1")
|
||||
# Legacy routers without version prefix
|
||||
# app.include_router(api_router)
|
||||
|
||||
@@ -65,6 +87,9 @@ install_problem_details_handlers(app)
|
||||
app.add_middleware(GZipMiddleware, minimum_size=1000)
|
||||
# 添加审计中间件(可选,记录关键操作)
|
||||
app.add_middleware(AuditMiddleware)
|
||||
if mcp_runtime is not None:
|
||||
from app.mcp.dispatch import McpDispatchMiddleware
|
||||
app.add_middleware(McpDispatchMiddleware, runtime=mcp_runtime)
|
||||
# 配置 CORS 中间件
|
||||
# 确保这是你最后一个添加的 app.add_middleware
|
||||
app.add_middleware(
|
||||
|
||||
Reference in New Issue
Block a user