{"record":{"id":"dc3dc4d9459beb19","repo":"iflytek/astron-agent","slug":"toolname-cannot-be-empty","errorCode":null,"errorMessage":"toolName cannot be empty","messagePattern":"toolName cannot be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"core/workflow/engine/nodes/mcp/mcp_node.py","lineNumber":42,"sourceCode":"    \"\"\"\n    MCP (Model Context Protocol) execution node for workflow execution.\n\n    This node enables calling MCP tools from external MCP servers within workflows,\n    supporting dynamic tool execution with configurable parameters and server endpoints.\n    \"\"\"\n\n    _private_config = PrivateConfig()\n    mcpServerId: str = Field(default=\"\", description=\"MCP server unique identifier\")\n    mcpServerUrl: str = Field(default=\"\", description=\"MCP server endpoint URL\")\n    toolName: str = Field(..., description=\"Name of the MCP tool to execute\")\n\n    @model_validator(mode=\"after\")\n    def validate_fields(self) -> \"MCPNode\":\n        \"\"\"Validate field constraints.\"\"\"\n        if not self.mcpServerId and not self.mcpServerUrl:\n            raise ValueError(\"mcpServerId and mcpServerUrl cannot both be empty\")\n        if not self.toolName:\n            raise ValueError(\"toolName cannot be empty\")\n        return self\n\n    async def execute(\n        self,\n        variable_pool: VariablePool,\n        span: Span,\n        event_log_node_trace: NodeLog | None = None,\n    ) -> NodeRunResult:\n        \"\"\"\n        Execute the MCP tool call operation.\n\n        Retrieves input variables, constructs the MCP tool call request,\n        sends it to the MCP server, and returns the results.\n\n        :param variable_pool: Pool containing workflow variables\n        :param span: Span object for tracing and logging\n        :param event_log_node_trace: Optional node log trace object\n        :return: NodeRunResult containing the tool execution results or error information","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/workflow/engine/nodes/mcp/mcp_node.py#L24-L60","documentation":"McpNode's model_validator (validate_fields) rejects construction when toolName is empty — a Pydantic declarative guard on the node config. A workflow MCP node without a tool name could never dispatch an execution, so it fails at model validation instead.","triggerScenarios":"An MCP node is defined with a valid server (mcpServerId or mcpServerUrl) but toolName is '' or missing, e.g. the user never picked a tool in the node editor.","commonSituations":"Tool list failed to load in the UI so no tool was selected; workflow JSON imported without the toolName field; server's tools changed and the previous selection was cleared.","solutions":["Set toolName to the exact MCP tool name exposed by the server (e.g. 'web_search')","In the workflow editor, open the MCP node and select a tool from the server's tool list","Verify the chosen MCP server actually exposes the tool name referenced"],"exampleFix":"// before\n{\"mcpServerId\": \"srv-123\", \"toolName\": \"\"}\n// after\n{\"mcpServerId\": \"srv-123\", \"toolName\": \"web_search\"}","handlingStrategy":"validation","validationCode":"if not node_config.get(\"toolName\"):\n    raise ValueError(\"toolName is required for MCP nodes\")","typeGuard":"def has_tool_name(cfg: dict) -> bool:\n    return bool(isinstance(cfg.get(\"toolName\"), str) and cfg[\"toolName\"].strip())","tryCatchPattern":"from pydantic import ValidationError\ntry:\n    node = MCPNode(**node_config)\nexcept ValidationError as e:\n    # surface 'toolName cannot be empty' to the workflow editor\n    ...","preventionTips":["Require tool selection in the MCP node UI before the workflow can be saved","Re-validate toolName against the server's tool list when the server changes","Check imported workflow JSON for missing toolName fields"],"tags":["python","pydantic","validation","workflow"],"backgroundTag":"empty-required-field","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}