io.github.xorrkaz/cml-mcp
An MCP server that provides access to common Cisco Modeling Labs (CML) operations.
Versions
0.10.0latestTools 51
add_interface_to_node Add a new interface to a node. Returns interface details (id, node, slot, type, MAC). Note: depending on the slot requested, multiple interfaces may be added, so a list of added interfaces is returned. Required: lab_id (lab UUID), node (node UUID). Optional: slot (0-128), mac_address (e.g. "00:11:22:33:44:55"). Examples: - "Add a new interface to node R1" - "Give the firewall another GigabitEthernet port" - "Add interface slot 3 to node xyz"
get_interfaces_for_node List all interfaces on a node by lab and node UUID. Returns id, node, label, slot, type, MAC address, and IP configuration. Examples: - "List the interfaces on R1" - "Show me the ports on the firewall" - "What interfaces does node xyz have?"
get_nodes_for_cml_lab List all nodes in a lab by lab UUID. Returns id, label, node_definition, x/y, state, interfaces, and operational data (CPU, RAM, serial consoles). Examples: - "List all nodes in my CML lab" - "What devices are in lab abc123?" - "Show me the topology nodes"
add_node_to_cml_lab Add a node to an existing lab. Returns the new node's UUID. Default interfaces are auto-created. Required: lab_id (lab UUID), node_definition (e.g. "alpine", "iosv", "csr1000v" -- discover via get_cml_node_definitions). Optional: label (1-128 chars), x/y coordinates (-15000..15000), image_definition, ram (MB, 1-1048576), cpus (1-128), cpu_limit (%, 20-100), data_volume (GB, 0-4096), boot_disk_size (GB, 0-4096), tags (list of strings), configuration (string or dict), parameters (dict), hide_links (bool), priority (0-10000), pyats (PyATS credentials dict). Examples: - "Add a CSR1000v router called 'R3' to my lab" - "Insert an IOSv switch into the topology" - "Add an Alpine node to lab abc123"
configure_cml_node Set the startup configuration for a node by lab and node UUID. The `config` is a plain string of device CLI commands. Node must be in the CREATED state (newly added or wiped). Prefer this over starting the node and using send_cli_command -- it is faster and avoids needing the node to be running. Examples: - "Set the startup config for R1 in lab abc123" - "Apply this bootstrap config to the ASAv node" - "Load the IOS config onto router xyz"
stop_cml_node Stop (power down) a single node by lab and node UUID. Examples: - "Stop node R1 in my lab" - "Power down the firewall" - "Shut down node xyz"
start_cml_node Start (boot) a single node by lab and node UUID. Set wait_for_convergence=true to block until the node reaches a stable state. Examples: - "Start router R1" - "Boot the firewall node" - "Power on node xyz and wait for convergence"
wipe_cml_node Wipe a single node's disks by lab and node UUID. Erases all node data. Node must be stopped first. CRITICAL: Destructive and irreversible. Always ask "Confirm wipe of [node]?" and wait for the user's "yes" before invoking this tool. Examples: - "Wipe node R1" - "Reset the firewall node to factory defaults" - "Erase the disk on node xyz"
delete_cml_node Delete a node from a lab by lab and node UUID. Auto-stops and wipes the node first. CRITICAL: Destructive and irreversible. Always ask "Confirm deletion of [node]?" and wait for the user's "yes" before invoking this tool. Examples: - "Delete node R1 from my lab" - "Remove the firewall from the topology" - "Get rid of node xyz"
get_annotations_for_cml_lab Get all visual annotations (text labels, shapes, lines) on a lab's canvas by lab UUID. Examples: - "Show me the annotations on my lab" - "List all labels and shapes in lab abc123" - "What's drawn on the OSPF lab canvas?"
add_text_annotation Add a text label annotation to a lab canvas. Returns the annotation UUID. Coordinates: x1/y1 are the text anchor (top-left). All coords -15000..15000. Required: x1, y1 (coords -15000 to 15000), text_content (0-8192 chars), text_font (0-128 chars), text_size (1-128), text_unit ("pt"/"px"/"em"), text_bold, text_italic (bool), border_color, color (e.g., "#FF0000"), border_style (""/"2,2"/"4,2"), thickness (1-32), z_index (-10240 to 10240), rotation (0-360 degrees). Examples: - "Add a 'Core Network' text label at position 0,0 in my lab" - "Label the router cluster at coordinates 100,200" - "Put a bold red 'IMPORTANT' note at -50,-50"
get_all_links_for_lab List all links in a lab by lab UUID. Returns id, label, interface_a, interface_b, node_a, node_b, state, and capture_key (for packet capture). Examples: - "Show all links in lab abc123" - "List the connections in my topology" - "What's wired up in my OSPF lab?"
add_rectangle_annotation Add a rectangle shape annotation to a lab canvas. Returns the annotation UUID. Coordinates: x1/y1 = top-left anchor; x2/y2 are WIDTH and HEIGHT (not bottom-right). All coords -15000..15000. Required: x1, y1 (anchor coords -15000 to 15000), x2, y2 (WIDTH and HEIGHT from anchor, not corners!), border_color, color (e.g., "#FF0000"), border_style (""/"2,2"/"4,2"), thickness (1-32), z_index (-10240 to 10240), rotation (0-360 degrees), border_radius (0-128). Examples: - "Draw a red rectangle around the routers in lab abc123" - "Add a blue box at 100,100 with width 200 height 150" - "Create a rounded rectangle to highlight the core switches"
add_ellipse_annotation Add an ellipse shape annotation to a lab canvas. Returns the annotation UUID. Coordinates: x1/y1 = anchor; x2/y2 are WIDTH and HEIGHT (per CML's X2Y2Mixin schema -- the same convention as rectangles). All coords -15000..15000. Required: x1, y1 (anchor coords -15000 to 15000), x2, y2 (WIDTH and HEIGHT from anchor), border_color, color (e.g., "#FF0000"), border_style (""/"2,2"/"4,2"), thickness (1-32), z_index (-10240 to 10240), rotation (0-360 degrees). Examples: - "Draw a green ellipse around the firewall cluster" - "Add a circle at position 50,50 with radius 100" - "Highlight the DMZ with a yellow oval"
add_line_annotation Add a line annotation to a lab canvas. Returns the annotation UUID. Coordinates: x1/y1 = start point; x2/y2 = end point (absolute, not width/height). All coords -15000..15000. Required: x1, y1 (start coords -15000 to 15000), x2, y2 (absolute end coords), border_color, color (e.g., "#0000FF"), border_style (""/"2,2"/"4,2"), thickness (1-32), z_index (-10240 to 10240), line_start, line_end ("arrow"/"square"/"circle" or None). Examples: - "Add an arrow pointing from R1 to R2" - "Draw a line from 0,0 to 200,200 with arrow on both ends" - "Connect the firewall to the internet cloud with a dashed line"
delete_annotation_from_lab Delete a single annotation by lab and annotation UUID. CRITICAL: Destructive. Always ask "Confirm deletion of [annotation]?" and wait for the user's "yes" before invoking this tool. Examples: - "Delete the 'Core Network' label" - "Remove annotation xyz from my lab" - "Get rid of the red rectangle"
get_cml_information Get CML server info: version, hostname, uptime, ready status, and configuration details. Examples: - "What version of CML is this?" - "Show me the CML server info" - "How long has the CML server been up?"
get_cml_status Get CML system health: compute, controller, virl2, and overall health indicators. Examples: - "Is CML healthy?" - "Check the CML server status" - "Are all CML components running?"
get_cml_statistics Get CML resource usage: CPU, memory, disk, and counts of running labs/nodes/links and cluster stats. Examples: - "How much CPU and memory is CML using?" - "Show me how busy the CML server is" - "How many labs and nodes are running?"
get_cml_licensing_details Get CML licensing info: registration status, features, node limits, and expiration dates. Examples: - "Is CML licensed?" - "When does my CML license expire?" - "How many nodes can I run on this license?"
get_cml_node_definitions List all available node types on this CML server. Returns id, label, general_nature (switch/router/server/desktop), and schema_version. Use this to discover valid `node_definition` values before calling add_node_to_cml_lab. Examples: - "What node types can I use in CML?" - "List all available device definitions" - "Show me the supported routers and switches"
get_node_definition_detail Get full details for one node definition by id: interfaces, default device config, boot options, and resource requirements. Examples: - "Tell me more about the csr1000v node definition" - "How many interfaces does iosv have by default?" - "What's the default RAM for an ASAv?"
connect_two_nodes Create a link between two interfaces in the same lab. Returns the new link's UUID. Required: src_int (source interface UUID) and dst_int (destination interface UUID). Get interface UUIDs from get_interfaces_for_node. Examples: - "Connect router R1 to switch SW1" - "Link the firewall to the core router" - "Wire R1 Gi0/0 to R2 Gi0/0"
stop_cml_lab Stop (power off) all running nodes in a CML lab by lab UUID. Examples: - "Stop my CML lab" - "Shut down lab abc123" - "Power off all nodes in the OSPF lab"
apply_link_conditioning Apply network impairment to a link (bandwidth limit, latency, loss, jitter, etc.) by lab and link UUID. Omitted fields keep their existing value. Optional: enabled (bool), bandwidth (kbps, 0-10M), latency (ms, 0-10K), loss (%, 0-100), jitter (ms, 0-10K), duplicate (%), corrupt_prob (%), gap (ms), limit (ms), reorder_prob (%), delay_corr/loss_corr/duplicate_corr/reorder_corr/corrupt_corr (%). Examples: - "Add 100ms latency to the link between R1 and R2" - "Limit the WAN link to 1 Mbps with 1% packet loss" - "Simulate a flaky connection on link xyz"
start_cml_link Start a link (enable connectivity) by lab and link UUID. Examples: - "Start the link between R1 and R2" - "Enable link xyz" - "Bring up the WAN connection"
stop_cml_link Stop a link (disable connectivity, simulate cable pull) by lab and link UUID. Examples: - "Stop the link between R1 and R2" - "Disable link xyz" - "Simulate a cable pull on the WAN link"
get_cml_users List all CML users. Returns id, username, fullname, email, admin status, groups, and resource_pool. Examples: - "Show me all CML users" - "Who has accounts on this CML server?" - "List the users and their groups"
create_cml_user Create a new CML user. Requires admin privileges. Returns the new user's UUID. Required: username, password. Optional: fullname, description, email (max 128 chars), groups (list of group UUIDs), admin (bool), resource_pool (UUID), associations (list of lab dicts), opt_in ("UNSET"/"ACCEPTED"/"DECLINED"), tour_version (max 128 chars), pubkey (SSH public key). Examples: - "Create a user named alice with password ChangeMe123" - "Add a new admin account 'bob'" - "Provision a CML user for carol"
delete_cml_user Delete a CML user by UUID. Requires admin privileges. CRITICAL: Destructive and irreversible. Always ask "Confirm deletion of [user]?" and wait for the user's "yes" before invoking this tool. Examples: - "Delete user alice" - "Remove the bob account from CML" - "Get rid of user xyz"
get_cml_groups List all CML groups. Returns id, name, description, members (user UUIDs), and lab associations. Examples: - "List all CML groups" - "Who's in the engineers group?" - "Show me group memberships"
create_cml_group Create a new CML group. Requires admin privileges. Returns the new group's UUID. Required: name (1-64 chars). Optional: description, members (list of user UUIDs), associations (list of lab/group association dicts). Examples: - "Create a group called 'engineers'" - "Add a new CML group named 'students'" - "Set up a group for the QA team"
delete_cml_group Delete a CML group by UUID. Requires admin privileges. CRITICAL: Destructive and irreversible. Always ask "Confirm deletion of [group]?" and wait for the user's "yes" before invoking this tool. Examples: - "Delete the 'students' group" - "Remove group xyz" - "Get rid of the QA team group"
get_console_log Get the console output history for a node by lab and node UUID. The node must be started. Returns log entries (time in ms since start + message) from the selected serial console (default 0). Some nodes (e.g. Docker-based) expose multiple consoles -- use console=1 for the second port. Useful for boot troubleshooting and verifying CLI command results. Examples: - "Show me the console output for router R1" - "Get the boot log for the firewall node" - "Tail the second console (console 1) on the Alpine container"
send_cli_command Send CLI commands to a running node via PyATS/Unicon. Identify the node by lab UUID and node label (NOT node UUID). Node must be in BOOTED state. Returns command output text. - Separate multiple commands with newlines. - config_command=false (default): exec/operational mode (e.g. "show version"). - config_command=true: configuration mode -- DO NOT include "configure terminal" or "end". - Optional console: pick a non-default serial console (e.g. console=1 for some Docker nodes). CRITICAL: Can modify device state. Review commands carefully before executing, especially when config_command=true. Examples: - "Run 'show ip route' on router R1 in lab abc123" - "Configure interface Gi0/1 with IP 10.0.0.1/24 on R1" - "Show the running config of the firewall"
start_packet_capture Start a packet capture on a link by lab and link UUID. At least one of maxtime (seconds, 1-86400) or maxpackets (1-1000000) is required. Returns true on success. Optional: bpfilter (Berkeley packet filter string, max 128 chars), encap (link encapsulation type, default "ethernet"). Examples: - "Start capturing packets on the link between R1 and R2 for 60 seconds" - "Capture 1000 packets on link xyz" - "Begin a pcap on the WAN link"
stop_packet_capture Stop an active packet capture on a link by lab and link UUID. Examples: - "Stop the packet capture on link xyz" - "End the pcap between R1 and R2" - "Stop capturing on the WAN link"
check_packet_capture_status Check whether a packet capture is active on a link, plus its config and packet count so far. Returns a PCAPStatusResponse. Examples: - "Is a capture running on link xyz?" - "How many packets have I captured so far?" - "Show packet capture status for the WAN link"
get_captured_packet_overview Get a brief one-line summary of each packet captured on a link (timestamps, src/dst, protocol). Lightweight alternative to downloading the full PCAP. Examples: - "Summarize the captured packets on link xyz" - "Show me a packet list for the WAN capture" - "What was captured between R1 and R2?"
get_packet_capture_data Download the complete PCAP file for a link by lab and link UUID. Returns base64-encoded binary PCAP data -- decode and save as a .pcap file for Wireshark, tcpdump, or other analysis tools. Examples: - "Download the pcap from link xyz" - "Give me the capture file for the WAN link" - "Get the full packet capture for the link between R1 and R2"
get_cml_labs List CML labs, optionally filtered by owner username. Returns Lab objects with id, lab_title, owner_username, description, state, and metadata. Omit `user` to get all labs (admin) or current user's labs (non-admin). Examples: - "Show me all my CML labs" - "List all available labs in CML" - "What labs does alice own?"
create_empty_lab Create an empty CML lab (no nodes/links). Returns the new lab UUID. Optional: title (1-64 chars), owner (UUID), description (<=4096 chars), notes (<=32768 chars). Use set_cml_lab_permissions to configure group/user access after creation. Examples: - "Create a new empty lab called 'OSPF Practice'" - "Make me a blank CML lab" - "Start a new lab titled 'Customer Demo'"
modify_cml_lab Update lab metadata (title, owner, description, notes) by lab UUID. Only provided fields are modified; omitted fields remain unchanged. Examples: - "Rename lab abc123 to 'Production Test'" - "Change the owner of my lab to bob" - "Update the description on lab abc123"
set_cml_lab_permissions Configure group and user permissions for a CML lab by lab UUID. Valid permissions: LAB_ADMIN (full control), LAB_EDIT (modify topology), LAB_EXEC (start/stop), LAB_VIEW (read-only). Validation: invalid entries raise an error before the request is sent. Each group dict: {"id": "<group-uuid>", "permissions": ["LAB_ADMIN", "LAB_EDIT", "LAB_EXEC", "LAB_VIEW"]} Each user dict: {"id": "<user-uuid>", "permissions": ["LAB_ADMIN", "LAB_EDIT", "LAB_EXEC", "LAB_VIEW"]} Examples: - "Give group abc read-only access to lab xyz" - "Grant user alice LAB_EDIT and LAB_EXEC permissions on my lab" - "Set permissions for lab 123: group xyz gets LAB_ADMIN, user bob gets LAB_VIEW"
create_full_lab_topology Import a complete CML lab from a Topology object (nodes + links + lab metadata). IMPORTANT: `topology` MUST be a structured object (or dict / JSON-encoded object string) matching the CML Topology schema with top-level keys `lab`, `nodes`, `links`, and optionally `annotations`. Do NOT pass a raw string such as a lab title, a YAML blob, or a non-Topology JSON string — those will fail. For simpler use cases, prefer `create_empty_lab` followed by `add_node_to_cml_lab` and `connect_two_nodes`. Expected shape: { "lab": {"title": "...", "version": "0.3.0"}, "nodes": [{"id": "n0", "label": "R1", "node_definition": "iol-xe", "x": 0, "y": 0, "interfaces": [...]}], "links": [{"id": "l0", "n1": "n0", "n2": "n1", "i1": "...", "i2": "..."}] } Required: lab (title, version), nodes (id, x, y, label, node_definition, interfaces), links (id, i1, i2, n1, n2). Optional: annotations, smart_annotations. Supports RAM, CPU, images, MAC addresses, link conditioning, and node startup configs. Examples: - "Create a full CML lab with 2 routers, 1 switch, and a firewall in a hub-spoke" - "Build a triangle topology with 3 CSR1000v routers" - "Set up a lab with an IOSv router connected to an ASAv firewall"
start_cml_lab Start (boot) a CML lab and all its nodes by lab UUID. Set wait_for_convergence=true to block until every node reports a stable state. Examples: - "Start the lab with ID abc123" - "Boot up my OSPF lab" - "Power on lab xyz and wait until it converges"
wipe_cml_lab Wipe a CML lab by UUID -- erases all node disk data and configurations. Lab is stopped first if needed. CRITICAL: Destructive and irreversible. Always ask "Confirm wipe of [lab]?" and wait for the user's "yes" before invoking this tool. Examples: - "Wipe the OSPF lab" - "Reset lab abc123 to a clean state" - "Erase all node data in my CML lab"
delete_cml_lab Delete a CML lab by UUID. Auto-stops and wipes the lab first. CRITICAL: Destructive and irreversible. Always ask "Confirm deletion of [lab]?" and wait for the user's "yes" before invoking this tool. Examples: - "Delete lab abc123" - "Remove my OSPF lab" - "Get rid of the test lab"
get_cml_lab_by_title Look up a single CML lab by its exact, case-sensitive title. Returns the Lab object. Examples: - "Get the lab titled 'OSPF Practice'" - "Find my lab named 'Customer Demo'" - "Look up the 'BGP Lab' by name"
download_lab_topology Download the full topology for a lab by UUID as a YAML string. Present this to the user for saving to a .yaml file (e.g. for backup or sharing). Examples: - "Export lab abc123 as YAML" - "Download my OSPF lab topology" - "Give me a backup of lab xyz"
clone_cml_lab Clone an existing lab by UUID, optionally with a new title. Returns the new lab's UUID. If new_title is omitted, the clone is named "Copy of <original title>". Examples: - "Clone lab abc123" - "Make a copy of my OSPF lab called 'OSPF Lab v2'" - "Duplicate the BGP lab"
Permissions 3
network medium filesystem low env_vars low