mirror of
https://github.com/microsoft/autogen.git
synced 2025-12-25 14:09:00 +00:00
Upgrade_mcp_version (#6814)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
This commit is contained in:
parent
ca39adc358
commit
d094a3fd47
@ -150,7 +150,7 @@ semantic-kernel-all = [
|
||||
|
||||
rich = ["rich>=13.9.4"]
|
||||
|
||||
mcp = ["mcp>=1.8.1"]
|
||||
mcp = ["mcp>=1.11.0"]
|
||||
canvas = [
|
||||
"unidiff>=0.7.5",
|
||||
]
|
||||
|
||||
@ -2,7 +2,7 @@ import asyncio
|
||||
import builtins
|
||||
import json
|
||||
from abc import ABC
|
||||
from typing import Any, Dict, Generic, Type, TypeVar
|
||||
from typing import Any, Dict, Generic, Sequence, Type, TypeVar
|
||||
|
||||
from autogen_core import CancellationToken
|
||||
from autogen_core.tools import BaseTool
|
||||
@ -11,7 +11,7 @@ from pydantic import BaseModel
|
||||
from pydantic.networks import AnyUrl
|
||||
|
||||
from mcp import ClientSession, Tool
|
||||
from mcp.types import EmbeddedResource, ImageContent, TextContent
|
||||
from mcp.types import AudioContent, ContentBlock, EmbeddedResource, ImageContent, ResourceLink, TextContent
|
||||
|
||||
from ._config import McpServerParams
|
||||
from ._session import create_mcp_server_session
|
||||
@ -75,21 +75,20 @@ class McpToolAdapter(BaseTool[BaseModel, Any], ABC, Generic[TServerParams]):
|
||||
await session.initialize()
|
||||
return await self._run(args=kwargs, cancellation_token=cancellation_token, session=session)
|
||||
|
||||
def _normalize_payload_to_content_list(
|
||||
self, payload: list[TextContent | ImageContent | EmbeddedResource]
|
||||
) -> list[TextContent | ImageContent | EmbeddedResource]:
|
||||
def _normalize_payload_to_content_list(self, payload: Sequence[ContentBlock]) -> list[ContentBlock]:
|
||||
"""
|
||||
Normalizes a raw tool output payload into a list of content items.
|
||||
- If payload is already a list of (TextContent, ImageContent, EmbeddedResource), it's returned as is.
|
||||
- If payload is a single TextContent, ImageContent, or EmbeddedResource, it's wrapped in a list.
|
||||
- If payload is already a sequence of ContentBlock items, it's converted to a list and returned.
|
||||
- If payload is a single ContentBlock item, it's wrapped in a list.
|
||||
- If payload is a string, it's wrapped in [TextContent(text=payload)].
|
||||
- Otherwise, the payload is stringified and wrapped in [TextContent(text=str(payload))].
|
||||
"""
|
||||
if isinstance(payload, list) and all(
|
||||
isinstance(item, (TextContent, ImageContent, EmbeddedResource)) for item in payload
|
||||
if isinstance(payload, Sequence) and all(
|
||||
isinstance(item, (TextContent, ImageContent, EmbeddedResource, AudioContent, ResourceLink))
|
||||
for item in payload
|
||||
):
|
||||
return payload
|
||||
elif isinstance(payload, (TextContent, ImageContent, EmbeddedResource)):
|
||||
return list(payload)
|
||||
elif isinstance(payload, (TextContent, ImageContent, EmbeddedResource, AudioContent, ResourceLink)):
|
||||
return [payload]
|
||||
elif isinstance(payload, str):
|
||||
return [TextContent(text=payload, type="text")]
|
||||
@ -154,18 +153,37 @@ class McpToolAdapter(BaseTool[BaseModel, Any], ABC, Generic[TServerParams]):
|
||||
"""Return a string representation of the result."""
|
||||
|
||||
def serialize_item(item: Any) -> dict[str, Any]:
|
||||
if isinstance(item, (TextContent, ImageContent)):
|
||||
return item.model_dump()
|
||||
if isinstance(item, (TextContent, ImageContent, AudioContent)):
|
||||
dumped = item.model_dump()
|
||||
# Remove the 'meta' field if it exists and is None (for backward compatibility)
|
||||
if dumped.get("meta") is None:
|
||||
dumped.pop("meta", None)
|
||||
return dumped
|
||||
elif isinstance(item, EmbeddedResource):
|
||||
type = item.type
|
||||
resource = {}
|
||||
for key, val in item.resource.model_dump().items():
|
||||
# Skip 'meta' field if it's None (for backward compatibility)
|
||||
if key == "meta" and val is None:
|
||||
continue
|
||||
if isinstance(val, AnyUrl):
|
||||
resource[key] = str(val)
|
||||
else:
|
||||
resource[key] = val
|
||||
annotations = item.annotations.model_dump() if item.annotations else None
|
||||
return {"type": type, "resource": resource, "annotations": annotations}
|
||||
dumped_annotations = item.annotations.model_dump() if item.annotations else None
|
||||
# Remove 'meta' from annotations if it exists and is None
|
||||
if dumped_annotations and dumped_annotations.get("meta") is None:
|
||||
dumped_annotations.pop("meta", None)
|
||||
return {"type": type, "resource": resource, "annotations": dumped_annotations}
|
||||
elif isinstance(item, ResourceLink):
|
||||
dumped = item.model_dump()
|
||||
# Remove the 'meta' field if it exists and is None (for backward compatibility)
|
||||
if dumped.get("meta") is None:
|
||||
dumped.pop("meta", None)
|
||||
# Convert AnyUrl to string for JSON serialization
|
||||
if "uri" in dumped and isinstance(dumped["uri"], AnyUrl):
|
||||
dumped["uri"] = str(dumped["uri"])
|
||||
return dumped
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@ from mcp.types import (
|
||||
Annotations,
|
||||
EmbeddedResource,
|
||||
ImageContent,
|
||||
ResourceLink,
|
||||
TextContent,
|
||||
TextResourceContents,
|
||||
)
|
||||
@ -909,3 +910,21 @@ async def test_mcp_tool_adapter_run_cancelled_during_call(
|
||||
await adapter._run(args=args, cancellation_token=cancellation_token, session=mock_session) # type: ignore[reportPrivateUsage]
|
||||
|
||||
mock_session.call_tool.assert_called_once_with(name=sample_tool.name, arguments=args)
|
||||
|
||||
|
||||
def test_return_value_as_string_with_resource_link(sample_tool: Tool, sample_server_params: StdioServerParams) -> None:
|
||||
"""Test return_value_as_string handles ResourceLink objects correctly."""
|
||||
adapter = StdioMcpToolAdapter(server_params=sample_server_params, tool=sample_tool)
|
||||
|
||||
# Test ResourceLink with meta field
|
||||
resource_link = ResourceLink(
|
||||
name="test_link",
|
||||
type="resource_link",
|
||||
uri=AnyUrl(url="http://example.com"),
|
||||
)
|
||||
|
||||
result = adapter.return_value_as_string([resource_link])
|
||||
# Verify the JSON serialization contains expected fields
|
||||
assert '"type": "resource_link"' in result
|
||||
assert '"name": "test_link"' in result
|
||||
assert '"uri": "http://example.com/"' in result # AnyUrl normalizes with trailing slash
|
||||
|
||||
30
python/uv.lock
generated
30
python/uv.lock
generated
@ -768,7 +768,7 @@ requires-dist = [
|
||||
{ name = "markitdown", extras = ["all"], marker = "extra == 'file-surfer'", specifier = "~=0.1.0a3" },
|
||||
{ name = "markitdown", extras = ["all"], marker = "extra == 'magentic-one'", specifier = "~=0.1.0a3" },
|
||||
{ name = "markitdown", extras = ["all"], marker = "extra == 'web-surfer'", specifier = "~=0.1.0a3" },
|
||||
{ name = "mcp", marker = "extra == 'mcp'", specifier = ">=1.8.1" },
|
||||
{ name = "mcp", marker = "extra == 'mcp'", specifier = ">=1.11.0" },
|
||||
{ name = "mem0ai", marker = "extra == 'mem0'", specifier = ">=0.1.98" },
|
||||
{ name = "mem0ai", marker = "extra == 'mem0-local'", specifier = ">=0.1.98" },
|
||||
{ name = "nbclient", marker = "extra == 'jupyter-executor'", specifier = ">=0.10.2" },
|
||||
@ -4210,22 +4210,24 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "mcp"
|
||||
version = "1.9.3"
|
||||
version = "1.11.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
{ name = "httpx" },
|
||||
{ name = "httpx-sse" },
|
||||
{ name = "jsonschema" },
|
||||
{ name = "pydantic" },
|
||||
{ name = "pydantic-settings" },
|
||||
{ name = "python-multipart" },
|
||||
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
||||
{ name = "sse-starlette" },
|
||||
{ name = "starlette" },
|
||||
{ name = "uvicorn", marker = "sys_platform != 'emscripten'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f2/df/8fefc0c6c7a5c66914763e3ff3893f9a03435628f6625d5e3b0dc45d73db/mcp-1.9.3.tar.gz", hash = "sha256:587ba38448e81885e5d1b84055cfcc0ca56d35cd0c58f50941cab01109405388", size = 333045, upload-time = "2025-06-05T15:48:25.681Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3a/f5/9506eb5578d5bbe9819ee8ba3198d0ad0e2fbe3bab8b257e4131ceb7dfb6/mcp-1.11.0.tar.gz", hash = "sha256:49a213df56bb9472ff83b3132a4825f5c8f5b120a90246f08b0dac6bedac44c8", size = 406907, upload-time = "2025-07-10T16:41:09.388Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/79/45/823ad05504bea55cb0feb7470387f151252127ad5c72f8882e8fe6cf5c0e/mcp-1.9.3-py3-none-any.whl", hash = "sha256:69b0136d1ac9927402ed4cf221d4b8ff875e7132b0b06edd446448766f34f9b9", size = 131063, upload-time = "2025-06-05T15:48:24.171Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/9c/c9ca79f9c512e4113a5d07043013110bb3369fc7770040c61378c7fbcf70/mcp-1.11.0-py3-none-any.whl", hash = "sha256:58deac37f7483e4b338524b98bc949b7c2b7c33d978f5fafab5bde041c5e2595", size = 155880, upload-time = "2025-07-10T16:41:07.935Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6339,18 +6341,18 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pywin32"
|
||||
version = "308"
|
||||
version = "311"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/72/a6/3e9f2c474895c1bb61b11fa9640be00067b5c5b363c501ee9c3fa53aec01/pywin32-308-cp310-cp310-win32.whl", hash = "sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e", size = 5927028, upload-time = "2024-10-12T20:41:58.898Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/b4/84e2463422f869b4b718f79eb7530a4c1693e96b8a4e5e968de38be4d2ba/pywin32-308-cp310-cp310-win_amd64.whl", hash = "sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e", size = 6558484, upload-time = "2024-10-12T20:42:01.271Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/8f/fb84ab789713f7c6feacaa08dad3ec8105b88ade8d1c4f0f0dfcaaa017d6/pywin32-308-cp310-cp310-win_arm64.whl", hash = "sha256:a5ab5381813b40f264fa3495b98af850098f814a25a63589a8e9eb12560f450c", size = 7971454, upload-time = "2024-10-12T20:42:03.544Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/e2/02652007469263fe1466e98439831d65d4ca80ea1a2df29abecedf7e47b7/pywin32-308-cp311-cp311-win32.whl", hash = "sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a", size = 5928156, upload-time = "2024-10-12T20:42:05.78Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/ef/f4fb45e2196bc7ffe09cad0542d9aff66b0e33f6c0954b43e49c33cad7bd/pywin32-308-cp311-cp311-win_amd64.whl", hash = "sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b", size = 6559559, upload-time = "2024-10-12T20:42:07.644Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/ef/68bb6aa865c5c9b11a35771329e95917b5559845bd75b65549407f9fc6b4/pywin32-308-cp311-cp311-win_arm64.whl", hash = "sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6", size = 7972495, upload-time = "2024-10-12T20:42:09.803Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/7c/d00d6bdd96de4344e06c4afbf218bc86b54436a94c01c71a8701f613aa56/pywin32-308-cp312-cp312-win32.whl", hash = "sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897", size = 5939729, upload-time = "2024-10-12T20:42:12.001Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/27/0c8811fbc3ca188f93b5354e7c286eb91f80a53afa4e11007ef661afa746/pywin32-308-cp312-cp312-win_amd64.whl", hash = "sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47", size = 6543015, upload-time = "2024-10-12T20:42:14.044Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/0f/d40f8373608caed2255781a3ad9a51d03a594a1248cd632d6a298daca693/pywin32-308-cp312-cp312-win_arm64.whl", hash = "sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091", size = 7976033, upload-time = "2024-10-12T20:42:16.215Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/40/44efbb0dfbd33aca6a6483191dae0716070ed99e2ecb0c53683f400a0b4f/pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3", size = 8760432, upload-time = "2025-07-14T20:13:05.9Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/bf/360243b1e953bd254a82f12653974be395ba880e7ec23e3731d9f73921cc/pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b", size = 9590103, upload-time = "2025-07-14T20:13:07.698Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/38/d290720e6f138086fb3d5ffe0b6caa019a791dd57866940c82e4eeaf2012/pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b", size = 8778557, upload-time = "2025-07-14T20:13:11.11Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/af/449a6a91e5d6db51420875c54f6aff7c97a86a3b13a0b4f1a5c13b988de3/pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151", size = 8697031, upload-time = "2025-07-14T20:13:13.266Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503", size = 9508308, upload-time = "2025-07-14T20:13:15.147Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/7b/9c2ab54f74a138c491aba1b1cd0795ba61f144c711daea84a88b63dc0f6c/pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2", size = 8703930, upload-time = "2025-07-14T20:13:16.945Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/ab/01ea1943d4eba0f850c3c61e78e8dd59757ff815ff3ccd0a84de5f541f42/pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31", size = 8706543, upload-time = "2025-07-14T20:13:20.765Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/a8/a0e8d07d4d051ec7502cd58b291ec98dcc0c3fff027caad0470b72cfcc2f/pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067", size = 9495040, upload-time = "2025-07-14T20:13:22.543Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/3a/2ae996277b4b50f17d61f0603efd8253cb2d79cc7ae159468007b586396d/pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852", size = 8710102, upload-time = "2025-07-14T20:13:24.682Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user