About Eos MCP Server
Eos MCP Server is an MCP server published by aristanetworks in the Developer Tools category: mCP server for EOS using eAPI.
The repository has 10 stars and 1 forks, with the last commit 16 days ago. Recent commit activity is the strongest signal that reported issues will get attention.
Install
git clone https://github.com/aristanetworks/eos-mcp-serverThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Ask AI
Ask AI about Eos MCP Server
Powered by Claude · Grounded in docs
Security checks
Static checks derived from the repository 6 days ago. Heuristics on the source, not an audit.
- ✓README presentThe repository ships documentation.
- ✓License declaredUsable under a stated license.
- ✓Tests presentA test suite exists in the repository.
- ✓Dependencies pinnedA lockfile pins dependency versions.
- ✓No dynamic code executionSource scan found no eval, dynamic Function, or shell execution.
1 check has not been run yet.
Releases
README
eos-mcp-server
Read-only MCP server for Arista EOS eAPI (JSON-RPC over HTTPS).
Beta status: this project is under active development. Support: best-effort only. This open source project is not currently supported by Arista TAC.
This server provides a set of read-only tools. It never exposes configuration-changing operations. The server can:
- introspect its own runtime and inventory
- list inventory hosts/groups
- probe EOS device readiness
- run
showcommands - retrieve bounded logging output for troubleshooting
- collect a fixed set of device facts
- retrieve running configuration
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.
Contents
- What's included
- Requirements
- Install and get started
- Server config file
- Connect to an MCP client
- Skills
- CLI usage
- MCP tool reference
- Inventory formats
- Connection and authentication
- TLS behavior
- Common troubleshooting
- EOS version compatibility
What's included
Implemented MCP tools:
eos_get_server_infoeos_list_inventoryeos_probe_deviceseos_run_showeos_show_loggingeos_get_factseos_get_running_config
Implemented local CLI commands:
servevalidate-inventoryprint-server-infoprobe
Requirements
- Node.js 24+
- Arista EOS devices reachable via eAPI over HTTPS
- EOS 4.20 or later
- Inventory in one of the supported YAML formats
Install and get started
The package is published on npm as @aristanetworks/eos-mcp-server. The package provides the eos-mcp-server command.
npx or global install?
Both run the same package. They differ in when the version changes and whether the npm registry must be reachable when the server starts.
| Use | When |
|---|---|
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. |
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. |
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. |
.tgz from a GitHub release |
The machine can't reach the npm registry at all. |
Run with npx (recommended)
No install step is needed. npx downloads the package on first use and caches it:
npx -y @aristanetworks/eos-mcp-server --help
The MCP client examples 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.6.1-beta.
Or install globally
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:
npm install -g @aristanetworks/eos-mcp-server
eos-mcp-server --help
Update it later with npm update -g @aristanetworks/eos-mcp-server, or remove it with npm uninstall -g @aristanetworks/eos-mcp-server.
Prereleases are published under the next tag (@aristanetworks/eos-mcp-server@next). Each GitHub release also attaches the package as a .tgz, for offline installs: npm install -g ./aristanetworks-eos-mcp-server-<version>.tgz.
Upgrading from a .tgz install
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:
npm uninstall -g eos-mcp-server
Validate your inventory
Create an inventory, provide the device password, and validate connectivity:
export EOS_MCP_PASSWORD='replace-with-device-password'
npx -y @aristanetworks/eos-mcp-server validate-inventory --inventory inventory.yml
npx -y @aristanetworks/eos-mcp-server probe --inventory inventory.yml --target leaf1
With a global install, run eos-mcp-server in place of npx -y @aristanetworks/eos-mcp-server. The CLI usage examples later in this README use the shorter eos-mcp-server form.
See Quickstart for a complete inventory example and MCP client setup. For building or contributing from source, see the developer workflow.
Server config file
The server needs an inventory to start. At minimum, provide one of:
--inventory <path>directly, or--config <path>pointing at a YAML config file that itself setsinventory: <path>
Beyond that minimum, a config file is optional — use one when you want to set additional options such as timeouts, request limits, or a default connection. CLI flags always override config-file values.
Example:
version: 1
inventory: ./inventory.yml
actor: lab-user
readTimeoutMs: 10000
overallOperationTimeoutMs: 30000
deviceConcurrency: 5
maxReadTargets: 50
maxShowCommandsPerRequest: 5
maxLoggingMessagesPerRequest: 1000
maxResponseSizeBytes: 1048576
eapiVersion: latest
secretEnvPrefixes:
- EOS_MCP_
defaultConnection:
ansibleUser: admin
mcpPasswordEnv: EOS_MCP_PASSWORD
mcpValidateCerts: false
Supported config fields:
inventoryactorlogFilecaFilereadTimeoutMsoverallOperationTimeoutMsdeviceConcurrencymaxReadTargetsmaxShowCommandsPerRequestmaxLoggingMessagesPerRequestmaxResponseSizeByteseapiVersionsecretEnvPrefixesdefaultConnection.ansibleUserdefaultConnection.ansibleHttpapiPortdefaultConnection.mcpValidateCertsdefaultConnection.mcpPasswordEnv
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 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.
actor and logFile are currently exposed only as sanitized runtime metadata; the server does not yet write an audit log.
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.
Connect to an MCP client
These examples assume you have an inventory file (and optionally a server config file) ready. They launch the server with npx, so nothing needs to be installed first. If you installed globally, use eos-mcp-server as the command and drop -y @aristanetworks/eos-mcp-server from the arguments.
Generic stdio example
Point the server at just an inventory file:
{
"mcpServers": {
"eos": {
"command": "npx",
"args": [
"-y",
"@aristanetworks/eos-mcp-server",
"serve",
"--inventory",
"/absolute/path/to/inventory.yml"
]
}
}
}
Or use a server config file if you want to set additional options:
{
"mcpServers": {
"eos": {
"command": "npx",
"args": [
"-y",
"@aristanetworks/eos-mcp-server",
"serve",
"--config",
"/absolute/path/to/eos-mcp-server.yml"
]
}
}
}
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.
Claude Code
With just an inventory file:
claude mcp add eos -- npx -y @aristanetworks/eos-mcp-server serve --inventory /absolute/path/to/inventory.yml
Or with a server config file for additional options:
claude mcp add eos -- npx -y @aristanetworks/eos-mcp-server serve --config /absolute/path/to/eos-mcp-server.yml
Add -s user before eos in either command to make the server available across all your projects instead of just the current one:
claude mcp add -s user eos -- npx -y @aristanetworks/eos-mcp-server serve --inventory /absolute/path/to/inventory.yml
Codex
Add the server to .codex/config.toml in a trusted project, or to
~/.codex/config.toml for all projects.
With just an inventory file:
[mcp_servers.eos]
command = "npx"
args = ["-y", "@aristanetworks/eos-mcp-server", "serve", "--inventory", "/absolute/path/to/inventory.yml"]
env_vars = ["EOS_MCP_PASSWORD"]
Or with a server config file for additional options:
[mcp_servers.eos]
command = "npx"
args = ["-y", "@aristanetworks/eos-mcp-server", "serve", "--config", "/absolute/path/to/eos-mcp-server.yml"]
env_vars = ["EOS_MCP_PASSWORD"]
serve is optional because it is the default command, but is shown explicitly
here for clarity. After exporting the password, you can also add the server and
pass its current value through with the Codex CLI:
export EOS_MCP_PASSWORD='replace-with-device-password'
codex mcp add eos \
--env EOS_MCP_PASSWORD="$EOS_MCP_PASSWORD" \
-- npx -y @aristanetworks/eos-mcp-server serve \
--inventory /absolute/path/to/inventory.yml
The --env form stores the expanded value in the generated Codex configuration.
To have Codex read the variable from its environment each time it starts the
server, use env_vars = ["EOS_MCP_PASSWORD"] as in the TOML examples above.
Passing secrets to the MCP server
To export secrets in the environment that launches the MCP client use:
export EOS_MCP_PASSWORD='super-secret'
For Codex, env_vars = ["EOS_MCP_PASSWORD"] forwards that exported variable to
the server. Other MCP clients may support per-server env blocks. Avoid
committing secret values to client config files when possible.
Skills
The 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.
The current skills cover:
- Health checks: BGP, EVPN and EVPN multicast, interfaces, Port-Channels/LACP, VLANs, routing tables and VRFs, IGMP snooping, and PIM.
- Validation: ISIS Segment Routing, RFC 9721 EVPN IP mobility, and MCS/CVX configuration.
- Troubleshooting: multicast flows that are missing, dropping, or corrupted; PTP grandmaster and connectivity problems; Segment Routing faults; and MCS mounts and agents.
See 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.
Contribute a skill
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.
- Add
skills/<skill-name>/SKILL.mdwithname,description,trigger, andallowed-toolsfrontmatter. The existing skills are good templates. - Keep it read-only, and keep it generic: no site-specific hostnames, group names, or inventory layouts.
- Document the EOS commands the skill runs, the JSON fields it relies on, and what to check when something looks wrong.
- Add a row for the skill to the table in
skills/README.md. - Open a pull request that changes only files under
skills/.
Pull requests that touch only skills/ can be accepted without a contributor license agreement. They are licensed under Apache-2.0. See CONTRIBUTING.md for details, and 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.
Inventory formats
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.
Supported formats:
- canonical Ansible-style YAML
- simplified YAML
Canonical inventories must have all as the only top-level key. Simplified inventories may use only version, vars, hosts, and groups at the top level. Unknown structural keys are rejected; unknown keys inside vars remain allowed.
Canonical Ansible-style example
all:
children:
eos:
vars:
ansible_user: admin
ansible_network_os: eos
mcp_password_env: EOS_MCP_PASSWORD
hosts:
leaf1:
ansible_host: 192.0.2.11
leaf2:
ansible_host: 192.0.2.12
Simplified YAML example
version: 1
vars:
ansible_user: admin
mcp_password_env: EOS_MCP_PASSWORD
hosts:
leaf1:
ansible_host: 192.0.2.11
ansible_network_os: eos
leaf2:
ansible_host: 192.0.2.12
ansible_network_os: eos
groups:
leafs:
hosts: [leaf1, leaf2]
For an inventory where devices do not share a password, see
example-inventories/multi-password.yaml.
Each host sets its own mcp_password_env reference, so the actual passwords
remain in the environment rather than in the inventory file. For example:
export EOS_MCP_SPINE1_PASSWORD='spine1-password'
export EOS_MCP_SPINE2_PASSWORD='spine2-password'
export EOS_MCP_LEAF1_PASSWORD='leaf1-password'
export EOS_MCP_LEAF2_PASSWORD='leaf2-password'
eos-mcp-server validate-inventory \
--inventory example-inventories/multi-password.yaml
eos-mcp-server serve --inventory example-inventories/multi-password.yaml
The password environment variable name is resolved independently for each
host. Host-level values override inherited group or global values, so devices
can be queried together through the FABRIC, SPINES, or LEAFS targets while
still using their individual credentials.
Important inventory rules
- Targets must be inventory host or group names, not IP addresses.
- Host/group names must match
^[A-Za-z0-9_.-]+$. - Duplicate YAML keys are rejected.
- The simplified schema reserves
all; do not definegroups.allthere. - Group graphs must be acyclic.
- EOS eligibility comes from either:
ansible_network_os: eosmcp_platform: arista_eos
mcp_read_alloweddefaults totruefor eligible EOS hosts. Set it tofalse— inherited like any other variable — to explicitly deny read access to a host or group.- Read operations fail closed if the resolved target contains ineligible or read-denied hosts.
Connection and authentication
Supported connection fields
The read path currently uses these effective fields:
ansible_host- device hostname/IP for HTTPS connectionansible_httpapi_port- optional eAPI port, default443ansible_user- usernamemcp_password_env- preferred password source, treated as an environment variable nameansible_password- literal password sourcemcp_validate_certs- optional boolean to disable TLS validation for a lab target;ansible_httpapi_validate_certsis also accepted as a fallback
Password source rules
Exactly one password source must resolve per EOS host:
mcp_password_envansible_password
Do not set both.
If you use mcp_password_env, the value must be the name of an environment variable, not the password itself.
Correct:
mcp_password_env: EOS_MCP_PASSWORD
Incorrect:
mcp_password_env: admin
The default allowed env var prefix is EOS_MCP_, so names like EOS_MCP_PASSWORD work by default.
Example:
export EOS_MCP_PASSWORD='replace-with-device-password'
TLS behavior
- HTTPS only
- certificate validation is on by default
- optional custom CA bundle via config file
caFile - per-target or inherited inventory override via
mcp_validate_certs: false(oransible_httpapi_validate_certs: false)
There is currently no CLI --insecure flag.
Disable cert validation for a lab inventory
all:
children:
eos:
vars:
ansible_user: admin
ansible_network_os: eos
mcp_password_env: EOS_MCP_PASSWORD
mcp_validate_certs: false
hosts:
leaf1:
ansible_host: 192.0.2.11
Prefer a CA bundle when possible
Server config:
inventory: inventory.yml
caFile: /path/to/ca.pem
CLI usage
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.
serve
Start the MCP server over stdio.
eos-mcp-server serve --inventory inventory.yml
eos-mcp-server serve --config eos-mcp-server.yml
On startup, serve loads the inventory and validates startup connection requirements for EOS-eligible hosts.
validate-inventory
Validate the inventory file.
Default behavior performs:
- inventory parsing and structural validation
- effective inventory validation
- startup-style connection validation for EOS-eligible hosts using the loaded config/default connection settings
Use --inventory-only to skip the startup connection checks.
print-server-info
Print the server's sanitized runtime/config summary.
eos-mcp-server print-server-info --inventory inventory.yml
eos-mcp-server print-server-info --config eos-mcp-server.yml --json
probe
Probe a host or group target using the same logic as the MCP tool.
eos-mcp-server probe --inventory inventory.yml --target leaf1
eos-mcp-server probe --inventory inventory.yml --target leafs --json
Human-readable example output:
Probe target: leaf1
Devices: 1/1 succeeded
- leaf1: success
MCP tool reference
eos_get_server_info
Returns a sanitized summary of server runtime, capabilities, limits, TLS/config posture, and inventory summary.
Input:
{}
eos_list_inventory
Returns a sanitized view of the loaded inventory.
Input:
{
"include_ineligible": false
}
eos_probe_devices
Checks operational readiness for a host or group by contacting devices and running a harmless command.
Input:
{
"target": "leaf1",
"include_raw": false
}
eos_run_show
Runs one or more show commands.
Rules:
- exactly one of
commandorcommands - every command is trimmed, must be a single line, and must be
showor begin withshow - commands with CLI output modifiers or shell metacharacters such as
|,>,<,;,&, backticks, or$are rejected before device contact output_formatis one ofauto,json,textinclude_rawoptionally attaches each command's raw eAPI result entry asraw_entryinsidecommand_results
Input examples:
{
"target": "leaf1",
"command": "show version",
"output_format": "auto"
}
{
"target": "leafs",
"commands": ["show version", "show interfaces status"],
"output_format": "json",
"include_raw": false
}
eos_show_logging
Retrieves bounded EOS logging output for a host or group target. The tool always uses text output and generates show logging threshold <minimum_severity> <message_count>. minimum_severity is a threshold, so warnings includes warning and more urgent log messages. Defaults are minimum_severity: "warnings" and message_count: 100; message_count is capped by maxLoggingMessagesPerRequest.
Input example:
{
"target": "leaf1",
"minimum_severity": "warnings",
"message_count": 100
}
Allowed severities are emergencies, alerts, critical, errors, warnings, notifications, informational, and debugging.
eos_get_facts
Collects a small, fixed core facts set from show version.
Input:
{
"target": "leaf1",
"include_raw": false
}
eos_get_running_config
Returns running config text for a host target, or for a group target when section is provided. Automatically enters enable mode via eAPI since show running-config requires privileged access. section is trimmed and must be a single-line EOS section selector without CLI output modifiers or shell metacharacters.
Input examples:
{
"target": "leaf1"
}
{
"target": "leafs",
"section": "router bgp"
}
Common troubleshooting
Password env var ... does not match any allowed prefix
mcp_password_env must contain an environment variable name like EOS_MCP_PASSWORD, not the password itself.
Password env var ... is not set
Export the referenced environment variable before launching probe or serve.
Certificate validation failure
Use one of:
caFilein the server config to trust your lab CAmcp_validate_certs: false(oransible_httpapi_validate_certs: false) in inventory for a lab/dev target
There is no CLI TLS-disable flag today.
Unknown inventory target ...
Tool and CLI targets must be inventory names, not ansible_host IPs.
Group running-config request failed without section
For eos_get_running_config, group targets require a section value.
Command or section rejected as invalid
eos_run_show accepts only single-line show commands. eos_get_running_config.section must also be a single-line selector. Newlines, other control characters, CLI output modifiers, and shell metacharacters are rejected before any device contact.
Response too large
Read tools are bounded by maxResponseSizeBytes. The server rejects oversized device HTTP responses before buffering them fully, and also rejects oversized aggregate tool results with narrowing guidance. For eos_show_logging, reduce message_count, target fewer devices, or raise minimum_severity.
Policy denied when probing a device
Example:
eos-mcp-server probe --inventory clab/clab-testlab/ansible-inventory.yml --target clab-testlab-node1-1
Policy denied: target clab-testlab-node1-1 includes host(s) not permitted for read operations: clab-testlab-node1-1
This means the target resolved to at least one host that is either not marked as EOS eligible (ansible_network_os: eos or mcp_platform: arista_eos) or has mcp_read_allowed: false set.
EOS version compatibility
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.
Design notes
- inventory is the trust boundary
- reads are fail-closed on ineligible or denied targets
- the server exposes only documented read-only operations
Project docs
Additional design and planning docs in the docs/ directory:
docs/DESIGN.md— detailed design specificationdocs/IMPLEMENTATION_PLAN.md— implemented scope and maintenance prioritiesdocs/CHECKPOINT.md— current implementation statusdocs/CODE_WALKTHROUGH.md— source layout and module guidedocs/QUICKSTART.md— quick start tutorialdocs/EXAMPLES.md— inventory and usage examples
License
Copyright 2026 Arista Networks, Inc.
This project is licensed under the Apache License, Version 2.0. Apache-2.0 applies to each released version of this repository. Arista may offer later versions under additional or different terms, but cannot revoke the Apache-2.0 rights granted for versions already released under it.
README fetched from the repository 6 days ago. The original is authoritative.