Skip to content

Releases: netcopilot-labs/netcopilot

v2.3.0 — The Agent as a Tool

Choose a tag to compare

@charlesaspe charlesaspe released this 30 Jul 15:33
8dd5719

NetCopilot's MCP server now offers two pure surfaces, chosen at startup
with MCP_SURFACE and never mixed:

  • full (default) — every registry tool, byte-identical to v2.2.0.
    Nothing added, nothing renamed, zero breaking: existing clients see
    exactly what they saw yesterday.
  • ask — a single tool, ask_netcopilot(question, site?), that runs
    NetCopilot's COMPLETE internal agent server-side (deterministic routing,
    the whole toolset, the eval-guarded answer quality) and returns the
    grounded answer plus which tools it used (structuredContent = {status, tools_used}). About 100 schema tokens in the client's context
    instead of ~5,500. Expect 10-60 s per call: a full agent conversation
    runs behind it.

Why: measured in the v2.2.0 study, an external client used to pay the full
schema cost every turn while none of the internal routing/eval quality
traveled the wire. Now delegating clients get the expert; composing clients
keep the full atomic registry. Precedent: Sentry's use_sentry.

Also in this release:

  • Errors are honest MCP citizens: provider down, loop errors, empty answers
    and a 170 s hang guard all map to isError with real messages; the
    server boots and lists tools with no LLM configured.
  • Era-agnostic fastmcp import (public fastmcp.tools path) — verified on
    fastmcp 3.2.4 and 4.0.0b1.
  • Gateway docs updated: the "structured results travel direct-only"
    limitation is gone since gridctl v0.1.0-beta.14 (the upstream fix we
    contributed, gridctl#849, verified end-to-end), and tool groups
    (beta.15+) are documented as the per-client curation axis.

Suite: 1449 passed (9 new tests, also green on fastmcp 4.0.0b1).

v2.2.0 — Measured Registry Hygiene

Choose a tag to compare

@charlesaspe charlesaspe released this 29 Jul 10:08
2b8b363

Everything in this release traces to a measurement. An 864-call tool-selection
study (31B + 4B tiers, random and adversarial distractor arms) found no
count degradation at 33 tools
— the failures that did exist were textual.
So this release fixes text, hardens the measuring instrument, and installs
gates so the registry stays healthy as it grows. The planned Tool-RAG build
was cancelled by its own feasibility data.

Highlights

  • get_security_policiesget_cisco_policies: the registry's worst
    name collision (0.794 embedding similarity with get_firewall_policies,
    both descriptions claiming Cisco ACLs) split on definitions-vs-verdicts.
    Re-measured at 0.547.
  • Discriminability gate: new test fails any NEW tool pair above 0.70
    similarity; the five known overlaps are explicit, documented debt.
  • Eval: all 33 tools asserted (25 → 40 questions), including
    honest-negative questions — the assistant must say "none" when the network
    has none.
  • The eval cannot lie: load-time catalogue validation (typo'd assertions
    used to pass forever), requires: preconditions that SKIP (never FAIL)
    when a feature is absent from the loaded run, and a baseline run-id guard
    that stops cross-network diffs from reporting phantom regressions.
  • llm/ollama.pyllm/openai_compat.py: one provider per wire
    format, not per vendor. OLLAMA_* env vars unchanged (back-compat).
  • Version-drift guard: the declared version can no longer silently lag
    the newest tag (it shipped stale twice).

Breaking change

The MCP tool get_security_policies is now get_cisco_policies. Clients
discovering tools via tools/list adapt automatically; hardcoded names must
update. Everything else is backwards compatible.

Full suite: 1440 passed. Live eval: 36 pass / 0 fail / 4 honest
skips, four identical consecutive runs.

v2.1.0 — Redundancy, First-Class

Choose a tag to compare

@charlesaspe charlesaspe released this 11 Jul 08:49
c8b3945

Three features that make network redundancy a first-class, fully-answerable domain — and make the agent's tool choice auditable.

🌐 FHRP (HSRP / VRRP) first-class

Your first-hop gateways are now modeled, checked, and answerable:

  • VRRP collected (show vrrp all parse-fallback), HSRP + VRRP modeled as fhrp_group shared services — members, VIP, active router, per-member priority/timers
  • 14 executable FHRP health rules (no active router, no standby peer, VIP outside the subnet, priority conflicts, timer/version mismatches, missing auth/tracking…)
  • Ask "how is VRRP configured?", "which router is the active gateway for VLAN 60?" — answered from the live network state, completely, in one call
  • trace_path resolves a gateway VIP to its active router; blast_radius reports each gateway as PROTECTED (a standby survives) or LOST
  • NetBox reconciliation: running-but-undocumented and declared-but-absent FHRP groups become drift findings
  • New demo scenario: demo/campus-ha/

🧭 Deterministic-first tool routing + a measured agent (merged via #19)

  • routing.yaml: known question intents route deterministically — for static-argument intents the orchestrator calls the tool itself and the model only narrates. Every entry must cite the documented failure that motivated it; every decision is an auditable routing event
  • scripts/eval/: a 25-question answer-quality harness (routing accuracy, tools called, answer facts, security probes) with a model-stamped baseline — answer quality is a measured property now
  • ANSWER DEPTH calibration: open questions get the complete picture; pointed questions stay short

🔗 LAG / port-channel first-class

  • The bundle lives on the Port-channel interface: protocol, oper status, per-member LACP state (bundled / activity / priority / partner)
  • 8 executable LAG rules (bundle down, member not bundled, static bundles, speed mismatch, min-links, partner system-id mismatch, member-count mismatch, etherchannel guard); the 9th (LACP_ERRORS) is honestly manual_review — its counter isn't collected, and we don't fake checks
  • "Is the port-channel between core-sw-01 and acc-sw-03 healthy?" — answered, with the members
  • FHRP-over-LAG correlation: if your gateway peers interconnect over a single-member bundle, the redundancy assessment says aloud that failover depends on one physical link

Numbers

  • Tests: 1346 → 1423
  • Eval: 25/25 × 3 consecutive runs (local Gemma), plus a 25-question adversarial edge audit: 0 broken, 0 hallucinations, security probes clean
  • Zero new node labels, zero new MCP tools, zero provider changes — everything extends existing constructs

Full diff: v2.0.0...v2.1.0

v2.0.0 — The Declared Network

Choose a tag to compare

@charlesaspe charlesaspe released this 10 Jul 06:25
cd824af

NetCopilot 2.0 joins three sources of truth into one deterministic model: the declared network (your NetBox), the observed network (collection), and the compute layer (your vCenter / ESXi).

Highlights

  • One-click NetBox inventory. Collect your network, press Bootstrap: devices, interfaces, IPs and cables are staged, shown to you, and written to your NetBox after you approve.
  • The Service view. Name an IP in NetBox IPAM ("lobby camera") and NetCopilot draws it on the switch and port that actually serves it, with an explicit confidence verdict: port-precise / gateway / approximate / never seen. A documented IP the network has no trace of is an answer, not an omission.
  • Client networks. Tag a prefix client-network and it lands on its real access switch (its VLAN's member ports), with VLAN, port-channels and member links in the detail panel.
  • VMware integration (read-only, enforced by tests). One inventory row (os: vcenter or os: esxi) and every service shows whether it is a VM, on which ESXi node, guest OS, VMware Tools state, CPU/mem, its health and its node's health. Idle VMs classify correctly: the network cannot see a machine that never talks, the hypervisor can. One batched PropertyCollector call per collection. Hypervisor host names never leave your machine (generic node-N labels).
  • Multi-site NetBox. Scope prefixes to sites and each run's Service view shows only its own site's services; cross-site skips are reported per item, never silent.
  • No silent wipes. The service join reads NetBox strictly: a mid-pull failure keeps the previous service layer instead of deleting it and calling that "empty".

Verification

1346 tests (+32), including collector-level routing for both VMware modes, the strict-read/no-wipe contracts, site-scoping longest-match, and a wire-surface proof that the VMware integration is retrieval-only. Full pre-release audit (leaks / NetBox / VMware / UX / regression) with every finding fixed. Live-verified end-to-end against a real production network and a real vSphere cluster.

Docs

  • INSTALLATION: new sections B2 Connect your VMware and B3 Connect your NetBox (bundled --profile netbox or bring-your-own; NetBox can be added after NetCopilot at any time).
  • README: client networks, multi-site scoping, VMware capability.
  • Docker image now includes the [esxi] extra.

🤖 Generated with Claude Code

v1.5.0 — Tools that don't lie

Choose a tag to compare

@charlesaspe charlesaspe released this 04 Jul 18:32
1d43298

Tools that don't lie

A quality sweep applying one rule to the whole MCP tool surface: never report a network as clean or complete when it isn't. Driven by a read-only audit of all 25 tools.

The headline fix — the false "0 findings". The findings loader conflated three states — "the graph is unreachable", "the query errored", and "the run genuinely has no findings" — into one indistinguishable result, so tools rendered "0 findings" for all three. A down graph read as a clean network. Now the loader raises a typed FindingsUnavailable (distinct from an empty result), and every consumer surfaces it honestly: primary findings tools return an error, dashboard APIs return 503 (not a false 404), and nothing presents a fabricated zero.

The rest of the sweep

  • No "reads clean when not collected" — security posture, site summary, and device detail now account for uncollected devices instead of hiding them.
  • blast_radius stops silently ignoring interface/max_hops; its verdict and map highlight now carry the affected blast area and internet impact.
  • Captured-but-unread fields rendered — route active/inactive state, QoS policer-vs-shaper type, firewall schedule and logging flags.
  • Honest status codes — empty or failed results return no_data/error, not a misleading ok.
  • Two machine-readable verdicts where a real consumer exists — a findings severity summary and a security pass/warn/fail — with no speculative verdicts added elsewhere.

Backward-compatible; deterministic model snapshots unchanged. Verified end-to-end on a real production collection.

v1.4.0 — Path-tracing truth

Choose a tag to compare

@charlesaspe charlesaspe released this 04 Jul 16:33
3ed2adc

The policy your automation couldn't see

trace_path now tells the whole truth about a flow — and closes a class of silent failure where firewall policies referencing the FortiGate Internet Service Database (ISDB) were invisible to the tracer. A flow governed by an Internet-Service block policy used to report "no matching firewall policy found." Now it returns a real blocked/permit verdict naming the policy.

What's new

  • ISDB resolution over REST — Internet-Service references are resolved to their IP ranges via the FortiOS monitor API (referenced services only; explicit truncation flag on huge feeds; degrades gracefully). No SSH.
  • Policies stored as datadst_isdb/src_isdb on policies; resolved feeds become :ISDBService graph nodes.
  • Every policy on the path — Cisco ACLs on transit devices are now evaluated at each hop (not just at the firewall), via one shared matcher on protocol and port.
  • A typed reachability verdicttrace_path carries {result, reasons, blocked_by, risks, return_path} to any MCP client: reachable / blocked / partial / unknown, with open findings on the path surfaced as risks, and honest reasons for anything it couldn't verify — never a clean-by-omission answer.
  • Flow-shaped tracing — optional src_ip / protocol / dst_port, plus run_id to trace a past run for pre/post-change path comparison.
  • Return-path awareness — a reverse walk flags asymmetric routing and stateless-ACL return holes.

Backward-compatible: all new trace_path arguments are optional. 1047 tests; deterministic model snapshots unchanged.

v1.3.0 — Change Validation: a deterministic verdict on every change

Choose a tag to compare

@charlesaspe charlesaspe released this 04 Jul 05:04
eccb94e

NetCopilot can now judge a network change, not just describe it.

The trap this release closes: after a change, the success check is usually chosen by whoever (or whatever) made the change — a local ping, a quick glance — and it passes. From anywhere else, things are broken. An agent grading its own homework picks the test it can pass. The antidote is a verdict chosen by policy, before the fact, and computed deterministically — never by the model.

✅ Change validation — pass / warn / fail

Declare what was supposed to change; NetCopilot diffs the pre-change and post-change snapshots and judges the drift:

  • fail — a new critical/high finding appeared (regardless of scope), or any drift touches only devices outside the declared scope.
  • warn — new minor findings, drift with no declared scope, or changes that can't be attributed to a device — honest uncertainty, surfaced instead of silently dropped, and never escalated into a false fail.
  • pass — every change touches the declared scope and nothing new broke.

The policy is explicit and documented — the policy is the spec. No LLM anywhere in the verdict path: same inputs, same verdict, every time. Operational noise (the drift feature's volatile/info field contract) never affects the result, and resolved findings are reported as the good news they are.

One engine, three surfaces

  • MCP tool validate_change — the 26th tool. Declared scope as an argument; the verdict travels to any MCP client as structured content. It appeared on the external server surface with zero server changes — the registry-generated surface from v1.2.0 doing exactly what it promised.
  • CLI pipeline gatenetcopilot validate --after <run> [--before <run>] [--scope dev1,dev2] exits 0/1/2 = pass/warn/fail, so a change pipeline can gate on it directly:
    netcopilot validate --after $(post_change_run) --scope core-sw-01 || rollback
  • Dashboard banner — the Audit-tab drift view now opens with an automatic green/amber/red verdict and its reasons, above the change list it already showed. In-app menu (list_capabilities) updated accordingly.

Numbers

  • Tests: 963 → 1000 passed
  • MCP tools: 25 → 26 (external surface followed automatically)
  • New verdict engine: pure function, every policy rule pinned by its own test; verdict schema frozen (external consumers can build on it)

Full changelog: v1.2.0...v1.3.0

v1.2.0 — From Tools to Contracts

Choose a tag to compare

@charlesaspe charlesaspe released this 03 Jul 17:09
9e895d0

Three releases of spec-driven hardening, in one theme: the discipline NetCopilot always practiced in prose is now machine-enforced — in the type system, in the rule catalog, and on the MCP wire.

🏛 A constitution as step 0

NetCopilot's operating principles are now codified in CONSTITUTION.md: context agent, never actuator · determinism over cleverness · null over guessing · least privilege in config · machine-enforced contracts over prose · evidence traceability. Every future spec and PR is checked against it.

📜 Rule-catalog spec hygiene

  • First-class status: active | deferred | manual_review on all 426 rules — deferral is now explicit metadata, never disguised by renaming.
  • Spec/implementation drift found by audit and fixed (CIS timezone rule aligned to its check; mismatch-family check-logic blocks corrected).
  • The loader validates status and reports what it skipped — nothing silently disappears.

📦 Typed tool-result envelope

Every one of the 25 MCP tools now returns a frozen ToolResult(status, text, verdict, highlight, verbatim) instead of a free-form string:

  • Named failure modes as machine-readable status codes: no_datanot_foundambiguouserror. A tool that has no evidence says so in a way code can branch on — the antidote to false-OK results.
  • The contract is enforced, not requested: a handler returning anything else raises. Prose contracts drift; typed contracts fail loud.
  • Three string-convention hacks (prose-scraping, inline markers, hardcoded tool-name sets) deleted; the orchestrator consumes typed fields. Model-facing text stayed byte-identical throughout.

🌐 The full MCP surface — generated, not enumerated

The server previously exposed 3 of 25 tools to external MCP clients while the README claimed the full surface (found by our own audit). Now:

  • The surface is generated from the tool registry — names, descriptions, and parameter schemas have a single source of truth; a new tool appears externally with zero server changes. Drift between the internal and external surface is structurally impossible.
  • The envelope travels: results carry {status, verdict} as MCP structured content alongside verbatim text; tool failures map to MCP-native isError. no_data is a valid answer, not an error.
  • Root fix included: every tool context now carries the run's data directory, so file-backed tools (path tracing, OSPF detail, security posture) work identically over the external surface.

Any MCP client — Claude Desktop, an agent framework, a gateway — now sees everything NetCopilot can do, with a machine-readable contract on every result. Read-only, as always: the network is the MCP server, and it never changes devices.

Numbers

  • Tests: 931 → 963 passed (+28 skipped)
  • MCP tools exposed externally: 3 → 25
  • Free-form str tool contracts: 25 → 0
  • Orchestrator: −85 lines (string-convention workarounds deleted)

Full changelog: v1.1.0...v1.2.0

v1.1.0 — Run-to-run drift

Choose a tag to compare

@charlesaspe charlesaspe released this 02 Jul 15:41
70b9d7e

v1.1.0 — Run-to-run drift

"What changed on my network, and does it matter?" NetCopilot now compares any two runs of a site and tells you exactly what changed.

Highlights

  • Deterministic drift engine — classifies every model entity as added / removed / changed, plus an info tier for semi-volatile signals (counters, ARP/FDB, DHCP, session uptime), so an unchanged network shows zero false drift.
  • Three surfaces:
    • netcopilot diff <runA> <runB> (CLI)
    • diff_runs MCP tool for chat + external agents, incl. "N runs ago" resolution
    • Audit-tab diff mode in the dashboard: grouped change list, click-to-filter, topology halos on affected elements + ghosts for removed ones
  • Synthetic before/after demo pair (demo/drift-demo/) with a golden regression guard.
  • README "What can NetCopilot do?" capabilities overview.

Under the hood

  • ~59 new tests; goldens byte-identical; MCP tools 24 → 25.
  • Same two runs always produce the same diff.

Context, never actuation — NetCopilot tells you what changed; you decide what to do.

Full changelog: v1.0.0...v1.1.0

NetCopilot v1.0.0 — Network Context Intelligence

Choose a tag to compare

@charlesaspe charlesaspe released this 29 Jun 07:56

Network Context Intelligence — a deterministic, verifiable model of your multi-vendor network, served over MCP to humans, LLMs, and agents. Open-source, Apache 2.0.

What's in v1.0.0

  • Read-only multi-vendor collection (Cisco IOS-XE / IOS-XR, Fortinet) → an evidence-backed graph model in Neo4j. NetCopilot never writes to your devices.
  • Deterministic & traceable — the same inputs always produce the same model, and every finding traces back to the device output that proves it.
  • MCP-native — query your network as a tool from any LLM, agent, or the built-in dashboard.
  • Multitenant — many networks in one deployment, isolated end-to-end by site + run_id.
  • Bring your own — model (local, or Claude / Gemini / GPT), inventory, RAG documents, Telegram bot, and SMTP, all via .env + models.yaml. No code changes.
  • One-command deploydocker compose up.

Get started

Quickstart and full guide in README and INSTALLATION.md. Deep-dives and the roadmap: netcopilot.io.