io.github.shigechika/junos-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| JUNOS_MCP_POOL | No | Set to '0' to disable the connection pool and open a fresh connection per call. | 1 |
| JUNOS_OPS_CONFIG | No | Path to the config.ini file. If not set, search order: JUNOS_OPS_CONFIG env var, ./config.ini, ~/.config/junos-ops/config.ini | |
| JUNOS_MCP_POOL_IDLE | No | Idle timeout in seconds for pooled connections. Set to '0' to disable eviction. | 60 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| get_device_factsA | Get basic device information (model, hostname, serial, version, etc.). Args: hostname: Target device hostname (must exist in config.ini) config_path: Path to config.ini (empty string uses default search) |
| get_versionA | Get JUNOS version information with upgrade status. Shows running version, planning version, pending version, local/remote package status, and reboot schedule. Args: hostname: Target device hostname (must exist in config.ini) config_path: Path to config.ini (empty string uses default search) |
| run_show_commandA | Run a CLI show command on the device and return output. Args: hostname: Target device hostname (must exist in config.ini) command: CLI command to execute (e.g., "show bgp summary") output_format: Output format — "text" (default), "json", or "xml". Note: pipe stages (| match, | last, | count, etc.) are silently dropped regardless of output_format — PyEZ's Device.cli() sends the command over NETCONF RPC, which JunOS does not pipe-process. Run the command without pipes; for line filtering, use run_show_command_batch's grep_pattern argument instead (works for a single host too — pass a one-element hostnames list). That workaround always fetches text output internally, so it cannot be combined with output_format="json"/"xml" — for structured output you must filter the result client-side instead. config_path: Path to config.ini (empty string uses default search) |
| run_show_commandsA | Run multiple CLI show commands on the device in a single session. Commands are executed in sequence and stop on the first failure. To run all commands regardless of individual errors, call run_show_command once per command instead. Args: hostname: Target device hostname (must exist in config.ini) commands: List of CLI commands to execute output_format: Output format — "text" (default), "json", or "xml". Note: pipe stages (| match, | last, | count, etc.) are silently dropped regardless of output_format — PyEZ's Device.cli() sends the command over NETCONF RPC, which JunOS does not pipe-process. Run commands without pipes and filter client-side. run_show_command_batch's grep_pattern argument offers server-side-style filtering, but it only accepts one command at a time — it does not cover this tool's multi-command case, so it is not a drop-in workaround here. config_path: Path to config.ini (empty string uses default search) |
| run_show_command_batchA | Run a CLI show command on multiple devices in parallel. Uses ThreadPoolExecutor for concurrent execution. Either Args:
command: CLI command to execute on all devices
hostnames: List of target device hostnames (must exist in config.ini)
tags: Tag filter. Each list element is one tag group (comma-separated
tags AND together within a group). Multiple list elements OR
together across groups. E.g. |
| list_remote_filesA | List files on the remote device path (/var/tmp by default). Args: hostname: Target device hostname (must exist in config.ini) config_path: Path to config.ini (empty string uses default search) |
| check_upgrade_readinessB | Check if a device is ready for upgrade. Verifies whether the device is already running the target version, and performs a dry-run to check local/remote package availability. Args: hostname: Target device hostname (must exist in config.ini) config_path: Path to config.ini (empty string uses default search) |
| compare_versionA | Compare two JUNOS version strings. Returns whether left is greater than, equal to, or less than right. No device connection required. Args: left: First JUNOS version string (e.g., "22.4R3-S6.5") right: Second JUNOS version string (e.g., "23.2R1.0") |
| get_router_listA | List routers defined in config.ini, optionally filtered by tags. Returns section names from config.ini, which represent the hostnames that can be used with other tools. No device connection required. Args:
tags: Tag filter. Each list element is one tag group (comma-separated
tags AND together within a group); multiple list elements OR
together across groups. E.g. |
| get_package_infoA | Get package file name and expected hash for a specific device model. Retrieves model-specific package information from config.ini. No device connection required. Args: hostname: Target device hostname (must exist in config.ini) model: Device model name (e.g., "EX2300-24T") config_path: Path to config.ini (empty string uses default search) |
| get_configB | Get device configuration. Args: hostname: Target device hostname (must exist in config.ini) output_format: Output format - "text" (default), "set", or "xml" config_path: Path to config.ini (empty string uses default search) |
| get_config_diffA | Show configuration difference compared to a rollback version. Args: hostname: Target device hostname (must exist in config.ini) rollback_id: Rollback version to compare against (0-49, default 1) config_path: Path to config.ini (empty string uses default search) |
| collect_rsiA | Collect RSI (Request Support Information) and SCF (Show Configuration) from a device. Saves two files: {hostname}.SCF (show configuration) and {hostname}.RSI (request support information). Model-specific timeouts are applied automatically (e.g., SRX Branch: 1200s, Virtual Chassis: 1800s). Args: hostname: Target device hostname (must exist in config.ini) output_dir: Directory to save output files (empty uses config RSI_DIR or current dir) config_path: Path to config.ini (empty string uses default search) |
| collect_rsi_batchA | Collect RSI/SCF from multiple devices in parallel. Uses ThreadPoolExecutor for concurrent collection. Default 20 workers
matches junos-ops CLI default for RSI collection. Either Args:
hostnames: List of target device hostnames
tags: Tag filter. Each list element is one tag group (comma-separated
tags AND together within a group); multiple list elements OR
together across groups. Combined with |
| check_reachabilityA | Probe NETCONF reachability for one or more devices. Equivalent to Args:
hostnames: List of target device hostnames (must exist in config.ini)
tags: Tag filter. Each list element is one tag group (comma-separated
tags AND together within a group); multiple list elements OR
together across groups. Combined with |
| check_local_inventoryA | Verify local firmware checksums against the config.ini inventory. Equivalent to Args: model: Restrict to a single model (empty = all configured models) config_path: Path to config.ini (empty string uses default search) |
| check_remote_packagesA | Verify the staged firmware checksum on one or more devices. Equivalent to Args:
hostnames: List of target device hostnames (must exist in config.ini)
tags: Tag filter. Each list element is one tag group (comma-separated
tags AND together within a group); multiple list elements OR
together across groups. Combined with |
| copy_packageA | Copy firmware package to remote device via SCP with checksum verification. Checks if copy is needed (already running target version, or package already present on device). Cleans up storage before copying. Args: hostname: Target device hostname (must exist in config.ini) dry_run: If True (default), show what would be done without copying force: If True, skip version checks and force copy config_path: Path to config.ini (empty string uses default search) |
| install_packageA | Install firmware package on device with pre-flight checks. Full upgrade flow: version check -> rollback pending if needed -> copy (with checksum) -> clear reboot schedule -> rescue config save -> request system software add (with validation). Args:
hostname: Target device hostname (must exist in config.ini)
dry_run: If True (default), show what would be done without installing
force: If True, skip version checks and force install
unlink: If True, run |
| rollback_packageA | Rollback to previously installed package version. Checks pending version first. If no pending version exists, rollback is skipped. Args: hostname: Target device hostname (must exist in config.ini) dry_run: If True (default), show what would be done without rolling back config_path: Path to config.ini (empty string uses default search) |
| schedule_rebootA | Schedule device reboot at a specified time. Checks for existing reboot schedules. If one exists and force is False, the existing schedule is preserved. Args: hostname: Target device hostname (must exist in config.ini) reboot_at: Reboot time in YYMMDDHHMM format (e.g., "2601020304" = 2026-01-02 03:04) dry_run: If True (default), show what would be done without scheduling force: If True, clear existing reboot schedule and set new one config_path: Path to config.ini (empty string uses default search) |
| daily_briefA | Run a morning health check across multiple devices in parallel. Checks per host (Phase 1):
Syslog patterns watched: BGP state change away from Established, STP port role change, OSPF neighbor down, ARP address conflict, IF_DOWN.
Output tiers:
Returns a Markdown summary with anomaly details for CRITICAL/WARNING hosts and a collapsed OK list. The call stops after |
| daily_brief_startA | Start a daily_brief in the background; returns immediately with a Use this for a fleet too large for one synchronous While a job is running, a call that would switch to a different config file is
refused (the config is process-global); use the same Args:
hostnames: Only these hosts (must exist in config.ini). Default: all hosts.
tags: Tag filter. Each element is one group: a comma inside an element means
the host must have ALL of those tags ( |
| daily_brief_resultA | Fetch a
|
| push_configA | Push configuration to a device with commit confirmed and health check. Supports two input methods (exactly one required):
Safety features (not available in Juniper's official MCP server):
Commit flow (normal): lock -> load -> diff -> commit_check -> commit confirmed -> health check -> confirm -> unlock Commit flow (no_commit=True — intentional auto-rollback): lock -> load -> diff -> commit_check -> commit confirmed -> unlock (health check and final confirm are skipped; JUNOS rolls back automatically after confirm_timeout minutes) RPC timeout: every step uses Per-call deadline: with Only one push per host runs at a time; a second one is refused. While a push holds a host, other tools on that host wait at most until the deadline and then answer "host busy". Args:
hostname: Target device hostname (must exist in config.ini)
config_file: Path to .set or .j2 file (mutually exclusive with set_commands)
set_commands: List of set commands (mutually exclusive with config_file)
dry_run: If True (default), show diff only without committing
confirm_timeout: Minutes before auto-rollback (default 1, used with commit confirmed)
no_commit: If True, issue commit confirmed but intentionally skip the final
commit so JUNOS auto-rolls back after confirm_timeout minutes. Useful
for triggering service restarts (e.g. syslog on EX3400) where no
|
| push_config_startA | Start push_config as a background job and return its diff and Use this instead of The job locks the candidate configuration, loads the change and computes the
diff, and this call returns that diff ( With Returns Args: hostname: Target device hostname (must exist in config.ini) config_file: Path to .set or .j2 file (mutually exclusive with set_commands) set_commands: List of set commands (mutually exclusive with config_file) dry_run: If True (default), return the diff only; nothing is committed confirm_timeout: Minutes before auto-rollback (default 1) no_commit: Commit confirmed only, then let JUNOS roll back (see push_config) health_check: Health check commands after commit (see push_config; default ["uptime"]) config_path: Path to config.ini (empty string uses default search) |
| push_config_resultA | Fetch a
|
| health_checkA | Report server version and config status — without connecting to any device. Call this at session start (or after a tool-call timeout) to confirm the MCP is up, see which version is running, and verify that config.ini loads and how many routers it defines. Lightweight by design: junos-mcp fans out to many Juniper devices, so this check ONLY loads config.ini and counts hosts — it opens NO NETCONF/SSH connection to any device. Always returns the same keys: Args: config_path: Path to config.ini (empty string uses default search). |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 28 tools
Most tools have clearly distinct purposes, and the descriptions carefully explain the sync/async split for push_config, daily_brief, and their _start/_result partners. The main hazard is the run_show_command / run_show_commands / run_show_command_batch trio, where a singular 's' distinguishes 'one command' from 'multiple commands on one host' vs 'one command on many hosts' — easy to misselect without reading descriptions. check_reachability vs health_check is also mildly confusable but documented.
Almost everything follows a snake_case verb_noun pattern (get_*, run_*, check_*, collect_*, copy/install/rollback_package, push_config_*, *_start/*_result). A few names drop the verb (daily_brief, health_check) and the singular/plural run_show_command(s) deviation is awkward, but conventions are otherwise predictable.
28 tools is on the heavy side, though the surface genuinely spans config push, show execution, firmware lifecycle, RSI collection, and fleet monitoring. The async/sync pairs (push_config*, daily_brief*) are justified by real client timeouts, but some consolidation and the near-duplicate show-command variants push this into 'heavy' territory.
Strong lifecycle coverage: config read/diff/push with commit-confirmed safety, firmware copy/install/rollback, reboot scheduling, RSI collection, and health monitoring with a job model. Gaps are minor — no explicit configuration rollback (only diff against a rollback_id) and no remote file upload/delete beyond package copy, but core workflows are covered.