@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.
- package/CHANGELOG.md +19 -0
- package/README.md +197 -44
- package/dist/cli.d.ts +4 -1
- package/dist/cli.js +63 -4
- package/dist/cli.js.map +1 -1
- package/dist/commands/inspectDiagnostics.d.ts +3 -0
- package/dist/commands/inspectDiagnostics.js +35 -0
- package/dist/commands/inspectDiagnostics.js.map +1 -0
- package/dist/commands/releaseDiagnostics.d.ts +9 -0
- package/dist/commands/releaseDiagnostics.js +87 -0
- package/dist/commands/releaseDiagnostics.js.map +1 -0
- package/dist/config/diagnostics.d.ts +60 -0
- package/dist/config/diagnostics.js +37 -0
- package/dist/config/diagnostics.js.map +1 -0
- package/dist/config/loadConfig.js +6 -1
- package/dist/config/loadConfig.js.map +1 -1
- package/dist/config/schema.d.ts +168 -8
- package/dist/config/schema.js +3 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/diagnostics/concurrency.d.ts +33 -0
- package/dist/diagnostics/concurrency.js +157 -0
- package/dist/diagnostics/concurrency.js.map +1 -0
- package/dist/diagnostics/eapiRunner.d.ts +10 -0
- package/dist/diagnostics/eapiRunner.js +46 -0
- package/dist/diagnostics/eapiRunner.js.map +1 -0
- package/dist/diagnostics/executionError.d.ts +7 -0
- package/dist/diagnostics/executionError.js +10 -0
- package/dist/diagnostics/executionError.js.map +1 -0
- package/dist/diagnostics/executor.d.ts +32 -0
- package/dist/diagnostics/executor.js +115 -0
- package/dist/diagnostics/executor.js.map +1 -0
- package/dist/diagnostics/journal.d.ts +14 -0
- package/dist/diagnostics/journal.js +317 -0
- package/dist/diagnostics/journal.js.map +1 -0
- package/dist/diagnostics/journalTypes.d.ts +8 -0
- package/dist/diagnostics/journalTypes.js +2 -0
- package/dist/diagnostics/journalTypes.js.map +1 -0
- package/dist/diagnostics/ping.d.ts +7 -0
- package/dist/diagnostics/ping.js +131 -0
- package/dist/diagnostics/ping.js.map +1 -0
- package/dist/diagnostics/releaseEvidence.d.ts +502 -0
- package/dist/diagnostics/releaseEvidence.js +115 -0
- package/dist/diagnostics/releaseEvidence.js.map +1 -0
- package/dist/diagnostics/reservationSchema.d.ts +49 -0
- package/dist/diagnostics/reservationSchema.js +18 -0
- package/dist/diagnostics/reservationSchema.js.map +1 -0
- package/dist/diagnostics/statePath.d.ts +4 -0
- package/dist/diagnostics/statePath.js +25 -0
- package/dist/diagnostics/statePath.js.map +1 -0
- package/dist/diagnostics/types.d.ts +82 -0
- package/dist/diagnostics/types.js +2 -0
- package/dist/diagnostics/types.js.map +1 -0
- package/dist/eapi/client.d.ts +3 -1
- package/dist/eapi/client.js +17 -6
- package/dist/eapi/client.js.map +1 -1
- package/dist/eapi/types.d.ts +6 -0
- package/dist/eapi/types.js.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/inventory/buildModel.js +1 -0
- package/dist/inventory/buildModel.js.map +1 -1
- package/dist/inventory/listInventoryView.d.ts +1 -0
- package/dist/inventory/listInventoryView.js +1 -0
- package/dist/inventory/listInventoryView.js.map +1 -1
- package/dist/inventory/policy.d.ts +1 -0
- package/dist/inventory/policy.js +3 -1
- package/dist/inventory/policy.js.map +1 -1
- package/dist/inventory/types.d.ts +1 -0
- package/dist/inventory/varValidation.js +1 -0
- package/dist/inventory/varValidation.js.map +1 -1
- package/dist/mcp/createServer.js +56 -4
- package/dist/mcp/createServer.js.map +1 -1
- package/dist/mcp/tools/getServerInfo.d.ts +2 -1
- package/dist/mcp/tools/getServerInfo.js +2 -2
- package/dist/mcp/tools/getServerInfo.js.map +1 -1
- package/dist/mcp/tools/ping.d.ts +38 -0
- package/dist/mcp/tools/ping.js +40 -0
- package/dist/mcp/tools/ping.js.map +1 -0
- package/dist/operations/readExecution.d.ts +3 -1
- package/dist/operations/readExecution.js +24 -16
- package/dist/operations/readExecution.js.map +1 -1
- package/dist/serverInfo/buildServerInfo.d.ts +2 -1
- package/dist/serverInfo/buildServerInfo.js +16 -2
- package/dist/serverInfo/buildServerInfo.js.map +1 -1
- package/dist/serverInfo/types.d.ts +15 -0
- package/dist/utils/privateFile.d.ts +3 -0
- package/dist/utils/privateFile.js +7 -0
- package/dist/utils/privateFile.js.map +1 -0
- package/docs/CHECKPOINT.md +11 -1
- package/docs/CODE_WALKTHROUGH.md +30 -6
- package/docs/DESIGN.md +17 -4
- package/docs/DIAGNOSTICS.md +218 -0
- package/docs/IMPLEMENTATION_PLAN.md +5 -4
- package/docs/QUICKSTART.md +13 -13
- package/docs/adr/0001-non-configuring-diagnostics.md +5 -0
- package/docs/adr/0002-fail-closed-diagnostic-reservations.md +7 -0
- package/docs/adr/0003-durable-diagnostic-ledger.md +9 -0
- package/docs/adr/0004-offline-operator-attested-release.md +5 -0
- package/docs/adr/0005-multi-destination-ping.md +9 -0
- package/docs/examples/diagnostic-release-evidence.template.json +26 -0
- package/docs/research/eos-diagnostic-lifecycle.md +84 -0
- package/package.json +1 -1
- package/dist/inventory/writePolicy.d.ts +0 -2
- package/dist/inventory/writePolicy.js +0 -36
- 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
|
|
1
|
+
# eos-mcp-server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/aristanetworks/eos-mcp-server/releases)
|
|
4
|
+
[](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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
66
|
-
npm install -g @aristanetworks/eos-mcp-server
|
|
67
|
-
```
|
|
84
|
+
### Run with npx (recommended)
|
|
68
85
|
|
|
69
|
-
|
|
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
|
-
|
|
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
|
-
|
|
74
|
-
eos-mcp-server --help
|
|
75
|
-
```
|
|
94
|
+
### Or install globally
|
|
76
95
|
|
|
77
|
-
|
|
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
|
|
99
|
+
npm install -g @aristanetworks/eos-mcp-server
|
|
100
|
+
eos-mcp-server --help
|
|
81
101
|
```
|
|
82
102
|
|
|
83
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
208
|
+
Point the server at just an inventory file:
|
|
155
209
|
|
|
156
210
|
```json
|
|
157
211
|
{
|
|
158
212
|
"mcpServers": {
|
|
159
213
|
"eos": {
|
|
160
|
-
"command": "
|
|
161
|
-
"args": [
|
|
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": "
|
|
174
|
-
"args": [
|
|
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
|
|
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
|
-
|
|
212
|
-
|
|
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
|
-
|
|
221
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
233
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAI1D,MAAM,aAAa,GAAG,IAAI,GAAG,CAAS,CAAC,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAI1D,MAAM,aAAa,GAAG,IAAI,GAAG,CAAS,CAAC,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,CAAC,CAAC,CAAC;AACnJ,MAAM,YAAY,GAAG,IAAI,GAAG,CAAS;IACnC,QAAQ;IACR,IAAI;IACJ,WAAW;IACX,IAAI;IACJ,UAAU;IACV,aAAa;IACb,SAAS;IACT,QAAQ;IACR,kBAAkB;IAClB,UAAU;IACV,kBAAkB;IAClB,iBAAiB;IACjB,kBAAkB;CACnB,CAAC,CAAC;AAEH,MAAM,eAAe,GAA6C;IAChE,OAAO,EAAE,IAAI,GAAG,CAAC;QACf,QAAQ;QACR,IAAI;QACJ,WAAW;QACX,IAAI;QACJ,UAAU;QACV,aAAa;QACb,SAAS;KACV,CAAC;IACF,oBAAoB,EAAE,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IAC3H,mBAAmB,EAAE,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IACtG,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IACtG,qBAAqB,EAAE,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IACxG,qBAAqB,EAAE,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;CACpK,CAAC;AAkBF,MAAM,UAAU,YAAY,CAAC,IAAc;IACzC,IAAI,OAAO,GAAgB,OAAO,CAAC;IACnC,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACpC,CAAC;IAED,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,KAAK,KAAK,SAAS,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,OAAO,GAAG,KAAoB,CAAC;QAC/B,eAAe,GAAG,IAAI,CAAC;QACvB,KAAK,GAAG,CAAC,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAe,EAAE,OAAO,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAE/F,OAAO,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,GAAG,KAAK,SAAS,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACpC,CAAC;QAED,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,QAAQ,CAAC;YACd,KAAK,IAAI;gBACP,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;gBACpB,OAAO,OAAO,CAAC;YACjB,KAAK,WAAW,CAAC;YACjB,KAAK,IAAI;gBACP,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;gBACvB,OAAO,OAAO,CAAC;YACjB,KAAK,UAAU,CAAC,CAAC,CAAC;gBAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;gBAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,MAAM,IAAI,QAAQ,CAAC,mBAAmB,EAAE,4BAA4B,CAAC,CAAC;gBACxE,CAAC;gBACD,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC;gBAC3B,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM;YACR,CAAC;YACD,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;gBAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,MAAM,IAAI,QAAQ,CAAC,mBAAmB,EAAE,+BAA+B,CAAC,CAAC;gBAC3E,CAAC;gBACD,OAAO,CAAC,aAAa,GAAG,KAAK,CAAC;gBAC9B,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM;YACR,CAAC;YACD,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;gBAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,MAAM,IAAI,QAAQ,CAAC,mBAAmB,EAAE,2BAA2B,CAAC,CAAC;gBACvE,CAAC;gBACD,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;gBACtB,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM;YACR,CAAC;YACD,KAAK,QAAQ;gBACX,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;gBACpB,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM;YACR,KAAK,kBAAkB;gBACrB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;gBAC7B,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM;YACR,KAAK,kBAAkB,CAAC,CAAC,CAAC;gBACxB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;gBAC9B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,MAAM,IAAI,QAAQ,CAAC,mBAAmB,EAAE,oCAAoC,CAAC,CAAC;gBACnH,IAAI,OAAO,CAAC,cAAc,EAAE,QAAQ,CAAC,KAAK,CAAC;oBAAE,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,0BAA0B,CAAC,CAAC;gBACpH,CAAC,OAAO,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAC5C,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM;YACR,CAAC;YACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;gBAC9B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,MAAM,IAAI,QAAQ,CAAC,mBAAmB,EAAE,mCAAmC,CAAC,CAAC;gBAClH,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS;oBAAE,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,2BAA2B,CAAC,CAAC;gBAChH,OAAO,CAAC,YAAY,GAAG,KAAK,CAAC;gBAC7B,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM;YACR,CAAC;YACD,KAAK,kBAAkB;gBACrB,IAAI,OAAO,CAAC,aAAa,KAAK,SAAS;oBAAE,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,4BAA4B,CAAC,CAAC;gBAClH,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;gBAC7B,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM;YACR,KAAK,UAAU,CAAC,CAAC,CAAC;gBAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;gBAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,MAAM,IAAI,QAAQ,CAAC,mBAAmB,EAAE,4BAA4B,CAAC,CAAC;gBACxE,CAAC;gBACD,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC;gBACvB,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM;YACR,CAAC;YACD;gBACE,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,qBAAqB,GAAG,EAAE,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAoB,EAAE,MAAc;IAC/D,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,QAAQ,CAAC,wBAAwB,EAAE,UAAU,MAAM,6BAA6B,OAAO,EAAE,CAAC,CAAC;IACvG,CAAC;AACH,CAAC;AAED,MAAM,cAAc,GAAG,GAAG,QAAQ,KAAK,WAAW,EAAE,CAAC;AAErD,MAAM,QAAQ,GAAG,GAAG,cAAc;;;SAGzB,QAAQ;;;;;;;;;;;;;;;;OAgBV,QAAQ,kDAAkD,CAAC;AAElE,MAAM,UAAU,GAAG,UAAU,QAAQ;;;;;;;;+CAQU,CAAC;AAEhD,MAAM,uBAAuB,GAAG,UAAU,QAAQ;;;;;;;;;;+CAUH,CAAC;AAEhD,MAAM,sBAAsB,GAAG,UAAU,QAAQ;;;;;;;;+CAQF,CAAC;AAEhD,MAAM,UAAU,GAAG,UAAU,QAAQ;;;;;;;;;;+CAUU,CAAC;AAEhD,MAAM,wBAAwB,GAAG,UAAU,QAAQ;;;;;;;;;+CASJ,CAAC;AAEhD,MAAM,wBAAwB,GAAG,UAAU,QAAQ;;;;;;;;;;;;;gDAaH,CAAC;AAEjD,MAAM,YAAY,GAAgC;IAChD,OAAO,EAAE,UAAU;IACnB,oBAAoB,EAAE,uBAAuB;IAC7C,mBAAmB,EAAE,sBAAsB;IAC3C,OAAO,EAAE,UAAU;IACnB,qBAAqB,EAAE,wBAAwB;IAC/C,qBAAqB,EAAE,wBAAwB;CAChD,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,GAAe;IACvC,MAAM,QAAQ,GAAG,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC5E,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAC9B,CAAC"}
|