From 0d22d275fb930df58a4971c47b3ad34250fe813a Mon Sep 17 00:00:00 2001 From: YueGuobin Date: Sat, 6 Jun 2026 23:26:21 +0800 Subject: [PATCH] fix: correct MCP template tool parameter handling for nested kwargs Fixed an issue where MCP template tools (update_template, create_template) were not correctly handling nested kwargs parameter structure from MCP clients. The problem occurred when MCP clients passed parameters in the format: {'template_id': 'xxx', 'kwargs': {'adapters': 3}} The original code was passing the entire kwargs dictionary as a parameter, instead of extracting the actual update parameters from within it. Changes: - Modified update_template_handler to extract params from nested kwargs - Modified create_template_handler to handle the same issue This fix ensures that template updates through MCP tools now work correctly, allowing proper modification of template properties like adapters count. --- gns3server/api/routes/mcp/templates.py | 29 ++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/gns3server/api/routes/mcp/templates.py b/gns3server/api/routes/mcp/templates.py index b5df86faf..e2cc71e76 100644 --- a/gns3server/api/routes/mcp/templates.py +++ b/gns3server/api/routes/mcp/templates.py @@ -52,12 +52,16 @@ def list_templates_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> def get_template_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any]: template_id = params.get("template_id") name = params.get("name") + if not template_id and not name: return {"error": "template_id or name is required"} + conn = _get_connector(gns3_ctx) template = conn.get_template(name=name, template_id=template_id) + if template is None: return {"error": "Template not found"} + return template @@ -66,26 +70,43 @@ def create_template_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> template_type = params.get("template_type") if not name or not template_type: return {"error": "name and template_type are required"} + conn = _get_connector(gns3_ctx) - return conn.create_template(**params) + + # Handle nested kwargs structure from MCP clients + if "kwargs" in params and isinstance(params["kwargs"], dict): + create_params = params["kwargs"] + else: + create_params = params + + return conn.create_template(**create_params) def update_template_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any]: template_id = params.get("template_id") name = params.get("name") + if not template_id and not name: return {"error": "template_id or name is required"} + conn = _get_connector(gns3_ctx) - return conn.update_template(name=name, template_id=template_id, **{ - k: v for k, v in params.items() if k not in ("template_id", "name") - }) + + # Extract update parameters - handle nested kwargs structure from MCP clients + if "kwargs" in params and isinstance(params["kwargs"], dict): + update_params = params["kwargs"] + else: + update_params = {k: v for k, v in params.items() if k not in ("template_id", "name", "kwargs")} + + return conn.update_template(name=name, template_id=template_id, **update_params) def delete_template_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dict[str, Any]: template_id = params.get("template_id") name = params.get("name") + if not template_id and not name: return {"error": "template_id or name is required"} + conn = _get_connector(gns3_ctx) conn.delete_template(name=name, template_id=template_id) return {"message": f"Template deleted"}