Agent skill

Packet Tracer

by Mats2208 in Mats2208/MCP-Packet-Tracer

A skill your agent uses when building, automating, or debugging Cisco Packet Tracer networks through the packet-tracer MCP (the pt tools) — planning topologies from natural language, live-deploying…

MITAuto-check passedAgent Workflows

Install Packet Tracer

skills CLI
$ npx skills add Mats2208/MCP-Packet-Tracer --skill packet-tracer -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Mats2208/MCP-Packet-Tracer packet-tracer --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/Mats2208/MCP-Packet-Tracer.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skill .claude/skills/packet-tracer && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
packet-tracer
GitHub stars
247
Token cost
~7.5k tokens
SKILL.md length
3,452 words
Files
1
Skills in repo
1
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when building, automating, or debugging Cisco Packet Tracer networks through the packet-tracer MCP (the pt tools) — planning topologies from natural language, live-deploying…

  • Works in 5 steps: If you did not read it from a tool… → Before planning/deploying:… → Before any raw JS: use only methods in… → …
  • Debugging Cisco Packet Tracer networks through the packet-tracer MCP (the pt tools) — planning topologies from natural language
  • SKILL.md covers ⛔ Prime directive: DISCOVER,…, The bridge (mental model), Mandatory workflow and Tool catalog (62), plus 9 more sections
  • Needs PT_MCP_BRIDGE_TOKEN

What it does

Packet Tracer is an agent skill from Mats2208/MCP-Packet-Tracer. Use when building, automating, or debugging Cisco Packet Tracer networks through the packet-tracer MCP (the pt tools) — planning topologies from natural language, live-deploying into a running Packet Tracer, adding devices / links / modules, applying ACL / NAT, exporting configs, or writing raw Script-Engine JS via ptsendraw. This is the authoritative reference for the tool catalog, the mandatory discover→plan→validate→deploy workflow, the EXACT PT Script-Engine API (so you never invent method names), and the…

Its SKILL.md is about 7.5k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Agent Workflows, covering MCP servers. It works with Model Context Protocol and Python. The repository describes itself as: AI-powered Cisco Packet Tracer automation over MCP. Describe a network in natural language and it generates, validates and deploys full topologies (OSPF, EIGRP, RIP, DHCP). The licence is MIT.

When your agent uses it

  • Debugging Cisco Packet Tracer networks through the packet-tracer MCP (the pt tools) — planning topologies from natural language
  • Live-deploying into a running Packet Tracer
  • Adding devices / links / modules
  • Applying ACL / NAT

Example prompts

  • “/packet-tracer”

Workflow steps

5 steps, taken from the first numbered list in SKILL.md.

  1. If you did not read it from a tool result, an MCP resource, or this skill, **you do not know
  2. Before planning/deploying: pt_list_devices, pt_list_templates, pt_get_device_details,
  3. Before any raw JS: use only methods in the Verified Script-Engine API table below. If you
  4. After every mutation, read back with pt_query_topology / pt_export_topology and confirm.
  5. When something isn't in the catalog, say so — do not fabricate a device/module to fill the gap.

What it can do on your machine

Read from SKILL.md and the folder at commit 3c7c7a4. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are javascript and python).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • PT_MCP_BRIDGE_TOKEN

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Packet Tracer loads about 7.5k tokens when it runs. Until then it costs about 158 tokens; SKILL.md has 3,452 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~158
When it runs · the whole SKILL.md, loaded when a task matches
~7.5k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from Mats2208/MCP-Packet-Tracer at commit 3c7c7a4, republished under its MIT licence (© Mats2208). 3,452 words, ~7,451 tokens.

Download SKILL.mdSave it as .claude/skills/packet-tracer/SKILL.md (or your agent's skills folder).
name
packet-tracer
description
Use when building, automating, or debugging Cisco Packet Tracer networks through the `packet-tracer` MCP (the `pt_*` tools) — planning topologies from natural language, live-deploying into a running Packet Tracer, adding devices / links / modules, applying ACL / NAT, exporting configs, or writing raw Script-Engine JS via `pt_send_raw`. This is the authoritative reference for the tool catalog, the mandatory discover→plan→validate→deploy workflow, the EXACT PT Script-Engine API (so you never invent method names), and the known rough edges. Load it before driving the MCP so you act from verified facts, not guesses.

Packet Tracer MCP — operating guide

A Model Context Protocol server (packet-tracer) that drives Cisco Packet Tracer: plan a topology, validate it, generate IOS/PTBuilder artifacts, and live-deploy into a running PT over an HTTP bridge. The pt_* tools are your only interface — plus raw JS via pt_send_raw.

⛔ Prime directive: DISCOVER, never invent

The single biggest failure mode for a model driving this MCP is guessing — a model name, a port name, a slot id, a cable type, a module name, or a Script-Engine API method. Every one of these is discoverable, and a wrong guess either fails validation or (for raw JS) freezes Packet Tracer (see the modal-freeze rule below).

Rules:

  1. If you did not read it from a tool result, an MCP resource, or this skill, you do not know it — look it up first.
  2. Before planning/deploying: pt_list_devices, pt_list_templates, pt_get_device_details, and pt_list_modules (if installing modules).
  3. Before any raw JS: use only methods in the Verified Script-Engine API table below. If you need something not listed, probe it inside a try/catch before relying on it.
  4. After every mutation, read back with pt_query_topology / pt_export_topology and confirm.
  5. When something isn't in the catalog, say so — do not fabricate a device/module to fill the gap.

The bridge (mental model)

LLM ──▶ MCP server ──▶ HTTP bridge :54321 ──▶ MCP Control Center (PT extension) ──▶ PT Script Engine
  • The MCP queues JS at :54321; the PT extension polls /next every 500 ms and runs each command via $se('runCode', …) in PT's Script Engine, posting results back to /result.
  • XMLHttpRequest does NOT exist in the Script Engine (only in the extension webview). That's why all I/O goes through the bridge.
  • Confirm the link first with pt_bridge_status → must say "ACTIVE and CONNECTED". If "NOT connected", the user opens Extensions → MCP BUILDER in PT (or dismisses a stuck error modal).

Mandatory workflow

  • New topology, one-shot: pt_full_build.
  • New topology, stepwise: pt_list_devices → pt_plan_topology → pt_validate_plan → pt_live_deploy.
  • Edit a live topology: pt_bridge_status → pt_query_topology → pt_add_*/pt_rename_device/….
  • Add modules: pt_query_topology → pt_list_modules(router_model=…) → pt_install_modules_batch.

Tool catalog (62)

Discovery / read-only: pt_list_devices, pt_get_device_details(model|alias), pt_list_templates, pt_list_modules(router_model, category), pt_list_projects, pt_load_project, pt_bridge_status, pt_query_topology, pt_export_topology (*need bridge). Pure planning/generation: pt_plan_topology, pt_estimate_plan, pt_validate_plan, pt_fix_plan, pt_explain_plan, pt_generate_script(include_configs), pt_generate_configs, pt_full_build(deploy=…). pt_plan_topology/pt_full_build accept vlans, dual_stack, ipv6_base, wireless_laptops. Disk / clipboard: pt_export, pt_deploy. PT project files: pt_save_project(filename) / pt_open_project(path) — these write and read the real .pkt, which is NOT what pt_export does (that one dumps the plan and scripts to disk). pt_open_project replaces the current topology. Live deploy & edit: pt_live_deploy (auto-reconciles dropped devices), pt_add_device, pt_add_link, pt_delete_link, pt_delete_device, pt_rename_device, pt_move_device, pt_set_port, pt_send_raw, pt_add_module, pt_install_modules_batch. ACL / NAT (live): pt_apply_acl, pt_apply_acl_object, pt_remove_acl, pt_remove_acl_object, pt_apply_nat, pt_remove_nat — all accept dry_run=True to preview CLI without touching PT. Config-driven (live, dry_run): pt_apply_vlan (VLAN/trunk/inter-VLAN subinterfaces), pt_apply_stp, pt_apply_port_security, pt_apply_hardening (hostname/banner/enable-secret/users/SSH), pt_apply_interface_tuning (serial clock-rate + OSPF/EIGRP per-interface knobs). Verification (live): pt_diff (plan vs live), pt_health_check (down links, dup IPs, cabled-no-IP). pt_verify_connectivity gives three verdicts, not two: CONECTIVIDAD OK (every packet returned), CONECTIVIDAD PARCIAL (some loss — normal on a first ping because of ARP, so re-run once before calling it a fault) and SIN CONECTIVIDAD. It works from routers and switches, not only hosts. pt_health_check no longer lists layer-2 ports as "cabled without IP", so anything it does report there is a real host that never got its DHCP lease. Live-state inspection (read the device, not the plan): pt_audit_security(device="") (security posture with severities; never returns passwords or hashes, only the algorithm label), pt_inspect_ports(device, only_linked) (per-port line/protocol, MAC, duplex, bandwidth, MTU, CDP, NAT mode, applied ACLs; flags cabled-but-down), pt_read_vlans(switch) (real VLAN database, separates your VLANs from PT's factory ones), pt_device_power(device, on) (power-cycle with read-back). Canvas (capture & annotate): pt_screenshot(filename, fmt, output_dir) writes the image to disk and returns the path — never the bytes, they would flood the context. pt_add_note(x, y, text) writes a label; font size is not settable. pt_clear_annotations(kind) removes annotations only, never devices or links (drawings included — redraw circles after clearing notes). There is no drawing tool, but PT's drawCircle does work from raw JS once you pass all seven arguments — see "Drawing IS possible" below. Colours still don't take. Canvas coordinates match pt_add_device: routers ~y=100, switches ~y=250, hosts ~y=400. Recipe for a diagram worth showing: pt_full_build → pt_add_note per subnet and link → drawCircle per LAN → pt_screenshot → adjust and repeat. Backup / workspace: pt_backup_config(device, include_xml) (real startup-config + serial, config-register, boot images), pt_project_metadata(description="") (saved filename, PT version, description, device/link count; pass description to set it), pt_workspace_options(...) — tri-state flags, -1 leaves a setting alone. Turn auto_cabling=0 before a scripted build if you need links on exact interfaces, and check external_network_access before assuming traffic stays in the simulator. DHCP on a Server-PT: pt_configure_dhcp_server(device, network, mask, gateway, dns, start_ip, max_users, pool_name="serverPool", port="FastEthernet0", enabled, drop_factory_pool, remove, dry_run) creates/edits a pool on a server (GUI: Services > DHCP), turns the service on and reads every pool back. Without network it only reads. Router DHCP is a different thing: IOS CLI ip dhcp pool, which is what dhcp=True in the planner emits. Give the server a static IP inside the pool's subnet first. Telemetry / QoS: pt_apply_netflow(device, name, destination_ip, udp_port, version, source_port, monitors, remove, dry_run) configures a NetFlow exporter directly (not via CLI) and reads it back to confirm. pt_read_qos(device) is read-only: QoS cannot be created programmatically, so author class-maps and policy-maps with IOS CLI and use this to verify. Simulation: pt_simulation_mode(on) (Realtime ↔ Simulation), pt_simulation_step(action, times) (forward/back/reset), pt_read_packet_trace(limit, device, include_decisions) — the event list plus PT's own per-OSI-layer explanation of each decision (same text as the GUI's PDU Details pane). Workflow: pt_simulation_mode(on=True) → generate traffic (pt_verify_connectivity) → pt_read_packet_trace. There is no pt_send_pdu: PT does not let an extension originate a packet the way the GUI's Add Simple PDU button does. Generate traffic with a real ping instead. Resources: pt://catalog/devices, /cables, /aliases, /templates, pt://capabilities.

Advanced builds (verified live 2026-06-27)

  • Inter-VLAN / router-on-a-stick: pt_full_build(template="router_on_a_stick", vlans=3) → N VLANs, trunk uplink, router .1q subinterfaces, one /24 + DHCP pool per VLAN. 2960 omits trunk encapsulation (dot1q-only); 3560 emits it.
  • IPv6 dual-stack: pt_plan_topology(dual_stack=True) → routers get ipv6 address via CLI + ipv6 unicast-routing; hosts use SLAAC (configurePcIpv6 = enable + auto-config). Static host IPv6 is NOT settable via the PT API (addIpv6Address fails on HostPort) — SLAAC is the path.
  • WiFi laptops: wireless_laptops=True swaps each Laptop-PT NIC to PT-LAPTOP-NM-1W (slot "0") → Wireless0, and adds one AccessPoint-PT per LAN, each wired to that LAN's own switch. ⚠️ Wireless addressing is NOT deterministic. Laptops auto-associate on the default SSID and PT exposes no SSID API (verified: neither the AP nor its port has setSsid), so with more than one AP a laptop can associate to any of them and take a DHCP lease from another LAN's pool. Measured on PT 9.0.1: LT10, sitting right next to its own LAN's AP, still associated to the LAN-1 AP and got 192.168.0.13; only with that AP powered off did it take 192.168.4.25. The planner now emits a WIRELESS_AMBIGUOUS_ASSOCIATION warning when ≥2 APs coexist. Always confirm with pt_inspect_ports; for deterministic addressing use wireless_laptops=False.

⚠️ Verified PT Script-Engine API (for pt_send_raw / raw JS)

These are the real signatures (verified against the MCP's runtime patches and live testing). If a method is not here, do not assume it exists.

Globals

  • getDevices(filter) → Array of NAME STRINGS, not device objects (filter "" = all, "router" = routers). Calling .getName() / .getPorts() on an element throws TypeError: Property 'getName' of object R1 is not a function — the element is "R1". To get the object, feed each name to ipc.network().getDevice(name).
  • allModuleTypes[name] → module-type handle (passed to addModule)
  • reportResult(data) → exists only when wait_result=True; POSTs the result back
  • ❌ there is no global getDevice(...); ❌ no XMLHttpRequest in the Script Engine

Network / device — var d = ipc.network().getDevice("R1"); // ← correct singular lookup, may be null

  • ipc.appWindow().getActiveWorkspace().getLogicalWorkspace() → lw
    • lw.addDevice(type, model, x, y) → autoName · lw.createLink(d1,p1,d2,p2,cableEnumInt)
  • d.getPorts() → Array of port-name strings — use .length, [i], .join(","). ❌ never .size(), .at(i), .getName() on it (TypeError → modal → freeze).
  • d.getPort(name) → Port | null · d.getPower()/setPower(bool)/skipBoot()/setName(name)
  • d.moveToLocation(x, y) → reposiciona en el canvas lógico. Es lo que usa pt_move_device; en un solo pt_send_raw podés reacomodar decenas de dispositivos sin una llamada por cada uno.
  • d.addModule(slot, allModuleTypes[model], modelName) → bool (slot is a STRING)
  • d.getProcess("AclProcess") → AclProcess | null (routers) · d.enterCommand(cmd, mode)
  • d.getCommandLine() → console handle with getOutput(), enterCommand(cmd), getPrompt(). Use this for console work: getCommandPrompt() exists ONLY on hosts and throws TypeError on any router. PCs expose both, so getCommandLine() covers both worlds. ⚠️ A router deployed by the MCP was never touched by console, so it sits at Would you like to enter the initial configuration dialog? [yes/no]: — a ping sent there is eaten as the yes/no answer. Prime it first: answer no, then send an empty command to clear Press RETURN to get started.
  • d.setDhcpFlag(bool), d.setDefaultGateway(ip)

Port — var p = d.getPort("GigabitEthernet0/0");

  • p.getLink() → link | null (null = free) · p.setIpSubnetMask(ip, mask) · p.setDefaultGateway(ip)
  • p.setDnsServerIp(ip) · p.setAclInID(id)/p.setAclOutID(id) (pass "" to clear)

AclProcess — var ap = d.getProcess("AclProcess");

  • ap.addAcl(name) · ap.getAcl(name) → acl|null · ap.removeAcl(name)
  • acl.addStatement(str) → bool · acl.getCommandCount() → int

DHCP server (Server-PT only) — verified PT 9.0 + IpcAPI reference (class_dhcp_server_process)

  • var s = d.getProcess("DhcpServerMain").getDhcpServerProcessByPortName("FastEthernet0"); getProcess("DhcpServerMain") is null on routers, switches and PCs; a wrong port name → null. ⚠️ DhcpServerMain itself has no pool methods (getPoolCount etc. are undefined there) — that is why issue #23 concluded it was impossible. They live one level down, on s.
  • s.addPool(name) (a repeated name does not duplicate) · s.getPool(name) → pool|null · s.removePool(name) · s.getPoolCount() / s.getPoolAt(i) · s.setEnable(bool) / s.isEnable() · s.addExcludedAddress(ip, ip). Avoid addNewPool(...): 8 unnamed arguments in the reference.
  • Pool: setNetworkAddress(ip) · setNetworkMask(network, mask) — TWO args, one arg throws Invalid arguments for IPC call · setDefaultRouter(ip) · setDnsServerIp(ip) · setStartIp(ip) · setMaxUsers(n) (recomputes the end from the start, so set start first) · setEndIp(ip). Getters: getDhcpPoolName/getNetworkAddress/getSubnetMask/getDefaultRouter/getDnsServerIp/ getStartIp/getEndIp/getMaxUsers. There is no setter for TFTP, WLC or domain name.
  • Behaviour measured live: PT never leases the server's own IP, but does lease the gateway's if the range covers it. The factory serverPool re-fits itself to the server's subnet with start = network address and no gateway, so next to a named pool it hands out .1. After changing a pool, clients keep their old lease — even one outside the new range. Toggling setDhcpFlag does not renew; run ipconfig /release then ipconfig /renew on the host console.

Cable enum ints (for lw.createLink): straight 8100 · cross 8101 · roll 8102 · fiber 8103 · phone 8104 · cable 8105 · serial 8106 · auto 8107 · console 8108 · wireless 8109 · coaxial 8110 · octal 8111 · cellular 8112 · usb 8113 · custom_io 8114.

🔒 ALWAYS wrap raw JS in try/catch
js
try { var d = ipc.network().getDevice("R1"); reportResult("ports="+d.getPorts().join(",")); }
catch (e) { reportResult("ERR: " + e); }

An uncaught error pops a modal QMessageBox in PT ("An error occurred… ReferenceError…") that is modal and freezes the webview polling loop — the bridge goes "NOT connected" until a human clicks OK. A caught error never does. (The server also guards commands now, but wrap anyway — it's free insurance and keeps results clean.)

Validation: read plan.errors before you deploy

pt_plan_topology / pt_full_build return errors[] and warnings[]; pt_validate_plan returns the same as typed codes. An empty errors[] is now meaningful — it did not used to be. The validator only checked per-device facts, so a topology split into islands passed with valid: true, deployed, and failed silently. It now walks the graph.

CodeWhat it meansWhat to do
TOPOLOGY_DISCONNECTEDThe cabled devices form more than one component — something has no path to the restUsually the hub ran out of ports (a 2911 has 3 Gigabit). Use a bigger model, add a module, or fewer routers. Do not deploy: the isolated part cannot route
OSPF_NO_NETWORKSAn OSPF process with zero network statementsThat router has no addressed, linked interface. Fix the links first
OSPF_INVALID_ROUTER_IDrouter-id 0.0.0.0, which IOS rejectsSame root cause as above
WIRELESS_AMBIGUOUS_ASSOCIATIONwarning — two or more APs share the default SSIDNot a blocker. Confirm with pt_inspect_ports which subnet each wireless host actually landed in
IP_CONFLICT / INVALID_IP_ADDRESSDuplicate or malformed addressRe-address
DHCP_GATEWAY_MISMATCHwarning — the pool gateway is on no interface of that routerCheck the pool against the router's interfaces

Wireless hosts are excluded from the connectivity graph on purpose: they carry no cable by design, so counting them as islands would flag every wireless topology as broken.

Big topologies: when the plan does not fit through a tool parameter

pt_live_deploy takes the plan as a string argument, so a plan with ~90 devices (thousands of lines of JSON) cannot practically be passed to it, and pt_load_project only hands the JSON back to you.

For anything past roughly 60 devices, or for shapes the templates do not cover (mixed IGPs per region, custom cores), build it locally and push it straight to the mailbox — the plan never has to travel through a tool call:

python
from src.packet_tracer_mcp.domain.models.plans import TopologyPlan, DevicePlan, LinkPlan
from src.packet_tracer_mcp.domain.services.validator import validate_plan
from src.packet_tracer_mcp.infrastructure.generator.ptbuilder_generator import (
    generate_executable_script,
)
from src.packet_tracer_mcp.infrastructure.execution.file_bridge import FileBridge

plan = TopologyPlan(...)                 # devices, links, ospf/eigrp/rip_configs, vlans
result = validate_plan(plan)             # same rules the MCP uses — check it first
script = generate_executable_script(plan)

bridge = FileBridge()
assert bridge.pt_alive()                 # Script Engine heartbeat
for batch in chunks(script.split("
"), 25):
    body = "".join(f"try{{{line}}}catch(e){{}}" for line in batch)
    bridge.send_and_wait(body + "reportResult('ok');", timeout=90.0)

Verified: 88 devices, 88 links, 282 JS statements in 12 batches over the file bridge. One try/catch per statement so a single failure does not take the batch down. A plan can carry ospf_configs, eigrp_configs and rip_configs at the same time — and one router can appear in two of them, which is how you build a redistribution boundary. redistribute itself is not in the plan model: push it as extra CLI with configureIosDevice(name, cli).

Show full SKILL.md (1,384 more words)Show less

Common mistakes → corrections (do not repeat these)

❌ Wrong✅ RightWhy
getDevice("R1")ipc.network().getDevice("R1") (or getDevices("") to list)no global getDevice → ReferenceError → freeze
d.getPorts().size() / .at(i) / .getName()d.getPorts()[i] (string array)getPorts returns strings
getProcess("DhcpServerMain").getPoolCount()getProcess("DhcpServerMain").getDhcpServerProcessByPortName("FastEthernet0").getPoolCount() (or pt_configure_dhcp_server)the pools live on the per-port process
pt_add_module(slot=0)slot="0" (string)int slot silently fails (=== compare)
cable "crossover""cross"alias works but cross is canonical
invent model "Cisco4500"pt_list_devices / pt_get_device_details firstuse real catalog names
invent module "NM-4T"pt_list_modules(router_model=…) firstuse real module names
raw JS unwrappedwrap in try/catch + reportResultuncaught error freezes the bridge
trust add_module "timeout" = failureverify with pt_query_topologyit often succeeds despite timeout

Cables, ports, IP conventions

  • Cables (15): straight, cross, roll, serial, fiber, console, phone, cable, coaxial, auto, wireless, octal, cellular, usb, custom_io. Omit cable_type in pt_add_link to infer (router↔router & switch↔switch → cross; router↔switch, switch↔host → straight).
  • Exact ports: 2911 GigabitEthernet0/0..0/2 but 1941/2901 only 0/0..0/1; ISR4321/4331 GigabitEthernet0/0/0..; 2960/3560 FastEthernet0/1..0/24 + GigabitEthernet0/1..0/2; PC/Laptop/Server FastEthernet0; HWIC-2T in "0/x" → Serial0/x/0,Serial0/x/1; Cloud-PT has 8 ports: Serial0..3, Modem4, Modem5, Ethernet6, Coaxial7. ⚠️ A cloud only forwards over its serial ports once frame relay is configured, and the MCP has no tool for that. For a WAN core that actually passes traffic, link routers to each other with /30s and hang the cloud off Ethernet6 as an external stub.
  • IP plan (pt_plan_topology): LANs /24 from 192.168.0.0, gateway .1, hosts from .2; router↔router /30 from 10.0.0.0; DHCP pool per LAN with .1 excluded; routing static|ospf|eigrp|rip|none (+ floating_routes, ospf_process_id, eigrp_as).

Module install by router family

slot is a STRING. Pick a module whose compatible_with includes the model — the MCP rejects an incompatible module up front when the module declares compatible_with (HWIC/NIM/built-ins); generic PT-* modules have no declared constraint, so choose sensibly there. Always confirm with pt_query_topology after install; a single pt_add_module may report a timeout yet still succeed.

Router familyModule typeSlot (string)Ports addedStatus
ISR G2 — 2911/2901HWIC (HWIC-2T, HWIC-1GE-SFP)"0/0".."0/3"Serial0/x/0,Serial0/x/1✅ verified 2911
ISR G2 — 1941HWIConly "0/0", "0/1" — it has 2 slots, not 4Serial0/x/0,Serial0/x/1✅ verified 1941 (PT 9.0.1)
ISR 4000 — ISR4321/4331NIM (NIM-2T, NIM-ES2-4)"0/1", "0/2"Serial0/1/0,Serial0/1/1✅ verified ISR4321 & ISR4331
2811 / 2620XM / 2621XMNM (NM-4A/S, NM-2FE2W,…)"1"Serial1/0..1/3✅ verified 2811
Router-PT (generic)NM (NM-*, PT-ROUTER-NM-*)"1"⚠️ non-standard ids (e.g. Serial2/0)installs, odd port names

⚠️ The pt_add_module docstring/SERVER_INSTRUCTIONS say NIM slots are "0"/"1" — that is wrong; the working slot is "0/1" (chassis/subslot). HWIC = "0/x", NM = "1", NIM = "0/1". The install mechanism (addModule) is identical across routers — only the slot string differs by family. Always confirm the result with pt_query_topology.

Prefer pt_install_modules_batch for multiple modules (one power-cycle); individual installs power-cycle the device and can exceed the wait window (and often report a timeout despite succeeding).

Known rough edges (verified by benchmark against PT 9.0.1)

  • Module compatibility is enforced for modules that declare compatible_with (HWIC/NIM/built-ins reject a wrong model); generic PT-* modules carry no constraint, so still pick sensibly.
  • pt_add_module (single) can report a timeout but still succeed — verify ports, don't blindly retry. (pt_install_modules_batch no longer guesses: it reports installed per module, see round 2 below.)
  • three_router_triangle closes the ring (R3↔R1) and hub_spoke wires R1→every spoke — the orchestrator honors the template shape (was a flat chain before). ⚠️ hub_spoke is limited by the hub's port count: a 2911 has 3 Gigabit ports, so it cannot serve 5 spokes plus its own LAN. Asking for more no longer fails silently — the plan comes back with TOPOLOGY_DISCONNECTED. Pick a router with more ports, add a module, or use multi_lan (a chain needs only 3 ports per router).
  • pt://capabilities is derived from the live tool registry (supported_live.nat/acl/modules/…) — it can no longer drift; trust it and the tools.
  • pt_live_deploy "N/N verified" checks device/link existence only — host IPs may lag a few seconds.
  • Invalid routing= raises a raw exception; invalid router_model returns a degenerate plan with an embedded errors[] — always check plan.errors before deploying.
  • A harmless phantom Power Distribution Device can appear after deploy (off-canvas).
☠️ Never iterate a native PT object with for...in
js
var d = lw.getEllipseItemData(id);
for (var k in d) { ... }   // ← CRASHES Packet Tracer. The whole app dies.

try/catch does not save you: this is not a JS exception, it is the script engine blowing up and taking the process with it. Verified the hard way against PT 9.0.1 — the app closed with "Cisco Packet Tracer quit unexpectedly".

Inspect native objects by calling known getters and stringifying the result, never by enumerating keys. If you don't know the shape, probe one accessor at a time.

Drawing IS possible — drawCircle takes SEVEN arguments
js
lw.drawCircle(x, y, ignored, diameter, 0, 0, 0)   // x,y = TOP-LEFT corner

Returns an ellipse id and really draws. With 3–6 arguments it throws, which is why it was believed unusable — same failure mode as setHideDevLabel (needs 2, not 1): the call was fine, the arity was wrong. The old note that "the size argument controls stacking order" came from passing the size in slot 3; slot 4 is the diameter and slot 3 is ignored.

Calibrated on PT 9.0.1 at default zoom: the drawn diameter is roughly 0.71 × the argument, so to circle a LAN centred at cx use drawCircle(cx - 173, y, 0, 480, 0,0,0). Don't compute it blind — draw, pt_screenshot, adjust. Clear with pt_clear_annotations (it removes drawings too, so redraw circles after clearing notes).

Colours still don't work: the last three arguments accept values but the ellipse comes out with the default outline.

Verified against PT 9.0.1 (audit round 2)
  • The bridge starts lazily. After the MCP server restarts (a /mcp reconnect), nothing is listening on :54321 until the first pt_* call — importing the server deliberately opens no socket. So "not connected" right after a reconnect usually means nobody has called a tool yet, not that the extension died: just call pt_bridge_status and PT resumes polling in seconds. Don't ask the user to reopen MCP BUILDER before trying that.
  • getClassName() is useless for telling a switch from a router. PT classifies by behaviour: a 3560 answers "Router" (it is multilayer) and a 2960 answers "CiscoDevice" — neither ever says "switch". Use getModel() and resolve it against the catalog.
  • addModule() returns false instead of throwing when the slot does not exist on that model. Check the return value; a silent false used to be reported as a successful install. pt_add_module and pt_install_modules_batch now verify it and report installed / failed per module.
  • Renaming to a name that is already taken used to be allowed and left two devices sharing it, with getDevice(name) resolving only to one — the other became unreachable by name. Now rejected.
Verified against PT 9.0.1 (audit round 3)
  • A router deployed by the MCP has never been touched through its console, so it is still parked at Would you like to enter the initial configuration dialog? [yes/no]:. A ping sent there is eaten as the yes/no answer and never runs. Prime it first: send no, then an empty command to clear Press RETURN to get started. (pt_verify_connectivity now does this for you.)
  • An IOS interface with no IP address stays shut down. The CLI generator only emits no shutdown for addressed interfaces, so a link you cabled but never addressed shows up as a red triangle on the canvas and as a down link in pt_health_check. Give it an address, even a throwaway /30.
  • PT does not associate a wireless host with the nearest AP. Measured: a laptop with its own LAN's AP right beside it did a fresh association and a fresh DHCP and still chose the AP of another LAN, taking that LAN's address. Between APs sharing the default SSID the choice is arbitrary, and there is no SSID API to force it (neither the AP nor its port has setSsid). If you need deterministic addressing, use wireless_laptops=False and cable the laptops.
  • PT_MCP_BRIDGE_TOKEN is validated. If the server refuses to start with BridgeTokenError, the variable is set to something shorter than 32 chars or outside [A-Za-z0-9_-]. Fix it or unset it so the on-disk token is used. It fails loudly on purpose: a bad value there would disable the only real defence the bridge has.
  • The layout adapts to the busiest LAN. Coordinates no longer go negative and LAN clusters no longer overlap, so you do not need to reposition devices by hand after pt_full_build — only if you want a specific arrangement.

Recipes

  • "2 routers, 2 switches, 4 PCs, DHCP, static" → pt_full_build(routers=2, switches_per_router=1, pcs_per_lan=2, dhcp=True, routing="static", deploy=True).
  • 4 serial ports on R1 (2911) → pt_install_modules_batch([{device:"R1",slot:"0/0",module:"HWIC-2T"}, {device:"R1",slot:"0/1",module:"HWIC-2T"}]).
  • Block telnet to a server on R1 → pt_apply_acl(router="R1", name_or_number="101", acl_type="extended", entries=[{action:"deny",protocol:"tcp",source:"any",destination:"host 192.168.0.10",dest_port_op:"eq", dest_port:23},{action:"permit",protocol:"ip",source:"any",destination:"any"}], binding_interface="GigabitEthernet0/0", binding_direction="in", dry_run=True) — preview first.
  • Read a device's ports safely → pt_send_raw('try{var d=ipc.network().getDevice("R1");reportResult(d?d.getPorts().join(","):"missing")}catch(e){reportResult("ERR:"+e)}', wait_result=True).

© Mats2208, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skill of Mats2208/MCP-Packet-Tracer.

Open the folder on GitHubat commit 3c7c7a4

Compare with similar skills

Packet Tracer next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Packet Tracer compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Packet Tracer this skillMats2208/MCP-Packet-Tracer247—~7.5kAutomated safety check: PassMIT
MCP Scaffoldtimothywarner-org/claude-code224—~940Automated safety check: PassMIT
Open PRArcadeAI/arcade-mcp1k—~2.9kAutomated safety check: PassMIT
MCP DeveloperJeffallan/claude-skills12k—~1.5kAutomated safety check: PassMIT
MCP Server Builderanthropics/skills180k63 repos~2.3kAutomated safety check: PassApache-2.0
MCP Server BuildershareAI-lab/learn-claude-code78k4 repos~1.2kAutomated safety check: PassMIT

Similar skills

  • MCP Scaffold

    timothywarner-org/claude-code

    Scaffold production-ready Python MCP servers using FastMCP. An agent skill from timothywarner-org/claude-code.

    224 GitHub stars~940 tokensUpdated 2 mo ago
    Agent WorkflowsAuto-check passed
  • Open PR

    ArcadeAI/arcade-mcp

    Prepare arcade-mcp changes for review by verifying intended behavior, filling the repository PR template, and creating or updating the PR.

    1k GitHub stars~2.9k tokensUpdated yesterday
    Agent WorkflowsAuto-check passed
  • MCP Developer

    Jeffallan/claude-skills

    Builds and debugs MCP servers and clients in TypeScript or Python, from tool and resource definitions to transport setup and inspector-based protocol checks.

    12k GitHub stars~1.5k tokensUpdated 7 days ago
    Agent WorkflowsAuto-check passed
  • MCP Server Builder

    anthropics/skills

    Official

    Guides the design and implementation of Model Context Protocol servers in TypeScript or Python, from tool naming and error messages to evaluation.

    180k GitHub starsUsed in 63 repos~2.3k tokens
    Agent WorkflowsAuto-check passed
  • MCP Server Builder

    shareAI-lab/learn-claude-code

    Walks through building MCP servers in Python or TypeScript that expose tools, resources and prompts to Claude, with templates, registration and testing.

    78k GitHub starsUsed in 4 repos~1.2k tokens
    Agent WorkflowsAuto-check passed
  • Installs and configures MemPalace as a private local palace, a shared-brain hub or a client of an existing hub, including MCP registration and version-correct initialization.

    59k GitHub stars~2.2k tokensUpdated today
    Agent WorkflowsAuto-check passed

Questions about Packet Tracer

What does Packet Tracer do?

A skill your agent uses when building, automating, or debugging Cisco Packet Tracer networks through the packet-tracer MCP (the pt tools) — planning topologies from natural language, live-deploying…. Packet Tracer is an agent skill from Mats2208/MCP-Packet-Tracer. Use when building, automating, or debugging Cisco Packet Tracer networks through the packet-tracer MCP (the pt tools) — planning topologies from natural language, live-deploying into a running Packet Tracer, adding devices / links / modules, applying ACL / NAT, exporting configs, or writing raw Script-Engine JS via ptsendraw.

When should I use Packet Tracer?

Packet Tracer fits situations like: debugging Cisco Packet Tracer networks through the packet-tracer MCP (the pt tools) — planning topologies from natural language; live-deploying into a running Packet Tracer; adding devices / links / modules; applying ACL / NAT.

How do I install Packet Tracer in Claude Code?

Run `npx skills add Mats2208/MCP-Packet-Tracer --skill packet-tracer -a claude-code`. Or copy the skill folder (skill in Mats2208/MCP-Packet-Tracer) into .claude/skills/packet-tracer in your project. Claude Code loads it when a task matches its description.

How do I install Packet Tracer in Codex?

Run `npx skills add Mats2208/MCP-Packet-Tracer --skill packet-tracer -a codex`. Or copy the skill folder (skill in Mats2208/MCP-Packet-Tracer) into .agents/skills/packet-tracer in your project. Codex loads it when a task matches its description.

Can I use Packet Tracer in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Mats2208/MCP-Packet-Tracer --skill packet-tracer -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/packet-tracer, .gemini/skills/packet-tracer, .github/skills/packet-tracer and .opencode/skills/packet-tracer in your project.

What does Packet Tracer need to run?

Going by SKILL.md and its folder, Packet Tracer needs credentials named PT_MCP_BRIDGE_TOKEN.

Does Packet Tracer access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Packet Tracer safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Packet Tracer use?

Packet Tracer is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Packet Tracer use?

About 7.5k tokens (SKILL.md is roughly 30k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Packet Tracer?

Skills that share tags, products or a category with Packet Tracer: MCP Scaffold (timothywarner-org/claude-code, 224 stars), Open PR (ArcadeAI/arcade-mcp, 1k stars), MCP Developer (Jeffallan/claude-skills, 12k stars) and MCP Server Builder (anthropics/skills, 180k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Packet Tracer?

Mats2208 (a GitHub user) maintains it in Mats2208/MCP-Packet-Tracer, which has 247 GitHub stars. The repository was last updated on October 7, 2026.

Source: Mats2208/MCP-Packet-Tracer on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.