Skip to content

fix(agentgateway): guard MCP session handshake with anyio.fail_after - #353

Open
cassiofariasmachado wants to merge 3 commits into
mainfrom
fix/plain-text-error-handling
Open

cassiofariasmachado wants to merge 3 commits into
mainfrom
fix/plain-text-error-handling

Conversation

@cassiofariasmachado

@cassiofariasmachado cassiofariasmachado commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

Disclaimer: Do not include SAP-internal or customer-specific information in this PR (e.g. internal system URLs, customer names, tenant IDs, or confidential configurations). This is a public repository.

Description

When an AGW MCP endpoint returns HTTP 200 with Content-Type: text/event-stream but a plain-text error body (e.g. "Jwt issuer is not configured"), list_mcp_tools hangs indefinitely. The httpx-sse SSEDecoder silently discards all non-SSE lines, so no events are ever yielded, nothing is written to the response stream, and session.initialize() / session.list_tools() block forever.

Wraps the MCP session handshake (initialize + list_tools) in both list_server_tools (_lob.py) and _list_server_tools (_customer.py) with anyio.fail_after(timeout), reusing the existing timeout parameter from ClientConfig (default 60 s). On expiry, TimeoutError is raised and caught by the asyncio.gather(return_exceptions=True) callers, which log it and continue.

Related Issue

Related to #348

Type of Change

  • Bug fix (non-breaking change that fixes an issue)

How to Test

  1. Point an AGW MCP destination at an endpoint that returns HTTP 200 with Content-Type: text/event-stream and a plain-text body (e.g. a misconfigured JWT issuer).
  2. Call client.list_mcp_tools(...) — previously hangs forever, now raises TimeoutError after the configured timeout.
  3. Run unit tests: uv run pytest tests/agentgateway/unit/ -v — all 257 pass.

Checklist

  • I have read the Contributing Guidelines
  • I have verified that my changes solve the issue
  • I have added/updated automated tests to cover my changes
  • All tests pass locally
  • I have verified that my code follows the Code Guidelines
  • I have updated documentation (if applicable)
  • I have added type hints for all public APIs
  • My code does not contain sensitive information (credentials, tokens, etc.)
  • I have followed Conventional Commits for commit messages

Additional Notes

anyio is already a transitive dependency via mcp — no new dependencies introduced.

@cassiofariasmachado
cassiofariasmachado requested a review from a team as a code owner September 25, 2026 17:29

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant