"""Resources adapter for converting MCP resources to LangChain [Blob objects][langchain_core.documents.base.Blob]. This module provides functionality to convert MCP resources into LangChain Blob objects, handling both text and binary resource content types. """ # noqa: E501 import base64 from langchain_core.documents.base import Blob from mcp import ClientSession from mcp.types import BlobResourceContents, ResourceContents, TextResourceContents def convert_mcp_resource_to_langchain_blob( resource_uri: str, contents: ResourceContents ) -> Blob: """Convert an MCP resource content to a LangChain Blob. Args: resource_uri: URI of the resource contents: The resource contents Returns: A LangChain Blob """ if isinstance(contents, TextResourceContents): data = contents.text elif isinstance(contents, BlobResourceContents): data = base64.b64decode(contents.blob) else: msg = f"Unsupported content type for URI {resource_uri}" raise TypeError(msg) return Blob.from_data( data=data, mime_type=contents.mimeType, metadata={"uri": resource_uri} ) async def get_mcp_resource(session: ClientSession, uri: str) -> list[Blob]: """Fetch a single MCP resource and convert it to LangChain [Blob objects][langchain_core.documents.base.Blob]. Args: session: MCP client session. uri: URI of the resource to fetch. Returns: A list of LangChain [Blob][langchain_core.documents.base.Blob] objects. """ # noqa: E501 contents_result = await session.read_resource(uri) if not contents_result.contents or len(contents_result.contents) == 0: return [] return [ convert_mcp_resource_to_langchain_blob(uri, content) for content in contents_result.contents ] async def load_mcp_resources( session: ClientSession, *, uris: str | list[str] | None = None, ) -> list[Blob]: """Load MCP resources and convert them to LangChain [Blob objects][langchain_core.documents.base.Blob]. Args: session: MCP client session. uris: List of URIs to load. If `None`, all resources will be loaded. !!! note Dynamic resources will NOT be loaded when `None` is specified, as they require parameters and are ignored by the MCP SDK's `session.list_resources()` method. Returns: A list of LangChain [Blob][langchain_core.documents.base.Blob] objects. Raises: RuntimeError: If an error occurs while fetching a resource. """ # noqa: E501 blobs = [] if uris is None: resources_list = await session.list_resources() uri_list = [r.uri for r in resources_list.resources] elif isinstance(uris, str): uri_list = [uris] else: uri_list = uris current_uri = None try: for uri in uri_list: current_uri = uri resource_blobs = await get_mcp_resource(session, uri) blobs.extend(resource_blobs) except Exception as e: msg = f"Error fetching resource {current_uri}" raise RuntimeError(msg) from e return blobs