328 Commits

Author SHA1 Message Date
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
5d0284e7be
Performance: accelerate project opening with parallel link creation and batch UDP port allocation
- Narrow IOU lock scope to only cover application_id allocation,
  allowing concurrent IOU node creation via Pool(concurrency=5)
- Parallelize link creation during project.open() using Pool(concurrency=5)
  instead of sequential processing
- Add batch UDP port allocation endpoint on compute to allocate N ports
  in a single HTTP call
- Pre-allocate UDP ports per compute before link creation during project
  loading, reducing HTTP round-trips
- UDPLink.create() falls back to individual port allocation if no
  pre-allocated port is available
2026-06-15 12:42:18 +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
8ecc35193d
feat: API key lifecycle — revoke/restore/delete
- POST /{id}/revoke: 吊销, revoked=True, 立即失效
- POST /{id}/restore: 恢复, revoked=False, 重新生效
- DELETE /{id}:       永久删除, 不可逆
- 列表接口显示所有 key 包括已吊销的
- 认证时过滤 revoked=False
2026-06-11 23:32:19 +08:00
YueGuobin
700d71d675
fix: Rename revoke_api_key → delete_api_key 2026-06-11 23:28:05 +08:00
YueGuobin
9d441517fd
fix: Hard-delete API keys instead of soft delete (revoked flag)
Removing the soft-delete approach — revoked keys are now deleted
from the database entirely via DELETE endpoint. This prevents the
api_keys table from accumulating stale records.
2026-06-11 23:27:43 +08:00
YueGuobin
bfef0a36e3
feat: Support API keys in REST API authentication (reuse gns3_ prefix keys)
API keys can now be used in Authorization: Bearer header
for all REST API endpoints, not just MCP.
2026-06-11 23:21:49 +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
YueGuobin
a79bc7dd20
feat: Add API Key support for MCP authentication
- New db model: api_keys table with bcrypt-hashed keys
- New API: POST/GET/DELETE /v3/access/api-keys endpoints
- MCP _resolve_token: validates API keys, resolves to 5-min JWT
- API keys inherit the creating user's RBAC permissions
- MCP auth supports both JWT (24h) and API key (permanent) tokens
2026-06-11 22:54:03 +08:00
YueGuobin
0b2c784b81
docs: Fix appliance_install description - it does NOT download images 2026-06-11 12:13:31 +08:00
YueGuobin
b69ff17850
docs: Fix image_install description - it auto-creates templates from uploaded images, not downloads 2026-06-11 12:00:36 +08:00
YueGuobin
05f12e1f15
docs: Clarify image_prune description - only removes unreferenced images 2026-06-11 01:42:27 +08:00
YueGuobin
d0960812aa
docs: Clarify symbol_delete limitations (built-in vs custom symbols) 2026-06-11 01:35:14 +08:00
YueGuobin
c2aae9529b
fix: Add image field to template_create, document type-specific params in description 2026-06-11 01:34:34 +08:00
YueGuobin
828a770489
fix: Remove .json() calls on 204 responses for prune/install images 2026-06-11 01:28:19 +08:00
YueGuobin
3db275b199
docs: Add GNS3 SVG rendering quirks to drawing_create description 2026-06-11 00:48:54 +08:00
YueGuobin
4b9572d565
docs: Add SVG shape examples to drawing_create tool description 2026-06-11 00:39:37 +08:00
YueGuobin
4266583922
fix: Add missing rotation parameter to drawing_update MCP tool
Parameter was defined in create_drawing but omitted from
update_drawing, causing rotation changes to be silently ignored.
2026-06-11 00:36:37 +08:00
YueGuobin
66975f54f7
fix: Map MCP device_command_run parameter to tool's expected field name
MCP sent 'device_commands' but the internal display_tools_nornir
expects 'device_configs'. Renamed parameter for consistency.
2026-06-11 00:14:00 +08:00
YueGuobin
571853599f
docs: Update link_reset description with accurate UDP connection behavior 2026-06-10 23:59:45 +08:00
YueGuobin
e7aa228ead
fix: Update link_reset description to match actual behavior (delete + recreate) 2026-06-10 23:56:30 +08:00
YueGuobin
4ec80f8989
fix: Remove unsupported description param from project_create
GNS3 REST API ProjectCreate schema does not have a description field.
The parameter was silently ignored; now removed to avoid confusion.
2026-06-10 23:32:27 +08:00
YueGuobin
80e64ebbae
fix: Fix symbol_get/upload/delete handlers for correct API paths
- get_symbol: URL was missing '/raw' suffix + tried .json() on binary SVG
  → now returns download URL + curl command (like download_capture_file)
- upload_symbol: URL was missing '/raw' suffix
  → now accepts SVG content string and POSTs to correct path
- delete_symbol: returns 204 No Content, .json() would fail
  → removed .json() call (just returns message)
2026-06-10 23:01:27 +08:00
YueGuobin
d431ff6eaa
feat: Log registered MCP tools at startup 2026-06-10 22:53:51 +08:00
YueGuobin
658a8d112b
docs: Clarify compute tools descriptions about local compute vs database computes
compute_list and compute_get only return database-registered computes.
The built-in local compute is returned by server_statistics instead.
2026-06-10 22:44:54 +08:00
YueGuobin
8b014693a8
fix: Type compute_id as uuid.UUID to reject non-UUID values at MCP input layer
Previously compute_id was typed as str, so 'local' would pass MCP validation
and reach the controller API where it crashed. Now uuid.UUID type ensures
Pydantic rejects any non-UUID string before the handler runs.
2026-06-10 22:38:38 +08:00
YueGuobin
67fa65a9e0
fix: Require UUID for compute_get/images, remove 'local' string default
The end /v3/computes/{compute_id} expects the compute_id to be a
valid UUID. Previously the MCP tool defaulted to the string 'local',
which caused a ValueError in the database layer. Now compute_id is
required and callers must use compute_list first to resolve names to UUIDs.
2026-06-10 22:31:17 +08:00