diff --git a/env.example b/env.example index be99bf9..eb6e081 100644 --- a/env.example +++ b/env.example @@ -1,7 +1,10 @@ # MCP Email Server - Docker Environment Variables +# MCP API key (Bearer auth for /mcp endpoints) +API_KEY= + # Logging -LOG_LEVEL=INFO +LOG_LEVEL=DEBUG # IMAP (incoming mail) IMAP_HOST=imap.example.com diff --git a/server.py b/server.py index eaff268..8f741f1 100644 --- a/server.py +++ b/server.py @@ -1950,6 +1950,8 @@ app = FastAPI( version="1.0.0", ) +API_KEY = os.getenv("API_KEY", "").strip() + @app.exception_handler(Exception) async def global_exception_handler(request, exc): @@ -1960,6 +1962,17 @@ async def global_exception_handler(request, exc): ) +def require_bearer(request: Request): + if not API_KEY: + return + auth = (request.headers.get("authorization") or "").strip() + if not auth.startswith("Bearer "): + raise HTTPException(status_code=401, detail="Missing or invalid Authorization header") + token = auth[len("Bearer "):].strip() + if token != API_KEY: + raise HTTPException(status_code=401, detail="Invalid API key") + + @app.get("/health") async def health_check(): return { @@ -1970,7 +1983,8 @@ async def health_check(): @app.get("/mcp/openapi.json") -async def mcp_openapi_spec(): +async def mcp_openapi_spec(request: Request): + require_bearer(request) # Minimal OpenAPI 3.1 document for compatibility with clients # that expect an OpenAPI spec at /mcp/openapi.json. # Actual tool definitions are provided via MCP tools/list. @@ -2045,6 +2059,7 @@ async def mcp_openapi_spec(): @app.post("/mcp") async def mcp_endpoint(request: Request): + require_bearer(request) if request.method != "POST": raise HTTPException(status_code=405, detail="Method Not Allowed")