iflytek/astron-agent · error · ValueError

mcpServerId and mcpServerUrl cannot both be empty

Error message

mcpServerId and mcpServerUrl cannot both be empty

What it means

MCPNode's pydantic model_validator (mode='after') enforces that at least one of mcpServerId or mcpServerUrl is provided, since the node needs a way to locate the MCP server. If both are empty, ValueError is raised during model construction, failing node validation.

Solutions

  1. Set mcpServerId to the registered MCP server's ID
  2. Or set mcpServerUrl to the MCP server's direct URL (when bypassing the registry)
  3. Re-open the node in the workflow editor and select the MCP server, then re-save the workflow

Example fix

// before
{"type": "mcp", "mcpServerId": "", "mcpServerUrl": "", "toolName": "search"}
// after
{"type": "mcp", "mcpServerId": "srv-123", "mcpServerUrl": "", "toolName": "search"}
Defensive patterns

Strategy: validation

Validate before calling

cfg = node_config.get("mcp", {})
if not cfg.get("mcpServerId") and not cfg.get("mcpServerUrl"):
    raise ValueError("Provide either mcpServerId or mcpServerUrl for the MCP node")

Type guard

def has_mcp_target(cfg: dict) -> bool:
    return bool(cfg.get("mcpServerId") or cfg.get("mcpServerUrl"))

Try / catch

from pydantic import ValidationError
try:
    node = MCPNode(**node_config)
except ValidationError as e:
    # inspect e.errors() for the validate_fields failure
    ...

Prevention

When it happens

Trigger: Creating/instantiating an MCP node from workflow config where neither mcpServerId nor mcpServerUrl is set — e.g. an MCP node dragged into the flow but no server chosen.

Common situations: Workflow JSON hand-edited or imported with the server fields blank; UI failed to persist the selected MCP server; a copied node lost its server binding.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/05433067ea1d7498. Report an issue: GitHub.

Appendix: source

Thrown at core/workflow/engine/nodes/mcp/mcp_node.py:40

class MCPNode(BaseNode):
    """
    MCP (Model Context Protocol) execution node for workflow execution.

    This node enables calling MCP tools from external MCP servers within workflows,
    supporting dynamic tool execution with configurable parameters and server endpoints.
    """

    _private_config = PrivateConfig()
    mcpServerId: str = Field(default="", description="MCP server unique identifier")
    mcpServerUrl: str = Field(default="", description="MCP server endpoint URL")
    toolName: str = Field(..., description="Name of the MCP tool to execute")

    @model_validator(mode="after")
    def validate_fields(self) -> "MCPNode":
        """Validate field constraints."""
        if not self.mcpServerId and not self.mcpServerUrl:
            raise ValueError("mcpServerId and mcpServerUrl cannot both be empty")
        if not self.toolName:
            raise ValueError("toolName cannot be empty")
        return self

    async def execute(
        self,
        variable_pool: VariablePool,
        span: Span,
        event_log_node_trace: NodeLog | None = None,
    ) -> NodeRunResult:
        """
        Execute the MCP tool call operation.

        Retrieves input variables, constructs the MCP tool call request,
        sends it to the MCP server, and returns the results.

        :param variable_pool: Pool containing workflow variables
        :param span: Span object for tracing and logging

View on GitHub (pinned to 5e758547a8)