Files
local-mcp/app/config.py
cabbage 009fd039a2 feat: optional Bearer-token authentication via API_TOKEN env var
Disabled by default (empty API_TOKEN). When set:
- All /api/* and /mcp requests require: Authorization: Bearer <token>
- Public exemptions: /, /healthz, /static/*, /auth-check
- Web UI: pre-flight /auth-check on load; shows token modal if required
- Token stored in sessionStorage, sent on every API request
- Mid-session 401s re-trigger the token modal
- MCP clients must pass the header: Authorization: Bearer <token>
Files changed:
- app/config.py: api_token field + API_TOKEN env var
- app/api/auth.py: Starlette BaseHTTPMiddleware for token enforcement
- main.py: register middleware + /auth-check public endpoint
- static/js/api.js: token storage, auth header, 401 handler hook
- static/js/app.js: auth pre-flight, showTokenModal(), bootstrap()
- static/css/components.css: .auth-overlay / .auth-card styles
- README.md: API_TOKEN env var docs + MCP client header example
2026-03-27 04:28:12 +08:00

67 lines
2.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
app/config.py
Runtime configuration loaded from environment variables with sensible defaults.
"""
from __future__ import annotations
import os
from dataclasses import dataclass, field
@dataclass
class Settings:
# Server
host: str = "0.0.0.0"
http_port: int = 8000
# Database
db_path: str = "data/local_mcp.sqlite3"
# Logging
log_level: str = "INFO"
# MCP / queue behaviour (runtime-editable values are stored in DB; these are defaults for first run)
default_wait_seconds: int = 10
default_empty_response: str = ""
agent_stale_after_seconds: int = 30
# MCP server name
mcp_server_name: str = "local-mcp"
# MCP transport — stateless=True means no session IDs, survives server restarts.
# Set MCP_STATELESS=false to use stateful sessions (needed for multi-turn MCP flows).
mcp_stateless: bool = True
# Authentication — set API_TOKEN env var to enable; empty string disables auth entirely.
api_token: str = ""
def _parse_bool(value: str, default: bool) -> bool:
if value.lower() in ("1", "true", "yes", "on"):
return True
if value.lower() in ("0", "false", "no", "off"):
return False
return default
def load_settings() -> Settings:
"""Load settings from environment variables, falling back to defaults."""
return Settings(
host=os.getenv("HOST", "0.0.0.0"),
http_port=int(os.getenv("HTTP_PORT", "8000")),
db_path=os.getenv("DB_PATH", "data/local_mcp.sqlite3"),
log_level=os.getenv("LOG_LEVEL", "INFO"),
default_wait_seconds=int(os.getenv("DEFAULT_WAIT_SECONDS", "10")),
default_empty_response=os.getenv("DEFAULT_EMPTY_RESPONSE", ""),
agent_stale_after_seconds=int(os.getenv("AGENT_STALE_AFTER_SECONDS", "30")),
mcp_server_name=os.getenv("MCP_SERVER_NAME", "local-mcp"),
mcp_stateless=_parse_bool(os.getenv("MCP_STATELESS", "true"), default=True),
api_token=os.getenv("API_TOKEN", ""),
)
# Singleton imported and used throughout the app
settings: Settings = load_settings()