Skip to content

Commit 9c8f763

Browse files
chore: Lazy import jsonschema library (#1596)
Co-authored-by: Max Isbey <[email protected]>
1 parent 5489e8b commit 9c8f763

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

‎src/mcp/client/session.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
importanyio.lowlevel
66
fromanyio.streams.memoryimportMemoryObjectReceiveStream, MemoryObjectSendStream
7-
fromjsonschemaimportSchemaError, ValidationError, validate
87
frompydanticimportAnyUrl, TypeAdapter
98
fromtyping_extensionsimportdeprecated
109

@@ -376,6 +375,8 @@ async def _validate_tool_result(self, name: str, result: types.CallToolResult) -
376375
logger.warning(f"Tool {name} not listed by server, cannot validate any structured content")
377376

378377
ifoutput_schemaisnotNone:
378+
fromjsonschemaimportSchemaError, ValidationError, validate
379+
379380
ifresult.structuredContentisNone:
380381
raiseRuntimeError(
381382
f"Tool {name} has an output schema but did not return structured content"

‎tests/client/test_output_schema_validation.py‎

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,27 @@ def bypass_server_output_validation():
1919
This simulates a malicious or non-compliant server that doesn't validate
2020
its outputs, allowing us to test client-side validation.
2121
"""
22-
# Patch jsonschema.validate in the server module to disable all validation
23-
withpatch("mcp.server.lowlevel.server.jsonschema.validate"):
24-
# The mock will simply return None (do nothing) for all validation calls
22+
importjsonschema
23+
24+
# Save the original validate function
25+
original_validate=jsonschema.validate
26+
27+
# Create a mock that tracks which module is calling it
28+
defselective_mock(instance: Any=None, schema: Any=None, *args: Any, **kwargs: Any) ->None:
29+
importinspect
30+
31+
# Check the call stack to see where this is being called from
32+
forframe_infoininspect.stack():
33+
# If called from the server module, skip validation
34+
# TODO: fix this as it's a rather gross workaround and will eventually break
35+
# Normalize path separators for cross-platform compatibility
36+
normalized_path=frame_info.filename.replace("\\", "/")
37+
if"mcp/server/lowlevel/server.py"innormalized_path:
38+
returnNone
39+
# Otherwise, use the real validation (for client-side)
40+
returnoriginal_validate(instance=instance, schema=schema, *args, **kwargs)
41+
42+
withpatch("jsonschema.validate", selective_mock):
2543
yield
2644

2745

0 commit comments

Comments
(0)