refactor: McpError renamed to MCPError and flatten parameters (#1956)

Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com>
This commit is contained in:
Marcelo Trylesinski 2026-01-26 14:37:44 +01:00 • committed by GitHub
commit acba5478a9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 253 additions and 326 deletions

View file

@ -337,7 +337,7 @@ if __name__ == "__main__":
Handle task errors gracefully:
```python
from mcp.shared.exceptions import McpError
from mcp.shared.exceptions import MCPError
try:
result = await session.experimental.call_tool_as_task("my_tool", args)
@ -349,8 +349,8 @@ try:
final = await session.experimental.get_task_result(task_id, CallToolResult)
except McpError as e:
print(f"MCP error: {e.error.message}")
except MCPError as e:
print(f"MCP error: {e.message}")
except Exception as e:
print(f"Error: {e}")
```

View file

@ -121,6 +121,38 @@ result = await session.list_resources(params=PaginatedRequestParams(cursor="next
result = await session.list_tools(params=PaginatedRequestParams(cursor="next_page_token"))
```
### `McpError` renamed to `MCPError`
The `McpError` exception class has been renamed to `MCPError` for consistent naming with the MCP acronym style used throughout the SDK.
**Before (v1):**
```python
from mcp.shared.exceptions import McpError
try:
result = await session.call_tool("my_tool")
except McpError as e:
print(f"Error: {e.error.message}")
```
**After (v2):**
```python
from mcp.shared.exceptions import MCPError
try:
result = await session.call_tool("my_tool")
except MCPError as e:
print(f"Error: {e.message}")
```
`MCPError` is also exported from the top-level `mcp` package:
```python
from mcp import MCPError
```
### `FastMCP` renamed to `MCPServer`
The `FastMCP` class has been renamed to `MCPServer` to better reflect its role as the main server class in the SDK. This is a simple rename with no functional changes to the class itself.

View file

@ -33,7 +33,7 @@ from urllib.parse import urlparse
from mcp import ClientSession, types
from mcp.client.sse import sse_client
from mcp.shared.context import RequestContext
from mcp.shared.exceptions import McpError, UrlElicitationRequiredError
from mcp.shared.exceptions import MCPError, UrlElicitationRequiredError
from mcp.types import URL_ELICITATION_REQUIRED
@ -160,9 +160,9 @@ async def call_tool_with_error_handling(
return result
except McpError as e:
except MCPError as e:
# Check if this is a URL elicitation required error
if e.error.code == URL_ELICITATION_REQUIRED:
if e.code == URL_ELICITATION_REQUIRED:
print("\n[Tool requires URL elicitation to proceed]")
# Convert to typed error to access elicitations

View file

@ -4,7 +4,7 @@ from .client.session_group import ClientSessionGroup
from .client.stdio import StdioServerParameters, stdio_client
from .server.session import ServerSession
from .server.stdio import stdio_server
from .shared.exceptions import McpError, UrlElicitationRequiredError
from .shared.exceptions import MCPError, UrlElicitationRequiredError
from .types import (
CallToolRequest,
ClientCapabilities,
@ -96,7 +96,7 @@ __all__ = [
"ListToolsResult",
"LoggingLevel",
"LoggingMessageNotification",
"McpError",
"MCPError",
"Notification",
"PingRequest",
"ProgressNotification",

View file

@ -25,7 +25,7 @@ from mcp.client.sse import sse_client
from mcp.client.stdio import StdioServerParameters
from mcp.client.streamable_http import streamable_http_client
from mcp.shared._httpx_utils import create_mcp_http_client
from mcp.shared.exceptions import McpError
from mcp.shared.exceptions import MCPError
from mcp.shared.session import ProgressFnT
@ -216,11 +216,9 @@ class ClientSessionGroup:
session_known_for_stack = session in self._session_exit_stacks
if not session_known_for_components and not session_known_for_stack:
raise McpError(
types.ErrorData(
code=types.INVALID_PARAMS,
message="Provided session is not managed or already disconnected.",
)
raise MCPError(
code=types.INVALID_PARAMS,
message="Provided session is not managed or already disconnected.",
)
if session_known_for_components: # pragma: no branch
@ -352,7 +350,7 @@ class ClientSessionGroup:
name = self._component_name(prompt.name, server_info)
prompts_temp[name] = prompt
component_names.prompts.add(name)
except McpError as err: # pragma: no cover
except MCPError as err: # pragma: no cover
logging.warning(f"Could not fetch prompts: {err}")
# Query the server for its resources and aggregate to list.
@ -362,7 +360,7 @@ class ClientSessionGroup:
name = self._component_name(resource.name, server_info)
resources_temp[name] = resource
component_names.resources.add(name)
except McpError as err: # pragma: no cover
except MCPError as err: # pragma: no cover
logging.warning(f"Could not fetch resources: {err}")
# Query the server for its tools and aggregate to list.
@ -373,7 +371,7 @@ class ClientSessionGroup:
tools_temp[name] = tool
tool_to_session_temp[name] = session
component_names.tools.add(name)
except McpError as err: # pragma: no cover
except MCPError as err: # pragma: no cover
logging.warning(f"Could not fetch tools: {err}")
# Clean up exit stack for session if we couldn't retrieve anything
@ -384,28 +382,19 @@ class ClientSessionGroup:
# Check for duplicates.
matching_prompts = prompts_temp.keys() & self._prompts.keys()
if matching_prompts:
raise McpError( # pragma: no cover
types.ErrorData(
code=types.INVALID_PARAMS,
message=f"{matching_prompts} already exist in group prompts.",
)
raise MCPError( # pragma: no cover
code=types.INVALID_PARAMS,
message=f"{matching_prompts} already exist in group prompts.",
)
matching_resources = resources_temp.keys() & self._resources.keys()
if matching_resources:
raise McpError( # pragma: no cover
types.ErrorData(
code=types.INVALID_PARAMS,
message=f"{matching_resources} already exist in group resources.",
)
raise MCPError( # pragma: no cover
code=types.INVALID_PARAMS,
message=f"{matching_resources} already exist in group resources.",
)
matching_tools = tools_temp.keys() & self._tools.keys()
if matching_tools:
raise McpError(
types.ErrorData(
code=types.INVALID_PARAMS,
message=f"{matching_tools} already exist in group tools.",
)
)
raise MCPError(code=types.INVALID_PARAMS, message=f"{matching_tools} already exist in group tools.")
# Aggregate components.
self._sessions[session] = component_names

View file

@ -13,7 +13,7 @@ from typing import Any
from mcp.server.experimental.task_context import ServerTaskContext
from mcp.server.experimental.task_support import TaskSupport
from mcp.server.session import ServerSession
from mcp.shared.exceptions import McpError
from mcp.shared.exceptions import MCPError
from mcp.shared.experimental.tasks.helpers import MODEL_IMMEDIATE_RESPONSE_KEY, is_terminal
from mcp.types import (
METHOD_NOT_FOUND,
@ -72,13 +72,13 @@ class Experimental:
Args:
tool_task_mode: The tool's execution.taskSupport value
("forbidden", "optional", "required", or None)
raise_error: If True, raises McpError on validation failure. If False, returns ErrorData.
raise_error: If True, raises MCPError on validation failure. If False, returns ErrorData.
Returns:
None if valid, ErrorData if invalid and raise_error=False
Raises:
McpError: If invalid and raise_error=True
MCPError: If invalid and raise_error=True
"""
mode = tool_task_mode or TASK_FORBIDDEN
@ -86,18 +86,12 @@ class Experimental:
error: ErrorData | None = None
if mode == TASK_REQUIRED and not self.is_task:
error = ErrorData(
code=METHOD_NOT_FOUND,
message="This tool requires task-augmented invocation",
)
error = ErrorData(code=METHOD_NOT_FOUND, message="This tool requires task-augmented invocation")
elif mode == TASK_FORBIDDEN and self.is_task:
error = ErrorData(
code=METHOD_NOT_FOUND,
message="This tool does not support task-augmented invocation",
)
error = ErrorData(code=METHOD_NOT_FOUND, message="This tool does not support task-augmented invocation")
if error is not None and raise_error:
raise McpError(error)
raise MCPError(code=error.code, message=error.message)
return error
@ -113,7 +107,7 @@ class Experimental:
Args:
tool: The Tool definition
raise_error: If True, raises McpError on validation failure.
raise_error: If True, raises MCPError on validation failure.
Returns:
None if valid, ErrorData if invalid and raise_error=False

View file

@ -114,7 +114,7 @@ class ExperimentalServerSessionFeatures:
The client's elicitation response
Raises:
McpError: If client doesn't support task-augmented elicitation
MCPError: If client doesn't support task-augmented elicitation
"""
client_caps = self._session.client_params.capabilities if self._session.client_params else None
require_task_augmented_elicitation(client_caps)
@ -174,7 +174,7 @@ class ExperimentalServerSessionFeatures:
The sampling result from the client
Raises:
McpError: If client doesn't support task-augmented sampling or tools
MCPError: If client doesn't support task-augmented sampling or tools
ValueError: If tool_use or tool_result message structure is invalid
"""
client_caps = self._session.client_params.capabilities if self._session.client_params else None

View file

@ -13,7 +13,7 @@ import anyio
from mcp.server.experimental.task_result_handler import TaskResultHandler
from mcp.server.session import ServerSession
from mcp.server.validation import validate_sampling_tools, validate_tool_use_result_messages
from mcp.shared.exceptions import McpError
from mcp.shared.exceptions import MCPError
from mcp.shared.experimental.tasks.capabilities import (
require_task_augmented_elicitation,
require_task_augmented_sampling,
@ -32,7 +32,6 @@ from mcp.types import (
ElicitationCapability,
ElicitRequestedSchema,
ElicitResult,
ErrorData,
IncludeContext,
ModelPreferences,
RequestId,
@ -173,22 +172,12 @@ class ServerTaskContext:
def _check_elicitation_capability(self) -> None:
"""Check if the client supports elicitation."""
if not self._session.check_client_capability(ClientCapabilities(elicitation=ElicitationCapability())):
raise McpError(
ErrorData(
code=INVALID_REQUEST,
message="Client does not support elicitation capability",
)
)
raise MCPError(code=INVALID_REQUEST, message="Client does not support elicitation capability")
def _check_sampling_capability(self) -> None:
"""Check if the client supports sampling."""
if not self._session.check_client_capability(ClientCapabilities(sampling=SamplingCapability())):
raise McpError(
ErrorData(
code=INVALID_REQUEST,
message="Client does not support sampling capability",
)
)
raise MCPError(code=INVALID_REQUEST, message="Client does not support sampling capability")
async def elicit(
self,
@ -213,7 +202,7 @@ class ServerTaskContext:
The client's response
Raises:
McpError: If client doesn't support elicitation capability
MCPError: If client doesn't support elicitation capability
"""
self._check_elicitation_capability()
@ -281,7 +270,7 @@ class ServerTaskContext:
The client's response indicating acceptance, decline, or cancellation
Raises:
McpError: If client doesn't support elicitation capability
MCPError: If client doesn't support elicitation capability
RuntimeError: If handler is not configured
"""
self._check_elicitation_capability()
@ -361,7 +350,7 @@ class ServerTaskContext:
The sampling result from the client
Raises:
McpError: If client doesn't support sampling capability or tools
MCPError: If client doesn't support sampling capability or tools
ValueError: If tool_use or tool_result message structure is invalid
"""
self._check_sampling_capability()
@ -436,7 +425,7 @@ class ServerTaskContext:
The client's elicitation response
Raises:
McpError: If client doesn't support task-augmented elicitation
MCPError: If client doesn't support task-augmented elicitation
RuntimeError: If handler is not configured
"""
client_caps = self._session.client_params.capabilities if self._session.client_params else None
@ -529,7 +518,7 @@ class ServerTaskContext:
The sampling result from the client
Raises:
McpError: If client doesn't support task-augmented sampling or tools
MCPError: If client doesn't support task-augmented sampling or tools
ValueError: If tool_use or tool_result message structure is invalid
RuntimeError: If handler is not configured
"""

View file

@ -15,7 +15,7 @@ from typing import Any
import anyio
from mcp.server.session import ServerSession
from mcp.shared.exceptions import McpError
from mcp.shared.exceptions import MCPError
from mcp.shared.experimental.tasks.helpers import RELATED_TASK_METADATA_KEY, is_terminal
from mcp.shared.experimental.tasks.message_queue import TaskMessageQueue
from mcp.shared.experimental.tasks.resolver import Resolver
@ -106,7 +106,7 @@ class TaskResultHandler:
while True:
task = await self._store.get_task(task_id)
if task is None:
raise McpError(ErrorData(code=INVALID_PARAMS, message=f"Task not found: {task_id}"))
raise MCPError(code=INVALID_PARAMS, message=f"Task not found: {task_id}")
await self._deliver_queued_messages(task_id, session, request_id)
@ -216,6 +216,6 @@ class TaskResultHandler:
"""
resolver = self._pending_requests.pop(request_id, None)
if resolver is not None and not resolver.done():
resolver.set_exception(McpError(error))
resolver.set_exception(MCPError.from_error_data(error))
return True
return False

View file

@ -11,7 +11,7 @@ from typing import TYPE_CHECKING
from mcp.server.experimental.task_support import TaskSupport
from mcp.server.lowlevel.func_inspection import create_call_wrapper
from mcp.shared.exceptions import McpError
from mcp.shared.exceptions import MCPError
from mcp.shared.experimental.tasks.helpers import cancel_task
from mcp.shared.experimental.tasks.in_memory_task_store import InMemoryTaskStore
from mcp.shared.experimental.tasks.message_queue import InMemoryTaskMessageQueue, TaskMessageQueue
@ -20,7 +20,6 @@ from mcp.types import (
INVALID_PARAMS,
CancelTaskRequest,
CancelTaskResult,
ErrorData,
GetTaskPayloadRequest,
GetTaskPayloadResult,
GetTaskRequest,
@ -135,12 +134,7 @@ class ExperimentalHandlers:
async def _default_get_task(req: GetTaskRequest) -> ServerResult:
task = await support.store.get_task(req.params.task_id)
if task is None:
raise McpError(
ErrorData(
code=INVALID_PARAMS,
message=f"Task not found: {req.params.task_id}",
)
)
raise MCPError(code=INVALID_PARAMS, message=f"Task not found: {req.params.task_id}")
return GetTaskResult(
task_id=task.task_id,
status=task.status,

View file

@ -101,7 +101,7 @@ from mcp.server.streamable_http import EventStore
from mcp.server.streamable_http_manager import StreamableHTTPASGIApp, StreamableHTTPSessionManager
from mcp.server.transport_security import TransportSecuritySettings
from mcp.shared.context import RequestContext
from mcp.shared.exceptions import McpError, UrlElicitationRequiredError
from mcp.shared.exceptions import MCPError, UrlElicitationRequiredError
from mcp.shared.message import ServerMessageMetadata, SessionMessage
from mcp.shared.session import RequestResponder
from mcp.shared.tool_name_validation import validate_and_warn_tool_name
@ -407,9 +407,7 @@ class Server(Generic[LifespanResultT, RequestT]):
case _: # pragma: no cover
raise ValueError(f"Unexpected return type from read_resource: {type(result)}")
return types.ReadResourceResult( # pragma: no cover
contents=[content],
)
return types.ReadResourceResult(contents=[content]) # pragma: no cover
self.request_handlers[types.ReadResourceRequest] = handler
return func
@ -781,13 +779,10 @@ class Server(Generic[LifespanResultT, RequestT]):
)
)
response = await handler(req)
except McpError as err:
except MCPError as err:
response = err.error
except anyio.get_cancelled_exc_class():
logger.info(
"Request %s cancelled - duplicate response suppressed",
message.request_id,
)
logger.info("Request %s cancelled - duplicate response suppressed", message.request_id)
return
except Exception as err:
if raise_exceptions: # pragma: no cover

View file

@ -314,7 +314,7 @@ class ServerSession(
The sampling result from the client.
Raises:
McpError: If tools are provided but client doesn't support them.
MCPError: If tools are provided but client doesn't support them.
ValueError: If tool_use or tool_result message structure is invalid.
StatelessModeNotSupported: If called in stateless HTTP mode.
"""

View file

@ -4,15 +4,8 @@ This module provides validation logic for sampling and elicitation requests
that is shared across normal and task-augmented code paths.
"""
from mcp.shared.exceptions import McpError
from mcp.types import (
INVALID_PARAMS,
ClientCapabilities,
ErrorData,
SamplingMessage,
Tool,
ToolChoice,
)
from mcp.shared.exceptions import MCPError
from mcp.types import INVALID_PARAMS, ClientCapabilities, SamplingMessage, Tool, ToolChoice
def check_sampling_tools_capability(client_caps: ClientCapabilities | None) -> bool:
@ -46,11 +39,11 @@ def validate_sampling_tools(
tool_choice: The tool choice setting, if provided
Raises:
McpError: If tools/tool_choice are provided but client doesn't support them
MCPError: If tools/tool_choice are provided but client doesn't support them
"""
if tools is not None or tool_choice is not None:
if not check_sampling_tools_capability(client_caps):
raise McpError(ErrorData(code=INVALID_PARAMS, message="Client does not support sampling tools capability"))
raise MCPError(code=INVALID_PARAMS, message="Client does not support sampling tools capability")
def validate_tool_use_result_messages(messages: list[SamplingMessage]) -> None:

View file

@ -2,18 +2,40 @@ from __future__ import annotations
from typing import Any, cast
from mcp.types import URL_ELICITATION_REQUIRED, ElicitRequestURLParams, ErrorData
from mcp.types import URL_ELICITATION_REQUIRED, ElicitRequestURLParams, ErrorData, JSONRPCError
class McpError(Exception):
class MCPError(Exception):
"""Exception type raised when an error arrives over an MCP connection."""
error: ErrorData
def __init__(self, error: ErrorData):
"""Initialize McpError."""
super().__init__(error.message)
self.error = error
def __init__(self, code: int, message: str, data: Any = None):
super().__init__(code, message, data)
self.error = ErrorData(code=code, message=message, data=data)
@property
def code(self) -> int:
return self.error.code
@property
def message(self) -> str:
return self.error.message
@property
def data(self) -> Any:
return self.error.data # pragma: no cover
@classmethod
def from_jsonrpc_error(cls, error: JSONRPCError) -> MCPError:
return cls.from_error_data(error.error)
@classmethod
def from_error_data(cls, error: ErrorData) -> MCPError:
return cls(code=error.code, message=error.message, data=error.data)
def __str__(self) -> str:
return self.message
class StatelessModeNotSupported(RuntimeError):
@ -33,7 +55,7 @@ class StatelessModeNotSupported(RuntimeError):
self.method = method
class UrlElicitationRequiredError(McpError):
class UrlElicitationRequiredError(MCPError):
"""Specialized error for when a tool requires URL mode elicitation(s) before proceeding.
Servers can raise this error from tool handlers to indicate that the client
@ -42,7 +64,6 @@ class UrlElicitationRequiredError(McpError):
Example:
raise UrlElicitationRequiredError([
ElicitRequestURLParams(
mode="url",
message="Authorization required for your files",
url="https://example.com/oauth/authorize",
elicitation_id="auth-001"
@ -50,23 +71,18 @@ class UrlElicitationRequiredError(McpError):
])
"""
def __init__(
self,
elicitations: list[ElicitRequestURLParams],
message: str | None = None,
):
def __init__(self, elicitations: list[ElicitRequestURLParams], message: str | None = None):
"""Initialize UrlElicitationRequiredError."""
if message is None:
message = f"URL elicitation{'s' if len(elicitations) > 1 else ''} required"
self._elicitations = elicitations
error = ErrorData(
super().__init__(
code=URL_ELICITATION_REQUIRED,
message=message,
data={"elicitations": [e.model_dump(by_alias=True, exclude_none=True) for e in elicitations]},
)
super().__init__(error)
@property
def elicitations(self) -> list[ElicitRequestURLParams]:

View file

@ -7,13 +7,8 @@ the main session code clean.
WARNING: These APIs are experimental and may change without notice.
"""
from mcp.shared.exceptions import McpError
from mcp.types import (
INVALID_REQUEST,
ClientCapabilities,
ClientTasksCapability,
ErrorData,
)
from mcp.shared.exceptions import MCPError
from mcp.types import INVALID_REQUEST, ClientCapabilities, ClientTasksCapability
def check_tasks_capability(
@ -76,36 +71,26 @@ def has_task_augmented_sampling(caps: ClientCapabilities) -> bool:
def require_task_augmented_elicitation(client_caps: ClientCapabilities | None) -> None:
"""Raise McpError if client doesn't support task-augmented elicitation.
"""Raise MCPError if client doesn't support task-augmented elicitation.
Args:
client_caps: The client's declared capabilities, or None if not initialized
Raises:
McpError: If client doesn't support task-augmented elicitation
MCPError: If client doesn't support task-augmented elicitation
"""
if client_caps is None or not has_task_augmented_elicitation(client_caps):
raise McpError(
ErrorData(
code=INVALID_REQUEST,
message="Client does not support task-augmented elicitation",
)
)
raise MCPError(code=INVALID_REQUEST, message="Client does not support task-augmented elicitation")
def require_task_augmented_sampling(client_caps: ClientCapabilities | None) -> None:
"""Raise McpError if client doesn't support task-augmented sampling.
"""Raise MCPError if client doesn't support task-augmented sampling.
Args:
client_caps: The client's declared capabilities, or None if not initialized
Raises:
McpError: If client doesn't support task-augmented sampling
MCPError: If client doesn't support task-augmented sampling
"""
if client_caps is None or not has_task_augmented_sampling(client_caps):
raise McpError(
ErrorData(
code=INVALID_REQUEST,
message="Client does not support task-augmented sampling",
)
)
raise MCPError(code=INVALID_REQUEST, message="Client does not support task-augmented sampling")

View file

@ -9,7 +9,7 @@ from contextlib import asynccontextmanager
from datetime import datetime, timezone
from uuid import uuid4
from mcp.shared.exceptions import McpError
from mcp.shared.exceptions import MCPError
from mcp.shared.experimental.tasks.context import TaskContext
from mcp.shared.experimental.tasks.store import TaskStore
from mcp.types import (
@ -19,7 +19,6 @@ from mcp.types import (
TASK_STATUS_FAILED,
TASK_STATUS_WORKING,
CancelTaskResult,
ErrorData,
Task,
TaskMetadata,
TaskStatus,
@ -68,7 +67,7 @@ async def cancel_task(
CancelTaskResult with the cancelled task state
Raises:
McpError: With INVALID_PARAMS (-32602) if:
MCPError: With INVALID_PARAMS (-32602) if:
- Task does not exist
- Task is already in a terminal state (completed, failed, cancelled)
@ -79,20 +78,10 @@ async def cancel_task(
"""
task = await store.get_task(task_id)
if task is None:
raise McpError(
ErrorData(
code=INVALID_PARAMS,
message=f"Task not found: {task_id}",
)
)
raise MCPError(code=INVALID_PARAMS, message=f"Task not found: {task_id}")
if is_terminal(task.status):
raise McpError(
ErrorData(
code=INVALID_PARAMS,
message=f"Cannot cancel task in terminal state '{task.status}'",
)
)
raise MCPError(code=INVALID_PARAMS, message=f"Cannot cancel task in terminal state '{task.status}'")
# Update task to cancelled status
cancelled_task = await store.update_task(task_id, status=TASK_STATUS_CANCELLED)

View file

@ -11,7 +11,7 @@ from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStre
from pydantic import BaseModel, TypeAdapter
from typing_extensions import Self
from mcp.shared.exceptions import McpError
from mcp.shared.exceptions import MCPError
from mcp.shared.message import MessageMetadata, ServerMessageMetadata, SessionMessage
from mcp.shared.response_router import ResponseRouter
from mcp.types import (
@ -237,7 +237,7 @@ class BaseSession(
) -> ReceiveResultT:
"""Sends a request and wait for a response.
Raises an McpError if the response contains an error. If a request read timeout is provided, it will take
Raises an MCPError if the response contains an error. If a request read timeout is provided, it will take
precedence over the session read timeout.
Do not use this method to emit notifications! Use send_notification() instead.
@ -271,18 +271,12 @@ class BaseSession(
with anyio.fail_after(timeout):
response_or_error = await response_stream_reader.receive()
except TimeoutError:
raise McpError(
ErrorData(
code=REQUEST_TIMEOUT,
message=(
f"Timed out while waiting for response to {request.__class__.__name__}. "
f"Waited {timeout} seconds."
),
)
)
class_name = request.__class__.__name__
message = f"Timed out while waiting for response to {class_name}. Waited {timeout} seconds."
raise MCPError(code=REQUEST_TIMEOUT, message=message)
if isinstance(response_or_error, JSONRPCError):
raise McpError(response_or_error.error)
raise MCPError.from_jsonrpc_error(response_or_error)
else:
return result_type.model_validate(response_or_error.result, by_name=False)

View file

@ -1654,8 +1654,8 @@ class ElicitRequestURLParams(RequestParams):
"""The URL that the user should navigate to."""
elicitation_id: str
"""
The ID of the elicitation, which must be unique within the context of the server.
"""The ID of the elicitation, which must be unique within the context of the server.
The client MUST treat this ID as an opaque value.
"""

View file

@ -59,15 +59,15 @@ class ErrorData(BaseModel):
"""The error type that occurred."""
message: str
"""
A short description of the error. The message SHOULD be limited to a concise single
sentence.
"""A short description of the error.
The message SHOULD be limited to a concise single sentence.
"""
data: Any = None
"""
Additional information about the error. The value of this member is defined by the
sender (e.g. detailed error information, nested errors etc.).
"""Additional information about the error.
The value of this member is defined by the sender (e.g. detailed error information, nested errors, etc.).
"""

View file

@ -13,7 +13,7 @@ from mcp.client.session_group import (
StreamableHttpParameters,
)
from mcp.client.stdio import StdioServerParameters
from mcp.shared.exceptions import McpError
from mcp.shared.exceptions import MCPError
@pytest.fixture
@ -225,7 +225,7 @@ async def test_client_session_group_disconnect_from_server():
async def test_client_session_group_connect_to_server_duplicate_tool_raises_error(
mock_exit_stack: contextlib.AsyncExitStack,
):
"""Test McpError raised when connecting a server with a dup name."""
"""Test MCPError raised when connecting a server with a dup name."""
# --- Setup Pre-existing State ---
group = ClientSessionGroup(exit_stack=mock_exit_stack)
existing_tool_name = "shared_tool"
@ -251,7 +251,7 @@ async def test_client_session_group_connect_to_server_duplicate_tool_raises_erro
mock_session_new.list_prompts.return_value = mock.AsyncMock(prompts=[])
# --- Test Execution and Assertion ---
with pytest.raises(McpError) as excinfo:
with pytest.raises(MCPError) as excinfo:
with mock.patch.object(
group,
"_establish_session",
@ -274,7 +274,7 @@ async def test_client_session_group_disconnect_non_existent_server():
"""Test disconnecting a server that isn't connected."""
session = mock.Mock(spec=mcp.ClientSession)
group = ClientSessionGroup()
with pytest.raises(McpError):
with pytest.raises(MCPError):
await group.disconnect_from_server(session)

Some files were not shown because too many files have changed in this diff Show more