← Back to search

Junos MCP

shigechika Scanned 3h ago

MCP server for Juniper Networks device operations via junos-ops

C
61.6 / 100

Versions

No versions found.

PermissionsTool SafetyAuthAnnotationsCode QualityStabilitySpecVuln HistoryAuthorTransparencyCommunity

Tools 24

get_device_facts
annotations: none low

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)

hostname str config_path str
get_version
annotations: none low

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)

hostname str config_path str
run_show_command
annotations: none low

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)

command str hostname str config_path str output_format str
run_show_commands
annotations: none low

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)

commands string hostname str config_path str output_format str
run_show_command_batch
annotations: none low

Run a CLI show command on multiple devices in parallel. Uses ThreadPoolExecutor for concurrent execution. Either ``hostnames`` or ``tags`` selects the targets; if both are omitted, every router in config.ini is targeted. When both are given, the intersection is used. 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. ``["tokyo,core", "backup"]`` means ``(tokyo AND core) OR backup``. Combined with ``hostnames`` the result is the intersection. grep_pattern: Optional Python ``re`` pattern. When set, only lines matching the pattern (via ``re.search``) are kept from each host's output. Header lines (starting with ``#``) are always preserved. Hosts with no matching lines show ``(no match)``. Reduces large batch outputs to the essential lines. This tool always fetches text output internally (there is no ``output_format`` parameter here) — ``grep_pattern`` filters plain-text lines and cannot be combined with structured JSON/XML output. max_workers: Maximum parallel threads (default 5) config_path: Path to config.ini (empty string uses default search)

tags string command str hostnames string config_path str max_workers int grep_pattern string
list_remote_files
annotations: none low

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)

hostname str config_path str
check_upgrade_readiness
annotations: none low

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)

hostname str config_path str
compare_version
annotations: none low

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")

left str right str
get_router_list
annotations: none low

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. ``["tokyo,core", "backup"]`` means ``(tokyo AND core) OR backup``. None/empty returns all. config_path: Path to config.ini (empty string uses default search)

tags string config_path str
get_package_info
annotations: none low

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)

model str hostname str config_path str
get_config
annotations: none low

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)

hostname str config_path str output_format str
get_config_diff
annotations: none low

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)

hostname str config_path str rollback_id int
collect_rsi
annotations: none low

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)

hostname str output_dir str config_path str
collect_rsi_batch
annotations: none low

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 ``hostnames`` or ``tags`` selects the targets; if both are omitted, every router in config.ini is targeted. When both are given, the intersection is used. 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 ``hostnames`` the result is the intersection. output_dir: Directory to save output files (empty uses config RSI_DIR or current dir) max_workers: Maximum parallel threads (default 20) config_path: Path to config.ini (empty string uses default search)

tags string hostnames string output_dir str config_path str max_workers int
check_reachability
annotations: none low

Probe NETCONF reachability for one or more devices. Equivalent to ``junos-ops check --connect``. Opens a fast NETCONF handshake (no full PyEZ facts gathering, 5-second TCP probe) and reports per-host status as a table. 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 ``hostnames`` the result is the intersection. max_workers: Maximum parallel threads (default 20, matches junos-ops) config_path: Path to config.ini (empty string uses default search)

tags string hostnames string config_path str max_workers int
check_local_inventory
annotations: none low

Verify local firmware checksums against the config.ini inventory. Equivalent to ``junos-ops check --local``. Iterates every ``<model>.file`` / ``<model>.hash`` pair in the DEFAULT section of ``config.ini`` and verifies the file on the staging server. No device connection required. Args: model: Restrict to a single model (empty = all configured models) config_path: Path to config.ini (empty string uses default search)

model str config_path str
check_remote_packages
annotations: none low

Verify the staged firmware checksum on one or more devices. Equivalent to ``junos-ops check --remote``. Connects to each device via NETCONF and verifies the package file (``<model>.file``) sitting on the device against ``<model>.hash``. Doubles as post-SCP copy verification. Per-host model resolution: ``model`` arg > config.ini ``[host].model`` > device facts. 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 ``hostnames`` the result is the intersection. model: Override model resolution for all hosts (empty = per-host resolution) max_workers: Maximum parallel threads (default 20) config_path: Path to config.ini (empty string uses default search)

tags string model str hostnames string config_path str max_workers int
push_config
annotations: none low

Push configuration to a device with commit confirmed and health check. Supports two input methods (exactly one required): - config_file: Path to a .set or .j2 file containing set commands - set_commands: List of set command strings (inline) Safety features (not available in Juniper's official MCP server): - dry_run mode (default True): shows diff without committing - commit confirmed: auto-rollback if not confirmed within timeout - health check: auto-rollback on connectivity failure after commit 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) 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 ``request ...restart`` command exists. dry_run=True takes precedence over no_commit (diff is shown but nothing is committed). health_check: Fallback health check commands tried in order after commit. Passes if ANY command succeeds. Supports "ping ..." (checks packets received), "uptime" (NETCONF RPC probe), or any CLI command (success if no exception). Default: ["uptime"] — uses the existing NETCONF session and does not depend on ICMP reachability. (Changed from broadcast ping in junos-mcp 0.11.0 to match junos-ops 0.16.8+.) Ignored when no_commit=True. config_path: Path to config.ini (empty string uses default search)

dry_run bool hostname str no_commit bool config_file str config_path str health_check string set_commands string confirm_timeout int
copy_package
annotations: none low

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)

force bool dry_run bool hostname str config_path str
install_package
annotations: none low

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 ``request system software add <pkg> unlink`` via CLI instead of PyEZ SW.install(). Use for low-flash devices (EX2300 / EX3400, ~1.3 GB /dev/gpt/junos) where major version upgrades fail with "ERROR: insufficient space" because PyEZ does not expose the unlink parameter. The CLI path frees ~330 MB by unlinking the source tgz during extraction. config_path: Path to config.ini (empty string uses default search)

force bool unlink bool dry_run bool hostname str config_path str
rollback_package
annotations: none low

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)

dry_run bool hostname str config_path str
schedule_reboot
annotations: none low

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)

force bool dry_run bool hostname str reboot_at str config_path str
daily_brief
annotations: none low

Run a morning health check across multiple devices in parallel. Checks per host (Phase 1): - ``show system alarms`` / ``show chassis alarms`` - ``show interfaces descriptions`` — a physical interface is flagged ``[IF_DOWN]`` only when it has a description (``Admin=up``, ``Link=down``) and its ``Last flapped`` time is within ``since_hours``. Undescribed unused ports and chronically-down ports are suppressed (loopback / mgmt / internal logical units are also excluded). - ``show log messages | last 200`` — alert patterns within ``since_hours`` - dual-RE redundancy — an explicit routing-engine fault is flagged ``[RE_FAULT]`` (skipped on SRX chassis clusters, whose facts misreport RE status; a failed cluster node raises chassis alarms instead) - ``route_baseline`` (optional) — when > 0, a device whose ``inet.0`` destination count differs from this value is flagged ``[ROUTE_BASELINE]``. Scope with ``tags`` (e.g. ``tags=["main"], route_baseline=152``), since full-table routers carry far more routes than access routers. Syslog patterns watched: BGP state change away from Established, STP port role change, OSPF neighbor down, ARP address conflict, IF_DOWN. ``since_hours`` defaults to 18 (≈ previous 15:00 for a 09:00 morning run). Tags default to none (all routers); pass ``tags=["main"]`` to limit scope. Output tiers: - CRITICAL — connection failure - WARNING — at least one anomaly found - OK — clean Returns a Markdown summary with anomaly details for CRITICAL/WARNING hosts and a collapsed OK list.

tags string hostnames string config_path str max_workers int since_hours int route_baseline int
health_check
annotations: none low

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: ``status`` (healthy / error), ``service``, ``version``, ``config_path`` (the resolved config.ini path it would use), ``router_count`` (number of host sections in config.ini), ``tags`` (sorted list of distinct tags across configured hosts), and ``config`` (ok / error / missing). On an error result, ``detail`` carries the reason. There is no degraded state: this check either loads config.ini or it does not. Args: config_path: Path to config.ini (empty string uses default search).

config_path str

Permissions 2

filesystem low
Server uses filesystem capabilities via: open(), os, pathlib
env_vars low
Server uses env_vars capabilities via: os.environ

Scan Findings 69

low
Tool 'get_device_facts' has no annotations annotation_checker · 100%
low
Tool 'get_version' has no annotations annotation_checker · 100%
low
Tool 'run_show_command' has no annotations annotation_checker · 100%
low
Tool 'run_show_commands' has no annotations annotation_checker · 100%
low
Tool 'run_show_command_batch' has no annotations annotation_checker · 100%
low
Tool 'list_remote_files' has no annotations annotation_checker · 100%
low
Tool 'check_upgrade_readiness' has no annotations annotation_checker · 100%
low
Tool 'compare_version' has no annotations annotation_checker · 100%
low
Tool 'get_router_list' has no annotations annotation_checker · 100%
low
Tool 'get_package_info' has no annotations annotation_checker · 100%
low
Tool 'get_config' has no annotations annotation_checker · 100%
low
Tool 'get_config_diff' has no annotations annotation_checker · 100%
low
Tool 'collect_rsi' has no annotations annotation_checker · 100%
low
Tool 'collect_rsi_batch' has no annotations annotation_checker · 100%
low
Tool 'check_reachability' has no annotations annotation_checker · 100%
low
Tool 'check_local_inventory' has no annotations annotation_checker · 100%
low
Tool 'check_remote_packages' has no annotations annotation_checker · 100%
low
Tool 'push_config' has no annotations annotation_checker · 100%
low
Tool 'copy_package' has no annotations annotation_checker · 100%
low
Tool 'install_package' has no annotations annotation_checker · 100%
low
Tool 'rollback_package' has no annotations annotation_checker · 100%
low
Tool 'schedule_reboot' has no annotations annotation_checker · 100%
low
Tool 'daily_brief' has no annotations annotation_checker · 100%
low
Tool 'health_check' has no annotations annotation_checker · 100%
high
Remote transport without authentication auth_checker · 70%
info
Sandbox failed to start for behavioral verification behavioral_verifier · 100%
medium
Vulnerable dependency: mcp@1.2,<2 (GHSA-3qhf-m339-9g5v) dependency_analyzer · 95%
medium
Vulnerable dependency: mcp@1.2,<2 (GHSA-9h52-p55h-vw2f) dependency_analyzer · 95%
medium
Vulnerable dependency: mcp@1.2,<2 (GHSA-j975-95f5-7wqh) dependency_analyzer · 95%
medium
Vulnerable dependency: mcp@1.2,<2 (GHSA-jpw9-pfvf-9f58) dependency_analyzer · 95%
medium
Vulnerable dependency: mcp@1.2,<2 (GHSA-vj7q-gjh5-988w) dependency_analyzer · 95%
medium
Vulnerable dependency: mcp@1.2,<2 (PYSEC-2026-1616) dependency_analyzer · 95%
medium
Vulnerable dependency: mcp@1.2,<2 (PYSEC-2026-1617) dependency_analyzer · 95%
medium
Vulnerable dependency: mcp@1.2,<2 (PYSEC-2026-1618) dependency_analyzer · 95%
medium
Vulnerable dependency: mcp@1.2,<2 (PYSEC-2026-3482) dependency_analyzer · 95%
medium
Vulnerable dependency: mcp@1.2,<2 (PYSEC-2026-3483) dependency_analyzer · 95%
info
pyproject.toml metadata manifest_parser · 100%
info
Tool: get_device_facts manifest_parser · 90%
info
Tool: get_version manifest_parser · 90%
info
Tool: run_show_command manifest_parser · 90%
info
Tool: run_show_commands manifest_parser · 90%
info
Tool: run_show_command_batch manifest_parser · 90%
info
Tool: list_remote_files manifest_parser · 90%
info
Tool: check_upgrade_readiness manifest_parser · 90%
info
Tool: compare_version manifest_parser · 90%
info
Tool: get_router_list manifest_parser · 90%
info
Tool: get_package_info manifest_parser · 90%
info
Tool: get_config manifest_parser · 90%
info
Tool: get_config_diff manifest_parser · 90%
info
Tool: collect_rsi manifest_parser · 90%
info
Tool: collect_rsi_batch manifest_parser · 90%
info
Tool: check_reachability manifest_parser · 90%
info
Tool: check_local_inventory manifest_parser · 90%
info
Tool: check_remote_packages manifest_parser · 90%
info
Tool: push_config manifest_parser · 90%
info
Tool: copy_package manifest_parser · 90%
info
Tool: install_package manifest_parser · 90%
info
Tool: rollback_package manifest_parser · 90%
info
Tool: schedule_reboot manifest_parser · 90%
info
Tool: daily_brief manifest_parser · 90%
info
Tool: health_check manifest_parser · 90%
info
Transport: streamable-http manifest_parser · 80%
info
Required env vars (5) manifest_parser · 80%
info
Sandbox failed to start for output poisoning scan output_poisoning · 100%
low
Permission: filesystem access detected permission_analyzer · 80%
low
Permission: env_vars access detected permission_analyzer · 90%
critical
Tool poisoning in 'run_show_command': Directive language: 'you must' poisoning · 85%
info
No dependency files found for SBOM generation sbom_generator · 100%
medium
No build provenance detected (SLSA L0) slsa_assessor · 90%