Bug: MCP transport autodetection treats uppercase URL schemes as stdio

Author: yifanxiong272Created Sep 1, 2026Updated Sep 1, 2026

Describe the bug

MCPClientManager.convert_configs_to_langchain_format performs case-sensitive URL-prefix checks when automatically selecting the transport for a remote MCP server.

URI scheme names are case-insensitive. However, remote URLs using uppercase or mixed-case schemes are not recognized.

For example, this configuration:

python
{
    "name": "remote",
    "connection_url": (
        "HTTPS://mcp.example.com/service"
    ),
    "connection_headers": {
        "Authorization": "Bearer test-token",
    },
}

is converted into:

python
{
    "transport": "stdio",
}

instead of:

python
{
    "transport": "streamable_http",
    "url": "HTTPS://mcp.example.com/service",
    "headers": {
        "Authorization": "Bearer test-token",
    },
}

The same behavior affects uppercase HTTP, WS, and WSS schemes.

The remote configuration is therefore reclassified as a local stdio configuration, and both its URL and connection headers are omitted.

To Reproduce

  1. Check out GPT Researcher main at commit:
6f998577d547b1e54ec662dac63583aa11e3b84b
  1. Install the project and test dependencies:
bash
python -m pip install -e ".[test]"
  1. Create tests/test_mcp_client_uppercase_url_schemes.py:
python
import pytest

from gpt_researcher.mcp.client import MCPClientManager


@pytest.mark.parametrize(
    ("url", "transport"),
    [
        (
            "HTTPS://mcp.example.com/service",
            "streamable_http",
        ),
        (
            "HTTP://mcp.example.com/service",
            "streamable_http",
        ),
        (
            "WSS://mcp.example.com/service",
            "websocket",
        ),
        (
            "WS://mcp.example.com/service",
            "websocket",
        ),
    ],
)
def test_uppercase_url_scheme_selects_remote_transport(
    url,
    transport,
):
    headers = {
        "Authorization": "Bearer test-token",
    }

    result = MCPClientManager(
        [
            {
                "name": "remote",
                "connection_url": url,
                "connection_headers": headers,
            }
        ]
    ).convert_configs_to_langchain_format()

    assert result["remote"] == {
        "transport": transport,
        "url": url,
        "headers": headers,
    }
  1. Run:
bash
python -m pytest \
  tests/test_mcp_client_uppercase_url_schemes.py \
  -q
  1. Observe that all four parameterized cases fail.

Representative failure:

Expected:
{
    "transport": "streamable_http",
    "url": "HTTPS://mcp.example.com/service",
    "headers": {
        "Authorization": "Bearer test-token",
    },
}

Received:
{
    "transport": "stdio",
}

Test summary:

4 failed

Expected behavior

Transport autodetection should treat URI scheme names case-insensitively.

The following schemes should select the HTTP transport:

http
HTTP
https
HTTPS

The following schemes should select the WebSocket transport:

ws
WS
wss
WSS

Mixed-case equivalents should behave the same way.

The original connection_url should remain available in the converted configuration, and valid connection_headers should be forwarded.

This follows the URI scheme requirement in RFC 3986 section 3.1:

https://www.rfc-editor.org/rfc/rfc3986.html#section-3.1

Actual behavior

The implementation recognizes only lowercase scheme prefixes.

Each uppercase URL in the reproduction is converted to:

python
{
    "transport": "stdio",
}

The converted configuration omits both:

url
headers

The resulting configuration no longer identifies the remote MCP endpoint.

Screenshots

Not applicable. This is a deterministic configuration-conversion reproduction without a browser, model, provider request, or live MCP server.

Desktop (please complete the following information):

  • OS: macOS 15.7.3, arm64
  • Browser: Not applicable
  • GPT Researcher version: 0.14.7
  • Revision: main@6f998577d547b1e54ec662dac63583aa11e3b84b
  • Python: 3.12.13
  • Installation: Source checkout

Smartphone (please complete the following information):

Not applicable.

Additional context

Transport selection currently uses case-sensitive prefix comparisons:

python
connection_url = config.get(
    "connection_url"
)

if connection_url:
    if connection_url.startswith(
        ("wss://", "ws://")
    ):
        server_config["transport"] = (
            "websocket"
        )
        server_config["url"] = connection_url
    elif connection_url.startswith(
        ("https://", "http://")
    ):
        server_config["transport"] = (
            "streamable_http"
        )
        server_config["url"] = connection_url
    else:
        connection_type = config.get(
            "connection_type",
            "stdio",
        )
        server_config["transport"] = (
            connection_type
        )

For an uppercase scheme such as:

HTTPS://mcp.example.com/service

neither recognized prefix matches. Since no explicit connection_type is present, the fallback assigns:

python
"transport": "stdio"

The URL is not added because the fallback only preserves it for an explicitly selected remote transport:

python
if connection_type in [
    "websocket",
    "streamable_http",
    "http",
]:
    server_config["url"] = connection_url

Connection headers are subsequently forwarded only when the selected transport is remote:

python
if server_config.get("transport") in [
    "streamable_http",
    "http",
    "websocket",
]:
    connection_headers = config.get(
        "connection_headers"
    )
    if (
        connection_headers
        and isinstance(
            connection_headers,
            dict,
        )
    ):
        server_config["headers"] = (
            connection_headers
        )

Because the uppercase URL was misclassified as stdio, the headers branch is also skipped.

A possible fix is to parse and normalize only the scheme while preserving the original URL:

python
from urllib.parse import urlsplit


connection_url = config.get(
    "connection_url"
)

if connection_url:
    scheme = urlsplit(
        connection_url
    ).scheme.lower()

    if scheme in {"ws", "wss"}:
        server_config["transport"] = (
            "websocket"
        )
        server_config["url"] = connection_url
    elif scheme in {"http", "https"}:
        server_config["transport"] = (
            "streamable_http"
        )
        server_config["url"] = connection_url

Regression coverage should include:

  • lowercase http, https, ws, and wss;
  • uppercase versions of all four schemes;
  • mixed-case scheme names;
  • preservation of the original URL;
  • preservation of connection headers;
  • explicit remote connection_type fallback;
  • unknown URL schemes;
  • local stdio configurations without a URL.

Targeted issue and pull-request searches found no existing report for this case-sensitive transport-autodetection root.

Source: assafelovic/gpt-researcher