Skip to content

Commit 5d74d74

Browse files
jope-bmclaude
andauthored
fix: Enable string-to-integer conversion for build_context depth parameter (#259)
Signed-off-by: Joe P <joe@basicmemory.com> Co-authored-by: Claude <noreply@anthropic.com>
1 parent b6aeb32 commit 5d74d74

3 files changed

Lines changed: 67 additions & 2 deletions

File tree

src/basic_memory/mcp/tools/build_context.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Build context tool for Basic Memory MCP server."""
22

3-
from typing import Optional
3+
from typing import Optional, Union
44

55
from loguru import logger
66

@@ -15,6 +15,7 @@
1515
memory_url_path,
1616
)
1717

18+
type StringOrInt = str | int
1819

1920
@mcp.tool(
2021
description="""Build context from a memory:// URI to continue conversations naturally.
@@ -35,7 +36,7 @@
3536
)
3637
async def build_context(
3738
url: MemoryUrl,
38-
depth: Optional[int] = 1,
39+
depth: Optional[StringOrInt] = 1,
3940
timeframe: Optional[TimeFrame] = "7d",
4041
page: int = 1,
4142
page_size: int = 10,
@@ -80,6 +81,15 @@ async def build_context(
8081
build_context("memory://specs/search", project="work-project")
8182
"""
8283
logger.info(f"Building context from {url}")
84+
85+
# Convert string depth to integer if needed
86+
if isinstance(depth, str):
87+
try:
88+
depth = int(depth)
89+
except ValueError:
90+
from mcp.server.fastmcp.exceptions import ToolError
91+
raise ToolError(f"Invalid depth parameter: '{depth}' is not a valid integer")
92+
8393
# URL is already validated and normalized by MemoryUrl type annotation
8494

8595
# Get the active project first to check project-specific sync status

tests/cli/test_cli_tools.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,41 @@ def test_build_context_with_options(cli_env, setup_test_note):
321321
assert found, "Context did not include the test note"
322322

323323

324+
def test_build_context_string_depth_parameter(cli_env, setup_test_note):
325+
"""Test build_context command handles string depth parameter correctly."""
326+
permalink = setup_test_note["permalink"]
327+
328+
# Test valid string depth parameter - Typer should convert it to int
329+
result = runner.invoke(
330+
tool_app,
331+
[
332+
"build-context",
333+
f"memory://{permalink}",
334+
"--depth",
335+
"2", # This is always a string from CLI
336+
],
337+
)
338+
assert result.exit_code == 0
339+
340+
# Result should be JSON containing our test note with correct depth
341+
context_result = json.loads(result.stdout)
342+
assert context_result["metadata"]["depth"] == 2
343+
344+
# Test invalid string depth parameter - should fail with Typer validation error
345+
result = runner.invoke(
346+
tool_app,
347+
[
348+
"build-context",
349+
f"memory://{permalink}",
350+
"--depth",
351+
"invalid",
352+
],
353+
)
354+
assert result.exit_code == 2 # Typer exits with code 2 for parameter validation errors
355+
# Typer should show a usage error for invalid integer
356+
assert "invalid" in result.stderr and "is not a valid" in result.stderr and "integer" in result.stderr
357+
358+
324359
# The get-entity CLI command was removed when tools were refactored
325360
# into separate files with improved error handling
326361

tests/mcp/test_tool_build_context.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,23 @@ async def test_build_context_timeframe_formats(client, test_graph):
114114
for timeframe in invalid_timeframes:
115115
with pytest.raises(ToolError):
116116
await build_context.fn(url=test_url, timeframe=timeframe)
117+
118+
119+
@pytest.mark.asyncio
120+
async def test_build_context_string_depth_parameter(client, test_graph):
121+
"""Test that build_context handles string depth parameter correctly."""
122+
test_url = "memory://test/root"
123+
124+
# Test valid string depth parameter - should either raise ToolError or convert to int
125+
try:
126+
result = await build_context.fn(url=test_url, depth="2")
127+
# If it succeeds, verify the depth was converted to an integer
128+
assert isinstance(result.metadata.depth, int)
129+
assert result.metadata.depth == 2
130+
except ToolError:
131+
# This is also acceptable behavior - type validation should catch it
132+
pass
133+
134+
# Test invalid string depth parameter - should raise ToolError
135+
with pytest.raises(ToolError):
136+
await build_context.fn(url=test_url, depth="invalid")

0 commit comments

Comments
 (0)