mirror of
https://github.com/hwchase17/langchain.git
synced 2026-07-13 20:47:15 +00:00
Apply patch [skip ci]
This commit is contained in:
@@ -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__ = [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user