Skip to content

Commit 157eeed

Browse files
committed
Add meta to Client methods
1 parent 656f887 commit 157eeed

File tree

24 files changed

+155
-147
lines changed

24 files changed

+155
-147
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2119,8 +2119,6 @@ uv run client
21192119
import asyncio
21202120
import os
21212121

2122-
from pydantic import AnyUrl
2123-
21242122
from mcp import ClientSession, StdioServerParameters, types
21252123
from mcp.client.stdio import stdio_client
21262124
from mcp.shared.context import RequestContext
@@ -2173,7 +2171,7 @@ async def run():
21732171
print(f"Available tools: {[t.name for t in tools.tools]}")
21742172

21752173
# Read a resource (greeting resource from fastmcp_quickstart)
2176-
resource_content = await session.read_resource(AnyUrl("greeting://World"))
2174+
resource_content = await session.read_resource("greeting://World")
21772175
content_block = resource_content.contents[0]
21782176
if isinstance(content_block, types.TextContent):
21792177
print(f"Resource content: {content_block.text}")

examples/servers/everything-server/mcp_everything_server/server.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ async def test_tool_with_progress(ctx: Context[ServerSession, None]) -> str:
161161
await ctx.report_progress(progress=100, total=100, message="Completed step 100 of 100")
162162

163163
# Return progress token as string
164-
progress_token = ctx.request_context.meta.progress_token if ctx.request_context and ctx.request_context.meta else 0
164+
progress_token = (
165+
ctx.request_context.meta.get("progress_token") if ctx.request_context and ctx.request_context.meta else 0
166+
)
165167
return str(progress_token)
166168

167169

examples/snippets/clients/stdio_client.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import asyncio
66
import os
77

8-
from pydantic import AnyUrl
9-
108
from mcp import ClientSession, StdioServerParameters, types
119
from mcp.client.stdio import stdio_client
1210
from mcp.shared.context import RequestContext
@@ -59,7 +57,7 @@ async def run():
5957
print(f"Available tools: {[t.name for t in tools.tools]}")
6058

6159
# Read a resource (greeting resource from fastmcp_quickstart)
62-
resource_content = await session.read_resource(AnyUrl("greeting://World"))
60+
resource_content = await session.read_resource("greeting://World")
6361
content_block = resource_content.contents[0]
6462
if isinstance(content_block, types.TextContent):
6563
print(f"Resource content: {content_block.text}")

src/mcp/client/client.py

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,16 @@
22

33
from __future__ import annotations
44

5-
import logging
65
from contextlib import AsyncExitStack
76
from typing import Any
87

9-
from pydantic import AnyUrl
10-
118
import mcp.types as types
129
from mcp.client._memory import InMemoryTransport
13-
from mcp.client.session import (
14-
ClientSession,
15-
ElicitationFnT,
16-
ListRootsFnT,
17-
LoggingFnT,
18-
MessageHandlerFnT,
19-
SamplingFnT,
20-
)
10+
from mcp.client.session import ClientSession, ElicitationFnT, ListRootsFnT, LoggingFnT, MessageHandlerFnT, SamplingFnT
2111
from mcp.server import Server
2212
from mcp.server.fastmcp import FastMCP
2313
from mcp.shared.session import ProgressFnT
24-
25-
logger = logging.getLogger(__name__)
14+
from mcp.types._types import RequestParamsMeta
2615

2716

2817
class Client:
@@ -42,8 +31,11 @@ class Client:
4231
def add(a: int, b: int) -> int:
4332
return a + b
4433
45-
async with Client(server) as client:
46-
result = await client.call_tool("add", {"a": 1, "b": 2})
34+
async def main():
35+
async with Client(server) as client:
36+
result = await client.call_tool("add", {"a": 1, "b": 2})
37+
38+
asyncio.run(main())
4739
```
4840
"""
4941

@@ -150,9 +142,9 @@ def server_capabilities(self) -> types.ServerCapabilities | None:
150142
"""The server capabilities received during initialization, or None if not yet initialized."""
151143
return self.session.get_server_capabilities()
152144

153-
async def send_ping(self) -> types.EmptyResult:
145+
async def send_ping(self, *, meta: RequestParamsMeta | None = None) -> types.EmptyResult:
154146
"""Send a ping request to the server."""
155-
return await self.session.send_ping()
147+
return await self.session.send_ping(meta=meta)
156148

157149
async def send_progress_notification(
158150
self,
@@ -169,19 +161,36 @@ async def send_progress_notification(
169161
message=message,
170162
)
171163

172-
async def set_logging_level(self, level: types.LoggingLevel) -> types.EmptyResult:
164+
async def set_logging_level(
165+
self,
166+
level: types.LoggingLevel,
167+
*,
168+
meta: RequestParamsMeta | None = None,
169+
) -> types.EmptyResult:
173170
"""Set the logging level on the server."""
174-
return await self.session.set_logging_level(level)
171+
return await self.session.set_logging_level(level=level, meta=meta)
175172

176-
async def list_resources(self, *, cursor: str | None = None) -> types.ListResourcesResult:
173+
async def list_resources(
174+
self,
175+
*,
176+
cursor: str | None = None,
177+
meta: RequestParamsMeta | None = None,
178+
) -> types.ListResourcesResult:
177179
"""List available resources from the server."""
178-
return await self.session.list_resources(params=types.PaginatedRequestParams(cursor=cursor))
180+
return await self.session.list_resources(params=types.PaginatedRequestParams(cursor=cursor, _meta=meta))
179181

180-
async def list_resource_templates(self, *, cursor: str | None = None) -> types.ListResourceTemplatesResult:
182+
async def list_resource_templates(
183+
self,
184+
*,
185+
cursor: str | None = None,
186+
meta: RequestParamsMeta | None = None,
187+
) -> types.ListResourceTemplatesResult:
181188
"""List available resource templates from the server."""
182-
return await self.session.list_resource_templates(params=types.PaginatedRequestParams(cursor=cursor))
189+
return await self.session.list_resource_templates(
190+
params=types.PaginatedRequestParams(cursor=cursor, _meta=meta)
191+
)
183192

184-
async def read_resource(self, uri: str | AnyUrl) -> types.ReadResourceResult:
193+
async def read_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> types.ReadResourceResult:
185194
"""Read a resource from the server.
186195
187196
Args:
@@ -190,15 +199,15 @@ async def read_resource(self, uri: str | AnyUrl) -> types.ReadResourceResult:
190199
Returns:
191200
The resource content.
192201
"""
193-
return await self.session.read_resource(uri)
202+
return await self.session.read_resource(uri, meta=meta)
194203

195-
async def subscribe_resource(self, uri: str | AnyUrl) -> types.EmptyResult:
204+
async def subscribe_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> types.EmptyResult:
196205
"""Subscribe to resource updates."""
197-
return await self.session.subscribe_resource(uri)
206+
return await self.session.subscribe_resource(uri, meta=meta)
198207

199-
async def unsubscribe_resource(self, uri: str | AnyUrl) -> types.EmptyResult:
208+
async def unsubscribe_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> types.EmptyResult:
200209
"""Unsubscribe from resource updates."""
201-
return await self.session.unsubscribe_resource(uri)
210+
return await self.session.unsubscribe_resource(uri, meta=meta)
202211

203212
async def call_tool(
204213
self,
@@ -207,7 +216,7 @@ async def call_tool(
207216
read_timeout_seconds: float | None = None,
208217
progress_callback: ProgressFnT | None = None,
209218
*,
210-
meta: dict[str, Any] | None = None,
219+
meta: RequestParamsMeta | None = None,
211220
) -> types.CallToolResult:
212221
"""Call a tool on the server.
213222
@@ -229,9 +238,14 @@ async def call_tool(
229238
meta=meta,
230239
)
231240

232-
async def list_prompts(self, *, cursor: str | None = None) -> types.ListPromptsResult:
241+
async def list_prompts(
242+
self,
243+
*,
244+
cursor: str | None = None,
245+
meta: RequestParamsMeta | None = None,
246+
) -> types.ListPromptsResult:
233247
"""List available prompts from the server."""
234-
return await self.session.list_prompts(params=types.PaginatedRequestParams(cursor=cursor))
248+
return await self.session.list_prompts(params=types.PaginatedRequestParams(cursor=cursor, _meta=meta))
235249

236250
async def get_prompt(self, name: str, arguments: dict[str, str] | None = None) -> types.GetPromptResult:
237251
"""Get a prompt from the server.

src/mcp/client/experimental/tasks.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import mcp.types as types
3030
from mcp.shared.experimental.tasks.polling import poll_until_terminal
31+
from mcp.types._types import RequestParamsMeta
3132

3233
if TYPE_CHECKING:
3334
from mcp.client.session import ClientSession
@@ -53,7 +54,7 @@ async def call_tool_as_task(
5354
arguments: dict[str, Any] | None = None,
5455
*,
5556
ttl: int = 60000,
56-
meta: dict[str, Any] | None = None,
57+
meta: RequestParamsMeta | None = None,
5758
) -> types.CreateTaskResult:
5859
"""Call a tool as a task, returning a CreateTaskResult for polling.
5960
@@ -87,17 +88,13 @@ async def call_tool_as_task(
8788
# Get result
8889
final = await session.experimental.get_task_result(task_id, CallToolResult)
8990
"""
90-
_meta: types.RequestParams.Meta | None = None
91-
if meta is not None:
92-
_meta = types.RequestParams.Meta(**meta)
93-
9491
return await self._session.send_request(
9592
types.CallToolRequest(
9693
params=types.CallToolRequestParams(
9794
name=name,
9895
arguments=arguments,
9996
task=types.TaskMetadata(ttl=ttl),
100-
_meta=_meta,
97+
_meta=meta,
10198
),
10299
),
103100
types.CreateTaskResult,
@@ -113,9 +110,7 @@ async def get_task(self, task_id: str) -> types.GetTaskResult:
113110
GetTaskResult containing the task status and metadata
114111
"""
115112
return await self._session.send_request(
116-
types.GetTaskRequest(
117-
params=types.GetTaskRequestParams(task_id=task_id),
118-
),
113+
types.GetTaskRequest(params=types.GetTaskRequestParams(task_id=task_id)),
119114
types.GetTaskResult,
120115
)
121116

src/mcp/client/session.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import anyio.lowlevel
55
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
6-
from pydantic import AnyUrl, TypeAdapter
6+
from pydantic import TypeAdapter
77

88
import mcp.types as types
99
from mcp.client.experimental import ExperimentalClientFeatures
@@ -12,6 +12,7 @@
1212
from mcp.shared.message import SessionMessage
1313
from mcp.shared.session import BaseSession, ProgressFnT, RequestResponder
1414
from mcp.shared.version import SUPPORTED_PROTOCOL_VERSIONS
15+
from mcp.types._types import RequestParamsMeta
1516

1617
DEFAULT_CLIENT_INFO = types.Implementation(name="mcp", version="0.1.0")
1718

@@ -216,16 +217,18 @@ def experimental(self) -> ExperimentalClientFeatures:
216217
self._experimental_features = ExperimentalClientFeatures(self)
217218
return self._experimental_features
218219

219-
async def send_ping(self) -> types.EmptyResult:
220+
async def send_ping(self, *, meta: RequestParamsMeta | None = None) -> types.EmptyResult:
220221
"""Send a ping request."""
221-
return await self.send_request(types.PingRequest(), types.EmptyResult)
222+
return await self.send_request(types.PingRequest(params=types.RequestParams(_meta=meta)), types.EmptyResult)
222223

223224
async def send_progress_notification(
224225
self,
225226
progress_token: str | int,
226227
progress: float,
227228
total: float | None = None,
228229
message: str | None = None,
230+
*,
231+
meta: RequestParamsMeta | None = None,
229232
) -> None:
230233
"""Send a progress notification."""
231234
await self.send_notification(
@@ -235,14 +238,20 @@ async def send_progress_notification(
235238
progress=progress,
236239
total=total,
237240
message=message,
241+
_meta=meta,
238242
),
239243
)
240244
)
241245

242-
async def set_logging_level(self, level: types.LoggingLevel) -> types.EmptyResult:
246+
async def set_logging_level(
247+
self,
248+
level: types.LoggingLevel,
249+
*,
250+
meta: RequestParamsMeta | None = None,
251+
) -> types.EmptyResult:
243252
"""Send a logging/setLevel request."""
244253
return await self.send_request( # pragma: no cover
245-
types.SetLevelRequest(params=types.SetLevelRequestParams(level=level)),
254+
types.SetLevelRequest(params=types.SetLevelRequestParams(level=level, _meta=meta)),
246255
types.EmptyResult,
247256
)
248257

@@ -267,24 +276,24 @@ async def list_resource_templates(
267276
types.ListResourceTemplatesResult,
268277
)
269278

270-
async def read_resource(self, uri: str | AnyUrl) -> types.ReadResourceResult:
279+
async def read_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> types.ReadResourceResult:
271280
"""Send a resources/read request."""
272281
return await self.send_request(
273-
types.ReadResourceRequest(params=types.ReadResourceRequestParams(uri=str(uri))),
282+
types.ReadResourceRequest(params=types.ReadResourceRequestParams(uri=uri, _meta=meta)),
274283
types.ReadResourceResult,
275284
)
276285

277-
async def subscribe_resource(self, uri: str | AnyUrl) -> types.EmptyResult:
286+
async def subscribe_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> types.EmptyResult:
278287
"""Send a resources/subscribe request."""
279288
return await self.send_request( # pragma: no cover
280-
types.SubscribeRequest(params=types.SubscribeRequestParams(uri=str(uri))),
289+
types.SubscribeRequest(params=types.SubscribeRequestParams(uri=uri, _meta=meta)),
281290
types.EmptyResult,
282291
)
283292

284-
async def unsubscribe_resource(self, uri: str | AnyUrl) -> types.EmptyResult:
293+
async def unsubscribe_resource(self, uri: str, *, meta: RequestParamsMeta | None = None) -> types.EmptyResult:
285294
"""Send a resources/unsubscribe request."""
286295
return await self.send_request( # pragma: no cover
287-
types.UnsubscribeRequest(params=types.UnsubscribeRequestParams(uri=str(uri))),
296+
types.UnsubscribeRequest(params=types.UnsubscribeRequestParams(uri=uri, _meta=meta)),
288297
types.EmptyResult,
289298
)
290299

@@ -295,17 +304,13 @@ async def call_tool(
295304
read_timeout_seconds: float | None = None,
296305
progress_callback: ProgressFnT | None = None,
297306
*,
298-
meta: dict[str, Any] | None = None,
307+
meta: RequestParamsMeta | None = None,
299308
) -> types.CallToolResult:
300309
"""Send a tools/call request with optional progress callback support."""
301310

302-
_meta: types.RequestParams.Meta | None = None
303-
if meta is not None:
304-
_meta = types.RequestParams.Meta(**meta)
305-
306311
result = await self.send_request(
307312
types.CallToolRequest(
308-
params=types.CallToolRequestParams(name=name, arguments=arguments, _meta=_meta),
313+
params=types.CallToolRequestParams(name=name, arguments=arguments, _meta=meta),
309314
),
310315
types.CallToolResult,
311316
request_read_timeout_seconds=read_timeout_seconds,
@@ -351,11 +356,17 @@ async def list_prompts(self, *, params: types.PaginatedRequestParams | None = No
351356
"""
352357
return await self.send_request(types.ListPromptsRequest(params=params), types.ListPromptsResult)
353358

354-
async def get_prompt(self, name: str, arguments: dict[str, str] | None = None) -> types.GetPromptResult:
359+
async def get_prompt(
360+
self,
361+
name: str,
362+
arguments: dict[str, str] | None = None,
363+
*,
364+
meta: RequestParamsMeta | None = None,
365+
) -> types.GetPromptResult:
355366
"""Send a prompts/get request."""
356367
return await self.send_request(
357368
types.GetPromptRequest(
358-
params=types.GetPromptRequestParams(name=name, arguments=arguments),
369+
params=types.GetPromptRequestParams(name=name, arguments=arguments, _meta=meta),
359370
),
360371
types.GetPromptResult,
361372
)

src/mcp/client/session_group.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ async def call_tool(
196196
read_timeout_seconds: float | None = None,
197197
progress_callback: ProgressFnT | None = None,
198198
*,
199-
meta: dict[str, Any] | None = None,
199+
meta: types.RequestParamsMeta | None = None,
200200
) -> types.CallToolResult:
201201
"""Executes a tool given its name and arguments."""
202202
session = self._tool_to_session[name]

0 commit comments

Comments
 (0)