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>
This commit is contained in:
Piotr Oleszczyk 2026-02-28 17:59:11 +01:00
parent 4954d4f449
commit ac829171d9
5 changed files with 1101 additions and 2 deletions

View file

@ -6,6 +6,7 @@ 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
@ -15,6 +16,9 @@ from innercontext.api import ( # noqa: E402
routines,
skincare,
)
from innercontext.mcp_server import mcp # noqa: E402
mcp_app = mcp.http_app(path="/mcp")
@asynccontextmanager
@ -23,7 +27,11 @@ async def lifespan(app: FastAPI):
yield
app = FastAPI(title="innercontext API", lifespan=lifespan, redirect_slashes=False)
app = FastAPI(
title="innercontext API",
lifespan=combine_lifespans(lifespan, mcp_app.lifespan),
redirect_slashes=False,
)
app.add_middleware(
CORSMiddleware, # ty: ignore[invalid-argument-type]
@ -39,6 +47,9 @@ 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"}