Skip to content

fix(mcp): flag a partial available_authorities list in list_alerts (closes #24) - #25

Open
dchaudhari7177 wants to merge 1 commit into
jamiusaliu:mainfrom
dchaudhari7177:fix/24-mcp-available-authorities-partial
Open

fix(mcp): flag a partial available_authorities list in list_alerts (closes #24)#25
dchaudhari7177 wants to merge 1 commit into
jamiusaliu:mainfrom
dchaudhari7177:fix/24-mcp-available-authorities-partial

Conversation

@dchaudhari7177

Copy link
Copy Markdown
Contributor

Mirrors #9's fix onto the MCP surface, as the issue describes.

What changed

ListAlertsResult gains available_authorities_partial, populated from the same response.partial /alerts uses, set on the line right after the list it qualifies so the two surfaces cannot drift apart again.

Two decisions worth flagging

None, not False, when there is no list. available_authorities is only built for an unknown authority, so most responses have nothing to qualify. A bare false there would read as "the authority list is complete" — a claim about a list that was never built. The field is bool | None and tracks the list's own presence. Third test covers this.

The description too. As the issue says, that text is what a model reads when deciding how to interpret the result, so it now names the field and says what to do with it:

Check available_authorities_partial before treating that list as complete: when it is true a source was down, so an authority absent from the list may still be real and may still have alerts. Do not report an authority as unknown or as having no alerts on the strength of a partial list.

The last sentence is deliberately imperative about the paraphrase rather than the JSON, since the paraphrase is where the false negative actually lands.

Tests

Four, using the FakeAdapter partial-fetch pattern from tests/test_mcp_server.py:

  • The real case: us-nws asked for, its source timed out, so it cannot appear in available_authorities — the response now says the list is partial rather than implying the authority does not exist.
  • The flag can say no: every source answered, so a missing authority really is absent.
  • The flag is absent when the list is.
  • The description names the field, read off the registered tool rather than the source string.

Red before green — stashing only src/alertmux/mcp_server.py and re-running:

FAILED test_unknown_authority_flags_a_partial_available_authorities_list
FAILED test_available_authorities_partial_is_false_on_a_complete_fetch
FAILED test_available_authorities_partial_is_absent_when_the_list_is
FAILED test_list_alerts_description_tells_the_model_to_check_the_flag
4 failed, 8 passed

Exactly the four new tests, nothing else.

Full suite: 435 passed, 2 failed. Both failures — test_gdacs.py::test_geometry_falls_back_to_bbox_polygon_when_no_point and test_tsunami.py::test_naive_updated_is_quarantined_rather_than_assuming_utc — reproduce on pristine main at 1ef609b with this branch's two files stashed, so they are the local baseline and not from this change.

One setup note: the tests need the mcp extra, and mcp>=2,<3 — the mcp.server.mcpserver.MCPServer import fails against 1.x with ModuleNotFoundError: No module named 'mcp.server.mcpserver', which is easy to misread as a path problem. pip install -e ".[dev,mcp]" in a clean venv is what makes tests/test_mcp_server.py collect at all.

/alerts has reported available_authorities_partial since jamiusaliu#9, so a caller
cannot read a short authority list as proof an authority is invalid. The MCP
tool built the same list from the same data and shipped no such flag, leaving
the original false negative intact over MCP.

That matters more here than over HTTP, as D14 argues: an HTTP caller reads the
JSON and can see a partial: true beside a short list, while an MCP caller is a
model that paraphrases -- and the paraphrase of an unqualified short list is
'there are no alerts for that authority', which is a stronger claim than the
data supports.

Populated from response.partial next to the list it qualifies, so the two
surfaces cannot drift apart again. Left as None rather than False when there
is no list, since a bare false would assert completeness about a list that was
never built.

Also names the field in the tool description=, which is the text a model reads
when deciding how to interpret the result.
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a51cb35-eecf-4c1e-ae0c-5f207b4f6102


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants