Coverage for src/ecnl/adapters/inbound/tools/matches.py: 100%
16 statements
« prev ^ index » next coverage.py v7.14.2, created at 2026-06-28 08:19 +0000
« prev ^ index » next coverage.py v7.14.2, created at 2026-06-28 08:19 +0000
1"""Match-detail and bracket tools.
3These return the upstream payload as pretty-printed JSON because match detail
4and bracket shapes vary by event and are not normalized into domain models.
5"""
7import logging
9from mcp.server.fastmcp import FastMCP
11from ....application.service import ECNLService
12from ....ports.inbound import Authorizer
13from ..formatters import _fmt_raw
14from ._base import _READ_ANNOTATIONS, _safe_call_authorized
16logger = logging.getLogger(__name__)
19def register_match_tools(mcp: FastMCP, service: ECNLService, authorizer: Authorizer) -> None:
20 """Register the match-detail and bracket tools on ``mcp``."""
22 @mcp.tool(annotations=_READ_ANNOTATIONS)
23 async def get_match(match_token: str) -> str:
24 """Get detailed information for a single match by its token.
26 Returns the match-detail / box-score payload (teams, score, events) as
27 JSON. The match token comes from a schedule entry's match data.
29 Args:
30 match_token: The match's token/ID string.
31 """
32 logger.info("tool=get_match match_token=%r", match_token)
33 return await _safe_call_authorized(authorizer, "get_match", service.get_match(match_token), _fmt_raw)
35 @mcp.tool(annotations=_READ_ANNOTATIONS)
36 async def get_brackets(event_id: int, flight_id: int) -> str:
37 """Get the playoff bracket for a flight, if one exists.
39 Returns the bracket structure as JSON. Many regular-season flights have
40 no bracket; in that case the payload is empty.
42 Args:
43 event_id: Numeric event ID (e.g. 3933).
44 flight_id: Flight ID from get_event_overview.
45 """
46 logger.info("tool=get_brackets event_id=%r flight_id=%r", event_id, flight_id)
47 return await _safe_call_authorized(
48 authorizer, "get_brackets", service.get_brackets(event_id, flight_id), _fmt_raw
49 )