Skip to content

One MCP resolution error covers six conditions, and none of them logs #1711

Description

@peteski22

What

McpServerResolutionFailedError is raised at nine sites in src/gateway/adapters/mcp_server_adapter.py, for seven distinct conditions:

  • a scope naming no workspace, in the local adapter (twice)
  • a scope holding no token, in the remote adapter
  • a peer answer that is not an object
  • a servers value that is not a list
  • a peer answering several entries for one requested ID
  • an entry whose ID does not match the one requested
  • an entry the model cannot validate (twice)

The fixed public message is correct: the underlying detail quotes the stored server URL and its credential, so it must not travel. But the error carries nothing else either, so an operator looking at a 502 has nothing that tells the nine apart.

Why it matters

A hybrid gateway returning MCP server resolution failed gives the operator no way to tell a peer that answered badly from a gateway that was wired wrong. The two have different owners and different fixes.

Suggested shape

A required, typed reason on the error, named at each raise site. The wire response does not change, and no reason names any part of the peer's answer. #1738 does this and nothing more.

Recording the reason is a separate problem, because a failure's record belongs where its response is produced and neither surface does both. On this router, _McpRoute.handler renders the error response and writes no log, while the route handlers log the outcome and re-raise so it can render. On the completions path there is no HTTPException handler and no middleware log at all. #1752 covers both surfaces, and this issue closes once that lands.

Not a logger.warning beside each raise, and not one at each handling boundary either. Both are log-and-raise: they put the choice of how loud a condition is in code that cannot know whether a caller recovers from it, and they leave the cause reachable only by scraping log text. McpExecutionError in src/gateway/services/mcp_stateless.py is the local pattern for carrying a cause, holding a code and an execution state rather than a message.

Notes

Found while reviewing #1683. Deliberately left out of it: that change's acceptance criterion is identical behavior in all three modes, and adding log lines is new behavior.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions