Apply patch [skip ci]

This commit is contained in:
open-swe[bot]
2025-11-14 14:48:34 +00:00
parent d38079589e
commit d9dbb73b68

View File

@@ -718,70 +718,55 @@ def create_agent( # noqa: PLR0915
# Handle MCP session configuration if provided
mcp_session = None
mcp_wrapped_tools = None
mcp_session_cleanup = None
if mcp_session_config:
# Check if any tools are MCP tools (by checking metadata or attributes)
has_mcp_tools = any(
hasattr(tool, "__mcp_server__") or
(hasattr(tool, "metadata") and isinstance(getattr(tool, "metadata", {}), dict) and
getattr(tool, "metadata", {}).get("mcp_server"))
for tool in tools
if isinstance(tool, BaseTool)
)
# MCP tools typically have metadata indicating their MCP origin
def is_mcp_tool(tool: Any) -> bool:
"""Check if a tool is an MCP tool by examining its metadata."""
if not isinstance(tool, BaseTool):
return False
# Check for MCP-specific attributes or metadata
if hasattr(tool, "__mcp_server__"):
return True
# Check tool metadata for MCP indicators
metadata = getattr(tool, "metadata", {})
if isinstance(metadata, dict):
# Look for MCP-related keys in metadata
if metadata.get("mcp_server") or metadata.get("mcp_tool") or metadata.get("source") == "mcp":
return True
# Check if tool name suggests MCP origin (common patterns)
tool_name = getattr(tool, "name", "")
if tool_name and any(prefix in tool_name for prefix in ["mcp_", "playwright_", "browser_"]):
return True
return False
has_mcp_tools = any(is_mcp_tool(tool) for tool in tools)
if has_mcp_tools:
# Import MCP utilities dynamically to avoid circular imports
try:
from langchain.agents.mcp_utils import create_stateful_mcp_agent
from langchain_mcp_adapters import load_mcp_tools
import asyncio
import warnings
# Create a stateful session for MCP tools
client = mcp_session_config["client"]
server_name = mcp_session_config["server_name"]
auto_cleanup = mcp_session_config.get("auto_cleanup", True)
# Create session and load tools asynchronously
async def _setup_mcp_session():
session = await client.session(server_name).__aenter__()
stateful_tools = await load_mcp_tools(session)
return session, stateful_tools
# Run async setup
try:
loop = asyncio.get_event_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
mcp_session, mcp_wrapped_tools = loop.run_until_complete(_setup_mcp_session())
# Replace MCP tools with stateful versions
non_mcp_tools = [
tool for tool in tools
if not (hasattr(tool, "__mcp_server__") or
(hasattr(tool, "metadata") and isinstance(getattr(tool, "metadata", {}), dict) and
getattr(tool, "metadata", {}).get("mcp_server")))
]
tools = non_mcp_tools + mcp_wrapped_tools
# Add cleanup handler if auto_cleanup is enabled
if auto_cleanup:
warnings.warn(
"MCP session auto-cleanup is enabled. The session will be closed "
"when the agent is garbage collected. For explicit control, "
"consider using StatefulMCPAgentExecutor or mcp_agent_session "
"context manager from langchain.agents.mcp_utils.",
UserWarning,
stacklevel=2
)
except ImportError as e:
raise ImportError(
"MCP session configuration requires langchain-mcp-adapters. "
"Install it with: pip install langchain-mcp-adapters"
) from e
import warnings
warnings.warn(
"MCP tools detected with mcp_session_config. Tools will be wrapped "
"with stateful session management. For more control, consider using "
"StatefulMCPAgentExecutor from langchain.agents.mcp_utils directly.",
UserWarning,
stacklevel=2
)
# Note: The actual session creation and tool wrapping would typically
# happen at runtime when the agent is invoked, not during graph creation.
# This is because MCP sessions are stateful and should be created
# when needed, not during configuration.
# Store the config for later use by the agent
# The agent will use this to create a session when needed
mcp_session_cleanup = mcp_session_config.get("auto_cleanup", True)
# Convert response format and setup structured output tools
# Raw schemas are wrapped in AutoStrategy to preserve auto-detection intent.
@@ -1767,3 +1752,4 @@ __all__ = [