Skip to content

Commit a5a4ad2

Browse files
committed
Upgrade types.py to 2025-03-26 protocol version
1 parent c2ca8e0 commit a5a4ad2

File tree

2 files changed

+120
-7
lines changed

2 files changed

+120
-7
lines changed

src/mcp/shared/session.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
ClientRequest,
2020
ClientResult,
2121
ErrorData,
22+
JSONRPCBatchResponse,
2223
JSONRPCError,
2324
JSONRPCMessage,
2425
JSONRPCNotification,
@@ -347,7 +348,9 @@ async def _receive_loop(self) -> None:
347348
f"Failed to validate notification: {e}. "
348349
f"Message was: {message.root}"
349350
)
350-
else: # Response or error
351+
elif isinstance(message.root, JSONRPCError) or isinstance(
352+
message.root, JSONRPCResponse
353+
):
351354
stream = self._response_streams.pop(message.root.id, None)
352355
if stream:
353356
await stream.send(message.root)
@@ -358,6 +361,11 @@ async def _receive_loop(self) -> None:
358361
f"request ID: {message}"
359362
)
360363
)
364+
else:
365+
# Couldn't be anything else.
366+
raise NotImplementedError(
367+
"Unhandled JSONRPCMessage type, message: " f"{message}"
368+
)
361369

362370
async def _received_request(
363371
self, responder: RequestResponder[ReceiveRequestT, SendResultT]

src/mcp/types.py

+111-6
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
not separate types in the schema.
3030
"""
3131

32-
LATEST_PROTOCOL_VERSION = "2024-11-05"
32+
LATEST_PROTOCOL_VERSION = "2025-03-26"
3333

3434
ProgressToken = str | int
3535
Cursor = str
@@ -131,6 +131,12 @@ class JSONRPCNotification(Notification[dict[str, Any] | None, str]):
131131
params: dict[str, Any] | None = None
132132

133133

134+
class JSONRPCBatchRequest(RootModel[list[JSONRPCRequest | JSONRPCNotification]]):
135+
"""A JSON-RPC batch request"""
136+
137+
pass
138+
139+
134140
class JSONRPCResponse(BaseModel):
135141
"""A successful (non-error) response to a request."""
136142

@@ -178,8 +184,21 @@ class JSONRPCError(BaseModel):
178184
model_config = ConfigDict(extra="allow")
179185

180186

187+
class JSONRPCBatchResponse(RootModel[list[JSONRPCResponse | JSONRPCError]]):
188+
"""A JSON-RPC batch response"""
189+
190+
pass
191+
192+
181193
class JSONRPCMessage(
182-
RootModel[JSONRPCRequest | JSONRPCNotification | JSONRPCResponse | JSONRPCError]
194+
RootModel[
195+
JSONRPCRequest
196+
| JSONRPCNotification
197+
| JSONRPCBatchRequest
198+
| JSONRPCResponse
199+
| JSONRPCError
200+
| JSONRPCBatchResponse
201+
]
183202
):
184203
pass
185204

@@ -254,13 +273,21 @@ class LoggingCapability(BaseModel):
254273
model_config = ConfigDict(extra="allow")
255274

256275

276+
class CompletionCapability(BaseModel):
277+
"""Capability for completion operations."""
278+
279+
model_config = ConfigDict(extra="allow")
280+
281+
257282
class ServerCapabilities(BaseModel):
258283
"""Capabilities that a server may support."""
259284

260285
experimental: dict[str, dict[str, Any]] | None = None
261286
"""Experimental, non-standard capabilities that the server supports."""
262287
logging: LoggingCapability | None = None
263288
"""Present if the server supports sending log messages to the client."""
289+
completions: CompletionCapability | None = None
290+
"""Present if the server supports argument autocompletion suggestions."""
264291
prompts: PromptsCapability | None = None
265292
"""Present if the server offers any prompt templates."""
266293
resources: ResourcesCapability | None = None
@@ -338,6 +365,8 @@ class ProgressNotificationParams(NotificationParams):
338365
"""
339366
total: float | None = None
340367
"""Total number of items to process (or total progress required), if known."""
368+
message: str | None = None
369+
"""An optional message describing the current progress."""
341370
model_config = ConfigDict(extra="allow")
342371

343372

@@ -646,11 +675,25 @@ class ImageContent(BaseModel):
646675
model_config = ConfigDict(extra="allow")
647676

648677

678+
class AudioContent(BaseModel):
679+
"""Audio provided to or from an LLM."""
680+
681+
type: Literal["audio"]
682+
data: str
683+
"""The base64-encoded audio data."""
684+
mimeType: str
685+
"""
686+
The MIME type of the audio. Different providers may support different audio
687+
types.
688+
"""
689+
annotations: Annotations | None = None
690+
691+
649692
class SamplingMessage(BaseModel):
650693
"""Describes a message issued to or received from an LLM API."""
651694

652695
role: Role
653-
content: TextContent | ImageContent
696+
content: TextContent | ImageContent | AudioContent
654697
model_config = ConfigDict(extra="allow")
655698

656699

@@ -672,7 +715,7 @@ class PromptMessage(BaseModel):
672715
"""Describes a message returned as part of a prompt."""
673716

674717
role: Role
675-
content: TextContent | ImageContent | EmbeddedResource
718+
content: TextContent | ImageContent | AudioContent | EmbeddedResource
676719
model_config = ConfigDict(extra="allow")
677720

678721

@@ -705,15 +748,77 @@ class ListToolsRequest(PaginatedRequest[RequestParams | None, Literal["tools/lis
705748
params: RequestParams | None = None
706749

707750

751+
class ToolAnnotations(BaseModel):
752+
"""
753+
Additional properties describing a Tool to clients.
754+
755+
NOTE: all properties in ToolAnnotations are **hints**.
756+
They are not guaranteed to provide a faithful description of
757+
tool behavior (including descriptive properties like `title`).
758+
759+
Clients should never make tool use decisions based on ToolAnnotations
760+
received from untrusted servers.
761+
"""
762+
763+
title: str | None = None
764+
"""A human-readable title for the tool."""
765+
766+
readOnlyHint: bool | None = None
767+
"""
768+
If true, the tool does not modify its environment.
769+
770+
Default: false
771+
"""
772+
773+
destructiveHint: bool | None = None
774+
"""
775+
If true, the tool may perform destructive updates to its environment.
776+
If false, the tool performs only additive updates.
777+
778+
(This property is meaningful only when `readOnlyHint == false`)
779+
780+
Default: true
781+
"""
782+
783+
idempotentHint: bool | None = None
784+
"""
785+
If true, calling the tool repeatedly with the same arguments
786+
will have no additional effect on the its environment.
787+
788+
(This property is meaningful only when `readOnlyHint == false`)
789+
790+
Default: false
791+
"""
792+
793+
openWorldHint: bool | None = None
794+
"""
795+
If true, this tool may interact with an "open world" of external
796+
entities. If false, the tool's domain of interaction is closed.
797+
For example, the world of a web search tool is open, whereas that
798+
of a memory tool is not.
799+
800+
Default: true
801+
"""
802+
803+
model_config = ConfigDict(extra="allow")
804+
805+
708806
class Tool(BaseModel):
709807
"""Definition for a tool the client can call."""
710808

711809
name: str
712810
"""The name of the tool."""
713811
description: str | None = None
714-
"""A human-readable description of the tool."""
812+
"""
813+
A human-readable description of the tool.
814+
815+
This can be used by clients to improve the LLM's understanding of available
816+
tools. It can be thought of like a "hint" to the model.
817+
"""
715818
inputSchema: dict[str, Any]
716819
"""A JSON Schema object defining the expected parameters for the tool."""
820+
annotations: ToolAnnotations | None = None
821+
"""Optional additional tool information."""
717822
model_config = ConfigDict(extra="allow")
718823

719824

@@ -741,7 +846,7 @@ class CallToolRequest(Request[CallToolRequestParams, Literal["tools/call"]]):
741846
class CallToolResult(Result):
742847
"""The server's response to a tool call."""
743848

744-
content: list[TextContent | ImageContent | EmbeddedResource]
849+
content: list[TextContent | ImageContent | AudioContent | EmbeddedResource]
745850
isError: bool = False
746851

747852

0 commit comments

Comments
 (0)