feat(mcp): get_host groups a host's parts by kind and says what it cut
#5012 "get_host cuts `parts` without saying so" - The agent's sub-resources come back as mounts (fullest first), interfaces and disk_io (busiest first) and temperatures (hottest first), each bounded on its own with total, truncated and a `more` that names parts_limit and query_metrics. - Per-core CPU is a summary (count, min/avg/max, three busiest), so 38 cores no longer push every interface out of the reply. - New argument parts_limit (default 20, max 200). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -238,3 +238,31 @@ def test_diagnostic_tools_are_registered_read_only_for_viewers(app):
|
||||
assert mcp.tool_roles[name] is UserRole.viewer, name
|
||||
assert mcp._tool_manager.get_tool(name).annotations.read_only_hint is True, name
|
||||
assert (mcp._tool_manager.get_tool(name).description or "").strip(), f"{name} has no docstring"
|
||||
|
||||
|
||||
def test_get_host_groups_parts_by_kind_and_summarises_cores():
|
||||
from steward.mcp.tools.hosts import agent_parts
|
||||
parts = {f"core{i}": {"cpu_pct": float(i)} for i in range(38)}
|
||||
parts.update({
|
||||
"/": {"disk_used_pct": 40.0, "disk_used_bytes": 4.0, "disk_total_bytes": 10.0},
|
||||
"/data": {"disk_used_pct": 91.0},
|
||||
"net:eth0": {"net_rx_bps": 10.0, "net_tx_bps": 5.0},
|
||||
"net:br-1": {"net_rx_bps": 900.0, "net_tx_bps": 0.0},
|
||||
"net:eth1": {"net_rx_bps": 0.0, "net_tx_bps": 0.0},
|
||||
"diskio:sda": {"disk_read_bps": 1.0, "disk_write_bps": 2.0},
|
||||
"temp:Package id 0": {"temp_c": 61.0},
|
||||
})
|
||||
got = agent_parts(parts, "box", limit=2)
|
||||
# Cores are a summary, so they can't crowd out the rest.
|
||||
assert got["cpu_cores"]["count"] == 38 and got["cpu_cores"]["max_pct"] == 37.0
|
||||
assert [c["core"] for c in got["cpu_cores"]["busiest"]] == [37, 36, 35]
|
||||
assert [m["mount"] for m in got["mounts"]["items"]] == ["/data", "/"] # fullest first
|
||||
# Busiest interface first; the cut is said, with how to get the rest.
|
||||
nets = got["interfaces"]
|
||||
assert [n["interface"] for n in nets["items"]] == ["br-1", "eth0"]
|
||||
assert nets["total"] == 3 and nets["truncated"] is True
|
||||
assert "parts_limit" in nets["more"] and 'resource="box:<part>"' in nets["more"]
|
||||
assert got["disk_io"]["items"][0]["device"] == "sda"
|
||||
assert got["temperatures"]["items"][0] == {"sensor": "Package id 0", "part": "temp:Package id 0",
|
||||
"temp_c": 61.0}
|
||||
assert "other" not in got
|
||||
|
||||
Reference in New Issue
Block a user