Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion backend/app/component/environment.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from app.utils import traceroot_wrapper as traceroot
import importlib.util
import os
from pathlib import Path
Expand All @@ -7,6 +8,8 @@
from typing import Any, overload
import threading

traceroot_logger = traceroot.get_logger("env")

# Thread-local storage for user-specific environment
_thread_local = threading.local()

Expand Down Expand Up @@ -70,13 +73,15 @@ def env(key: str, default=None):
def env_or_fail(key: str):
value = env(key)
if value is None:
traceroot_logger.warning(f"[ENVIRONMENT] can't get env config value.")
raise Exception("can't get env config value.")
return value


@traceroot.trace()
def env_not_empty(key: str):
value = env(key)
if not value:
traceroot_logger.warning(f"[ENVIRONMENT] env config value can't be empty.")
raise Exception("env config value can't be empty.")
return value

Expand Down
34 changes: 28 additions & 6 deletions backend/app/utils/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -1377,9 +1377,14 @@ async def mcp_agent(options: Chat):
]
if len(options.installed_mcp["mcpServers"]) > 0:
try:
tools = [*tools, *await get_mcp_tools(options.installed_mcp)]
mcp_tools = await get_mcp_tools(options.installed_mcp)
traceroot_logger.info(f"Retrieved {len(mcp_tools)} MCP tools for task {options.task_id}")
if mcp_tools:
tool_names = [tool.get_function_name() if hasattr(tool, 'get_function_name') else str(tool) for tool in mcp_tools]
traceroot_logger.debug(f"MCP tools: {tool_names}")
tools = [*tools, *mcp_tools]
except Exception as e:
logger.debug(repr(e))
traceroot_logger.debug(repr(e))

task_lock = get_task_lock(options.task_id)
agent_id = str(uuid.uuid4())
Expand Down Expand Up @@ -1475,12 +1480,29 @@ async def get_mcp_tools(mcp_server: McpServers):
# Set global auth directory to persist authentication across tasks
if "MCP_REMOTE_CONFIG_DIR" not in server_config["env"]:
server_config["env"]["MCP_REMOTE_CONFIG_DIR"] = env("MCP_REMOTE_CONFIG_DIR", os.path.expanduser("~/.mcp-auth"))

mcp_toolkit = MCPToolkit(config_dict=config_dict, timeout=20)

try:
mcp_toolkit = MCPToolkit(config_dict=config_dict, timeout=180)
await mcp_toolkit.connect()

traceroot_logger.info(f"Successfully connected to MCP toolkit with {len(mcp_server['mcpServers'])} servers")
tools = mcp_toolkit.get_tools()
if tools:
tool_names = [tool.get_function_name() if hasattr(tool, 'get_function_name') else str(tool) for tool in tools]
traceroot_logger.debug(f"MCP tool names: {tool_names}")
return tools
except asyncio.CancelledError:
traceroot_logger.info("MCP connection cancelled during get_mcp_tools")
return []
except Exception as e:
logger.warning(f"Failed to connect MCP toolkit: {e!r}")
traceroot_logger.error(f"Failed to connect MCP toolkit: {e}", exc_info=True)
return mcp_toolkit.get_tools()
return []
finally:
# Ensure proper cleanup without causing scope issues
if mcp_toolkit is not None:
try:
# Don't explicitly close here as it may cause scope issues
# Let the toolkit handle its own cleanup
pass
except Exception as cleanup_error:
traceroot_logger.debug(f"MCP toolkit cleanup error: {cleanup_error}")
4 changes: 2 additions & 2 deletions backend/app/utils/toolkit/mcp_search_toolkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __init__(self, api_task_id: str, timeout: float | None = None):
page: f"keyword: {keyword}, size: {size}, page: {page}",
return_msg=lambda res: f"Search {len(res)} results: ",
)
async def search(
async def search_mcp_from_url(
self,
keyword: str,
size: int = 15,
Expand Down Expand Up @@ -56,4 +56,4 @@ async def search(
return data

def get_tools(self) -> List[FunctionTool]:
return [FunctionTool(self.search)]
return [FunctionTool(self.search_mcp_from_url)]