feat: prepare ARR for controlled public deployment

This commit is contained in:
Wyndham ARR
2026-07-29 16:38:05 +08:00
commit a701de9f0e
271 changed files with 48472 additions and 0 deletions

89
arr_mcp/run.py Normal file
View File

@@ -0,0 +1,89 @@
"""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())