From f0ae9305f91aa18f5f71b1bd655c31031131be1a Mon Sep 17 00:00:00 2001 From: Federico Kamelhar Date: Fri, 17 Apr 2026 14:12:33 -0400 Subject: [PATCH 1/2] feat(mcp): add strands.mcp as canonical MCP import path Introduces a top-level strands.mcp package that re-exports the public API from strands.tools.mcp. Object identity is preserved, so users can migrate `from strands.tools.mcp import X` to `from strands.mcp import X` today with no behavior change. This is the first of two steps for #1431. A follow-up will move the implementation into strands.mcp and convert strands.tools.mcp into a deprecated alias. Refs #1431 --- src/strands/mcp/__init__.py | 17 +++++++++++++ tests/strands/mcp/__init__.py | 0 .../strands/mcp/test_canonical_import_path.py | 25 +++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 src/strands/mcp/__init__.py create mode 100644 tests/strands/mcp/__init__.py create mode 100644 tests/strands/mcp/test_canonical_import_path.py diff --git a/src/strands/mcp/__init__.py b/src/strands/mcp/__init__.py new file mode 100644 index 000000000..77daed8a5 --- /dev/null +++ b/src/strands/mcp/__init__.py @@ -0,0 +1,17 @@ +"""Canonical import path for the Model Context Protocol (MCP) integration. + +Model Context Protocol functionality is being promoted from +``strands.tools.mcp`` to this top-level ``strands.mcp`` package because MCP +now spans tools, prompts, resources, tasks, and elicitation -- concepts +that extend beyond ``tools``. + +For now this package is a thin re-export of ``strands.tools.mcp``. A +follow-up change will invert the relationship: the implementation will +live here and ``strands.tools.mcp`` will become a deprecated alias. +Users can safely migrate imports to ``strands.mcp`` today; the public +API is identical and object identity is preserved. +""" + +from ..tools.mcp import MCPAgentTool, MCPClient, MCPTransport, TasksConfig, ToolFilters + +__all__ = ["MCPAgentTool", "MCPClient", "MCPTransport", "TasksConfig", "ToolFilters"] diff --git a/tests/strands/mcp/__init__.py b/tests/strands/mcp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/strands/mcp/test_canonical_import_path.py b/tests/strands/mcp/test_canonical_import_path.py new file mode 100644 index 000000000..0194d3bee --- /dev/null +++ b/tests/strands/mcp/test_canonical_import_path.py @@ -0,0 +1,25 @@ +"""Tests for the canonical ``strands.mcp`` import path. + +The implementation currently lives in ``strands.tools.mcp``. This test +locks in the contract that ``strands.mcp`` re-exports the same objects so +that users can migrate imports ahead of the follow-up refactor that +moves the implementation. +""" + + +def test_strands_mcp_reexports_public_api() -> None: + import strands.mcp as new + import strands.tools.mcp as old + + assert new.MCPClient is old.MCPClient + assert new.MCPAgentTool is old.MCPAgentTool + assert new.MCPTransport is old.MCPTransport + assert new.TasksConfig is old.TasksConfig + assert new.ToolFilters is old.ToolFilters + + +def test_strands_mcp_all_matches_tools_mcp_all() -> None: + import strands.mcp as new + import strands.tools.mcp as old + + assert sorted(new.__all__) == sorted(old.__all__) From 2b141b5f9de2465952f00c60ba1a62a031e77b72 Mon Sep 17 00:00:00 2001 From: Federico Kamelhar Date: Fri, 17 Apr 2026 17:49:42 -0400 Subject: [PATCH 2/2] feat(mcp): move MCP implementation to strands.mcp, deprecate old path Moves the MCP implementation from strands.tools.mcp to strands.mcp using git-tracked renames. strands.tools.mcp becomes a deprecation alias: - Emits a DeprecationWarning on import pointing to strands.mcp. - Re-exports the public API (object identity preserved). - Registers legacy submodule paths (strands.tools.mcp.mcp_client, etc.) via sys.modules so ``from strands.tools.mcp.mcp_client import X`` continues to resolve to the canonical modules. Follow-up PR will move the tests into tests/strands/mcp, update integration tests, README, and AGENTS.md. Refs #1431 --- src/strands/mcp/__init__.py | 19 +++++------- src/strands/{tools => }/mcp/mcp_agent_tool.py | 4 +-- src/strands/{tools => }/mcp/mcp_client.py | 10 +++--- .../{tools => }/mcp/mcp_instrumentation.py | 0 src/strands/{tools => }/mcp/mcp_tasks.py | 0 src/strands/{tools => }/mcp/mcp_types.py | 2 +- src/strands/tools/mcp/__init__.py | 31 +++++++++++++------ 7 files changed, 38 insertions(+), 28 deletions(-) rename src/strands/{tools => }/mcp/mcp_agent_tool.py (97%) rename src/strands/{tools => }/mcp/mcp_client.py (99%) rename src/strands/{tools => }/mcp/mcp_instrumentation.py (100%) rename src/strands/{tools => }/mcp/mcp_tasks.py (100%) rename src/strands/{tools => }/mcp/mcp_types.py (98%) diff --git a/src/strands/mcp/__init__.py b/src/strands/mcp/__init__.py index 77daed8a5..8d2c1daa2 100644 --- a/src/strands/mcp/__init__.py +++ b/src/strands/mcp/__init__.py @@ -1,17 +1,14 @@ -"""Canonical import path for the Model Context Protocol (MCP) integration. +"""Model Context Protocol (MCP) integration. -Model Context Protocol functionality is being promoted from -``strands.tools.mcp`` to this top-level ``strands.mcp`` package because MCP -now spans tools, prompts, resources, tasks, and elicitation -- concepts -that extend beyond ``tools``. +This package provides integration with the Model Context Protocol (MCP), allowing agents to use tools provided by MCP +servers. -For now this package is a thin re-export of ``strands.tools.mcp``. A -follow-up change will invert the relationship: the implementation will -live here and ``strands.tools.mcp`` will become a deprecated alias. -Users can safely migrate imports to ``strands.mcp`` today; the public -API is identical and object identity is preserved. +- Docs: https://www.anthropic.com/news/model-context-protocol """ -from ..tools.mcp import MCPAgentTool, MCPClient, MCPTransport, TasksConfig, ToolFilters +from .mcp_agent_tool import MCPAgentTool +from .mcp_client import MCPClient, ToolFilters +from .mcp_tasks import TasksConfig +from .mcp_types import MCPTransport __all__ = ["MCPAgentTool", "MCPClient", "MCPTransport", "TasksConfig", "ToolFilters"] diff --git a/src/strands/tools/mcp/mcp_agent_tool.py b/src/strands/mcp/mcp_agent_tool.py similarity index 97% rename from src/strands/tools/mcp/mcp_agent_tool.py rename to src/strands/mcp/mcp_agent_tool.py index bedd93f24..5ae4d2c9e 100644 --- a/src/strands/tools/mcp/mcp_agent_tool.py +++ b/src/strands/mcp/mcp_agent_tool.py @@ -12,8 +12,8 @@ from mcp.types import Tool as MCPTool from typing_extensions import override -from ...types._events import ToolResultEvent -from ...types.tools import AgentTool, ToolGenerator, ToolSpec, ToolUse +from ..types._events import ToolResultEvent +from ..types.tools import AgentTool, ToolGenerator, ToolSpec, ToolUse if TYPE_CHECKING: from .mcp_client import MCPClient diff --git a/src/strands/tools/mcp/mcp_client.py b/src/strands/mcp/mcp_client.py similarity index 99% rename from src/strands/tools/mcp/mcp_client.py rename to src/strands/mcp/mcp_client.py index 2ac632925..1665f5bf5 100644 --- a/src/strands/tools/mcp/mcp_client.py +++ b/src/strands/mcp/mcp_client.py @@ -44,11 +44,11 @@ from pydantic import AnyUrl from typing_extensions import Protocol, TypedDict -from ...types import PaginatedList -from ...types.exceptions import MCPClientInitializationError, ToolProviderException -from ...types.media import ImageFormat -from ...types.tools import AgentTool, ToolResultContent, ToolResultStatus -from ..tool_provider import ToolProvider +from ..tools.tool_provider import ToolProvider +from ..types import PaginatedList +from ..types.exceptions import MCPClientInitializationError, ToolProviderException +from ..types.media import ImageFormat +from ..types.tools import AgentTool, ToolResultContent, ToolResultStatus from .mcp_agent_tool import MCPAgentTool from .mcp_instrumentation import mcp_instrumentation from .mcp_tasks import DEFAULT_TASK_CONFIG, DEFAULT_TASK_POLL_TIMEOUT, DEFAULT_TASK_TTL, TasksConfig diff --git a/src/strands/tools/mcp/mcp_instrumentation.py b/src/strands/mcp/mcp_instrumentation.py similarity index 100% rename from src/strands/tools/mcp/mcp_instrumentation.py rename to src/strands/mcp/mcp_instrumentation.py diff --git a/src/strands/tools/mcp/mcp_tasks.py b/src/strands/mcp/mcp_tasks.py similarity index 100% rename from src/strands/tools/mcp/mcp_tasks.py rename to src/strands/mcp/mcp_tasks.py diff --git a/src/strands/tools/mcp/mcp_types.py b/src/strands/mcp/mcp_types.py similarity index 98% rename from src/strands/tools/mcp/mcp_types.py rename to src/strands/mcp/mcp_types.py index 09feb624f..e80ef2fd4 100644 --- a/src/strands/tools/mcp/mcp_types.py +++ b/src/strands/mcp/mcp_types.py @@ -9,7 +9,7 @@ from mcp.shared.message import SessionMessage from typing_extensions import NotRequired -from ...types.tools import ToolResult +from ..types.tools import ToolResult """ MCPTransport defines the interface for MCP transport implementations. This abstracts diff --git a/src/strands/tools/mcp/__init__.py b/src/strands/tools/mcp/__init__.py index 8d2c1daa2..0edd82125 100644 --- a/src/strands/tools/mcp/__init__.py +++ b/src/strands/tools/mcp/__init__.py @@ -1,14 +1,27 @@ -"""Model Context Protocol (MCP) integration. +"""Deprecated: MCP integration has moved to ``strands.mcp``. -This package provides integration with the Model Context Protocol (MCP), allowing agents to use tools provided by MCP -servers. - -- Docs: https://www.anthropic.com/news/model-context-protocol +This module re-exports the public API from its new location and emits a +``DeprecationWarning`` at import time. Legacy submodule paths such as +``strands.tools.mcp.mcp_client`` continue to resolve to the canonical +modules under ``strands.mcp`` via ``sys.modules`` aliasing. Update +imports to ``strands.mcp``; this alias will be removed in a future +release. """ -from .mcp_agent_tool import MCPAgentTool -from .mcp_client import MCPClient, ToolFilters -from .mcp_tasks import TasksConfig -from .mcp_types import MCPTransport +import sys as _sys +import warnings as _warnings + +from strands import mcp as _mcp +from strands.mcp import MCPAgentTool, MCPClient, MCPTransport, TasksConfig, ToolFilters + +for _submod_name in ("mcp_agent_tool", "mcp_client", "mcp_instrumentation", "mcp_tasks", "mcp_types"): + _sys.modules[f"strands.tools.mcp.{_submod_name}"] = getattr(_mcp, _submod_name) + +_warnings.warn( + "strands.tools.mcp has moved to strands.mcp. " + "Import from strands.mcp instead; strands.tools.mcp will be removed in a future release.", + DeprecationWarning, + stacklevel=2, +) __all__ = ["MCPAgentTool", "MCPClient", "MCPTransport", "TasksConfig", "ToolFilters"]