innercontext/backend/main.py
Piotr Oleszczyk ac829171d9 feat(mcp): add FastMCP server with 14 tools for LLM agent access
- Add backend/innercontext/mcp_server.py with tools covering products,
  inventory, routines, skin snapshots, medications, lab results, and
  grooming schedule
- Mount MCP app at /mcp in main.py using combine_lifespans
- Fix test isolation: patch app.router.lifespan_context in conftest to
  avoid StreamableHTTPSessionManager single-run limitation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 17:59:11 +01:00

55 lines
1.4 KiB
Python

from contextlib import asynccontextmanager
from dotenv import load_dotenv
load_dotenv() # load .env before db.py reads DATABASE_URL
from fastapi import FastAPI # noqa: E402
from fastapi.middleware.cors import CORSMiddleware # noqa: E402
from fastmcp.utilities.lifespan import combine_lifespans # noqa: E402
from db import create_db_and_tables # noqa: E402
from innercontext.api import ( # noqa: E402
health,
inventory,
products,
routines,
skincare,
)
from innercontext.mcp_server import mcp # noqa: E402
mcp_app = mcp.http_app(path="/mcp")
@asynccontextmanager
async def lifespan(app: FastAPI):
create_db_and_tables()
yield
app = FastAPI(
title="innercontext API",
lifespan=combine_lifespans(lifespan, mcp_app.lifespan),
redirect_slashes=False,
)
app.add_middleware(
CORSMiddleware, # ty: ignore[invalid-argument-type]
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(products.router, prefix="/products", tags=["products"])
app.include_router(inventory.router, prefix="/inventory", tags=["inventory"])
app.include_router(health.router, prefix="/health", tags=["health"])
app.include_router(routines.router, prefix="/routines", tags=["routines"])
app.include_router(skincare.router, prefix="/skincare", tags=["skincare"])
app.mount("/mcp", mcp_app)
@app.get("/health-check")
def health_check():
return {"status": "ok"}