105 Commits

Author SHA1 Message Date
YueGuobin
37867a1e44
fix(mcp): remove unreliable node_reload / node_reload_all tools
For Docker nodes, reload bottoms out as a raw POST /containers/{id}/restart
to the Docker daemon, bypassing GNS3's start/stop lifecycle (uBridge
re-attach, console servers, NIC setup). The container restarts at the
Docker level but GNS3's plumbing goes out of sync, and the daemon call can
block up to the controller's 240s timeout — manifesting as "reload hangs /
no response". stop+start runs the full lifecycle and is reliable.

Remove the node_reload and node_reload_all MCP tools (tool functions,
handlers, NODE_TOOLS entry, tests, docs). The underlying REST endpoints
(POST /nodes/{id}/reload, POST /nodes/reload) are kept for native API
users. MCP callers should use node_stop + node_start (partial) or
close/open project (full restart) instead.
2026-07-16 13:27:21 +08:00
YueGuobin
884c40038c
docs(mcp): note --no-close for node_console websocat usage
A heredoc (<<<) closes stdin at once, so websocat dropped the WebSocket
before the device's reply arrived. Add --no-close to the node_console usage
examples and the returned command field so the connection stays open while
output is read.
2026-07-16 00:51:45 +08:00
YueGuobin
3d6d9a3396
fix(mcp): thread token_version into console/download token minting
Token revocation is a strict version check (token_data.token_version !=
user.token_version). create_access_token defaults token_version to 0, so the
short-lived JWTs minted for the console WebSocket URL (nodes) and the download
URLs (symbols, links) carried ver=0. Any user who had logged out at least once
(token_version >= 1, e.g. the default admin) got tokens rejected as "revoked"
on first use.

e433991cf fixed this in _resolve_token's API-key branch but missed these three
independent minting sites. Now resolve token_version during _resolve_token (the
JWT branch decodes it, the API-key branch reads user.token_version), carry it
through gns3_ctx, and pass it at every minting call.
2026-07-16 00:51:45 +08:00
YueGuobin
89e11d265f
fix(mcp): pass user.token_version when generating temp JWT from API key
_resolve_token generated a temp JWT with a hardcoded ver=0 after
validating the API key. Users who had logged out at least once
(token_version >= 1) would hit "Token has been revoked" 401 on
every MCP tool call, because the REST auth chain rejects ver=0
when the user's token_version no longer matches.

Fix: pass the user's actual token_version to create_access_token
so the temp JWT carries the correct ver claim.
2026-07-16 00:51:45 +08:00
YueGuobin
ead9747e1b
Fix appliance_install: add version parameter 2026-06-17 23:03:28 +08:00
YueGuobin
0d21f294f6
Document canvas coordinate system in node_create x/y params 2026-06-16 23:16:17 +08:00
YueGuobin
00647d092c
Update docstring: batch concurrency from 10 to 100 2026-06-16 23:05:17 +08:00
YueGuobin
10ff5b2283
Add list type check before nodes[0] access in _normalize_link_nodes 2026-06-16 23:00:47 +08:00
YueGuobin
0d45bfbae5
Add fields type validation in create handlers 2026-06-16 22:58:36 +08:00
YueGuobin
f7abb62603
Rename device_command_run_handler → device_show_run_handler to match tool name 2026-06-16 12:44:12 +08:00
YueGuobin
fbb8924a8e
Rename device_command_run → device_show_run for clarity
The name device_command_run was ambiguous and easily confused with
device_config_send. device_show_run makes the read-only intent explicit,
forming a clear pair: config_send (write) vs show_run (read).
2026-06-16 12:27:35 +08:00
YueGuobin
e627481ec2
Fix device_command_run KeyError('commands'): tool desc said show_commands but backend expects commands
- Tool description and param schema now use 'commands' (matching ExecuteMultipleDeviceCommands)
- Updated error message in handler
- Clarified in docstring that this is read-only; use device_config_send for config changes
2026-06-16 12:23:15 +08:00
YueGuobin
ec58bea24b
Fix template_list return type annotation to match _run_handler_sync envelope
template_list was annotated as dict[str, Any] but _run_handler_sync always
returns a list envelope ([{"type":"text",...}]). Other tools use
list[dict[str, Any]] consistently. This caused a Pydantic dict_type
validation error on the client.
2026-06-16 12:08:07 +08:00
YueGuobin
74192f454f
Increase BATCH_MAX_WORKERS and Pool concurrency from 20 to 100 2026-06-16 00:49:08 +08:00
YueGuobin
bd15c8d019
Remove remaining dead timing variables and imports 2026-06-16 00:40:03 +08:00
YueGuobin
ccb629f48f
Clean up all timing/debug logs
Remove all [MCP-TIMING] and [CTRL-TIMING] log lines, timing middleware,
and related import time statements across 11 files.
2026-06-16 00:34:11 +08:00
YueGuobin
7d8ab399da
Fix: add missing UUID imports 2026-06-16 00:24:37 +08:00
YueGuobin
d6b337bc3a
Generate fresh JWT on API key auth instead of returning raw key
When MCP client authenticates with API key, _resolve_token now
returns a newly generated JWT. This JWT is stored in the ContextVar
and used by all subsequent tool handler API calls - zero extra bcrypt.
2026-06-16 00:09:36 +08:00
YueGuobin
e5797c3da0
Fix: pass template_id to batch mode handler so top-level template_id works as default 2026-06-15 22:57:40 +08:00
YueGuobin
cef6dc6bd2
Add detailed timing logs to MCP node creation and HTTP client
Logs with [MCP-TIMING] prefix at:
- create_node_handler entry, setup, http_call start/end, total
- http_call entry, auth, response
- _authenticate_v3 entry, done, fail
2026-06-15 22:51:43 +08:00
YueGuobin
58ca6b1dd4
Add fields filter to template_list tool with description for AI 2026-06-15 22:11:14 +08:00
YueGuobin
b79fb89866
Fix: add missing _filter_link_response function
Previously the function was referenced in create_link_handler
but never defined, causing NameError at runtime.
2026-06-15 21:51:17 +08:00
YueGuobin
1bb010d274
Pass name parameter through to controller API when creating node from template 2026-06-15 21:50:14 +08:00
YueGuobin
eb3ac64016
Add validation to compact link format with clear error messages
- Validate array length (must be exactly 6)
- Validate node_id types at positions 0 and 3
- Return descriptive errors so AI can self-correct
2026-06-15 21:46:27 +08:00
YueGuobin
a8a83051ff
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
2026-06-15 21:42:26 +08:00
YueGuobin
27a489a3fd
Add fields filter to link_create tool
- Default response: link_id, link_type, nodes (3 fields vs full 13)
- Available fields listed in tool description for AI
2026-06-15 13:50:04 +08:00
YueGuobin
11bf2d8cef
Add fields filter to node_create tool description for AI
- Expose optional 'fields' parameter to AI via tool description
- List all available node fields in the parameter description
- Mention inherited template_id in batch mode
2026-06-15 13:22:32 +08:00
YueGuobin
f4c8f9bf61
Optimize MCP create_node: support inherited template_id and default fields filter
- Batch mode now inherits top-level template_id as default per-node
- Both single and batch modes filter response to minimal fields by default
  (node_id, name, node_type, status, console)
- Optional 'fields' parameter overrides the default field set
2026-06-15 13:21:06 +08:00
YueGuobin
be69670333
feat: Add batch link_ids to link_delete/link_reset, fields filter to link_list 2026-06-14 22:43:44 +08:00
YueGuobin
d6c362b3f0
feat: Add fields filter to link_list 2026-06-14 22:37:10 +08:00
YueGuobin
3b42eea112
feat: Add batch node_ids to node_delete 2026-06-14 22:28:28 +08:00
YueGuobin
e17d298bc7
fix: Convert http to ws scheme in node_console WebSocket URL 2026-06-14 21:57:58 +08:00
YueGuobin
f14d30cb7e
feat: Add batch link_ids to link_capture_download 2026-06-14 21:36:24 +08:00
YueGuobin
6df9374a4c
feat: Add batch link_ids to link_capture_start/stop 2026-06-14 21:32:47 +08:00
YueGuobin
e02f1a8cd0
fix: Store username in gns3_ctx during auth, use for short-lived download JWTs
_ jw t_username_var set in _resolve_token for both JWT and API key auth.
Passed to handlers via gns3_ctx['jwt_username']. No raw key exposure,
no fake-user fallback.
2026-06-14 14:00:41 +08:00
YueGuobin
678b1868f5
fix: Generate independent short-lived JWT for pcap download
No longer depends on the original token type (JWT or API key).
Always creates a fresh 10-min JWT for the download URL.
2026-06-14 13:49:24 +08:00
YueGuobin
647c5c0e65
docs: Add snapshot prerequisite and suppress telnetlib3 noise 2026-06-14 12:41:14 +08:00
YueGuobin
c3c78f99a1
revert: Remove _configs_map changes in tools_v2 (handled by template renderer now) 2026-06-14 12:15:30 +08:00
YueGuobin
fb032ade78
fix: Actually pass template param to device_config/command handlers
template was defined in the tool signature but omitted from
the params dict passed to the handler, making Jinja2 rendering
completely non-functional.
2026-06-14 01:40:48 +08:00
YueGuobin
fed40c683e
fix: Correct Jinja2 template commands_field per tool type
config_tools_nornir expects config_commands, while
display_tools_nornir and vpcs_tools_netmiko expect commands.
Render template now uses the correct field name.
2026-06-14 01:33:23 +08:00
YueGuobin
8aa7f2bde5
feat: Jinja2 template support in device_command_run 2026-06-14 00:27:49 +08:00
YueGuobin
06e1511773
feat: Jinja2 template support in device_config_send
- Add optional 'template' param with Jinja2 syntax
- Each device entry can use 'vars' dict instead of 'config_commands'
- Template rendered per device, merged with existing commands
- Rendering errors returned inline for AI self-correction
2026-06-14 00:27:13 +08:00
YueGuobin
c647805cfb
feat: Add batch node_ids support to node_start/stop/reload/suspend
- Each tool accepts either node_id (single) or node_ids (batch)
- Batch mode runs actions in parallel via ThreadPoolExecutor
- Useful for starting/stopping nodes by topology region
2026-06-14 00:14:34 +08:00
YueGuobin
3d3c0eb8db
feat: Add fields filter to appliance_list
Appliances list can be very large (hundreds of entries). Use
fields=["name","category"] to return only what the AI needs.
2026-06-13 23:59:12 +08:00
YueGuobin
cd8bb7cca2
feat: Add fields filter to node_list
- Matches same VALID_NODE_FIELDS as node_get
- Return only selected fields per node to save tokens
2026-06-13 23:54:24 +08:00
YueGuobin
b9cc2d8bee
feat: node_get fields filter — match controller Node schema fields 2026-06-13 23:26:41 +08:00
YueGuobin
8f8abe4106
fix: Set auto_close=False on project_create so projects stay open when clients disconnect 2026-06-13 23:13:31 +08:00
YueGuobin
2c1a83114d
feat: Add batch mode to node_create and link_create (parallel, max 10 workers)
- node_create accepts nodes=[{template_id, x, y, name?}] for batch creation
- link_create accepts links=[{nodes, link_type?, filters?}] for batch creation
- Uses ThreadPoolExecutor for parallel REST API calls
- Max 10 concurrent workers per batch, backward compatible with single mode
2026-06-13 22:29:27 +08:00
YueGuobin
f2e5d69a2c
fix: Pass API key directly instead of generating short-lived JWT
REST API auth already supports gns3_ keys, so there's no need
to create a temporary 5-min JWT. The raw API key is passed
through as the Bearer token, eliminating token expiry issues.
2026-06-12 00:25:01 +08:00
YueGuobin
aed8830052
fix: Lazily access db engine for API key validation
_db_engine is not available when register_starlette_routes() is
called (it's set later during lifespan startup). Store the app
reference instead and access app.state._db_engine lazily.
2026-06-11 23:18:05 +08:00