Skip to content

Commit 1b5e677

Browse files
committed
fix: ruff format + 100% coverage on dereference_local_refs
CI was failing on two checks (not test failures — earlier diagnostic was wrong): 1. pre-commit / Ruff Format — base.py had a multi-line wrap ruff wanted single-line. 2. Coverage check — project requires 100% coverage; schema.py was at 92.86% with 3 uncovered lines (empty/null $defs short-circuits + a defensive non-dict branch). Changes: - Apply ruff format to base.py. - Mark the defensive non-dict branch in inline() with '# pragma: no cover' with comment explaining it's only reachable for non-JSON-shaped values. - Add 3 tests covering the previously-uncovered branches: * empty $defs container ('{}') * null $defs ('None') * refs nested inside a list (anyOf array) Local verification: 349 server tests pass, dereference_local_refs at 100% coverage (14 tests), ruff check clean, ruff format clean. Signed-off-by: Mukunda Katta <mukunda.vjcs6@gmail.com>
1 parent 5109e64 commit 1b5e677

File tree

3 files changed

+35
-6
lines changed

3 files changed

+35
-6
lines changed

src/mcp/server/mcpserver/tools/base.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ def from_function(
7878
# JSON instead of structured objects. Inline local refs so tool schemas
7979
# are self-contained and LLM-consumable. Matches behavior of
8080
# typescript-sdk (#1563) and go-sdk.
81-
parameters = dereference_local_refs(
82-
func_arg_metadata.arg_model.model_json_schema(by_alias=True)
83-
)
81+
parameters = dereference_local_refs(func_arg_metadata.arg_model.model_json_schema(by_alias=True))
8482

8583
return cls(
8684
fn=fn,

src/mcp/server/mcpserver/utilities/schema.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
from __future__ import annotations
1616

17-
from copy import copy
1817
from typing import Any
1918

2019

@@ -68,7 +67,9 @@ def inline(node: Any, stack: set[str]) -> Any:
6867
return node
6968
if isinstance(node, list):
7069
return [inline(item, stack) for item in node]
71-
if not isinstance(node, dict):
70+
if not isinstance(node, dict): # pragma: no cover
71+
# Defensive: valid JSON only contains None/str/int/float/bool/list/dict.
72+
# Reachable only if a non-JSON-shaped value sneaks into a schema.
7273
return node
7374

7475
ref = node.get("$ref")

tests/server/mcpserver/utilities/test_schema.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from __future__ import annotations
44

5-
import pytest
5+
from typing import Any
66

77
from mcp.server.mcpserver.utilities.schema import dereference_local_refs
88

@@ -140,3 +140,33 @@ def test_original_schema_not_mutated(self) -> None:
140140
# Original still has $defs intact
141141
assert schema["$defs"] == original_defs
142142
assert schema["properties"]["x"] == {"$ref": "#/$defs/A"}
143+
144+
def test_empty_defs_returns_schema_unchanged(self) -> None:
145+
"""`$defs: {}` (empty container) is a no-op — returns input as-is."""
146+
schema = {"type": "object", "$defs": {}}
147+
result = dereference_local_refs(schema)
148+
assert result is schema # same object — no copy made on the empty path
149+
150+
def test_null_defs_returns_schema_unchanged(self) -> None:
151+
"""`$defs: null` falls through the same empty-defs path."""
152+
schema: dict[str, Any] = {"type": "object", "$defs": None}
153+
result = dereference_local_refs(schema)
154+
assert result is schema
155+
156+
def test_inlines_through_array_of_objects(self) -> None:
157+
"""Refs nested inside arrays of dict items are recursed properly.
158+
159+
Covers the `if isinstance(node, list)` branch of the inner inline().
160+
"""
161+
schema = {
162+
"anyOf": [
163+
{"$ref": "#/$defs/A"},
164+
{"$ref": "#/$defs/B"},
165+
],
166+
"$defs": {
167+
"A": {"type": "string"},
168+
"B": {"type": "integer"},
169+
},
170+
}
171+
result = dereference_local_refs(schema)
172+
assert result["anyOf"] == [{"type": "string"}, {"type": "integer"}]

0 commit comments

Comments
 (0)