chore: Lazy import jsonschema library (#1596)

Co-authored-by: Max Isbey <224885523+maxisbey@users.noreply.github.com>
This commit is contained in:
Liang Wu 2025-11-19 07:30:52 -08:00 • committed by GitHub
commit 9c8f763aa8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 4 deletions

View file

@ -4,7 +4,6 @@ from typing import Any, Protocol, overload
import anyio.lowlevel import anyio.lowlevel
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
from jsonschema import SchemaError, ValidationError, validate
from pydantic import AnyUrl, TypeAdapter from pydantic import AnyUrl, TypeAdapter
from typing_extensions import deprecated from typing_extensions import deprecated
@ -376,6 +375,8 @@ class ClientSession(
logger.warning(f"Tool {name} not listed by server, cannot validate any structured content") logger.warning(f"Tool {name} not listed by server, cannot validate any structured content")
if output_schema is not None: if output_schema is not None:
from jsonschema import SchemaError, ValidationError, validate
if result.structuredContent is None: if result.structuredContent is None:
raise RuntimeError( raise RuntimeError(
f"Tool {name} has an output schema but did not return structured content" f"Tool {name} has an output schema but did not return structured content"

View file

@ -19,9 +19,27 @@ def bypass_server_output_validation():
This simulates a malicious or non-compliant server that doesn't validate This simulates a malicious or non-compliant server that doesn't validate
its outputs, allowing us to test client-side validation. its outputs, allowing us to test client-side validation.
""" """
# Patch jsonschema.validate in the server module to disable all validation import jsonschema
with patch("mcp.server.lowlevel.server.jsonschema.validate"):
# The mock will simply return None (do nothing) for all validation calls # Save the original validate function
original_validate = jsonschema.validate
# Create a mock that tracks which module is calling it
def selective_mock(instance: Any = None, schema: Any = None, *args: Any, **kwargs: Any) -> None:
import inspect
# Check the call stack to see where this is being called from
for frame_info in inspect.stack():
# If called from the server module, skip validation
# TODO: fix this as it's a rather gross workaround and will eventually break
# Normalize path separators for cross-platform compatibility
normalized_path = frame_info.filename.replace("\\", "/")
if "mcp/server/lowlevel/server.py" in normalized_path:
return None
# Otherwise, use the real validation (for client-side)
return original_validate(instance=instance, schema=schema, *args, **kwargs)
with patch("jsonschema.validate", selective_mock):
yield yield