Add transport handling for trailing slashes

This commit is contained in:
Jeremiah Lowin 2025-06-20 13:12:23 -04:00
commit fbe2fc3533
2 changed files with 17 additions and 2 deletions

View file

@ -9,6 +9,7 @@ import warnings
from collections.abc import AsyncIterator, Callable
from pathlib import Path
from typing import Any, Literal, TypedDict, TypeVar, cast, overload
from urllib.parse import urlparse, urlunparse
import anyio
import httpx
@ -159,6 +160,13 @@ class SSETransport(ClientTransport):
url = str(url)
if not isinstance(url, str) or not url.startswith("http"):
raise ValueError("Invalid HTTP/S URL provided for SSE.")
# Ensure the URL path ends with a trailing slash to avoid automatic redirects
parsed = urlparse(url)
if not parsed.path.endswith("/"):
parsed = parsed._replace(path=parsed.path + "/")
url = urlunparse(parsed)
self.url = url
self.headers = headers or {}
self._set_auth(auth)
@ -227,6 +235,13 @@ class StreamableHttpTransport(ClientTransport):
url = str(url)
if not isinstance(url, str) or not url.startswith("http"):
raise ValueError("Invalid HTTP/S URL provided for Streamable HTTP.")
# Ensure the URL path ends with a trailing slash to avoid automatic redirects
parsed = urlparse(url)
if not parsed.path.endswith("/"):
parsed = parsed._replace(path=parsed.path + "/")
url = urlunparse(parsed)
self.url = url
self.headers = headers or {}
self._set_auth(auth)

View file

@ -39,7 +39,7 @@ def test_parse_single_remote_config():
mcp_config = MCPConfig.from_dict(config)
transport = mcp_config.mcpServers["test_server"].to_transport()
assert isinstance(transport, StreamableHttpTransport)
assert transport.url == "http://localhost:8000"
assert transport.url == "http://localhost:8000/"
def test_parse_remote_config_with_transport():
@ -54,7 +54,7 @@ def test_parse_remote_config_with_transport():
mcp_config = MCPConfig.from_dict(config)
transport = mcp_config.mcpServers["test_server"].to_transport()
assert isinstance(transport, SSETransport)
assert transport.url == "http://localhost:8000"
assert transport.url == "http://localhost:8000/"
def test_parse_remote_config_with_url_inference():