HKUDS/Vibe-Trading · error · ValueError

stdio MCP servers do not accept url/headers

Error message

stdio MCP servers do not accept url/headers

What it means

Raised by validate_transport_config when a stdio MCP server also defines a url or headers. stdio servers communicate over a child process pipe, so HTTP-style fields are contradictory and rejected to catch config mistakes early.

Source

Thrown at agent/src/config/schema.py:390

    @model_validator(mode="after")
    def validate_transport_config(self) -> "MCPServerConfig":
        """Validate transport-specific MCP server configuration.

        Returns:
            The validated MCP server config instance.

        Raises:
            ValueError: If required fields are missing for the resolved
                transport or conflicting fields are provided.
        """
        transport = self.resolved_transport()

        if transport == "stdio":
            if not self.command.strip():
                raise ValueError("stdio MCP servers require a command")
            if self.url.strip() or self.headers:
                raise ValueError("stdio MCP servers do not accept url/headers")
            if self.auth is not None:
                raise ValueError("stdio MCP servers do not accept auth (OAuth is HTTP-only)")
            return self

        if not self.url.strip():
            raise ValueError(f"{transport} MCP servers require a url")
        if self.command.strip() or self.args or self.env:
            raise ValueError(f"{transport} MCP servers do not accept command/args/env")

        if self.auth is not None:
            # The OAuth provider owns the runtime Authorization header; a
            # hand-set static header alongside it is always a config error.
            if self.headers:
                raise ValueError(
                    "MCP servers using auth must not also set static headers "
                    "(the OAuth provider owns the Authorization header)"
                )
            # A refresh token must never traverse cleartext.

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Remove url and headers from the stdio server entry.
  2. If you actually want the HTTP server, set type: sse or streamableHttp and remove command/args/env.

Example fix

# before
mcp_servers:
  mixed:
    command: npx
    url: https://mcp.example.com/sse

# after
mcp_servers:
  mixed:
    command: npx
    args: ["-y", "some-mcp-server"]
Defensive patterns

Strategy: validation

Validate before calling

STDIO_FORBIDDEN = {'url', 'headers', 'auth'}

def stdio_entry_clean(entry: dict) -> bool:
    if entry.get('type') == 'stdio' or entry.get('command'):
        return not any(entry.get(k) for k in STDIO_FORBIDDEN)
    return True

Prevention

When it happens

Trigger: An entry with command set (implying stdio) plus a url or headers field; leftover HTTP fields after converting a server from sse to stdio.

Common situations: Editing an existing HTTP server entry to run locally but forgetting to delete url/headers; merging configs where both halves survive.

Understand the failure class

Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/92d37da9104823b5. Report an issue: GitHub.