mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-08-27 12:30:13 +03:00
Add compact array format for link node entries to reduce token usage
Supports both standard and compact formats:
Standard: [{"node_id": "uuid", "adapter_number": 0, "port_number": 0}]
Compact: ["uuid", 0, 0, "uuid", 0, 0] - 3x less tokens
This commit is contained in:
parent
27a489a3fd
commit
a8a83051ff
@ -596,10 +596,10 @@ async def link_get(
|
||||
@mcp.tool()
|
||||
async def link_create(
|
||||
project_id: Annotated[str, Field(description="UUID of the project")],
|
||||
nodes: Annotated[list | None, Field(description="Single mode: [{node_id, adapter_number, port_number}]")] = None,
|
||||
nodes: Annotated[list | None, Field(description="Single mode: [{node_id, adapter_number, port_number}] or compact [id, ad, pt, id, ad, pt]")] = None,
|
||||
link_type: Annotated[str, Field(description="Link type - ethernet or serial")] = "ethernet",
|
||||
filters: Annotated[dict | None, Field(description="Optional packet filters")] = None,
|
||||
links: Annotated[list | None, Field(description="Batch mode: [{nodes, link_type?, filters?}] — creates multiple links in parallel")] = None,
|
||||
links: Annotated[list | None, Field(description="Batch mode: [{nodes, link_type?, filters?}] — nodes supports compact [id, ad, pt, id, ad, pt] format")] = None,
|
||||
fields: Annotated[list[str] | None, Field(description="Response fields to include (default: [link_id, link_type, nodes]). "
|
||||
"Available: link_id, project_id, link_type, nodes, suspend, "
|
||||
"link_style, filters, show_filters_icon, capturing, "
|
||||
|
||||
@ -46,6 +46,26 @@ def _get_connector(gns3_ctx: dict[str, Any]):
|
||||
)
|
||||
|
||||
|
||||
def _normalize_link_nodes(nodes) -> list[dict[str, Any]]:
|
||||
"""
|
||||
Normalize link node entries, accepting both standard object format and
|
||||
compact array format to reduce token usage.
|
||||
|
||||
Standard: [{"node_id": "uuid", "adapter_number": 0, "port_number": 0}]
|
||||
Compact: ["uuid", 0, 0, "uuid", 0, 0]
|
||||
"""
|
||||
if not nodes:
|
||||
return nodes
|
||||
if isinstance(nodes[0], dict):
|
||||
return nodes
|
||||
if isinstance(nodes, list) and len(nodes) == 6:
|
||||
return [
|
||||
{"node_id": nodes[0], "adapter_number": nodes[1], "port_number": nodes[2]},
|
||||
{"node_id": nodes[3], "adapter_number": nodes[4], "port_number": nodes[5]},
|
||||
]
|
||||
return nodes
|
||||
|
||||
|
||||
# ── Tool handlers ──────────────────────────────────────────────────────────
|
||||
|
||||
VALID_LINK_FIELDS = {
|
||||
@ -100,10 +120,11 @@ def create_link_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dic
|
||||
results = []
|
||||
conn = _get_connector(gns3_ctx)
|
||||
def _create_one(link_data):
|
||||
if not link_data.get("nodes"):
|
||||
raw_nodes = link_data.get("nodes")
|
||||
if not raw_nodes:
|
||||
return {"status": "error", "error": "nodes is required for each link"}
|
||||
try:
|
||||
body = {"nodes": link_data["nodes"]}
|
||||
body = {"nodes": _normalize_link_nodes(raw_nodes)}
|
||||
if link_data.get("link_type"):
|
||||
body["link_type"] = link_data["link_type"]
|
||||
if link_data.get("filters"):
|
||||
@ -126,7 +147,7 @@ def create_link_handler(params: dict[str, Any], gns3_ctx: dict[str, Any]) -> dic
|
||||
if not nodes:
|
||||
return {"error": "nodes is required"}
|
||||
conn = _get_connector(gns3_ctx)
|
||||
data = {"nodes": nodes}
|
||||
data = {"nodes": _normalize_link_nodes(nodes)}
|
||||
if "link_type" in params:
|
||||
data["link_type"] = params["link_type"]
|
||||
if "filters" in params:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user