HKUDS/Vibe-Trading · error · ValueError

stdio MCP servers do not accept auth (OAuth is HTTP-only)

Error message

stdio MCP servers do not accept auth (OAuth is HTTP-only)

What it means

Raised by validate_transport_config when a stdio MCP server carries an auth (OAuth) block. OAuth is HTTP-only in this schema: stdio child processes have no HTTP layer for token exchange, so auth on stdio is always a config error.

Solutions

  1. Delete the auth block from the stdio server entry.
  2. If OAuth is required, configure the server as HTTP (type: sse or streamableHttp) with an https url and the auth block.

Example fix

# before
mcp_servers:
  local:
    command: ./server
    auth:
      client_id: abc

# after
mcp_servers:
  local:
    command: ./server
Defensive patterns

Strategy: validation

Validate before calling

def stdio_without_auth(entry: dict) -> bool:
    if entry.get('type') == 'stdio' or entry.get('command'):
        return entry.get('auth') is None
    return True

Prevention

When it happens

Trigger: An entry with command set plus an auth: {client_id, refresh_token, ...} block, typically copied from an OAuth HTTP broker server config.

Common situations: Copying a live-broker OAuth server template into a stdio wrapper entry; assuming auth applies globally rather than per-transport.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

    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.
            if not self.url.strip().lower().startswith("https://"):
                raise ValueError("OAuth MCP servers require an https url")

View on GitHub (pinned to 80ffdda44c)