fix: list_pending_devices MCP tool leaked approved/hidden inventory rows
The backend GET /scan/pending endpoint intentionally returns the whole inventory — approved devices stay listed so the frontend can show the canvas-presence badge. The MCP tool proxied that response verbatim while its description promises devices "not yet approved or hidden", so MCP clients saw every approved device as if it were still awaiting triage (59 "pending" entries on a fully-triaged canvas, 58 of them approved). Filter the tool response to status == "pending", keeping legacy rows that predate the status field. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Udrvtwi3cqcxUNHZtBHkBg
This commit is contained in:
+6
-1
@@ -228,7 +228,12 @@ async def _dispatch(name: str, args: dict) -> dict:
|
||||
return await backend.get("/api/v1/nodes")
|
||||
|
||||
if name == "list_pending_devices":
|
||||
return await backend.get("/api/v1/scan/pending")
|
||||
# Backend /scan/pending returns the whole inventory: approved rows stay
|
||||
# listed so the frontend can show a canvas-presence badge. This tool
|
||||
# promises only devices "not yet approved or hidden", so filter to
|
||||
# actual pending rows (legacy rows without a status count as pending).
|
||||
devices = await backend.get("/api/v1/scan/pending")
|
||||
return [d for d in devices if d.get("status", "pending") == "pending"]
|
||||
|
||||
if name == "list_designs":
|
||||
return await backend.get("/api/v1/designs")
|
||||
|
||||
@@ -266,3 +266,19 @@ def test_create_design_schema_requires_name():
|
||||
async def test_unknown_tool():
|
||||
with pytest.raises(ValueError, match="Unknown tool"):
|
||||
await _dispatch("nonexistent", {})
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_list_pending_devices_filters_non_pending(mock_backend):
|
||||
"""The tool promises devices *not yet approved or hidden*; the backend
|
||||
endpoint returns the whole inventory including approved rows (they carry
|
||||
the canvas-presence badge). The tool must filter to status == "pending"
|
||||
and keep legacy rows that lack the field."""
|
||||
mock_backend.get = AsyncMock(return_value=[
|
||||
{"id": "p1", "ip": "192.168.1.50", "status": "pending"},
|
||||
{"id": "a1", "ip": "192.168.1.60", "status": "approved"},
|
||||
{"id": "h1", "ip": "192.168.1.70", "status": "hidden"},
|
||||
{"id": "legacy", "ip": "192.168.1.80"},
|
||||
])
|
||||
result = await _dispatch("list_pending_devices", {})
|
||||
assert [d["id"] for d in result] == ["p1", "legacy"]
|
||||
|
||||
Reference in New Issue
Block a user