"""FastMCP server for pdac-genomics-agent — mirrors the sibling specialists. One sub-`FastMCP` per tool module, mounted here, exactly as `pdac-subtype-agent/src/server.py` and `DecoupleRpy_Agent/src/server.py` do. The MCP tools are thin registered wrappers over the plain functions in `src/tools/`, which the Gradio handlers call directly — so the two surfaces can never drift apart in behaviour, only in transport. Run standalone:: python -m src.server # default transport (stdio) python -m src.server --transport http --port 8765 In the deployed Space, MCP is served by `demo.launch(..., mcp_server=True)` in `gradio_ui.py` instead — this entry point is for local/CLI use and for an orchestrator that prefers MCP over `gradio_client`. **Note on authorization.** The ADR-0004 allow-list gate lives in the *app* layer (`gradio_ui.py` handlers and the `gr.api` endpoints), not here — this MCP surface has no HTTP identity to gate on. Do not expose it publicly without putting a gate in front of it; that is the same open question `pdac-subtype-agent` ADR-0018 raised about unauthenticated machine surfaces. """ from __future__ import annotations import sys from pathlib import Path PROJECT_ROOT = Path(__file__).resolve().parents[1] if str(PROJECT_ROOT) not in sys.path: sys.path.insert(0, str(PROJECT_ROOT)) from fastmcp import FastMCP # noqa: E402 from src.tools.query_variant_status import variant_status_mcp # noqa: E402 from src.tools.variant_by_subtype import variant_by_subtype_mcp # noqa: E402 mcp = FastMCP(name="pdac-genomics-agent") mcp.mount(variant_status_mcp) mcp.mount(variant_by_subtype_mcp) if __name__ == "__main__": import argparse parser = argparse.ArgumentParser(add_help=False) parser.add_argument("--transport", default=None) parser.add_argument("--port", type=int, default=8765) args, _ = parser.parse_known_args() if args.transport: mcp.run(transport=args.transport, host="0.0.0.0", port=args.port) else: mcp.run()