auth: verify MCP HTTP clients against the API key (#181)

The MCP server now gates its HTTP transports with a token verifier that
requires the connecting client to present the API key, compared with
hmac.compare_digest to match the FastAPI layer. The stdio transport is
local and does not pass through the HTTP auth layer, so it keeps working
unchanged. Raises the fastmcp floor to >=4.0.0, where the auth API used
here is available.
This commit is contained in:
Classic298 authored and GitHub committed 2026-09-23 12:38:11 -04:00
1 parent 542094a0ad
commit 83bafddf87
2 files changed
+17 -2

No files matched your search

+16 -1
View File
@@ -1,9 +1,23 @@
"""MCP server — exposes every FastAPI endpoint as an MCP tool."""
import hmac
from fastmcp import FastMCP
from fastmcp.server.auth import AccessToken, TokenVerifier
from open_terminal.main import app
from open_terminal.env import API_KEY
class ApiKeyVerifier(TokenVerifier):
"""Accept a client bearer token only when it matches the API key."""
async def verify_token(self, token: str) -> AccessToken | None:
if not hmac.compare_digest(token, API_KEY):
return None
return AccessToken(token=token, client_id="open-terminal", scopes=[])
# HTTP transports gate on the API key; stdio is local and never hits this layer.
mcp = FastMCP.from_fastapi(
app=app,
name="Open Terminal",
@@ -12,4 +26,5 @@ mcp = FastMCP.from_fastapi(
"Authorization": f"Bearer {API_KEY}",
}
},
)
auth=ApiKeyVerifier(),
)
+1 -1
View File
@@ -27,7 +27,7 @@ dependencies = [
]
[project.optional-dependencies]
mcp = ["fastmcp>=2.0.0"]
mcp = ["fastmcp>=4.0.0"]
[project.scripts]
open-terminal = "open_terminal.cli:main"