mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-08-10 17:05:57 +00:00
Resolve effective policy through inherited layers without letting empty upper configs shadow restrictions, and carry canonical tool identities through local and MCP execution. Enforce required policy hooks and parent delegation checks at runtime, keep installed connector capabilities configurable while disconnected, and remove complete blocked-tool examples from rendered prompts. Use the canonical tool prompts for concise catalog descriptions and add regressions for plugin activation, dotted local names, MCP calls, layered policies, and parallel subordinate paths.
8.8 KiB
8.8 KiB
mcp_handler.py DOX
Purpose
- Own the
mcp_handler.pyhelper module. - This module loads global and project-scoped MCP server configuration and exposes MCP tools to agents.
- Keep this file-level DOX profile synchronized with
mcp_handler.pybecause this directory is intentionally flat.
Ownership
mcp_handler.pyowns the runtime implementation.mcp_handler.py.dox.mdowns durable notes about responsibilities, contracts, side effects, and verification for that implementation.- Classes:
MCPTool(Tool)get_log_object(self) -> LogItemasync execute(self, **kwargs)async before_execution(self, **kwargs)async after_execution(self, response: Response, **kwargs)
MCPServerRemote(BaseModel)get_error(self) -> strget_log(self) -> strget_tools(self) -> List[dict[str, Any]]get_all_tools(self) -> List[dict[str, Any]]has_tool(self, tool_name: str) -> boolasync call_tool(self, tool_name: str, input_data: Dict[str, Any]) -> CallToolResultupdate(self, config: dict[str, Any]) -> 'MCPServerRemote'async initialize(self) -> 'MCPServerRemote'
MCPServerLocal(BaseModel)get_error(self) -> strget_log(self) -> strget_tools(self) -> List[dict[str, Any]]get_all_tools(self) -> List[dict[str, Any]]has_tool(self, tool_name: str) -> boolasync call_tool(self, tool_name: str, input_data: Dict[str, Any]) -> CallToolResultupdate(self, config: dict[str, Any]) -> 'MCPServerLocal'async initialize(self) -> 'MCPServerLocal'
MCPConfig(BaseModel)get_instance(cls) -> 'MCPConfig'clear_project_instances(cls)parse_config_string(cls, config_str: str) -> List[Dict[str, Any]]merge_config_strings(cls, global_config: str, project_config: str) -> tuple[List[Dict[str, Any]], str]get_project_instance(cls, project_name: str | None, *, force: bool = False) -> 'MCPConfig'refresh_project(cls, project_name: str) -> 'MCPConfig'get_for_agent(cls, agent: Any) -> 'MCPConfig'wait_for_lock(cls)update(cls, config_str: str) -> Anynormalize_config(cls, servers: Any)get_server_log(self, server_name: str) -> strget_servers_status(self) -> list[dict[str, Any]]get_server_detail(self, server_name: str) -> dict[str, Any]is_initialized(self) -> bool
MCPClientBase(ABC)async update_tools(self) -> 'MCPClientBase'has_tool(self, tool_name: str) -> boolget_tools(self) -> List[dict[str, Any]]async call_tool(self, tool_name: str, input_data: Dict[str, Any]) -> CallToolResultget_log(self)
MCPClientLocal(MCPClientBase)CustomHTTPClientFactory(ABC)MCPClientRemote(MCPClientBase)get_session_id(self) -> Optional[str]
- Top-level functions:
_mcp_get(item: Any, key: str, default: Any=...) -> Anynormalize_name(name: str) -> str_determine_server_type(config_dict: dict) -> str: Determine the server type based on configuration, with backward compatibility._is_streaming_http_type(server_type: str) -> bool: Check if the server type is a streaming HTTP variant._split_qualified_tool_name(tool_name: str) -> tuple[str, str]: Splitserver.toolnames while preserving dots inside MCP tool names._normalize_disabled_tools(value: Any) -> list[str]: Normalize the optional per-server disabled tool list._split_stdio_command(command: Any) -> tuple[str, list[str]]: Split shell-style local MCP command lines into an executable plus leading arguments._split_stdio_arg_fragment(arg: str) -> list[str]: Split collapsed option/value argument fragments while preserving obvious single values with spaces._normalize_stdio_args(value: Any) -> list[str]: Normalize local MCP argument lists after manager/raw JSON parsing.initialize_mcp(mcp_servers_config: str)- Notable constants/configuration names:
DEFAULT_MCP_SERVERS_CONFIG,MCP_MEDIA_TOKENS_ESTIMATE,MAX_MCP_RESOURCE_TEXT_CHARS,MCP_SESSION_CLEANUP_TIMEOUT_SECONDS,MCP_OPERATION_TIMEOUT_GRACE_SECONDS,T.
Runtime Contracts
- Helper modules own reusable framework APIs and must preserve public callers unless all callers, tests, and docs are updated together.
- Update this file whenever public functions, classes, persistence behavior, path/security assumptions, side effects, or cross-module contracts change.
MCPToolis aTool.MCPTooldefinesexecute(...).- Global MCP configuration remains backed by settings; project MCP configuration is loaded through
helpers.projectsand merged with global config when an active agent context hascontext.project. - Project-scoped MCP servers overlay global servers by normalized name. The resulting
MCPConfigcache key is derived from both config strings so project instances refresh when either scope changes. - Server status and detail responses include
scope, and MCP tools resolve throughMCPConfig.get_for_agent(agent)before execution. - MCP tool names are qualified as
server_name.tool_name; server names are normalized without dots, and the tool portion may contain dots. - Agent-facing MCP prompt descriptions filter through the central profile tool
policy, and
MCPTool.execute()rechecks the same policy with the explicit MCP canonical ID before invocation. MCPConfig.get_tool()tries the supplied qualified name first, then restores an advertised Responses alias from the calling agent's name map; names that still do not identify an MCP tool returnNoneunchanged for downstream local-tool resolution.- Servers may define
disabled_toolsas a list of MCP tool names. Disabled tools are omitted from agent-facing prompts, status counts,has_tool, and calls, while detail views can still retrieve them throughget_all_tools()with adisabledflag so users can re-enable them. - Server-specific
init_timeoutandtool_timeoutoverride global MCP client timeout settings for list-tools and call-tool operations. - Local stdio server configs accept either strict MCP JSON (
command: "uvx", args: [...]) or manager-style command lines (command: "uvx package") and normalize them before spawning the process. - MCP image and image-resource content is materialized to scoped artifact files and returned both as model-visible image attachments and as path metadata (
attachments/media_paths) for downstream delivery. - MCP config locks must not be held across awaited server initialization or tool-call operations. Slow or wedged MCP servers must not block status reads, prompt construction, unrelated MCP servers, or later tool calls through the shared config lock.
- MCP client session work runs inside disposable isolated
DeferredTaskworkers with an outer timeout. NormalAsyncExitStackcleanup is also bounded; if cleanup or transport shutdown does not finish, the operation reports failure or warning while Agent Zero keeps control of the agent loop. - Server status marks initialized server objects with cached initialization errors as disconnected, even if the config object exists.
- Observed side-effect areas: filesystem writes, network calls, WebSocket state, settings/state persistence, secret handling.
- Imported dependency areas include:
abc,anyio.streams.memory,asyncio,contextlib,datetime,helpers,helpers.defer,helpers.log,helpers.print_style,helpers.tool,httpx,json,mcp,mcp.client.sse,mcp.client.stdio,mcp.client.streamable_http,mcp.shared.message,shlex.
Key Concepts
- Important called helpers/classes observed in the source:
TypeVar,name.strip.lower,re.sub,Field,PrivateAttr,threading.Lock,DeferredTask,_split_qualified_tool_name,config_dict.lower,server_type.lower,MCPConfig.get_instance.is_initialized,MCPConfig.get_for_agent,projects.validate_project_name,projects.load_project_mcp_servers,settings.get_settings,self.agent.context.log.log,str.strip,media_artifacts.guess_extension,callable,self._content_item_dump,join,Response,self.get_log_object,self._raw_tool_response,additional.pop,self._coerce_media_token_estimate. - Keep request/response, tool, or helper semantics documented here at the same time as source changes.
Work Guidance
- Preserve public helper APIs used by core code and plugins unless every caller is updated.
- Keep path, auth, secret, persistence, network, and subprocess behavior explicit and bounded.
- Prefer adding cohesive helper functions here only when behavior is reused across modules.
- Keep MCP timeout and cleanup changes covered by deterministic tests that do not require real MCP servers or network credentials.
Verification
- Run targeted tests for changed helper behavior; run security regressions for auth, filesystem, WebSocket, tunnel, upload, or secret-handling helpers.
- Related tests observed by source search:
tests/test_mcp_handler_multimodal.pytests/test_tool_policy.py
Child DOX Index
No child DOX files.