generated from kgod/ai-review-template
104 lines
3.1 KiB
Python
104 lines
3.1 KiB
Python
"""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
|