@aristanetworks/eos-mcp-server 0.6.1-beta → 0.8.0-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +197 -44
  3. package/dist/cli.d.ts +4 -1
  4. package/dist/cli.js +63 -4
  5. package/dist/cli.js.map +1 -1
  6. package/dist/commands/inspectDiagnostics.d.ts +3 -0
  7. package/dist/commands/inspectDiagnostics.js +35 -0
  8. package/dist/commands/inspectDiagnostics.js.map +1 -0
  9. package/dist/commands/releaseDiagnostics.d.ts +9 -0
  10. package/dist/commands/releaseDiagnostics.js +87 -0
  11. package/dist/commands/releaseDiagnostics.js.map +1 -0
  12. package/dist/config/diagnostics.d.ts +60 -0
  13. package/dist/config/diagnostics.js +37 -0
  14. package/dist/config/diagnostics.js.map +1 -0
  15. package/dist/config/loadConfig.js +6 -1
  16. package/dist/config/loadConfig.js.map +1 -1
  17. package/dist/config/schema.d.ts +168 -8
  18. package/dist/config/schema.js +3 -0
  19. package/dist/config/schema.js.map +1 -1
  20. package/dist/diagnostics/concurrency.d.ts +33 -0
  21. package/dist/diagnostics/concurrency.js +157 -0
  22. package/dist/diagnostics/concurrency.js.map +1 -0
  23. package/dist/diagnostics/eapiRunner.d.ts +10 -0
  24. package/dist/diagnostics/eapiRunner.js +46 -0
  25. package/dist/diagnostics/eapiRunner.js.map +1 -0
  26. package/dist/diagnostics/executionError.d.ts +7 -0
  27. package/dist/diagnostics/executionError.js +10 -0
  28. package/dist/diagnostics/executionError.js.map +1 -0
  29. package/dist/diagnostics/executor.d.ts +32 -0
  30. package/dist/diagnostics/executor.js +115 -0
  31. package/dist/diagnostics/executor.js.map +1 -0
  32. package/dist/diagnostics/journal.d.ts +14 -0
  33. package/dist/diagnostics/journal.js +317 -0
  34. package/dist/diagnostics/journal.js.map +1 -0
  35. package/dist/diagnostics/journalTypes.d.ts +8 -0
  36. package/dist/diagnostics/journalTypes.js +2 -0
  37. package/dist/diagnostics/journalTypes.js.map +1 -0
  38. package/dist/diagnostics/ping.d.ts +7 -0
  39. package/dist/diagnostics/ping.js +131 -0
  40. package/dist/diagnostics/ping.js.map +1 -0
  41. package/dist/diagnostics/releaseEvidence.d.ts +502 -0
  42. package/dist/diagnostics/releaseEvidence.js +115 -0
  43. package/dist/diagnostics/releaseEvidence.js.map +1 -0
  44. package/dist/diagnostics/reservationSchema.d.ts +49 -0
  45. package/dist/diagnostics/reservationSchema.js +18 -0
  46. package/dist/diagnostics/reservationSchema.js.map +1 -0
  47. package/dist/diagnostics/statePath.d.ts +4 -0
  48. package/dist/diagnostics/statePath.js +25 -0
  49. package/dist/diagnostics/statePath.js.map +1 -0
  50. package/dist/diagnostics/types.d.ts +82 -0
  51. package/dist/diagnostics/types.js +2 -0
  52. package/dist/diagnostics/types.js.map +1 -0
  53. package/dist/eapi/client.d.ts +3 -1
  54. package/dist/eapi/client.js +17 -6
  55. package/dist/eapi/client.js.map +1 -1
  56. package/dist/eapi/types.d.ts +6 -0
  57. package/dist/eapi/types.js.map +1 -1
  58. package/dist/index.js +10 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/inventory/buildModel.js +1 -0
  61. package/dist/inventory/buildModel.js.map +1 -1
  62. package/dist/inventory/listInventoryView.d.ts +1 -0
  63. package/dist/inventory/listInventoryView.js +1 -0
  64. package/dist/inventory/listInventoryView.js.map +1 -1
  65. package/dist/inventory/policy.d.ts +1 -0
  66. package/dist/inventory/policy.js +3 -1
  67. package/dist/inventory/policy.js.map +1 -1
  68. package/dist/inventory/types.d.ts +1 -0
  69. package/dist/inventory/varValidation.js +1 -0
  70. package/dist/inventory/varValidation.js.map +1 -1
  71. package/dist/mcp/createServer.js +56 -4
  72. package/dist/mcp/createServer.js.map +1 -1
  73. package/dist/mcp/tools/getServerInfo.d.ts +2 -1
  74. package/dist/mcp/tools/getServerInfo.js +2 -2
  75. package/dist/mcp/tools/getServerInfo.js.map +1 -1
  76. package/dist/mcp/tools/ping.d.ts +38 -0
  77. package/dist/mcp/tools/ping.js +40 -0
  78. package/dist/mcp/tools/ping.js.map +1 -0
  79. package/dist/operations/readExecution.d.ts +3 -1
  80. package/dist/operations/readExecution.js +24 -16
  81. package/dist/operations/readExecution.js.map +1 -1
  82. package/dist/serverInfo/buildServerInfo.d.ts +2 -1
  83. package/dist/serverInfo/buildServerInfo.js +16 -2
  84. package/dist/serverInfo/buildServerInfo.js.map +1 -1
  85. package/dist/serverInfo/types.d.ts +15 -0
  86. package/dist/utils/privateFile.d.ts +3 -0
  87. package/dist/utils/privateFile.js +7 -0
  88. package/dist/utils/privateFile.js.map +1 -0
  89. package/docs/CHECKPOINT.md +11 -1
  90. package/docs/CODE_WALKTHROUGH.md +30 -6
  91. package/docs/DESIGN.md +17 -4
  92. package/docs/DIAGNOSTICS.md +218 -0
  93. package/docs/IMPLEMENTATION_PLAN.md +5 -4
  94. package/docs/QUICKSTART.md +13 -13
  95. package/docs/adr/0001-non-configuring-diagnostics.md +5 -0
  96. package/docs/adr/0002-fail-closed-diagnostic-reservations.md +7 -0
  97. package/docs/adr/0003-durable-diagnostic-ledger.md +9 -0
  98. package/docs/adr/0004-offline-operator-attested-release.md +5 -0
  99. package/docs/adr/0005-multi-destination-ping.md +9 -0
  100. package/docs/examples/diagnostic-release-evidence.template.json +26 -0
  101. package/docs/research/eos-diagnostic-lifecycle.md +84 -0
  102. package/package.json +1 -1
  103. package/dist/inventory/writePolicy.d.ts +0 -2
  104. package/dist/inventory/writePolicy.js +0 -36
  105. package/dist/inventory/writePolicy.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -2,7 +2,26 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.8.0-beta
6
+
7
+ 0.7.0-beta was not published to npm, so upgrading from 0.6.1-beta picks up both this section and the 0.7.0-beta section below.
8
+
9
+ - **Breaking:** `eos_ping` replaces `destination` with `destinations`, an array of 1 to `diagnostics.maxDestinationsPerRequest` (default 16) unique IP literals. Use `destinations: ["<ip>"]` for a single ping; the old field is rejected with guidance. Duplicates are compared by canonical address, so different IPv6 spellings of one address are rejected, while an IPv4 address and its IPv4-mapped IPv6 form stay distinct. Destinations run concurrently within the existing diagnostic concurrency, each with its own reservation. Results always contain one entry per host and destination, each carrying `destination`, and `summary` counts those entries rather than devices. All destinations are validated before dispatch, and `maxProbesPerRequest` now counts hosts × destinations × count. Server info reports `limits.diagnostics.max_destinations_per_request`. See [ADR 0005](docs/adr/0005-multi-destination-ping.md).
10
+ - Routes diagnostics through a per-kind `DiagnosticDefinition` (prepare, probe cost, interpret), so the executor no longer contains ping-specific logic.
11
+ - Documents the Codex `supports_parallel_tool_calls = true` opt-in in the README's Codex configuration examples. Without it, Codex runs independent EOS tool calls serially.
12
+ - Refreshes locked dependencies with `npm audit fix`, including `@modelcontextprotocol/sdk` 1.32.2 and its HTTP-transport dependencies. One advisory remains: zod's memory exhaustion when validating oversized constrained collections is fixed only in zod 4, which needs a separate migration.
13
+
14
+ ## 0.7.0-beta
15
+
16
+ - Refactors diagnostic queueing and reservation transitions into separate paths, makes pre-/post-dispatch error handling explicit, and shares audit hashing and snapshot normalization. Ledger formats, schema versions, and safety policy are unchanged; adds coverage for queued journal failure without invalidating already-completed work.
17
+ - Retains uncertain diagnostic capacity for correlated malformed text results instead of mistaking validation failure for completion. Offline inspection now reads integrity, schema, reservations, and audit in one SQLite transaction, preventing mixed before/after release snapshots.
18
+ - Adds offline `release-diagnostics` with exact ID scope, a private bounded fencing-attestation file, explicit confirmation, exclusive ledger ownership, and atomic audit-plus-release. Records actual OS identity separately from the claimed verifier and checks content digests; it does not verify fencing truth or expose an MCP reset. Schema 1 migrates transactionally to schema 2, preserving unresolved work; `inspect-diagnostics` exposes read-only audit history. Exact committed retries are no-ops; changed attestation reuse is rejected.
19
+ - Validates JSON-RPC 2.0 response IDs and exclusive result/error envelopes before accepting output or retrying read-only JSON fallback. Missing/stale acknowledgements retain uncertain diagnostic capacity. New ledger reservations persist the exact wire RPC ID before dispatch; offline inspection distinguishes legacy records without one. IDs provide correlation, not an EOS status token or retry/deduplication guarantee.
20
+ - Adds `eos_ping`: bounded IPv4/IPv6 diagnostics executed on inventory hosts/groups, optional VRF/source IP, normalized loss/RTT and reachability findings, and opt-in original EOS text. Requires inherited `mcp_diagnostics_allowed: true`; read denial still vetoes execution. No configuration changes, automatic retries, or SSH/shell fallback.
21
+ - Fixes read-only auto output fallback for EOS code 1003 (`unconverted command`) and aligns optional read integration hostnames with the checked-in unprefixed topology. Ping's single-execution text path still never retries.
22
+ - Adds configurable `diagnostics` limits/timeouts with sensible defaults, ledger-scoped admission across simultaneous calls, and indefinite fail-closed reservations when device completion is unknown. Reports permission in inventory views, effective limits and live reservation state in server info, and a structured `diagnostic_capacity_uncertain` error when uncertainty exhausts capacity. Reservations are committed before dispatch to a private, inventory-keyed SQLite ledger and survive restart as uncertain. A crash-released ownership lock prevents competing owners; storage errors fail closed. Adds optional `diagnostics.stateFile` and offline, read-only `inspect-diagnostics`. Offline operator-attested release is available; a machine-verified native remote deadline/completion facility remains unresolved; post-dispatch RPC interruption errors do not prove completion. Qualified on cEOS 4.34.3M; traceroute and packet capture remain future work.
5
23
  - Publishes the package to npm as `@aristanetworks/eos-mcp-server` (#14). The installed command is still `eos-mcp-server`. The release workflow publishes through npm trusted publishing, and prerelease tags go to the `next` dist-tag. The release tarball is now named `aristanetworks-eos-mcp-server-<version>.tgz`.
24
+ - Upgrading from a `.tgz` install: run `npm uninstall -g eos-mcp-server` before `npm install -g @aristanetworks/eos-mcp-server`. Both packages provide the same `eos-mcp-server` command.
6
25
 
7
26
  ## 0.6.1-beta
8
27
 
package/README.md CHANGED
@@ -1,11 +1,14 @@
1
- # eos-mcp-server BETA
1
+ # eos-mcp-server
2
2
 
3
- Read-only MCP server for Arista EOS eAPI (JSON-RPC over HTTPS).
3
+ [![Project status: Beta](https://img.shields.io/badge/status-beta-orange.svg)](https://github.com/aristanetworks/eos-mcp-server/releases)
4
+ [![npm version](https://img.shields.io/npm/v/%40aristanetworks%2Feos-mcp-server.svg)](https://www.npmjs.com/package/@aristanetworks/eos-mcp-server)
5
+
6
+ Read-only (non-configuring) MCP server for Arista EOS eAPI (JSON-RPC over HTTPS).
4
7
 
5
8
  > **Beta status:** this project is under active development.
6
9
  > **Support:** best-effort only. This open source project is not currently supported by Arista TAC.
7
10
 
8
- This server provides a set of **read-only** tools. It never exposes configuration-changing operations. The server can:
11
+ This server never exposes configuration-changing operations. It provides read-only inspection and explicitly authorized, bounded **active diagnostics**. Non-configuring does not mean passive or harmless: diagnostics generate traffic. The server can:
9
12
 
10
13
  - introspect its own runtime and inventory
11
14
  - list inventory hosts/groups
@@ -14,8 +17,9 @@ This server provides a set of **read-only** tools. It never exposes configuratio
14
17
  - retrieve bounded logging output for troubleshooting
15
18
  - collect a fixed set of device facts
16
19
  - retrieve running configuration
20
+ - run bounded ping diagnostics on EOS devices, including group fan-out
17
21
 
18
- > **Security note:** LLMs have occasionally tried to bypass the MCP server and make configuration changes through other means (for example, SSH). As a best practice, use AAA and scope the authentication credentials used by this server to read-only access.
22
+ > **Security note:** LLMs have occasionally tried to bypass the MCP server and make configuration changes through other means (for example, SSH). As a best practice, use AAA and scope the authentication credentials used by this server to the intended inspection and diagnostic commands only.
19
23
 
20
24
  ## Contents
21
25
 
@@ -24,6 +28,7 @@ This server provides a set of **read-only** tools. It never exposes configuratio
24
28
  - [Install and get started](#install-and-get-started)
25
29
  - [Server config file](#server-config-file)
26
30
  - [Connect to an MCP client](#connect-to-an-mcp-client)
31
+ - [Skills](#skills)
27
32
  - [CLI usage](#cli-usage)
28
33
  - [MCP tool reference](#mcp-tool-reference)
29
34
  - [Inventory formats](#inventory-formats)
@@ -39,6 +44,7 @@ Implemented MCP tools:
39
44
  - `eos_get_server_info`
40
45
  - `eos_list_inventory`
41
46
  - `eos_probe_devices`
47
+ - `eos_ping`
42
48
  - `eos_run_show`
43
49
  - `eos_show_logging`
44
50
  - `eos_get_facts`
@@ -50,45 +56,75 @@ Implemented local CLI commands:
50
56
  - `validate-inventory`
51
57
  - `print-server-info`
52
58
  - `probe`
59
+ - `inspect-diagnostics` (offline, read-only ledger inspection)
60
+ - `release-diagnostics` (offline, explicitly attested and audited operator release)
53
61
 
54
62
  ## Requirements
55
63
 
56
64
  - Node.js 24+
57
65
  - Arista EOS devices reachable via eAPI over HTTPS
58
- - EOS 4.20 or later
66
+ - EOS 4.20 or later for existing read operations; `eos_ping` is qualified on cEOS 4.34.3M
59
67
  - Inventory in one of the supported YAML formats
60
68
 
61
69
  ## Install and get started
62
70
 
63
- 1. Install the package globally from npm:
71
+ The package is published on npm as [`@aristanetworks/eos-mcp-server`](https://www.npmjs.com/package/@aristanetworks/eos-mcp-server). The package provides the `eos-mcp-server` command.
72
+
73
+ ### npx or global install?
74
+
75
+ Both run the same package. They differ in when the version changes and whether the npm registry must be reachable when the server starts.
76
+
77
+ | Use | When |
78
+ | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
79
+ | `npx -y @aristanetworks/eos-mcp-server` | You're trying the server out, or mainly run it from an MCP client. Nothing to install, and it picks up the latest release when it launches. |
80
+ | `npx -y @aristanetworks/eos-mcp-server@<version>` | You want a reproducible setup, such as an MCP config shared with a team. Everyone runs the same version until you change it. |
81
+ | `npm install -g @aristanetworks/eos-mcp-server` | You run the CLI often, want to control when upgrades happen, or the npm registry isn't always reachable. The command starts without a registry lookup and stays on one version until you run `npm update -g`. |
82
+ | `.tgz` from a [GitHub release](https://github.com/aristanetworks/eos-mcp-server/releases) | The machine can't reach the npm registry at all. |
64
83
 
65
- ```bash
66
- npm install -g @aristanetworks/eos-mcp-server
67
- ```
84
+ ### Run with npx (recommended)
68
85
 
69
- Prereleases are published under the `next` tag (`npm install -g @aristanetworks/eos-mcp-server@next`). Each [GitHub release](https://github.com/aristanetworks/eos-mcp-server/releases) also attaches the package as a `.tgz`, which you can install with `npm install -g ./aristanetworks-eos-mcp-server-<version>.tgz`.
86
+ No install step is needed. `npx` downloads the package on first use and caches it:
87
+
88
+ ```bash
89
+ npx -y @aristanetworks/eos-mcp-server --help
90
+ ```
70
91
 
71
- 2. Confirm that the command is available:
92
+ The [MCP client examples](#connect-to-an-mcp-client) below use `npx`. `-y` skips npm's install confirmation prompt, which an MCP client can't answer. Without a version, npx checks the registry for the latest release each time it launches the server. To pin a specific release, append a version, for example `@aristanetworks/eos-mcp-server@0.8.0-beta`.
72
93
 
73
- ```bash
74
- eos-mcp-server --help
75
- ```
94
+ ### Or install globally
76
95
 
77
- The global install places `eos-mcp-server` on your `PATH`. To remove it later:
96
+ A global install puts `eos-mcp-server` on your `PATH`, starts without a registry lookup, and stays on the installed version until you update it:
78
97
 
79
98
  ```bash
80
- npm uninstall -g @aristanetworks/eos-mcp-server
99
+ npm install -g @aristanetworks/eos-mcp-server
100
+ eos-mcp-server --help
81
101
  ```
82
102
 
83
- Next, create an inventory, provide the device password, and validate connectivity:
103
+ Update it later with `npm update -g @aristanetworks/eos-mcp-server`, or remove it with `npm uninstall -g @aristanetworks/eos-mcp-server`.
104
+
105
+ Prereleases are published under the `next` tag (`@aristanetworks/eos-mcp-server@next`). Each [GitHub release](https://github.com/aristanetworks/eos-mcp-server/releases) also attaches the package as a `.tgz`, for offline installs: `npm install -g ./aristanetworks-eos-mcp-server-<version>.tgz`.
106
+
107
+ ### Upgrading from a `.tgz` install
108
+
109
+ Versions up to 0.6.1-beta were distributed as `.tgz` files under the unscoped package name `eos-mcp-server`. Both packages provide the same `eos-mcp-server` command, so remove the old package before switching to npm. Otherwise the global install can fail with a conflict, or the old version keeps running:
110
+
111
+ ```bash
112
+ npm uninstall -g eos-mcp-server
113
+ ```
114
+
115
+ ### Validate your inventory
116
+
117
+ Create an inventory, provide the device password, and validate connectivity:
84
118
 
85
119
  ```bash
86
120
  export EOS_MCP_PASSWORD='replace-with-device-password'
87
121
 
88
- eos-mcp-server validate-inventory --inventory inventory.yml
89
- eos-mcp-server probe --inventory inventory.yml --target leaf1
122
+ npx -y @aristanetworks/eos-mcp-server validate-inventory --inventory inventory.yml
123
+ npx -y @aristanetworks/eos-mcp-server probe --inventory inventory.yml --target leaf1
90
124
  ```
91
125
 
126
+ With a global install, run `eos-mcp-server` in place of `npx -y @aristanetworks/eos-mcp-server`. The [CLI usage](#cli-usage) examples later in this README use the shorter `eos-mcp-server` form.
127
+
92
128
  See [Quickstart](docs/QUICKSTART.md) for a complete inventory example and MCP client setup. For building or contributing from source, see the [developer workflow](docs/DEVELOPMENT.md).
93
129
 
94
130
  ## Server config file
@@ -114,6 +150,18 @@ maxShowCommandsPerRequest: 5
114
150
  maxLoggingMessagesPerRequest: 1000
115
151
  maxResponseSizeBytes: 1048576
116
152
  eapiVersion: latest
153
+ diagnostics:
154
+ # Optional: otherwise use the private, inventory-keyed XDG state directory.
155
+ # stateFile: ./private/diagnostics.sqlite
156
+ defaultPingCount: 3
157
+ maxPingCount: 10
158
+ maxProbesPerRequest: 100
159
+ maxDestinationsPerRequest: 16
160
+ deviceConcurrency: 5
161
+ pingReplyTimeoutMs: 1000
162
+ commandTimeoutMs: 30000
163
+ httpTimeoutMs: 35000
164
+ overallOperationTimeoutMs: 60000
117
165
  secretEnvPrefixes:
118
166
  - EOS_MCP_
119
167
  defaultConnection:
@@ -126,6 +174,7 @@ Supported config fields:
126
174
 
127
175
  - `inventory`
128
176
  - `actor`
177
+ - `logFile`
129
178
  - `caFile`
130
179
  - `readTimeoutMs`
131
180
  - `overallOperationTimeoutMs`
@@ -135,30 +184,41 @@ Supported config fields:
135
184
  - `maxLoggingMessagesPerRequest`
136
185
  - `maxResponseSizeBytes`
137
186
  - `eapiVersion`
187
+ - `diagnostics` — optional limits/timeouts mapping; see [Network diagnostics](docs/DIAGNOSTICS.md#settings-and-defaults)
138
188
  - `secretEnvPrefixes`
139
189
  - `defaultConnection.ansibleUser`
140
190
  - `defaultConnection.ansibleHttpapiPort`
141
191
  - `defaultConnection.mcpValidateCerts`
142
192
  - `defaultConnection.mcpPasswordEnv`
143
193
 
144
- `readTimeoutMs` applies to each device eAPI request. `overallOperationTimeoutMs`, when set, bounds the whole tool call and aborts in-flight device requests once the limit is reached. `maxLoggingMessagesPerRequest` caps `eos_show_logging.message_count` and defaults to 1000. `maxResponseSizeBytes` limits both the buffered HTTP response from each device and the final serialized read-tool result. `eapiVersion` selects the eAPI JSON output schema sent as the `runCmds` `version` parameter: `latest` (the default) returns the current schema for each command, and `1` pins the original schema for consumers that depend on it. It only affects JSON output, so `eos_get_running_config` and `eos_show_logging` are unchanged.
194
+ For read tools, `readTimeoutMs` applies to each device eAPI request. `overallOperationTimeoutMs`, when set, bounds the whole read-tool call and aborts in-flight device requests once the limit is reached. `maxLoggingMessagesPerRequest` caps `eos_show_logging.message_count` and defaults to 1000. `maxResponseSizeBytes` limits both the buffered HTTP response from each device and the final serialized result of device read operations. `eapiVersion` selects the eAPI JSON output schema sent as the `runCmds` `version` parameter: `latest` (the default) returns the current schema for each command, and `1` pins the original schema for consumers that depend on it. It only affects JSON output, so `eos_get_running_config` and `eos_show_logging` are unchanged.
195
+
196
+ `eos_ping` uses its own configurable `diagnostics` timeouts and server-wide concurrency, while sharing `maxReadTargets` and `maxResponseSizeBytes`. Omitted diagnostic settings retain the defaults shown above; invalid or contradictory settings fail validation. Ping requires explicit inventory permission and has no automatic retries. Unknown remote completion retains capacity indefinitely; inspect the running server's `eos_get_server_info.diagnostics.capacity`. Reservations and their wire request IDs are committed before dispatch; response IDs/protocol envelopes are validated before output is accepted. Uncertain attempts survive restarts in a private SQLite ledger, with one active server per ledger. Exhausted uncertain capacity returns `diagnostic_capacity_uncertain`; restarting with the same ledger does not clear it. Use `inspect-diagnostics` for offline inspection and audit history. `release-diagnostics` permits only an offline operator-attested release backed by independent fencing evidence and explicit reservation IDs; it is never an MCP tool or automatic reset. A verified remote kill mechanism is not implemented; do not delete or relocate state to bypass uncertainty. See [Network diagnostics](docs/DIAGNOSTICS.md), including the distinction between a reply timeout, command budget, and remote process termination.
197
+
198
+ `actor` and `logFile` remain sanitized runtime metadata and do not enable a general tool-call audit log. Offline operator releases have a separate mandatory ledger audit, including the actual OS account and the claimed accountable verifier.
145
199
 
146
200
  `defaultConnection.mcpPasswordEnv` is a fallback password source. A host or inherited inventory value for `mcp_password_env` or `ansible_password` overrides it. Setting both `mcp_password_env` and `ansible_password` for the same host remains invalid.
147
201
 
148
202
  ## Connect to an MCP client
149
203
 
150
- These examples assume you've already installed `eos-mcp-server` per [Install and get started](#install-and-get-started) above, and have an inventory file (and optionally a [server config file](#server-config-file)) ready.
204
+ These examples assume you have an inventory file (and optionally a [server config file](#server-config-file)) ready. They launch the server with `npx`, so nothing needs to be installed first. If you [installed globally](#or-install-globally), use `eos-mcp-server` as the command and drop `-y @aristanetworks/eos-mcp-server` from the arguments.
151
205
 
152
206
  ### Generic stdio example
153
207
 
154
- If `eos-mcp-server` is installed on your `PATH`, point it at just an inventory file:
208
+ Point the server at just an inventory file:
155
209
 
156
210
  ```json
157
211
  {
158
212
  "mcpServers": {
159
213
  "eos": {
160
- "command": "eos-mcp-server",
161
- "args": ["serve", "--inventory", "/absolute/path/to/inventory.yml"]
214
+ "command": "npx",
215
+ "args": [
216
+ "-y",
217
+ "@aristanetworks/eos-mcp-server",
218
+ "serve",
219
+ "--inventory",
220
+ "/absolute/path/to/inventory.yml"
221
+ ]
162
222
  }
163
223
  }
164
224
  }
@@ -170,33 +230,39 @@ Or use a [server config file](#server-config-file) if you want to set additional
170
230
  {
171
231
  "mcpServers": {
172
232
  "eos": {
173
- "command": "eos-mcp-server",
174
- "args": ["serve", "--config", "/absolute/path/to/eos-mcp-server.yml"]
233
+ "command": "npx",
234
+ "args": [
235
+ "-y",
236
+ "@aristanetworks/eos-mcp-server",
237
+ "serve",
238
+ "--config",
239
+ "/absolute/path/to/eos-mcp-server.yml"
240
+ ]
175
241
  }
176
242
  }
177
243
  }
178
244
  ```
179
245
 
180
- If you built the project locally instead of installing the package, replace `"command": "eos-mcp-server"` with `"command": "node"` and put `/absolute/path/to/eos-mcp-server/dist/index.js` first in `args`.
246
+ If you built the project locally instead, use `"command": "node"` and put `/absolute/path/to/eos-mcp-server/dist/index.js` first in `args`, in place of `-y` and the package name.
181
247
 
182
248
  ### Claude Code
183
249
 
184
250
  With just an inventory file:
185
251
 
186
252
  ```bash
187
- claude mcp add eos -- eos-mcp-server serve --inventory /absolute/path/to/inventory.yml
253
+ claude mcp add eos -- npx -y @aristanetworks/eos-mcp-server serve --inventory /absolute/path/to/inventory.yml
188
254
  ```
189
255
 
190
256
  Or with a [server config file](#server-config-file) for additional options:
191
257
 
192
258
  ```bash
193
- claude mcp add eos -- eos-mcp-server serve --config /absolute/path/to/eos-mcp-server.yml
259
+ claude mcp add eos -- npx -y @aristanetworks/eos-mcp-server serve --config /absolute/path/to/eos-mcp-server.yml
194
260
  ```
195
261
 
196
262
  Add `-s user` before `eos` in either command to make the server available across all your projects instead of just the current one:
197
263
 
198
264
  ```bash
199
- claude mcp add -s user eos -- eos-mcp-server serve --inventory /absolute/path/to/inventory.yml
265
+ claude mcp add -s user eos -- npx -y @aristanetworks/eos-mcp-server serve --inventory /absolute/path/to/inventory.yml
200
266
  ```
201
267
 
202
268
  ### Codex
@@ -208,8 +274,9 @@ With just an inventory file:
208
274
 
209
275
  ```toml
210
276
  [mcp_servers.eos]
211
- command = "eos-mcp-server"
212
- args = ["serve", "--inventory", "/absolute/path/to/inventory.yml"]
277
+ supports_parallel_tool_calls = true
278
+ command = "npx"
279
+ args = ["-y", "@aristanetworks/eos-mcp-server", "serve", "--inventory", "/absolute/path/to/inventory.yml"]
213
280
  env_vars = ["EOS_MCP_PASSWORD"]
214
281
  ```
215
282
 
@@ -217,24 +284,42 @@ Or with a [server config file](#server-config-file) for additional options:
217
284
 
218
285
  ```toml
219
286
  [mcp_servers.eos]
220
- command = "eos-mcp-server"
221
- args = ["serve", "--config", "/absolute/path/to/eos-mcp-server.yml"]
287
+ supports_parallel_tool_calls = true
288
+ command = "npx"
289
+ args = ["-y", "@aristanetworks/eos-mcp-server", "serve", "--config", "/absolute/path/to/eos-mcp-server.yml"]
222
290
  env_vars = ["EOS_MCP_PASSWORD"]
223
291
  ```
224
292
 
293
+ Set `supports_parallel_tool_calls = true` under `[mcp_servers.eos]` to let
294
+ Codex dispatch independent tool calls, including pings, concurrently. Without
295
+ this opt-in, tools that omit the MCP read-only annotation may run serially even
296
+ when requested together. Reload Codex after changing the setting. The server
297
+ still enforces its configured diagnostic concurrency and packet limits.
298
+ A single `eos_ping` call with several `destinations` already runs them
299
+ concurrently on the server, so this setting matters for other independent
300
+ calls, such as show commands on different devices or pings that need different
301
+ VRFs, sources, or counts.
302
+
225
303
  `serve` is optional because it is the default command, but is shown explicitly
226
- here for clarity. You can also add the server with:
304
+ here for clarity. After exporting the password, you can also add the server and
305
+ pass its current value through with the Codex CLI:
227
306
 
228
307
  ```bash
229
- codex mcp add eos -- eos-mcp-server serve --inventory /absolute/path/to/inventory.yml
308
+ export EOS_MCP_PASSWORD='replace-with-device-password'
309
+
310
+ codex mcp add eos \
311
+ --env EOS_MCP_PASSWORD="$EOS_MCP_PASSWORD" \
312
+ -- npx -y @aristanetworks/eos-mcp-server serve \
313
+ --inventory /absolute/path/to/inventory.yml
230
314
  ```
231
315
 
232
- Then add `env_vars = ["EOS_MCP_PASSWORD"]` to the generated
233
- `[mcp_servers.eos]` table.
316
+ The `--env` form stores the expanded value in the generated Codex configuration.
317
+ To have Codex read the variable from its environment each time it starts the
318
+ server, use `env_vars = ["EOS_MCP_PASSWORD"]` as in the TOML examples above.
234
319
 
235
320
  ### Passing secrets to the MCP server
236
321
 
237
- Prefer exporting secrets in the environment that launches the MCP client:
322
+ To export secrets in the environment that launches the MCP client use:
238
323
 
239
324
  ```bash
240
325
  export EOS_MCP_PASSWORD='super-secret'
@@ -244,6 +329,30 @@ For Codex, `env_vars = ["EOS_MCP_PASSWORD"]` forwards that exported variable to
244
329
  the server. Other MCP clients may support per-server `env` blocks. Avoid
245
330
  committing secret values to client config files when possible.
246
331
 
332
+ ## Skills
333
+
334
+ The [`skills/`](skills/) folder holds community-created skills for everyday network operations workflows. Each skill is a `SKILL.md` file that teaches an AI assistant, such as Claude Code or Codex, how to carry out one workflow with this server's read-only tools: which `show` commands to run, how to read the output, what to investigate next, and how to report results.
335
+
336
+ The current skills cover:
337
+
338
+ - **Health checks:** BGP, EVPN and EVPN multicast, interfaces, Port-Channels/LACP, VLANs, routing tables and VRFs, IGMP snooping, and PIM.
339
+ - **Validation:** ISIS Segment Routing, RFC 9721 EVPN IP mobility, and MCS/CVX configuration.
340
+ - **Troubleshooting:** multicast flows that are missing, dropping, or corrupted; PTP grandmaster and connectivity problems; Segment Routing faults; and MCS mounts and agents.
341
+
342
+ See [`skills/README.md`](skills/README.md) for the full list and for how to load the skills into Claude Code or Codex. Skills aren't included in the npm package, so clone this repository to use them.
343
+
344
+ ### Contribute a skill
345
+
346
+ If you have a workflow you run by hand, such as a check you do after a change window, a runbook for a recurring problem, or an audit for a feature your network depends on, consider contributing it as a skill so other network engineers can use it too.
347
+
348
+ 1. Add `skills/<skill-name>/SKILL.md` with `name`, `description`, `trigger`, and `allowed-tools` frontmatter. The existing skills are good templates.
349
+ 2. Keep it **read-only**, and keep it **generic**: no site-specific hostnames, group names, or inventory layouts.
350
+ 3. Document the EOS commands the skill runs, the JSON fields it relies on, and what to check when something looks wrong.
351
+ 4. Add a row for the skill to the table in [`skills/README.md`](skills/README.md).
352
+ 5. Open a pull request that changes only files under `skills/`.
353
+
354
+ Pull requests that touch only `skills/` can be accepted without a contributor license agreement. They are licensed under Apache-2.0. See [CONTRIBUTING.md](CONTRIBUTING.md) for details, and [Writing a new skill](skills/README.md#writing-a-new-skill) for the full guidelines. Improvements to existing skills are welcome too, such as coverage for another EOS feature, a better diagnostic drill-down, or a fix for output that changed between EOS releases.
355
+
247
356
  ## Inventory formats
248
357
 
249
358
  The server supports exactly one inventory file loaded at startup. The inventory is not watched for changes — to pick up inventory edits, restart the server. Most MCP clients will do this automatically when you restart the client or re-launch the MCP connection.
@@ -326,6 +435,8 @@ still using their individual credentials.
326
435
  - `mcp_platform: arista_eos`
327
436
  - `mcp_read_allowed` defaults to `true` for eligible EOS hosts. Set it to `false` — inherited like any other variable — to explicitly deny read access to a host or group.
328
437
  - Read operations fail closed if the resolved target contains ineligible or read-denied hosts.
438
+ - `mcp_diagnostics_allowed` defaults to `false`. Set this inherited boolean to `true` to permit `eos_ping`; read denial still vetoes diagnostics. A mixed-permission group fails before any dispatch.
439
+ - A diagnostic destination is distinct from the inventory target and may be an address outside inventory.
329
440
 
330
441
  ## Connection and authentication
331
442
 
@@ -407,7 +518,7 @@ caFile: /path/to/ca.pem
407
518
 
408
519
  ## CLI usage
409
520
 
410
- If no subcommand is provided, the CLI defaults to `serve`.
521
+ If no subcommand is provided, the CLI defaults to `serve`. These examples use the globally installed `eos-mcp-server` command; with npx, run `npx -y @aristanetworks/eos-mcp-server` in its place.
411
522
 
412
523
  ### `serve`
413
524
 
@@ -441,6 +552,29 @@ eos-mcp-server print-server-info --inventory inventory.yml
441
552
  eos-mcp-server print-server-info --config eos-mcp-server.yml --json
442
553
  ```
443
554
 
555
+ ### `inspect-diagnostics`
556
+
557
+ Inspect existing persisted reservations without credentials, device access, ownership takeover, or reset. `diagnostics.stateFile` can select a ledger; otherwise the same canonical inventory identity determines the default path.
558
+
559
+ ```bash
560
+ eos-mcp-server inspect-diagnostics --config eos-mcp-server.yml --json
561
+ eos-mcp-server inspect-diagnostics --inventory inventory.yml --json
562
+ ```
563
+
564
+ Recorded state does not prove remote completion. Preserve the state files on private, persistent local storage; see [Network diagnostics](docs/DIAGNOSTICS.md#offline-inspection-and-operator-recovery).
565
+
566
+ ### `release-diagnostics`
567
+
568
+ Offline local-state administration only: stop the ledger owner, independently establish that running **and accepted queued** work is fenced against later execution/replay, and prepare a private JSON attestation. This is operator authority, not machine-confirmed EOS completion.
569
+
570
+ ```bash
571
+ eos-mcp-server release-diagnostics --config eos-mcp-server.yml \
572
+ --reservation-id '<exact-id>' --evidence-file ./evidence.json \
573
+ --confirm-fenced --json
574
+ ```
575
+
576
+ There is no wildcard or release-all operation. Audit and selected deletions commit atomically; unselected reservations remain held. See the [required workflow and intentionally invalid template](docs/DIAGNOSTICS.md#operator-release-workflow) before use. No device command, credential resolution, or evidence-reference fetch is performed. Protect the CLI and ledger owner's OS privileges; the attestation is not a cryptographic proof of human presence or fencing truth.
577
+
444
578
  ### `probe`
445
579
 
446
580
  Probe a host or group target using the same logic as the MCP tool.
@@ -462,7 +596,7 @@ Devices: 1/1 succeeded
462
596
 
463
597
  ### `eos_get_server_info`
464
598
 
465
- Returns a sanitized summary of server runtime, capabilities, limits, TLS/config posture, and inventory summary.
599
+ Returns a sanitized summary of server runtime, capabilities, limits, TLS/config posture, inventory summary, and live active/uncertain diagnostic reservations. Reservation metadata excludes destinations, credentials, and original EOS output.
466
600
 
467
601
  Input:
468
602
 
@@ -495,6 +629,23 @@ Input:
495
629
  }
496
630
  ```
497
631
 
632
+ ### `eos_ping`
633
+
634
+ Runs bounded ping from an inventory host or group to one or more destinations, requiring inherited `mcp_diagnostics_allowed: true`. It generates traffic without changing configuration. Each destination must be a unicast IPv4/IPv6 literal, and duplicates are rejected, including different spellings of the same IPv6 address; use a one-element `destinations` array for a single ping. Destinations run concurrently within the server's diagnostic concurrency, up to 16 per call by default. Optional VRF and source IP apply to every destination and never silently fall back. Count defaults to 3 per destination and is capped at 10 unless changed in settings.
635
+
636
+ ```json
637
+ {
638
+ "target": "leaf1",
639
+ "destinations": ["192.0.2.10", "192.0.2.20"],
640
+ "count": 3,
641
+ "vrf": "BLUE",
642
+ "source": "192.0.2.11",
643
+ "include_raw": false
644
+ }
645
+ ```
646
+
647
+ `count`, `vrf`, `source`, and `include_raw` are optional. Results contain one entry per host and destination, each naming its `destination`; `summary` counts those entries. Results separate execution status from `reachable`/`partial`/`unreachable` findings and include loss/RTT measurements. Zero replies do not establish a cause. See [Network diagnostics](docs/DIAGNOSTICS.md) for all limits, address restrictions, lifecycle caveats, and result semantics. Traceroute and packet capture are not yet implemented.
648
+
498
649
  ### `eos_run_show`
499
650
 
500
651
  Runs one or more `show` commands.
@@ -624,18 +775,20 @@ This means the target resolved to at least one host that is either not marked as
624
775
 
625
776
  The read-path tools have been validated against EOS 4.34.3M. The minimum supported EOS version for read operations is 4.20, which is when eAPI JSON-RPC became stable and `show` commands reliably produce structured JSON output.
626
777
 
778
+ `eos_ping` has separately been validated on cEOS 4.34.3M. Older EOS versions and physical platforms have not been qualified for this new tool.
779
+
627
780
  ## Design notes
628
781
 
629
- - inventory is the trust boundary
782
+ - inventory is the execution-target trust boundary; diagnostic destinations may be outside inventory
630
783
  - reads are fail-closed on ineligible or denied targets
631
- - the server exposes only documented read-only operations
784
+ - the server exposes only documented non-configuring operations; active diagnostics require explicit opt-in
632
785
 
633
786
  ## Project docs
634
787
 
635
788
  Additional design and planning docs in the `docs/` directory:
636
789
 
637
- - `docs/design-overview.md` — design overview for evaluators
638
790
  - `docs/DESIGN.md` — detailed design specification
791
+ - `docs/DIAGNOSTICS.md` — ping usage, settings, safety, lifecycle, and extension seam
639
792
  - `docs/IMPLEMENTATION_PLAN.md` — implemented scope and maintenance priorities
640
793
  - `docs/CHECKPOINT.md` — current implementation status
641
794
  - `docs/CODE_WALKTHROUGH.md` — source layout and module guide
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type CommandName = "serve" | "validate-inventory" | "print-server-info" | "probe";
1
+ export type CommandName = "serve" | "validate-inventory" | "print-server-info" | "probe" | "inspect-diagnostics" | "release-diagnostics";
2
2
  export interface CliOptions {
3
3
  command: CommandName;
4
4
  explicitCommand?: boolean;
@@ -10,6 +10,9 @@ export interface CliOptions {
10
10
  json?: boolean;
11
11
  inventoryOnly?: boolean;
12
12
  target?: string;
13
+ reservationIds?: string[];
14
+ evidenceFile?: string;
15
+ confirmFenced?: boolean;
13
16
  }
14
17
  export declare function parseCliArgs(argv: string[]): CliOptions;
15
18
  export declare function printHelp(cli: CliOptions): void;
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AppError } from "./core/errors.js";
2
2
  import { APP_NAME, APP_VERSION } from "./core/version.js";
3
- const COMMAND_NAMES = new Set(["serve", "validate-inventory", "print-server-info", "probe"]);
3
+ const COMMAND_NAMES = new Set(["serve", "validate-inventory", "print-server-info", "probe", "inspect-diagnostics", "release-diagnostics"]);
4
4
  const OPTION_NAMES = new Set([
5
5
  "--help",
6
6
  "-h",
@@ -11,7 +11,10 @@ const OPTION_NAMES = new Set([
11
11
  "--actor",
12
12
  "--json",
13
13
  "--inventory-only",
14
- "--target"
14
+ "--target",
15
+ "--reservation-id",
16
+ "--evidence-file",
17
+ "--confirm-fenced"
15
18
  ]);
16
19
  const COMMAND_OPTIONS = {
17
20
  "serve": new Set([
@@ -25,7 +28,9 @@ const COMMAND_OPTIONS = {
25
28
  ]),
26
29
  "validate-inventory": new Set(["--help", "-h", "--version", "-V", "--config", "--inventory", "--inventory-only", "--json"]),
27
30
  "print-server-info": new Set(["--help", "-h", "--version", "-V", "--config", "--inventory", "--json"]),
28
- "probe": new Set(["--help", "-h", "--version", "-V", "--config", "--inventory", "--target", "--json"])
31
+ "probe": new Set(["--help", "-h", "--version", "-V", "--config", "--inventory", "--target", "--json"]),
32
+ "inspect-diagnostics": new Set(["--help", "-h", "--version", "-V", "--config", "--inventory", "--json"]),
33
+ "release-diagnostics": new Set(["--help", "-h", "--version", "-V", "--config", "--inventory", "--json", "--reservation-id", "--evidence-file", "--confirm-fenced"])
29
34
  };
30
35
  export function parseCliArgs(argv) {
31
36
  let command = "serve";
@@ -93,6 +98,32 @@ export function parseCliArgs(argv) {
93
98
  options.inventoryOnly = true;
94
99
  index += 1;
95
100
  break;
101
+ case "--reservation-id": {
102
+ const value = argv[index + 1];
103
+ if (!value || value.startsWith("-"))
104
+ throw new AppError("cli_missing_value", "Missing value for --reservation-id");
105
+ if (options.reservationIds?.includes(value))
106
+ throw new AppError("cli_duplicate_option", "Duplicate reservation ID");
107
+ (options.reservationIds ??= []).push(value);
108
+ index += 2;
109
+ break;
110
+ }
111
+ case "--evidence-file": {
112
+ const value = argv[index + 1];
113
+ if (!value || value.startsWith("-"))
114
+ throw new AppError("cli_missing_value", "Missing value for --evidence-file");
115
+ if (options.evidenceFile !== undefined)
116
+ throw new AppError("cli_duplicate_option", "Duplicate --evidence-file");
117
+ options.evidenceFile = value;
118
+ index += 2;
119
+ break;
120
+ }
121
+ case "--confirm-fenced":
122
+ if (options.confirmFenced !== undefined)
123
+ throw new AppError("cli_duplicate_option", "Duplicate --confirm-fenced");
124
+ options.confirmFenced = true;
125
+ index += 1;
126
+ break;
96
127
  case "--target": {
97
128
  const value = argv[index + 1];
98
129
  if (!value) {
@@ -124,6 +155,8 @@ Commands:
124
155
  validate-inventory Validate an inventory file
125
156
  print-server-info Print server runtime/config summary
126
157
  probe Probe device readiness for a target
158
+ inspect-diagnostics Inspect persisted reservations and release audit (read-only)
159
+ release-diagnostics Offline, audited operator-attested reservation release
127
160
 
128
161
  Global options:
129
162
  --config <path> Path to server config YAML file
@@ -172,11 +205,37 @@ Options:
172
205
  --target <name> Host or group name to probe (required)
173
206
  --json Output as JSON
174
207
  -h, --help Show this help message`;
208
+ const HELP_INSPECT_DIAGNOSTICS = `Usage: ${APP_NAME} inspect-diagnostics [options]
209
+
210
+ Read the diagnostic ledger without device access, ownership takeover, or reset.
211
+ Recorded state is not proof of remote completion.
212
+
213
+ Options:
214
+ --config <path> Settings file, including optional diagnostics.stateFile
215
+ --inventory <path> Inventory identity used for the default ledger path
216
+ --json Output persisted reservations as JSON
217
+ -h, --help Show this help message`;
218
+ const HELP_RELEASE_DIAGNOSTICS = `Usage: ${APP_NAME} release-diagnostics [options]
219
+
220
+ Release only explicit reservations after independently verified fencing.
221
+ Requires exclusive offline ledger ownership. No device commands or MCP reset.
222
+ The evidence is operator authority, not machine-confirmed EOS completion.
223
+
224
+ Options:
225
+ --config <path> Settings file selecting the existing ledger
226
+ --inventory <path> Expected canonical inventory identity
227
+ --reservation-id <id> Exact reservation to release (repeat for a batch)
228
+ --evidence-file <path> Private UTF-8 JSON fencing attestation (max 65536 bytes)
229
+ --confirm-fenced Confirm running, queued and replayable work is fenced
230
+ --json Output committed release metadata or error as JSON
231
+ -h, --help Show this help message`;
175
232
  const COMMAND_HELP = {
176
233
  "serve": HELP_SERVE,
177
234
  "validate-inventory": HELP_VALIDATE_INVENTORY,
178
235
  "print-server-info": HELP_PRINT_SERVER_INFO,
179
- "probe": HELP_PROBE
236
+ "probe": HELP_PROBE,
237
+ "inspect-diagnostics": HELP_INSPECT_DIAGNOSTICS,
238
+ "release-diagnostics": HELP_RELEASE_DIAGNOSTICS
180
239
  };
181
240
  export function printHelp(cli) {
182
241
  const helpText = cli.explicitCommand ? COMMAND_HELP[cli.command] : HELP_TOP;
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ResolvedServerConfig } from "../config/schema.js";
2
+ /** Offline/read-only: no credentials, device calls, ownership takeover, or capacity reset. */
3
+ export declare function runInspectDiagnostics(config: ResolvedServerConfig, asJson: boolean): Promise<number>;