v0.2.2 — add_device + reload_devices (full upstream parity)
Sub-project #4 PR #7 / 2 — closes the upstream parity gap. Tool surface now matches Juniper/junos-mcp-server exactly (11 tools).
Highlights
add_device— add a Junos device to the in-memory inventory and persist todevices.json. Atomic write (tempfile::NamedTempFile::persist+fsync), preserves_blocklist_defaults, per-deviceblocklist, and any other top-level keys viaserde_json::Valueround-trip withpreserve_order. SHA-256 TOCTOU guard rejects calls that race with external edits.reload_devices— re-read the current--device-mapping(no args) or swap to a new inventory file (file_name). Reportsadded/removed/changeddevice names plusprevious_router_count,new_router_count, andinventory_path.- rmcp elicitation pass-through with structured args fallback. Missing required fields surface as
JmcpError::MissingArguments.
Architecture notes
DeviceManagerswitched toArc<ArcSwap<Inventory>>for lock-free hot-swap. Per-request reads still snapshot at handler entry. Writes serialized through atokio::sync::MutexonDeviceManager.inventory_write_lock.JmcpHandlerno longer holds a staleArc<Inventory>snapshot field;get_router_listreads live fromDeviceManager.inventory()so post-mutation router list reflects reality immediately.- SIGHUP now reloads inventory in addition to the token store. Inventory reload runs first; the token-store reload then refreshes its
knownrouter list fromDeviceManager.inventory().names(). KNOWN_TOOLS(rust-junosmcp-auth) extended with"add_device"and"reload_devices"— 11 entries.
New CLI flags
--inventory-readonly— rejectadd_deviceandreload_devicesunconditionally (independent of token scopes).--allow-password-auth-add— permitauth.type=passwordinadd_device. Off by default. Mutually exclusive with--inventory-readonly.
Documented sharp edge
add_device does not modify the token store. If a token has --routers 'edge-*' and you add core-3, the existing token will not see the new router. Mint a new token or rotate scopes after add_device.
Gating order (unchanged)
transport → AuthLayer → CallerCtx → tool scope → router scope → blocklist. The two new tools are tool-scope-gated only — they don't take a router_name argument.
Install
cargo install --git https://github.com/fastrevmd-lab/RustJunosMCP --tag v0.2.2Or build from source — see README.md. LXC tarball is rust-junosmcp_0.2.2_amd64.tar.gz.
Plan & spec
- Spec:
docs/superpowers/specs/2026-05-05-templates-inventory-design.md - Plan:
docs/superpowers/plans/2026-05-05-inventory-mutation.md(16 tasks, all complete) - PR: #7
Diff
v0.2.1...v0.2.2. 244 tests passing / 9 ignored (real-device, gated on JMCP_TEST_HOST/USER/PASS).