refactor: sink shared REST handlers into gns3_client, drop gns3fy wrappers

- Slim custom_gns3fy.py to connector-only Gns3Connector and rename to
  connector.py; delete the unused Node/Link/Project dataclasses and
  endpoint wrapper methods (~3000 lines)
- Move the MCP node/link handler implementations into
  gns3_client/api_handlers.py as the shared REST client layer consumed
  by both the MCP service and copilot tools; add available_filters
  handler (exposed as link_available_filters MCP tool) and
  build_gns3_ctx() for copilot callers
- Rewrite the tools_v2 node/link tools on top of the handlers: batch
  lifecycle actions now run in parallel, node creation is a single
  POST, project-wide status reads replace per-node GETs
- Port Project.nodes_inventory/links_summary aggregation into
  project_inventory.py (output shape preserved) and rewrite the
  topology reader / project info tools on it, dropping the unused
  stats/snapshots/drawings calls
- Delete the dead mcp/nodes.py and mcp/links.py (NODE_TOOLS/LINK_TOOLS
  had no consumers; __init__ imports handlers from api_handlers)
- Retarget mcp handler tests to patch api_handlers._get_connector and
  replace test_custom_gns3fy.py with inventory contract tests
This commit is contained in:
YueGuobin committed 2026-08-25 09:15:32 +08:00
1 parent 1649fb7b7a
commit 629bb9194f
35 files changed
+2180 -5298

No files matched your search

@@ -516,29 +516,39 @@ gns3server/agent/gns3_copilot/tools_v2/
### API Integration
The tools use the `Node` and `Link` classes from `custom_gns3fy`:
The tools call the shared REST handler layer (`gns3_copilot.gns3_client.api_handlers`), the same functions the MCP service exposes as MCP tools:
```python
from gns3server.agent.gns3_copilot.gns3_client import Node, Link, get_gns3_connector
from gns3server.agent.gns3_copilot.gns3_client.api_handlers import (
build_gns3_ctx, create_node_handler, create_link_handler,
get_nodes_handler, start_node_handler, stop_node_handler,
suspend_node_handler, update_node_handler,
)
# Get templates
templates = get_gns3_connector().get_templates()
gns3_ctx = build_gns3_ctx() # JWT + server URL from the request context
# Create node
node = Node(project_id=project_id, template_id=template_id, x=x, y=y, connector=gns3_server)
node.create()
# Create node (single POST, batch mode is parallel)
created = create_node_handler(
{"project_id": project_id, "template_id": template_id, "x": x, "y": y, "name": name},
gns3_ctx,
)
# Create link
link = Link(project_id=project_id, connector=gns3_server, nodes=[...])
link.create()
link = create_link_handler(
{"project_id": project_id, "nodes": [{"node_id": nid, "adapter_number": 0, "port_number": 0}, ...]},
gns3_ctx,
)
# Update node name
node = Node(project_id=project_id, node_id=node_id, connector=gns3_server)
node.update(name=new_name)
# Update node name — the PUT response is the updated node
updated = update_node_handler({"project_id": project_id, "node_id": node_id, "name": new_name}, gns3_ctx)
# Start/stop/suspend node
node = Node(project_id=project_id, node_id=node_id, connector=gns3_server)
node.start() # or node.stop() / node.suspend()
# Start/stop/suspend nodes (node_ids batch runs in parallel)
start_node_handler({"project_id": project_id, "node_ids": [nid1, nid2]}, gns3_ctx)
stop_node_handler({"project_id": project_id, "node_ids": [nid1, nid2]}, gns3_ctx)
suspend_node_handler({"project_id": project_id, "node_ids": [nid1, nid2]}, gns3_ctx)
# Node listing/status (single call for the whole project)
listing = get_nodes_handler({"project_id": project_id}, gns3_ctx)
```
### Progress Tracking