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

@@ -38,8 +38,10 @@ from typing import Any
from langchain.tools import BaseTool
from langchain_core.callbacks import CallbackManagerForToolRun
from gns3server.agent.gns3_copilot.gns3_client import Node
from gns3server.agent.gns3_copilot.gns3_client import get_gns3_connector
from gns3server.agent.gns3_copilot.gns3_client.api_handlers import (
build_gns3_ctx,
create_node_handler,
)
# Configure logging
logger = logging.getLogger(__name__)
@@ -194,11 +196,11 @@ class GNS3CreateNodeTool(BaseTool):
f"template_id, x, or y."
}
# Initialize Gns3Connector using factory function
# Build handler context (JWT + server URL from request context)
logger.info("Connecting to GNS3 server...")
gns3_server = get_gns3_connector()
gns3_ctx = build_gns3_ctx()
if gns3_server is None:
if gns3_ctx is None:
logger.error("Failed to create GNS3 connector")
return {
"error": "Failed to connect to GNS3 server. "
@@ -228,22 +230,22 @@ class GNS3CreateNodeTool(BaseTool):
name,
)
# Create node
node = Node(
project_id=project_id,
template_id=template_id,
x=x,
y=y,
name=name,
connector=gns3_server,
# Create node via the shared REST handler
created = create_node_handler(
{
"project_id": project_id,
"template_id": template_id,
"x": x,
"y": y,
"name": name,
},
gns3_ctx,
)
node.create()
# Retrieve node details
node.get()
if "error" in created:
raise RuntimeError(created["error"])
node_info = {
"node_id": node.node_id,
"name": node.name,
"node_id": created.get("node_id"),
"name": created.get("name"),
"status": "success",
}