fix(mcp): surface query() failures as data, not exceptions#88
Merged
Conversation
A failing query (404, DNS miss, binary response) was raising up through
fastmcp into pydantic-ai's tool-call layer, where the default
max_retries=1 would abort the entire agent run after a single bad host
guess. Exploration calls — picking the wrong PDS, hitting an endpoint
that returns blob bytes — should be cheap to fail.
The MCP query tool now catches httpx.HTTPStatusError, httpx.RequestError,
and JSON/Unicode decode errors and returns a structured
`{"error": ..., "message": ...}` dict instead. The CLI/library path
(_internal.operations.query) is unchanged — it still raises, preserving
existing error flow for non-MCP callers.
Covers two motivating failure modes from a live phi batch:
- 404 on a wrong-host listRepos guess took down the whole run
- query("com.atproto.sync.getBlob", ...) blew up on the PNG header
trying to JSON-decode binary bytes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A failing
query(404, DNS miss, binary response) was raising up through fastmcp into pydantic-ai's tool-call layer, wheremax_retries=1would abort the entire agent run after a single bad host guess. Exploration calls — picking the wrong PDS, hitting an endpoint that returns blob bytes — should be cheap to fail.The MCP
querytool now catcheshttpx.HTTPStatusError,httpx.RequestError, and JSON/Unicode decode errors and returns a structured{\"error\": ..., \"message\": ...}dict instead. The CLI/library path (_internal.operations.query) is unchanged — it still raises, preserving existing error flow for non-MCP callers.Motivating failures (live phi batch)
query(\"com.atproto.sync.listRepos\", host=\"grain.social\")→ 404 → retry withpds.grain.social→ DNS miss → whole agent run aborted with `UnexpectedModelBehavior: Tool 'query' exceeded max retries count of 1`query(\"com.atproto.sync.getBlob\", ...)→ tried to JSON-decode PNG header → `UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89`Both now come back as data the model can read and adapt to.
Test plan