"""Standalone Streamable HTTP entry point for ARR MCP.""" from __future__ import annotations import argparse from pathlib import Path from typing import Optional, Sequence from arr_mcp.auth import BearerAuthConfig from arr_mcp.database import controlled_connect from arr_mcp.gateway import DirectResultGateway from arr_mcp.server import create_http_application from arr_web.direct_ingestion_runtime import compose_oss_direct_ingestion PROJECT_ROOT = Path(__file__).resolve().parents[1] _LOOPBACK_HOSTS = {"127.0.0.1", "localhost", "::1"} def _parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser(prog="arr-mcp") parser.add_argument("--host", default="127.0.0.1") parser.add_argument("--port", type=int, default=8890) parser.add_argument( "--db-config", type=Path, help="private 0600 ARR_DB_* configuration file", ) parser.add_argument( "--allowed-host", action="append", default=[], help="exact HTTP Host value or host:*; repeat for reverse-proxy names", ) parser.add_argument( "--max-concurrency", type=int, default=2, help="maximum concurrent deterministic replays (1-8)", ) return parser def _allowed_hosts(bind_host: str, configured: list[str]) -> list[str]: if configured: return list(dict.fromkeys(configured)) if bind_host not in _LOOPBACK_HOSTS: raise ValueError( "--allowed-host is required when ARR MCP binds beyond loopback" ) return ["localhost:*", "127.0.0.1:*", "[::1]:*"] def main(argv: Optional[Sequence[str]] = None) -> int: args = _parser().parse_args(argv) if not 1 <= args.port <= 65535: raise ValueError("ARR MCP port is invalid") connect = controlled_connect(args.db_config) if args.db_config else None runtime = compose_oss_direct_ingestion( project_root=PROJECT_ROOT, connect=connect, ) try: runtime.service.assert_ready() gateway = DirectResultGateway( runtime.service, max_concurrency=args.max_concurrency, ) application = create_http_application( gateway, BearerAuthConfig.from_environment(), allowed_hosts=_allowed_hosts(args.host, args.allowed_host), ) import uvicorn uvicorn.run( application, host=args.host, port=args.port, access_log=True, log_level="info", ) finally: runtime.close() return 0 if __name__ == "__main__": raise SystemExit(main())