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:
@@ -0,0 +1,58 @@
|
||||
"""Public process probes, separate from authenticated project diagnostics."""
|
||||
|
||||
import asyncio
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import JSONResponse
|
||||
from sqlalchemy import text
|
||||
|
||||
from app.infra.db.metadb.database import engine
|
||||
|
||||
|
||||
router = APIRouter(include_in_schema=False)
|
||||
METADATA_TIMEOUT_SECONDS = 2
|
||||
|
||||
|
||||
async def metadata_database_ready() -> bool:
|
||||
try:
|
||||
async with asyncio.timeout(METADATA_TIMEOUT_SECONDS):
|
||||
async with engine.connect() as connection:
|
||||
result = await connection.execute(text("SELECT 1"))
|
||||
return result.scalar_one() == 1
|
||||
except Exception:
|
||||
# Public probes must not expose connection strings or driver errors.
|
||||
return False
|
||||
|
||||
|
||||
@router.get("/health")
|
||||
async def health() -> dict[str, str]:
|
||||
"""Check HTTP liveness without project or database dependencies."""
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
@router.get("/ready")
|
||||
async def readiness(request: Request) -> JSONResponse:
|
||||
"""Check startup, metadata connectivity and the enabled MCP lifecycle."""
|
||||
started = getattr(request.app.state, "startup_complete", False)
|
||||
runtime = getattr(request.app.state, "mcp_runtime", None)
|
||||
mcp_ready = runtime is None or runtime.ready
|
||||
metadata_ready = await metadata_database_ready() if started else False
|
||||
ready = started and metadata_ready and mcp_ready
|
||||
return JSONResponse(
|
||||
status_code=200 if ready else 503,
|
||||
content={
|
||||
"status": "ready" if ready else "not_ready",
|
||||
"checks": {
|
||||
"startup": "ready" if started else "not_ready",
|
||||
"metadata_database": (
|
||||
"not_checked" if not started
|
||||
else "ready" if metadata_ready else "unavailable"
|
||||
),
|
||||
"mcp_transport": (
|
||||
"disabled" if runtime is None
|
||||
else "ready" if mcp_ready else "not_ready"
|
||||
),
|
||||
},
|
||||
},
|
||||
headers={"Cache-Control": "no-store"},
|
||||
)
|
||||
Reference in New Issue
Block a user