- Notifications
You must be signed in to change notification settings - Fork 2.8k
fix: handle MCP upstream HTTP errors gracefully (fixes #879) #1948
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix: handle MCP upstream HTTP errors gracefully (fixes #879) #1948
Conversation
When MCP tools receive non-2xx HTTP responses from upstream services (e.g., 422, 404, 500), catch McpError and return structured JSON error instead of raising AgentsException. This allows agents to handle errors gracefully and decide how to respond (retry, inform user, etc.) instead of crashing the entire run. Backward compatible: programming errors still raise AgentsException. Fixes openai#879
maybe we don't need it but maybe it's good. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes issue #879 by implementing graceful handling of HTTP errors from MCP upstream services, preventing agent runs from crashing when tools encounter non-2xx responses.
Key changes:
- MCP HTTP errors (via
McpError
) now return structured JSON error responses instead of raising exceptions - Programming errors continue to raise
AgentsException
as before, preserving safety - Added comprehensive test suite with 8 test cases covering various HTTP error scenarios
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/agents/mcp/util.py Outdated
try: | ||
from mcp.shared.exceptions import McpError | ||
| ||
if isinstance(e, McpError): |
Copilot AI Oct 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The McpError
import occurs inside the exception handler on every tool invocation error. Move this import to the module level to avoid repeated import overhead during error handling.
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with this
src/agents/mcp/util.py Outdated
} | ||
return json.dumps(error_response) | ||
except ImportError: | ||
# MCP not available (Python < 3.10), fall through to original behavior |
Copilot AI Oct 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment incorrectly states 'MCP not available (Python < 3.10)' when handling ImportError. This is misleading because ImportError could occur for other reasons (missing package, incorrect import path). Consider clarifying that this handles cases where the mcp package or McpError class is unavailable.
# MCP not available (Python < 3.10), fall through to original behavior | |
# mcp package or McpError class unavailable (e.g., missing package, incorrect import path, or Python version); fall through to original behavior |
Copilot uses AI. Check for mistakes.
Address review feedback from @seratch and Copilot AI. Previously, McpError was imported inside the exception handler on every tool invocation error, causing repeated import overhead. This change moves the import to module level with proper fallback for Python < 3.10 (where mcp package is not available).
@codex review |
Codex Review: Didn't find any major issues. Keep them coming! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Thanks for sending this. At a glance, the code looks good but we need to take time to verify the behavior using a simple example returning an error status for tool calls. |
Hi @seratch! I've added a simple demonstration script to help verify the behavior. You can find it at Quick DemoThe script demonstrates 4 scenarios:
Run the Demopython examples/mcp_http_error_handling_demo.py Expected Output:
Key Behavior ChangeBefore PR #1948: agent.run("Search for: invalid query") # → McpError raised → AgentsException → Crash ❌ After PR #1948: agent.run("Search for: invalid query") # → Returns {"error": {...}} → Agent continues → Handles gracefully ✅ The demo uses a mock MCP server to simulate HTTP errors, so it doesn't require an actual MCP server running. Let me know if you'd like me to adjust anything! |
Fixes mypy type errors in examples/mcp_http_error_handling_demo.py: - Use ErrorData(error_code, message) instead of McpError(string) - Add proper type annotation for model_dump_json() return value - Import ErrorData and INTERNAL_ERROR from mcp.types - Add mypy type: ignore comments for conditional MCP imports Resolves 4 mypy errors: 1. Line 39: McpError expects ErrorData, not str 2. Line 45: McpError expects ErrorData, not str 3. Line 51: McpError expects ErrorData, not str 4. Line 93: Returning Any from function declared to return str
0f1e65c
to 06b9aa6
Compare - Change ErrorData(code, message) to use named parameters: code=, message= - Replace None checks with MCP_AVAILABLE boolean flag - Provide proper fallback values: McpError=Exception, INTERNAL_ERROR=-32603 - This fixes all 10 mypy errors in the demo script
- Use TYPE_CHECKING block to declare types for mypy - Declare MCP_AVAILABLE and INTERNAL_ERROR as type stubs - Remove unused type: ignore comments - This properly handles the case where MCP is not installed
- Remove TYPE_CHECKING block that caused mypy type conflicts - Keep only import-not-found ignores for MCP imports - Remove unused type: ignore comments in except block - Tested with --python-version 3.9 to match GitHub Actions
- Check Python version before importing MCP (only available in 3.10+) - Set McpError/ErrorData to None as fallback instead of Exception/type - This prevents mypy type conflicts when MCP is installed - Tested with Python 3.12 + MCP to match GitHub Actions environment
Summary
Fixes #879 - MCP tools now handle upstream HTTP errors gracefully instead of crashing the agent run.
Problem
When MCP tools received non-2xx HTTP responses from upstream services (e.g., 422 Validation Error, 404 Not Found, 500 Internal Server Error), the SDK raised
AgentsException
, crashing the entire agent run. This prevented agents from handling errors gracefully.Example Before Fix
Solution
McpError
(HTTP errors from upstream) separately from programming errorsAgentsException
)Example After Fix
Changes
File:
src/agents/mcp/util.py
(lines 202-225)Added graceful error handling:
Error Response Format
When upstream HTTP error occurs:
Testing
Comprehensive test suite included (8 test cases):
Test file:
tests/mcp/test_issue_879_http_error_handling.py
(attached in PR files)(Requires Python 3.10+ due to MCP package dependency)
Backward Compatibility
✅ Fully backward compatible
AgentsException
Impact
Author: Lucas Wang (lucas_wang@lucas-futures.com)