mirror of
https://github.com/jmagar/unraid-mcp.git
synced 2026-03-23 20:42:58 -07:00
fix: address PR review threads (test-actions, diagnostics, docker, health, storage, plugin)
Resolves review threads:
- PRRT_kwDOO6Hdxs50R8VI (test-actions.sh: remove || echo "000" curl fallback)
- PRRT_kwDOO6Hdxs50R8VJ (test-actions.sh: JSON parse failures → FAIL not silent)
- PRRT_kwDOO6Hdxs50QdKd (diagnostics.py: sanitize raw exception text from ToolError)
- PRRT_kwDOO6Hdxs50QdKs (storage.py: unassigned uses unassignedDevices query)
- PRRT_kwDOO6Hdxs50Mwlk (docker.py: port_conflicts returns flat merged list)
- PRRT_kwDOO6Hdxs50Mwlo (docker.py: logs returns plain string not dict)
- PRRT_kwDOO6Hdxs50Mt5K (docker.py: unraid_docker logs format compatibility)
- PRRT_kwDOO6Hdxs50Mt5L (health.py: or {} null guards throughout)
- PRRT_kwDOO6Hdxs50Mt5r (docker.py: port_conflicts flat list backward compat)
- plugin.json: version synced to 0.4.4 to match pyproject.toml
Changes:
- test-actions.sh: curl exit code captured directly; JSON failures surface as FAIL
- diagnostics.py: 4 ToolError sites log exc_info=True, raise sanitized messages
- storage.py: unassigned action queries unassignedDevices instead of disks
- docker.py: logs action returns newline-joined string; port_conflicts merges
containerPorts + lanPorts into a flat list for backward compatibility
- health.py: all nested dict lookups use `or {}` instead of `.get(k, {})` to
handle explicit GraphQL null values
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -447,10 +447,21 @@ def register_docker_tool(mcp: FastMCP) -> None:
|
||||
data = await make_graphql_request(
|
||||
QUERIES["logs"], {"id": actual_id, "tail": tail_lines}
|
||||
)
|
||||
logs = safe_get(data, "docker", "logs")
|
||||
if logs is None:
|
||||
logs_data = safe_get(data, "docker", "logs")
|
||||
if logs_data is None:
|
||||
raise ToolError(f"No logs returned for container '{container_id}'")
|
||||
return {"logs": logs}
|
||||
# Extract log lines into a plain text string for backward compatibility.
|
||||
# The GraphQL response is { containerId, lines: [{ timestamp, message }], cursor }
|
||||
# but callers expect result["logs"] to be a string of log text.
|
||||
lines = logs_data.get("lines", []) if isinstance(logs_data, dict) else []
|
||||
log_text = "\n".join(
|
||||
f"{line.get('timestamp', '')} {line.get('message', '')}".strip()
|
||||
for line in lines
|
||||
)
|
||||
return {
|
||||
"logs": log_text,
|
||||
"cursor": logs_data.get("cursor") if isinstance(logs_data, dict) else None,
|
||||
}
|
||||
|
||||
if action == "networks":
|
||||
data = await make_graphql_request(QUERIES["networks"])
|
||||
@@ -468,7 +479,16 @@ def register_docker_tool(mcp: FastMCP) -> None:
|
||||
|
||||
if action == "port_conflicts":
|
||||
data = await make_graphql_request(QUERIES["port_conflicts"])
|
||||
conflicts = safe_get(data, "docker", "portConflicts", default=[])
|
||||
conflicts_data = safe_get(data, "docker", "portConflicts", default={})
|
||||
# The GraphQL response is { containerPorts: [...], lanPorts: [...] }
|
||||
# but callers expect result["port_conflicts"] to be a flat list.
|
||||
# Merge both conflict lists for backward compatibility.
|
||||
if isinstance(conflicts_data, dict):
|
||||
conflicts: list[Any] = []
|
||||
conflicts.extend(conflicts_data.get("containerPorts", []))
|
||||
conflicts.extend(conflicts_data.get("lanPorts", []))
|
||||
else:
|
||||
conflicts = list(conflicts_data) if conflicts_data else []
|
||||
return {"port_conflicts": conflicts}
|
||||
|
||||
if action == "check_updates":
|
||||
|
||||
Reference in New Issue
Block a user