fix serialization issue in streamablehttp mcp tools (#6721)

<!-- Thank you for your contribution! Please review
https://microsoft.github.io/autogen/docs/Contribute before opening a
pull request. -->

The current `StreamableHttpServerParams` has timedelta values that are
not JSON serializable (config.dump_component.model_dump_json()).
This make is unusable in UIs like AGS that expect configs to be
serializable to json,

```python
class StreamableHttpServerParams(BaseModel):
    """Parameters for connecting to an MCP server over Streamable HTTP."""

    type: Literal["StreamableHttpServerParams"] = "StreamableHttpServerParams"

    url: str  # The endpoint URL.
    headers: dict[str, Any] | None = None  # Optional headers to include in requests.
    timeout: timedelta = timedelta(seconds=30)  # HTTP timeout for regular operations.
    sse_read_timeout: timedelta = timedelta(seconds=60 * 5)  # Timeout for SSE read operations.
    terminate_on_close: bool = True
```

This PR uses float for time outs and casts it to timedelta as needed. 

```python
class StreamableHttpServerParams(BaseModel):
    """Parameters for connecting to an MCP server over Streamable HTTP."""

    type: Literal["StreamableHttpServerParams"] = "StreamableHttpServerParams"

    url: str  # The endpoint URL.
    headers: dict[str, Any] | None = None  # Optional headers to include in requests.
    timeout: float = 30.0  # HTTP timeout for regular operations in seconds.
    sse_read_timeout: float = 300.0  # Timeout for SSE read operations in seconds.
    terminate_on_close: bool = True
```

<!-- Please add a reviewer to the assignee section when you create a PR.
If you don't have the access to it, we will shortly find a reviewer and
assign them to your PR. -->

## Why are these changes needed?

<!-- Please give a short summary of the change and the problem this
solves. -->

## Related issue number

<!-- For example: "Closes #1234" -->

## Checks

- [ ] I've included any doc changes needed for
<https://microsoft.github.io/autogen/>. See
<https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to
build and test documentation locally.
- [ ] I've added tests (if relevant) corresponding to the changes
introduced in this PR.
- [ ] I've made sure all auto checks have passed.
This commit is contained in:
Victor Dibia 2025-06-25 12:28:09 -07:00 committed by GitHub
parent 9b8dc8d707
commit 1183962a59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 11 additions and 8 deletions

View File

@ -1,4 +1,3 @@
from datetime import timedelta
from typing import Any, Literal
from mcp import StdioServerParameters
@ -32,8 +31,8 @@ class StreamableHttpServerParams(BaseModel):
url: str # The endpoint URL.
headers: dict[str, Any] | None = None # Optional headers to include in requests.
timeout: timedelta = timedelta(seconds=30) # HTTP timeout for regular operations.
sse_read_timeout: timedelta = timedelta(seconds=60 * 5) # Timeout for SSE read operations.
timeout: float = 30.0 # HTTP timeout for regular operations in seconds.
sse_read_timeout: float = 300.0 # Timeout for SSE read operations in seconds.
terminate_on_close: bool = True

View File

@ -32,7 +32,12 @@ async def create_mcp_server_session(
) as session:
yield session
elif isinstance(server_params, StreamableHttpServerParams):
async with streamablehttp_client(**server_params.model_dump(exclude={"type"})) as (
# Convert float seconds to timedelta for the streamablehttp_client
params_dict = server_params.model_dump(exclude={"type"})
params_dict["timeout"] = timedelta(seconds=server_params.timeout)
params_dict["sse_read_timeout"] = timedelta(seconds=server_params.sse_read_timeout)
async with streamablehttp_client(**params_dict) as (
read,
write,
session_id_callback, # type: ignore[assignment, unused-variable]
@ -41,6 +46,6 @@ async def create_mcp_server_session(
async with ClientSession(
read_stream=read,
write_stream=write,
read_timeout_seconds=server_params.sse_read_timeout,
read_timeout_seconds=timedelta(seconds=server_params.sse_read_timeout),
) as session:
yield session

View File

@ -49,7 +49,6 @@ class StreamableHttpMcpToolAdapter(
.. code-block:: python
import asyncio
from datetime import timedelta
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_ext.tools.mcp import StreamableHttpMcpToolAdapter, StreamableHttpServerParams
from autogen_agentchat.agents import AssistantAgent
@ -62,8 +61,8 @@ class StreamableHttpMcpToolAdapter(
server_params = StreamableHttpServerParams(
url="https://api.example.com/mcp",
headers={"Authorization": "Bearer your-api-key", "Content-Type": "application/json"},
timeout=timedelta(seconds=30),
sse_read_timeout=timedelta(seconds=60 * 5),
timeout=30.0, # HTTP timeout in seconds
sse_read_timeout=300.0, # SSE read timeout in seconds (5 minutes)
terminate_on_close=True,
)