forked from HomeLab/unraid-mcp
feat: add 28 GraphQL mutations across storage, info, docker, and new settings tool
- storage: flash_backup mutation (initiates rclone flash backup, destructive) - info: update_server and update_ssh mutations - docker: 11 organizer mutations (create_folder, set_folder_children, delete_entries, move_to_folder, move_to_position, rename_folder, create_folder_with_items, update_view_prefs, sync_templates, reset_template_mappings, refresh_digests); delete_entries and reset_template_mappings added to DESTRUCTIVE_ACTIONS - settings: new unraid_settings tool with 9 mutations (update, update_temperature, update_time, configure_ups, update_api, connect_sign_in, connect_sign_out, setup_remote_access, enable_dynamic_remote_access); registered in server.py - tests: 82 new tests (28 settings, 23 docker organizer, 7 info, 6 storage + 18 existing fixes for notification regex and safety audit list) - bump version 0.3.0 → 0.4.0 (11 tools, ~104 actions) 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -156,7 +156,22 @@ QUERIES: dict[str, str] = {
|
||||
""",
|
||||
}
|
||||
|
||||
ALL_ACTIONS = set(QUERIES)
|
||||
MUTATIONS: dict[str, str] = {
|
||||
"update_server": """
|
||||
mutation UpdateServerIdentity($name: String!, $comment: String, $sysModel: String) {
|
||||
updateServerIdentity(name: $name, comment: $comment, sysModel: $sysModel) {
|
||||
id name comment status
|
||||
}
|
||||
}
|
||||
""",
|
||||
"update_ssh": """
|
||||
mutation UpdateSshSettings($input: UpdateSshInput!) {
|
||||
updateSshSettings(input: $input) { id useSsh portssh }
|
||||
}
|
||||
""",
|
||||
}
|
||||
|
||||
ALL_ACTIONS = set(QUERIES) | set(MUTATIONS)
|
||||
|
||||
INFO_ACTIONS = Literal[
|
||||
"overview",
|
||||
@@ -178,6 +193,8 @@ INFO_ACTIONS = Literal[
|
||||
"ups_devices",
|
||||
"ups_device",
|
||||
"ups_config",
|
||||
"update_server",
|
||||
"update_ssh",
|
||||
]
|
||||
|
||||
if set(get_args(INFO_ACTIONS)) != ALL_ACTIONS:
|
||||
@@ -310,6 +327,11 @@ def register_info_tool(mcp: FastMCP) -> None:
|
||||
async def unraid_info(
|
||||
action: INFO_ACTIONS,
|
||||
device_id: str | None = None,
|
||||
server_name: str | None = None,
|
||||
server_comment: str | None = None,
|
||||
sys_model: str | None = None,
|
||||
ssh_enabled: bool | None = None,
|
||||
ssh_port: int | None = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Query Unraid system information.
|
||||
|
||||
@@ -333,6 +355,8 @@ def register_info_tool(mcp: FastMCP) -> None:
|
||||
ups_devices - List UPS devices
|
||||
ups_device - Single UPS device (requires device_id)
|
||||
ups_config - UPS configuration
|
||||
update_server - Update server name, comment, and model (requires server_name)
|
||||
update_ssh - Enable/disable SSH and set port (requires ssh_enabled, ssh_port)
|
||||
"""
|
||||
if action not in ALL_ACTIONS:
|
||||
raise ToolError(f"Invalid action '{action}'. Must be one of: {sorted(ALL_ACTIONS)}")
|
||||
@@ -340,6 +364,40 @@ def register_info_tool(mcp: FastMCP) -> None:
|
||||
if action == "ups_device" and not device_id:
|
||||
raise ToolError("device_id is required for ups_device action")
|
||||
|
||||
# Mutation handlers — must return before query = QUERIES[action]
|
||||
if action == "update_server":
|
||||
if server_name is None:
|
||||
raise ToolError("server_name is required for 'update_server' action")
|
||||
variables_mut: dict[str, Any] = {"name": server_name}
|
||||
if server_comment is not None:
|
||||
variables_mut["comment"] = server_comment
|
||||
if sys_model is not None:
|
||||
variables_mut["sysModel"] = sys_model
|
||||
with tool_error_handler("info", action, logger):
|
||||
logger.info("Executing unraid_info action=update_server")
|
||||
data = await make_graphql_request(MUTATIONS["update_server"], variables_mut)
|
||||
return {
|
||||
"success": True,
|
||||
"action": "update_server",
|
||||
"data": data.get("updateServerIdentity"),
|
||||
}
|
||||
|
||||
if action == "update_ssh":
|
||||
if ssh_enabled is None:
|
||||
raise ToolError("ssh_enabled is required for 'update_ssh' action")
|
||||
if ssh_port is None:
|
||||
raise ToolError("ssh_port is required for 'update_ssh' action")
|
||||
with tool_error_handler("info", action, logger):
|
||||
logger.info("Executing unraid_info action=update_ssh")
|
||||
data = await make_graphql_request(
|
||||
MUTATIONS["update_ssh"], {"input": {"enabled": ssh_enabled, "port": ssh_port}}
|
||||
)
|
||||
return {
|
||||
"success": True,
|
||||
"action": "update_ssh",
|
||||
"data": data.get("updateSshSettings"),
|
||||
}
|
||||
|
||||
query = QUERIES[action]
|
||||
variables: dict[str, Any] | None = None
|
||||
if action == "ups_device":
|
||||
|
||||
Reference in New Issue
Block a user