Add meta to Client methods (#1923)
This commit is contained in:
parent
d77292fb06
commit
f0ab53e194
4 changed files with 221 additions and 156 deletions
|
|
@ -5,21 +5,29 @@ from __future__ import annotations
|
|||
from contextlib import AsyncExitStack
|
||||
from typing import Any
|
||||
|
||||
from pydantic import AnyUrl
|
||||
|
||||
import mcp.types as types
|
||||
from mcp.client._memory import InMemoryTransport
|
||||
from mcp.client.session import (
|
||||
ClientSession,
|
||||
ElicitationFnT,
|
||||
ListRootsFnT,
|
||||
LoggingFnT,
|
||||
MessageHandlerFnT,
|
||||
SamplingFnT,
|
||||
)
|
||||
from mcp.client.session import ClientSession, ElicitationFnT, ListRootsFnT, LoggingFnT, MessageHandlerFnT, SamplingFnT
|
||||
from mcp.server import Server
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.shared.session import ProgressFnT
|
||||
from mcp.types import (
|
||||
CallToolResult,
|
||||
CompleteResult,
|
||||
EmptyResult,
|
||||
GetPromptResult,
|
||||
Implementation,
|
||||
ListPromptsResult,
|
||||
ListResourcesResult,
|
||||
ListResourceTemplatesResult,
|
||||
ListToolsResult,
|
||||
LoggingLevel,
|
||||
PaginatedRequestParams,
|
||||
PromptReference,
|
||||
ReadResourceResult,
|
||||
RequestParamsMeta,
|
||||
ResourceTemplateReference,
|
||||
ServerCapabilities,
|
||||
)
|
||||
|
||||
|
||||
class Client:
|
||||
|
|
@ -39,8 +47,11 @@ class Client:
|
|||
def add(a: int, b: int) -> int:
|
||||
return a + b
|
||||
|
||||
async with Client(server) as client:
|
||||
result = await client.call_tool("add", {"a": 1, "b": 2})
|
||||
async def main():
|
||||
async with Client(server) as client:
|
||||
result = await client.call_tool("add", {"a": 1, "b": 2})
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
"""
|
||||
|
||||
|
|
@ -62,7 +73,7 @@ class Client:
|
|||
list_roots_callback: ListRootsFnT | None = None,
|
||||
logging_callback: LoggingFnT | None = None,
|
||||
message_handler: MessageHandlerFnT | None = None,
|
||||
client_info: types.Implementation | None = None,
|
||||
client_info: Implementation | None = None,
|
||||
elicitation_callback: ElicitationFnT | None = None,
|
||||
) -> None:
|
||||
"""Initialize the client with a server.
|
||||
|
|
@ -143,13 +154,13 @@ class Client:
|
|||
return self._session
|
||||
|
||||
@property
|
||||
def server_capabilities(self) -> types.ServerCapabilities | None:
|
||||
def server_capabilities(self) -> ServerCapabilities | None:
|
||||
"""The server capabilities received during initialization, or None if not yet initialized."""
|
||||
return self.session.get_server_capabilities()
|
||||
|
||||
async def send_ping(self) -> types.EmptyResult:
|
||||
async def send_ping(self, *, meta: RequestParamsMeta | None = None) -> EmptyResult:
|
||||
"""Send a ping request to the server."""
|
||||
return await self.session.send_ping()
|
||||
return await self.session.send_ping(meta=meta)
|
||||
|
||||
async def send_progress_notification(
|
||||
self,
|
||||
|
|
@ -166,36 +177,47 @@ class Client:
|
|||
message=message,
|
||||
)
|
||||
|
||||
async def set_logging_level(self, level: types.LoggingLevel) -> types.EmptyResult:
|
||||
async def set_logging_level(self, level: LoggingLevel, *, meta: RequestParamsMeta | None = None) -> EmptyResult:
|
||||
"""Set the logging level on the server."""
|
||||
return await self.session.set_logging_level(level)
|
||||
return await self.session.set_logging_level(level=level, meta=meta)
|
||||
|
||||
async def list_resources(self, *, cursor: str | None = None) -> types.ListResourcesResult:
|
||||
async def list_resources(
|
||||
self,
|
||||
*,
|
||||
cursor: str | None = None,
|
||||
meta: RequestParamsMeta | None = None,
|
||||
) -> ListResourcesResult:
|
||||
"""List available resources from the server."""
|
||||
return await self.session.list_resources(params=types.PaginatedRequestParams(cursor=cursor))
|
||||
return await self.session.list_resources(params=PaginatedRequestParams(cursor=cursor, _meta=meta))
|
||||
|
||||
async def list_resource_templates(self, *, cursor: str | None = None) -> types.ListResourceTemplatesResult:
|
||||
async def list_resource_templates(
|
||||
self,
|
||||
*,
|
||||
cursor: str | None = None,
|
||||
meta: RequestParamsMeta | None = None,
|
||||
) -> ListResourceTemplatesResult:
|
||||
"""List available resource templates from the server."""
|
||||
return await self.session.list_resource_templates(params=types.PaginatedRequestParams(cursor=cursor))
|
||||
return await self.session.list_resource_templates(params=PaginatedRequestParams(cursor=cursor, _meta=meta))
|
||||
|
||||
async def read_resource(self, uri: str | AnyUrl) -> types.ReadResourceResult:
|
||||
async def read_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> ReadResourceResult:
|
||||
"""Read a resource from the server.
|
||||
|
||||
Args:
|
||||
uri: The URI of the resource to read.
|
||||
meta: Additional metadata for the request
|
||||
|
||||
Returns:
|
||||
The resource content.
|
||||
"""
|
||||
return await self.session.read_resource(uri)
|
||||
return await self.session.read_resource(uri, meta=meta)
|
||||
|
||||
async def subscribe_resource(self, uri: str | AnyUrl) -> types.EmptyResult:
|
||||
async def subscribe_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> EmptyResult:
|
||||
"""Subscribe to resource updates."""
|
||||
return await self.session.subscribe_resource(uri)
|
||||
return await self.session.subscribe_resource(uri, meta=meta)
|
||||
|
||||
async def unsubscribe_resource(self, uri: str | AnyUrl) -> types.EmptyResult:
|
||||
async def unsubscribe_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> EmptyResult:
|
||||
"""Unsubscribe from resource updates."""
|
||||
return await self.session.unsubscribe_resource(uri)
|
||||
return await self.session.unsubscribe_resource(uri, meta=meta)
|
||||
|
||||
async def call_tool(
|
||||
self,
|
||||
|
|
@ -204,8 +226,8 @@ class Client:
|
|||
read_timeout_seconds: float | None = None,
|
||||
progress_callback: ProgressFnT | None = None,
|
||||
*,
|
||||
meta: dict[str, Any] | None = None,
|
||||
) -> types.CallToolResult:
|
||||
meta: RequestParamsMeta | None = None,
|
||||
) -> CallToolResult:
|
||||
"""Call a tool on the server.
|
||||
|
||||
Args:
|
||||
|
|
@ -226,28 +248,36 @@ class Client:
|
|||
meta=meta,
|
||||
)
|
||||
|
||||
async def list_prompts(self, *, cursor: str | None = None) -> types.ListPromptsResult:
|
||||
async def list_prompts(
|
||||
self,
|
||||
*,
|
||||
cursor: str | None = None,
|
||||
meta: RequestParamsMeta | None = None,
|
||||
) -> ListPromptsResult:
|
||||
"""List available prompts from the server."""
|
||||
return await self.session.list_prompts(params=types.PaginatedRequestParams(cursor=cursor))
|
||||
return await self.session.list_prompts(params=PaginatedRequestParams(cursor=cursor, _meta=meta))
|
||||
|
||||
async def get_prompt(self, name: str, arguments: dict[str, str] | None = None) -> types.GetPromptResult:
|
||||
async def get_prompt(
|
||||
self, name: str, arguments: dict[str, str] | None = None, *, meta: RequestParamsMeta | None = None
|
||||
) -> GetPromptResult:
|
||||
"""Get a prompt from the server.
|
||||
|
||||
Args:
|
||||
name: The name of the prompt
|
||||
arguments: Arguments to pass to the prompt
|
||||
meta: Additional metadata for the request
|
||||
|
||||
Returns:
|
||||
The prompt content.
|
||||
"""
|
||||
return await self.session.get_prompt(name=name, arguments=arguments)
|
||||
return await self.session.get_prompt(name=name, arguments=arguments, meta=meta)
|
||||
|
||||
async def complete(
|
||||
self,
|
||||
ref: types.ResourceTemplateReference | types.PromptReference,
|
||||
ref: ResourceTemplateReference | PromptReference,
|
||||
argument: dict[str, str],
|
||||
context_arguments: dict[str, str] | None = None,
|
||||
) -> types.CompleteResult:
|
||||
) -> CompleteResult:
|
||||
"""Get completions for a prompt or resource template argument.
|
||||
|
||||
Args:
|
||||
|
|
@ -260,9 +290,9 @@ class Client:
|
|||
"""
|
||||
return await self.session.complete(ref=ref, argument=argument, context_arguments=context_arguments)
|
||||
|
||||
async def list_tools(self, *, cursor: str | None = None) -> types.ListToolsResult:
|
||||
async def list_tools(self, *, cursor: str | None = None, meta: RequestParamsMeta | None = None) -> ListToolsResult:
|
||||
"""List available tools from the server."""
|
||||
return await self.session.list_tools(params=types.PaginatedRequestParams(cursor=cursor))
|
||||
return await self.session.list_tools(params=PaginatedRequestParams(cursor=cursor, _meta=meta))
|
||||
|
||||
async def send_roots_list_changed(self) -> None:
|
||||
"""Send a notification that the roots list has changed."""
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ from typing import TYPE_CHECKING, Any, TypeVar
|
|||
|
||||
import mcp.types as types
|
||||
from mcp.shared.experimental.tasks.polling import poll_until_terminal
|
||||
from mcp.types._types import RequestParamsMeta
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from mcp.client.session import ClientSession
|
||||
|
|
@ -53,7 +54,7 @@ class ExperimentalClientFeatures:
|
|||
arguments: dict[str, Any] | None = None,
|
||||
*,
|
||||
ttl: int = 60000,
|
||||
meta: dict[str, Any] | None = None,
|
||||
meta: RequestParamsMeta | None = None,
|
||||
) -> types.CreateTaskResult:
|
||||
"""Call a tool as a task, returning a CreateTaskResult for polling.
|
||||
|
||||
|
|
@ -87,17 +88,13 @@ class ExperimentalClientFeatures:
|
|||
# Get result
|
||||
final = await session.experimental.get_task_result(task_id, CallToolResult)
|
||||
"""
|
||||
_meta: types.RequestParams.Meta | None = None
|
||||
if meta is not None:
|
||||
_meta = types.RequestParams.Meta(**meta)
|
||||
|
||||
return await self._session.send_request(
|
||||
types.CallToolRequest(
|
||||
params=types.CallToolRequestParams(
|
||||
name=name,
|
||||
arguments=arguments,
|
||||
task=types.TaskMetadata(ttl=ttl),
|
||||
_meta=_meta,
|
||||
_meta=meta,
|
||||
),
|
||||
),
|
||||
types.CreateTaskResult,
|
||||
|
|
@ -113,9 +110,7 @@ class ExperimentalClientFeatures:
|
|||
GetTaskResult containing the task status and metadata
|
||||
"""
|
||||
return await self._session.send_request(
|
||||
types.GetTaskRequest(
|
||||
params=types.GetTaskRequestParams(task_id=task_id),
|
||||
),
|
||||
types.GetTaskRequest(params=types.GetTaskRequestParams(task_id=task_id)),
|
||||
types.GetTaskResult,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from typing import Any, Protocol
|
|||
|
||||
import anyio.lowlevel
|
||||
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
|
||||
from pydantic import AnyUrl, TypeAdapter
|
||||
from pydantic import TypeAdapter
|
||||
|
||||
import mcp.types as types
|
||||
from mcp.client.experimental import ExperimentalClientFeatures
|
||||
|
|
@ -12,6 +12,7 @@ from mcp.shared.context import RequestContext
|
|||
from mcp.shared.message import SessionMessage
|
||||
from mcp.shared.session import BaseSession, ProgressFnT, RequestResponder
|
||||
from mcp.shared.version import SUPPORTED_PROTOCOL_VERSIONS
|
||||
from mcp.types._types import RequestParamsMeta
|
||||
|
||||
DEFAULT_CLIENT_INFO = types.Implementation(name="mcp", version="0.1.0")
|
||||
|
||||
|
|
@ -216,9 +217,9 @@ class ClientSession(
|
|||
self._experimental_features = ExperimentalClientFeatures(self)
|
||||
return self._experimental_features
|
||||
|
||||
async def send_ping(self) -> types.EmptyResult:
|
||||
async def send_ping(self, *, meta: RequestParamsMeta | None = None) -> types.EmptyResult:
|
||||
"""Send a ping request."""
|
||||
return await self.send_request(types.PingRequest(), types.EmptyResult)
|
||||
return await self.send_request(types.PingRequest(params=types.RequestParams(_meta=meta)), types.EmptyResult)
|
||||
|
||||
async def send_progress_notification(
|
||||
self,
|
||||
|
|
@ -226,6 +227,8 @@ class ClientSession(
|
|||
progress: float,
|
||||
total: float | None = None,
|
||||
message: str | None = None,
|
||||
*,
|
||||
meta: RequestParamsMeta | None = None,
|
||||
) -> None:
|
||||
"""Send a progress notification."""
|
||||
await self.send_notification(
|
||||
|
|
@ -235,14 +238,20 @@ class ClientSession(
|
|||
progress=progress,
|
||||
total=total,
|
||||
message=message,
|
||||
_meta=meta,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
async def set_logging_level(self, level: types.LoggingLevel) -> types.EmptyResult:
|
||||
async def set_logging_level(
|
||||
self,
|
||||
level: types.LoggingLevel,
|
||||
*,
|
||||
meta: RequestParamsMeta | None = None,
|
||||
) -> types.EmptyResult:
|
||||
"""Send a logging/setLevel request."""
|
||||
return await self.send_request( # pragma: no cover
|
||||
types.SetLevelRequest(params=types.SetLevelRequestParams(level=level)),
|
||||
types.SetLevelRequest(params=types.SetLevelRequestParams(level=level, _meta=meta)),
|
||||
types.EmptyResult,
|
||||
)
|
||||
|
||||
|
|
@ -267,24 +276,24 @@ class ClientSession(
|
|||
types.ListResourceTemplatesResult,
|
||||
)
|
||||
|
||||
async def read_resource(self, uri: str | AnyUrl) -> types.ReadResourceResult:
|
||||
async def read_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> types.ReadResourceResult:
|
||||
"""Send a resources/read request."""
|
||||
return await self.send_request(
|
||||
types.ReadResourceRequest(params=types.ReadResourceRequestParams(uri=str(uri))),
|
||||
types.ReadResourceRequest(params=types.ReadResourceRequestParams(uri=uri, _meta=meta)),
|
||||
types.ReadResourceResult,
|
||||
)
|
||||
|
||||
async def subscribe_resource(self, uri: str | AnyUrl) -> types.EmptyResult:
|
||||
async def subscribe_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> types.EmptyResult:
|
||||
"""Send a resources/subscribe request."""
|
||||
return await self.send_request( # pragma: no cover
|
||||
types.SubscribeRequest(params=types.SubscribeRequestParams(uri=str(uri))),
|
||||
types.SubscribeRequest(params=types.SubscribeRequestParams(uri=uri, _meta=meta)),
|
||||
types.EmptyResult,
|
||||
)
|
||||
|
||||
async def unsubscribe_resource(self, uri: str | AnyUrl) -> types.EmptyResult:
|
||||
async def unsubscribe_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> types.EmptyResult:
|
||||
"""Send a resources/unsubscribe request."""
|
||||
return await self.send_request( # pragma: no cover
|
||||
types.UnsubscribeRequest(params=types.UnsubscribeRequestParams(uri=str(uri))),
|
||||
types.UnsubscribeRequest(params=types.UnsubscribeRequestParams(uri=uri, _meta=meta)),
|
||||
types.EmptyResult,
|
||||
)
|
||||
|
||||
|
|
@ -295,17 +304,13 @@ class ClientSession(
|
|||
read_timeout_seconds: float | None = None,
|
||||
progress_callback: ProgressFnT | None = None,
|
||||
*,
|
||||
meta: dict[str, Any] | None = None,
|
||||
meta: RequestParamsMeta | None = None,
|
||||
) -> types.CallToolResult:
|
||||
"""Send a tools/call request with optional progress callback support."""
|
||||
|
||||
_meta: types.RequestParams.Meta | None = None
|
||||
if meta is not None:
|
||||
_meta = types.RequestParams.Meta(**meta)
|
||||
|
||||
result = await self.send_request(
|
||||
types.CallToolRequest(
|
||||
params=types.CallToolRequestParams(name=name, arguments=arguments, _meta=_meta),
|
||||
params=types.CallToolRequestParams(name=name, arguments=arguments, _meta=meta),
|
||||
),
|
||||
types.CallToolResult,
|
||||
request_read_timeout_seconds=read_timeout_seconds,
|
||||
|
|
@ -351,11 +356,17 @@ class ClientSession(
|
|||
"""
|
||||
return await self.send_request(types.ListPromptsRequest(params=params), types.ListPromptsResult)
|
||||
|
||||
async def get_prompt(self, name: str, arguments: dict[str, str] | None = None) -> types.GetPromptResult:
|
||||
async def get_prompt(
|
||||
self,
|
||||
name: str,
|
||||
arguments: dict[str, str] | None = None,
|
||||
*,
|
||||
meta: RequestParamsMeta | None = None,
|
||||
) -> types.GetPromptResult:
|
||||
"""Send a prompts/get request."""
|
||||
return await self.send_request(
|
||||
types.GetPromptRequest(
|
||||
params=types.GetPromptRequestParams(name=name, arguments=arguments),
|
||||
params=types.GetPromptRequestParams(name=name, arguments=arguments, _meta=meta),
|
||||
),
|
||||
types.GetPromptResult,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ class ClientSessionGroup:
|
|||
read_timeout_seconds: float | None = None,
|
||||
progress_callback: ProgressFnT | None = None,
|
||||
*,
|
||||
meta: dict[str, Any] | None = None,
|
||||
meta: types.RequestParamsMeta | None = None,
|
||||
) -> types.CallToolResult:
|
||||
"""Executes a tool given its name and arguments."""
|
||||
session = self._tool_to_session[name]
|
||||
|
|
|
|||
Loading…
Reference in a new issue