fix: shared MCP truncate() crashes on None/non-string tool output (#1605)
This commit is contained in:
@@ -13,6 +13,10 @@ SEARCH_TIMEOUT = 30
|
|||||||
|
|
||||||
def truncate(text: str, limit: int = MAX_OUTPUT_CHARS) -> str:
|
def truncate(text: str, limit: int = MAX_OUTPUT_CHARS) -> str:
|
||||||
"""Truncate text to *limit* characters with a suffix note."""
|
"""Truncate text to *limit* characters with a suffix note."""
|
||||||
|
if not isinstance(text, str):
|
||||||
|
# Tool output is occasionally None or a non-string; len(None) would
|
||||||
|
# raise. Coerce so this shared helper never crashes a tool response.
|
||||||
|
text = "" if text is None else str(text)
|
||||||
if len(text) > limit:
|
if len(text) > limit:
|
||||||
return text[:limit] + f"\n... (truncated, {len(text)} chars total)"
|
return text[:limit] + f"\n... (truncated, {len(text)} chars total)"
|
||||||
return text
|
return text
|
||||||
|
|||||||
27
tests/test_mcp_common_truncate.py
Normal file
27
tests/test_mcp_common_truncate.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
"""Regression: the shared MCP truncate() must tolerate non-string input."""
|
||||||
|
import importlib.machinery
|
||||||
|
import importlib.util
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
_PATH = Path(__file__).resolve().parents[1] / "mcp_servers" / "_common.py"
|
||||||
|
|
||||||
|
|
||||||
|
def _load():
|
||||||
|
loader = importlib.machinery.SourceFileLoader("odysseus_mcp_common", str(_PATH))
|
||||||
|
spec = importlib.util.spec_from_loader(loader.name, loader)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
loader.exec_module(module)
|
||||||
|
return module
|
||||||
|
|
||||||
|
|
||||||
|
def test_truncate_handles_none_and_nonstring():
|
||||||
|
c = _load()
|
||||||
|
assert c.truncate(None) == ""
|
||||||
|
assert c.truncate(12345) == "12345"
|
||||||
|
|
||||||
|
|
||||||
|
def test_truncate_string_behaviour_unchanged():
|
||||||
|
c = _load()
|
||||||
|
assert c.truncate("hello", limit=100) == "hello"
|
||||||
|
out = c.truncate("x" * 50, limit=10)
|
||||||
|
assert out.startswith("x" * 10) and "truncated" in out
|
||||||
Reference in New Issue
Block a user