Fix create_network + delete_network: POST with DevTools-confirmed format

create_network:
  - Switch from GET request() to post_request()
  - name, subnet, gateway, iprange → json.dumps(value) per DSM convention
  - disable_masquerade=json.dumps(False) added as required fixed param

delete_network:
  - Switch from GET request() to post_request() with method "remove"
    (was "delete" — wrong method name)
  - Send full network object from list response as
    networks=json.dumps([{...}]) including all DSM fields plus _key=id
    (ipv6_gateway, ipv6_subnet, ipv6_iprange, disable_masquerade with
    safe defaults for fields absent from the list response)

Tests updated: mock post_request, assert correct method/params structure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-13 18:56:21 +02:00
parent 4cee16922f
commit 59f7fc1d6c
2 changed files with 67 additions and 39 deletions
+32 -6
View File
@@ -89,20 +89,22 @@ def register_networks(mcp: FastMCP, config: AppConfig, client: DsmClient) -> Non
+ f"\n\nCall create_network(name={name!r}, confirmed=True) to confirm."
)
# DevTools-confirmed POST format: all string/bool params as json.dumps.
params: dict[str, Any] = {
"name": name,
"name": json.dumps(name),
"driver": driver,
"enable_ipv6": json.dumps(enable_ipv6),
"disable_masquerade": json.dumps(False),
}
if subnet is not None:
params["subnet"] = subnet
params["subnet"] = json.dumps(subnet)
if gateway is not None:
params["gateway"] = gateway
params["gateway"] = json.dumps(gateway)
if ip_range is not None:
params["iprange"] = ip_range
params["iprange"] = json.dumps(ip_range)
try:
result = await client.request("SYNO.Docker.Network", "create", params=params)
result = await client.post_request("SYNO.Docker.Network", "create", params=params)
except Exception as e:
return f"Error creating network '{name}': {e}"
@@ -147,8 +149,32 @@ def register_networks(mcp: FastMCP, config: AppConfig, client: DsmClient) -> Non
f"Call delete_network(name={name!r}, confirmed=True) to confirm."
)
# DevTools-confirmed POST format: method="remove", full network object
# as a JSON array in the "networks" parameter. The object must include
# all fields from the list response plus "_key" set to the network ID.
net_id = target.get("id", "")
network_obj: dict[str, Any] = {
"containers": target.get("containers") or [],
"driver": target.get("driver", ""),
"enable_ipv6": target.get("enable_ipv6", False),
"ipv6_gateway": target.get("ipv6_gateway", ""),
"ipv6_subnet": target.get("ipv6_subnet", ""),
"ipv6_iprange": target.get("ipv6_iprange", ""),
"gateway": target.get("gateway", ""),
"id": net_id,
"iprange": target.get("iprange", ""),
"name": name,
"subnet": target.get("subnet", ""),
"disable_masquerade": target.get("disable_masquerade", False),
"_key": net_id,
}
try:
await client.request("SYNO.Docker.Network", "delete", params={"name": name})
await client.post_request(
"SYNO.Docker.Network",
"remove",
params={"networks": json.dumps([network_obj])},
)
except Exception as e:
return f"Error deleting network '{name}': {e}"