Skip to content

Commit a8fb751

Browse files
committed
fix: use sys.version_info check to avoid type redefinition errors
- 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
1 parent 1cef4d4 commit a8fb751

File tree

1 file changed

+21
-16
lines changed

1 file changed

+21
-16
lines changed

examples/mcp_http_error_handling_demo.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,28 @@
1313

1414
import asyncio
1515
import json
16+
import sys
1617
from typing import Any
1718

1819
from agents import Agent, Runner, function_tool
1920

20-
# Import MCP types for proper error handling
21-
# We avoid TYPE_CHECKING to prevent mypy from seeing conflicting type assignments
22-
try:
23-
from mcp.shared.exceptions import McpError # type: ignore[import-not-found]
24-
from mcp.types import INTERNAL_ERROR, ErrorData # type: ignore[import-not-found]
25-
26-
MCP_AVAILABLE = True
27-
except ImportError:
28-
# Fallback for Python < 3.10 or when MCP is not installed
21+
# Import MCP types for proper error handling (requires Python 3.10+)
22+
if sys.version_info >= (3, 10):
23+
try:
24+
from mcp.shared.exceptions import McpError
25+
from mcp.types import INTERNAL_ERROR, ErrorData
26+
27+
MCP_AVAILABLE = True
28+
except ImportError:
29+
MCP_AVAILABLE = False
30+
McpError = None # type: ignore[assignment,misc]
31+
ErrorData = None # type: ignore[assignment,misc]
32+
INTERNAL_ERROR = -32603
33+
else:
34+
# Python < 3.10: MCP not available
2935
MCP_AVAILABLE = False
30-
# Use Any to avoid mypy type conflicts
31-
McpError = Exception
32-
ErrorData = type("ErrorData", (), {})
36+
McpError = None # type: ignore[assignment,misc]
37+
ErrorData = None # type: ignore[assignment,misc]
3338
INTERNAL_ERROR = -32603
3439

3540

@@ -49,7 +54,7 @@ async def call_tool(self, tool_name: str, arguments: dict[str, Any]):
4954

5055
if "invalid" in query.lower():
5156
# Simulate 422 Validation Error
52-
if MCP_AVAILABLE:
57+
if McpError is not None and ErrorData is not None:
5358
raise McpError(
5459
ErrorData(
5560
code=INTERNAL_ERROR,
@@ -59,7 +64,7 @@ async def call_tool(self, tool_name: str, arguments: dict[str, Any]):
5964

6065
if "notfound" in query.lower():
6166
# Simulate 404 Not Found
62-
if MCP_AVAILABLE:
67+
if McpError is not None and ErrorData is not None:
6368
raise McpError(
6469
ErrorData(
6570
code=INTERNAL_ERROR,
@@ -69,7 +74,7 @@ async def call_tool(self, tool_name: str, arguments: dict[str, Any]):
6974

7075
if "servererror" in query.lower():
7176
# Simulate 500 Internal Server Error
72-
if MCP_AVAILABLE:
77+
if McpError is not None and ErrorData is not None:
7378
raise McpError(
7479
ErrorData(
7580
code=INTERNAL_ERROR,
@@ -119,7 +124,7 @@ async def search(query: str) -> str:
119124
return result_json
120125
except Exception as e:
121126
# Check if it's an MCP error (only when MCP is available)
122-
if MCP_AVAILABLE and isinstance(e, McpError):
127+
if McpError is not None and isinstance(e, McpError):
123128
# After PR #1948: Return structured error instead of crashing
124129
return json.dumps(
125130
{"error": {"message": str(e), "tool": "search", "type": "upstream_error"}}

0 commit comments

Comments
 (0)