network-aiops 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. network_aiops-0.1.0/.gitignore +22 -0
  2. network_aiops-0.1.0/LICENSE +21 -0
  3. network_aiops-0.1.0/PKG-INFO +150 -0
  4. network_aiops-0.1.0/README.md +133 -0
  5. network_aiops-0.1.0/RELEASE_NOTES.md +24 -0
  6. network_aiops-0.1.0/SECURITY.md +82 -0
  7. network_aiops-0.1.0/mcp_server/__init__.py +0 -0
  8. network_aiops-0.1.0/mcp_server/_shared.py +113 -0
  9. network_aiops-0.1.0/mcp_server/server.py +33 -0
  10. network_aiops-0.1.0/mcp_server/tools/__init__.py +0 -0
  11. network_aiops-0.1.0/mcp_server/tools/config_ops.py +107 -0
  12. network_aiops-0.1.0/mcp_server/tools/facts.py +87 -0
  13. network_aiops-0.1.0/mcp_server/tools/netbox.py +39 -0
  14. network_aiops-0.1.0/network_aiops/__init__.py +11 -0
  15. network_aiops-0.1.0/network_aiops/cli/__init__.py +9 -0
  16. network_aiops-0.1.0/network_aiops/cli/_common.py +84 -0
  17. network_aiops-0.1.0/network_aiops/cli/_root.py +50 -0
  18. network_aiops-0.1.0/network_aiops/cli/config.py +111 -0
  19. network_aiops-0.1.0/network_aiops/cli/device.py +86 -0
  20. network_aiops-0.1.0/network_aiops/cli/doctor.py +21 -0
  21. network_aiops-0.1.0/network_aiops/cli/netbox.py +39 -0
  22. network_aiops-0.1.0/network_aiops/config.py +159 -0
  23. network_aiops-0.1.0/network_aiops/connection.py +202 -0
  24. network_aiops-0.1.0/network_aiops/doctor.py +76 -0
  25. network_aiops-0.1.0/network_aiops/governance/__init__.py +40 -0
  26. network_aiops-0.1.0/network_aiops/governance/audit.py +377 -0
  27. network_aiops-0.1.0/network_aiops/governance/budget.py +225 -0
  28. network_aiops-0.1.0/network_aiops/governance/decorators.py +474 -0
  29. network_aiops-0.1.0/network_aiops/governance/paths.py +23 -0
  30. network_aiops-0.1.0/network_aiops/governance/patterns.py +378 -0
  31. network_aiops-0.1.0/network_aiops/governance/policy.py +411 -0
  32. network_aiops-0.1.0/network_aiops/governance/sanitize.py +39 -0
  33. network_aiops-0.1.0/network_aiops/governance/undo.py +218 -0
  34. network_aiops-0.1.0/network_aiops/ops/__init__.py +0 -0
  35. network_aiops-0.1.0/network_aiops/ops/_shared.py +38 -0
  36. network_aiops-0.1.0/network_aiops/ops/config_ops.py +135 -0
  37. network_aiops-0.1.0/network_aiops/ops/facts.py +130 -0
  38. network_aiops-0.1.0/network_aiops/ops/netbox_ops.py +50 -0
  39. network_aiops-0.1.0/pyproject.toml +60 -0
  40. network_aiops-0.1.0/server.json +21 -0
  41. network_aiops-0.1.0/skills/network-aiops/SKILL.md +189 -0
  42. network_aiops-0.1.0/skills/network-aiops/references/capabilities.md +61 -0
  43. network_aiops-0.1.0/skills/network-aiops/references/cli-reference.md +57 -0
  44. network_aiops-0.1.0/skills/network-aiops/references/setup-guide.md +112 -0
  45. network_aiops-0.1.0/tests/test_smoke.py +366 -0
@@ -0,0 +1,22 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+
8
+ # Virtual envs / build
9
+ .venv/
10
+ dist/
11
+ build/
12
+
13
+ # uv
14
+ uv.lock
15
+
16
+ # Local config / secrets (never commit)
17
+ *.env
18
+ .env
19
+ config.yaml
20
+
21
+ # OS
22
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 wei <zhouwei008@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,150 @@
1
+ Metadata-Version: 2.4
2
+ Name: network-aiops
3
+ Version: 0.1.0
4
+ Summary: Governed multi-vendor network device operations for AI agents (NAPALM) with a built-in governance harness (audit, budget, undo, risk tiers)
5
+ Author-email: wei <zhouwei008@gmail.com>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.11
9
+ Requires-Dist: mcp[cli]<2.0,>=1.10
10
+ Requires-Dist: napalm<6,>=4.1
11
+ Requires-Dist: pynetbox<8,>=7
12
+ Requires-Dist: python-dotenv<2.0,>=1.0
13
+ Requires-Dist: pyyaml<7.0,>=6.0
14
+ Requires-Dist: rich<16.0,>=13.0
15
+ Requires-Dist: typer<1.0,>=0.12
16
+ Description-Content-Type: text/markdown
17
+
18
+ <!-- mcp-name: io.github.AIops-tools/network-aiops -->
19
+ # network-aiops (preview)
20
+
21
+ > **Disclaimer**: This is a community-maintained open-source project and is **not
22
+ > affiliated with, endorsed by, or sponsored by Cisco, Arista, Juniper, NetBox
23
+ > Labs, or any network vendor.** Vendor and product names are trademarks of their
24
+ > respective owners. Source code is publicly auditable at
25
+ > [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)
26
+ > under the MIT license.
27
+
28
+ Governed multi-vendor network device operations for AI agents — **13 MCP tools**,
29
+ every one wrapped with the bundled `@governed_tool` harness: a local unified audit
30
+ log under `~/.network-aiops/`, policy engine, token/runaway budget guard,
31
+ undo-token recording, and graduated-autonomy risk tiers.
32
+
33
+ Devices are reached over [NAPALM](https://napalm.readthedocs.io/); an optional
34
+ NetBox block adds source-of-truth lookups.
35
+
36
+ > **Standalone**: the governance harness is bundled in the package
37
+ > (`network_aiops.governance`) — network-aiops has no external skill-family
38
+ > dependency. Preview: common device operations, not yet exhaustive.
39
+
40
+ ## What works
41
+
42
+ Read device facts/interfaces/IP/BGP/LLDP/ARP, back up the running config, dry-run
43
+ a config diff, and merge/replace/rollback config — across the five core NAPALM
44
+ platforms below. Optional NetBox lookups confirm intended state before a change.
45
+
46
+ ## Supported devices
47
+
48
+ | Platform | NAPALM driver | Transport |
49
+ |----------|---------------|-----------|
50
+ | Cisco IOS / IOS-XE | `ios` | SSH |
51
+ | Cisco Nexus NX-OS | `nxos` (NX-API) / `nxos_ssh` (SSH) | HTTPS / SSH |
52
+ | Cisco IOS-XR | `iosxr` | SSH (XML agent) |
53
+ | Arista EOS | `eos` | eAPI (HTTPS) |
54
+ | Juniper Junos | `junos` | NETCONF (SSH) |
55
+
56
+ Additional platforms (Nokia SR OS / SR Linux, Huawei VRP, etc.) are reachable via
57
+ NAPALM **community drivers** but are **not officially tested here**. Need one?
58
+ See [Contributing](#contributing--feature-requests).
59
+
60
+ ## Supported actions
61
+
62
+ | Action | Tool | R/W | Risk |
63
+ |--------|------|:---:|:----:|
64
+ | Device facts (hostname/vendor/model/OS/serial/uptime) | `device_facts` | R | low |
65
+ | Interfaces (up/down, speed, description) | `get_interfaces` | R | low |
66
+ | Interface IP addresses | `get_interfaces_ip` | R | low |
67
+ | BGP neighbors | `get_bgp_neighbors` | R | low |
68
+ | LLDP neighbors | `get_lldp_neighbors` | R | low |
69
+ | ARP table | `get_arp_table` | R | low |
70
+ | Back up running config | `config_backup` | R | low |
71
+ | Diff a candidate (dry-run) | `config_diff` | R | low |
72
+ | Merge config + commit | `config_merge` | W | medium |
73
+ | Replace full config + commit | `config_replace` | W | **high** |
74
+ | Roll back last commit | `config_rollback` | W | medium |
75
+ | NetBox list devices | `netbox_list_devices` | R | low |
76
+ | NetBox get device | `netbox_get_device` | R | low |
77
+
78
+ ## Quick Start
79
+
80
+ ```bash
81
+ uv tool install network-aiops
82
+ network-aiops doctor
83
+ network-aiops device facts -t core-sw1
84
+ network-aiops config backup -t core-sw1 -o core-sw1.cfg
85
+ ```
86
+
87
+ Create `~/.network-aiops/config.yaml`:
88
+
89
+ ```yaml
90
+ devices:
91
+ - name: core-sw1 # used as -t core-sw1
92
+ driver: eos # ios | nxos | nxos_ssh | iosxr | eos | junos
93
+ host: 10.0.0.1
94
+ username: admin
95
+ optional_args: # passed verbatim to NAPALM (optional)
96
+ secret: enable-pw # enable/secret
97
+ port: 443
98
+ # Optional source-of-truth:
99
+ netbox:
100
+ url: https://netbox.example.com
101
+ ```
102
+
103
+ Put secrets in `~/.network-aiops/.env` (chmod 600) — never in config.yaml:
104
+
105
+ ```bash
106
+ NETWORK_CORE_SW1_PASSWORD=... # NETWORK_<TARGET_UPPER>_PASSWORD
107
+ NETWORK_NETBOX_TOKEN=...
108
+ ```
109
+
110
+ ## MCP
111
+
112
+ ```jsonc
113
+ {
114
+ "command": "network-aiops",
115
+ "args": ["mcp"],
116
+ "env": { "NETWORK_AIOPS_CONFIG": "~/.network-aiops/config.yaml" }
117
+ }
118
+ ```
119
+
120
+ ## Audit & Safety
121
+
122
+ - Every tool call is logged to `~/.network-aiops/audit.db` (local SQLite;
123
+ relocate with `NETWORK_AIOPS_HOME`).
124
+ - `config_merge` / `config_replace` capture the pre-change running config and
125
+ record an inverse `config_replace`-to-backup undo descriptor.
126
+ - `config_replace` is `risk_level=high`; CLI destructive commands (`config
127
+ merge/replace/rollback`) require double confirmation and support `--dry-run`
128
+ (which prints the diff without committing).
129
+ - All device text passes through `sanitize()` (prompt-injection defense).
130
+
131
+ See `skills/network-aiops/SKILL.md` and `SECURITY.md` for details.
132
+
133
+ ## Companion Skills
134
+
135
+ | If you want… | Use |
136
+ |--------------|-----|
137
+ | Network device config / facts (Cisco/Arista/Juniper) | **network-aiops** (this) |
138
+ | Kubernetes cluster operations | a cluster ops skill |
139
+ | Hypervisor VM lifecycle | a hypervisor ops skill |
140
+
141
+ ## Contributing & feature requests
142
+
143
+ This is a preview — coverage is intentionally focused. **Need a device or action
144
+ that isn't here yet?** Open an issue or pull request at
145
+ [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops/issues)
146
+ — contributions, feature requests, and comments are all welcome.
147
+
148
+ ## License
149
+
150
+ MIT — [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)
@@ -0,0 +1,133 @@
1
+ <!-- mcp-name: io.github.AIops-tools/network-aiops -->
2
+ # network-aiops (preview)
3
+
4
+ > **Disclaimer**: This is a community-maintained open-source project and is **not
5
+ > affiliated with, endorsed by, or sponsored by Cisco, Arista, Juniper, NetBox
6
+ > Labs, or any network vendor.** Vendor and product names are trademarks of their
7
+ > respective owners. Source code is publicly auditable at
8
+ > [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)
9
+ > under the MIT license.
10
+
11
+ Governed multi-vendor network device operations for AI agents — **13 MCP tools**,
12
+ every one wrapped with the bundled `@governed_tool` harness: a local unified audit
13
+ log under `~/.network-aiops/`, policy engine, token/runaway budget guard,
14
+ undo-token recording, and graduated-autonomy risk tiers.
15
+
16
+ Devices are reached over [NAPALM](https://napalm.readthedocs.io/); an optional
17
+ NetBox block adds source-of-truth lookups.
18
+
19
+ > **Standalone**: the governance harness is bundled in the package
20
+ > (`network_aiops.governance`) — network-aiops has no external skill-family
21
+ > dependency. Preview: common device operations, not yet exhaustive.
22
+
23
+ ## What works
24
+
25
+ Read device facts/interfaces/IP/BGP/LLDP/ARP, back up the running config, dry-run
26
+ a config diff, and merge/replace/rollback config — across the five core NAPALM
27
+ platforms below. Optional NetBox lookups confirm intended state before a change.
28
+
29
+ ## Supported devices
30
+
31
+ | Platform | NAPALM driver | Transport |
32
+ |----------|---------------|-----------|
33
+ | Cisco IOS / IOS-XE | `ios` | SSH |
34
+ | Cisco Nexus NX-OS | `nxos` (NX-API) / `nxos_ssh` (SSH) | HTTPS / SSH |
35
+ | Cisco IOS-XR | `iosxr` | SSH (XML agent) |
36
+ | Arista EOS | `eos` | eAPI (HTTPS) |
37
+ | Juniper Junos | `junos` | NETCONF (SSH) |
38
+
39
+ Additional platforms (Nokia SR OS / SR Linux, Huawei VRP, etc.) are reachable via
40
+ NAPALM **community drivers** but are **not officially tested here**. Need one?
41
+ See [Contributing](#contributing--feature-requests).
42
+
43
+ ## Supported actions
44
+
45
+ | Action | Tool | R/W | Risk |
46
+ |--------|------|:---:|:----:|
47
+ | Device facts (hostname/vendor/model/OS/serial/uptime) | `device_facts` | R | low |
48
+ | Interfaces (up/down, speed, description) | `get_interfaces` | R | low |
49
+ | Interface IP addresses | `get_interfaces_ip` | R | low |
50
+ | BGP neighbors | `get_bgp_neighbors` | R | low |
51
+ | LLDP neighbors | `get_lldp_neighbors` | R | low |
52
+ | ARP table | `get_arp_table` | R | low |
53
+ | Back up running config | `config_backup` | R | low |
54
+ | Diff a candidate (dry-run) | `config_diff` | R | low |
55
+ | Merge config + commit | `config_merge` | W | medium |
56
+ | Replace full config + commit | `config_replace` | W | **high** |
57
+ | Roll back last commit | `config_rollback` | W | medium |
58
+ | NetBox list devices | `netbox_list_devices` | R | low |
59
+ | NetBox get device | `netbox_get_device` | R | low |
60
+
61
+ ## Quick Start
62
+
63
+ ```bash
64
+ uv tool install network-aiops
65
+ network-aiops doctor
66
+ network-aiops device facts -t core-sw1
67
+ network-aiops config backup -t core-sw1 -o core-sw1.cfg
68
+ ```
69
+
70
+ Create `~/.network-aiops/config.yaml`:
71
+
72
+ ```yaml
73
+ devices:
74
+ - name: core-sw1 # used as -t core-sw1
75
+ driver: eos # ios | nxos | nxos_ssh | iosxr | eos | junos
76
+ host: 10.0.0.1
77
+ username: admin
78
+ optional_args: # passed verbatim to NAPALM (optional)
79
+ secret: enable-pw # enable/secret
80
+ port: 443
81
+ # Optional source-of-truth:
82
+ netbox:
83
+ url: https://netbox.example.com
84
+ ```
85
+
86
+ Put secrets in `~/.network-aiops/.env` (chmod 600) — never in config.yaml:
87
+
88
+ ```bash
89
+ NETWORK_CORE_SW1_PASSWORD=... # NETWORK_<TARGET_UPPER>_PASSWORD
90
+ NETWORK_NETBOX_TOKEN=...
91
+ ```
92
+
93
+ ## MCP
94
+
95
+ ```jsonc
96
+ {
97
+ "command": "network-aiops",
98
+ "args": ["mcp"],
99
+ "env": { "NETWORK_AIOPS_CONFIG": "~/.network-aiops/config.yaml" }
100
+ }
101
+ ```
102
+
103
+ ## Audit & Safety
104
+
105
+ - Every tool call is logged to `~/.network-aiops/audit.db` (local SQLite;
106
+ relocate with `NETWORK_AIOPS_HOME`).
107
+ - `config_merge` / `config_replace` capture the pre-change running config and
108
+ record an inverse `config_replace`-to-backup undo descriptor.
109
+ - `config_replace` is `risk_level=high`; CLI destructive commands (`config
110
+ merge/replace/rollback`) require double confirmation and support `--dry-run`
111
+ (which prints the diff without committing).
112
+ - All device text passes through `sanitize()` (prompt-injection defense).
113
+
114
+ See `skills/network-aiops/SKILL.md` and `SECURITY.md` for details.
115
+
116
+ ## Companion Skills
117
+
118
+ | If you want… | Use |
119
+ |--------------|-----|
120
+ | Network device config / facts (Cisco/Arista/Juniper) | **network-aiops** (this) |
121
+ | Kubernetes cluster operations | a cluster ops skill |
122
+ | Hypervisor VM lifecycle | a hypervisor ops skill |
123
+
124
+ ## Contributing & feature requests
125
+
126
+ This is a preview — coverage is intentionally focused. **Need a device or action
127
+ that isn't here yet?** Open an issue or pull request at
128
+ [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops/issues)
129
+ — contributions, feature requests, and comments are all welcome.
130
+
131
+ ## License
132
+
133
+ MIT — [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)
@@ -0,0 +1,24 @@
1
+ # Release Notes
2
+
3
+ ## 0.1.0 (preview)
4
+
5
+ Initial preview release of **network-aiops** — governed multi-vendor network
6
+ device operations for AI agents.
7
+
8
+ - **13 MCP tools** (10 read / 3 write), every one wrapped with the bundled
9
+ `@governed_tool` harness (audit, policy, token/runaway budget, undo-token
10
+ recording, graduated risk tiers).
11
+ - Devices reached over **NAPALM**. Officially supported drivers: `ios`,
12
+ `nxos`, `nxos_ssh`, `iosxr`, `eos`, `junos`.
13
+ - Read getters: device facts, interfaces, interface IPs, BGP neighbors, LLDP
14
+ neighbors, ARP table, config backup, config diff (dry-run).
15
+ - Config writes: merge (medium), replace (high), rollback (medium). Merge and
16
+ replace capture the pre-change running config and record a `config_replace`
17
+ undo descriptor that restores it.
18
+ - Optional **NetBox** source-of-truth lookups (`netbox_list_devices`,
19
+ `netbox_get_device`); degrade gracefully when not configured.
20
+ - CLI: `device facts/interfaces/bgp/lldp/arp`, `config backup/diff/merge/replace/rollback`,
21
+ `netbox list/get`, `doctor`, `mcp`. Destructive config ops require double
22
+ confirmation and `--dry-run`.
23
+ - Standalone: governance harness bundled under `network_aiops.governance`; no
24
+ external skill-family dependency.
@@ -0,0 +1,82 @@
1
+ # Security Policy
2
+
3
+ ## Disclaimer
4
+
5
+ This is a community-maintained open-source project and is **not affiliated with,
6
+ endorsed by, or sponsored by Cisco, Arista, Juniper, NetBox Labs, or any network
7
+ vendor.** Vendor and product names are trademarks of their respective owners.
8
+ Source code is publicly auditable at
9
+ [github.com/AIops-tools/Network-AIops](https://github.com/AIops-tools/Network-AIops)
10
+ under the MIT license.
11
+
12
+ ## Reporting Vulnerabilities
13
+
14
+ Report security issues privately to **zhouwei008@gmail.com** or via a GitHub
15
+ private security advisory on the repository. Please do not open public issues for
16
+ undisclosed vulnerabilities.
17
+
18
+ ## Security Design
19
+
20
+ ### Credential Management
21
+
22
+ Device passwords are read from `~/.network-aiops/.env` as
23
+ `NETWORK_<TARGET_UPPER>_PASSWORD` (one per device); enable/secret and transport
24
+ options go in the device's `optional_args` and are passed verbatim to NAPALM. The
25
+ optional NetBox token is read from `NETWORK_NETBOX_TOKEN`. `config.yaml` holds
26
+ only device names, drivers, hosts, usernames, and `optional_args` — never
27
+ secrets. The state directory `~/.network-aiops` should be owner-only
28
+ (`chmod 700`) and `.env` `chmod 600`; the skill warns if the directory is more
29
+ permissive. Credentials are never read into results, logged, or echoed.
30
+
31
+ ### Destructive Operation Safety
32
+
33
+ Config write operations (merge, replace, rollback) all pass through the bundled
34
+ `@governed_tool` decorator: policy pre-check, token / runaway budget guard,
35
+ graduated-autonomy risk-tier gate, and audit logging. The CLI layer additionally
36
+ requires double confirmation and supports `--dry-run` (which prints the diff
37
+ without committing) for `config merge`, `config replace`, and `config rollback`.
38
+ `config_merge` and `config_replace` capture the pre-change running config and
39
+ record an inverse `config_replace`-to-backup undo descriptor; `config_rollback`
40
+ declares no undo; `config_replace` is tagged `risk_level=high`. `config_diff` is a
41
+ pure dry-run (stage candidate → compare → discard).
42
+
43
+ ### Least Privilege
44
+
45
+ Use a device account with only the privilege you need — a read-only login for
46
+ facts/backup, and a config-capable login only for the merge/replace/rollback
47
+ tools. The optional NetBox token should be read-only.
48
+
49
+ ### Webhooks / Outbound Network
50
+
51
+ None. The skill makes no outbound network calls beyond the configured device
52
+ sessions (NAPALM) and the optional NetBox API. There are no background services
53
+ or post-install scripts.
54
+
55
+ ### TLS Verification
56
+
57
+ NAPALM driver transports (eAPI / NX-API over HTTPS, NETCONF / SSH) follow each
58
+ device's own certificate and SSH host-key configuration. The skill does not
59
+ weaken transport security.
60
+
61
+ ### Prompt Injection Protection
62
+
63
+ All text returned from a device (facts, configs, diffs, interface descriptions,
64
+ neighbor data) and from NetBox is run through `sanitize()` — truncation plus
65
+ C0/C1 control-character stripping — before reaching the agent.
66
+
67
+ ### Transitive Dependencies
68
+
69
+ `napalm` (device drivers), `pynetbox` (optional source-of-truth), `typer`/`rich`
70
+ (CLI), `pyyaml`/`python-dotenv` (config), and the MCP SDK. No external
71
+ skill-family dependency — the governance harness is vendored under
72
+ `network_aiops.governance`.
73
+
74
+ ## Static Analysis
75
+
76
+ ```bash
77
+ uvx bandit -r network_aiops/ mcp_server/
78
+ ```
79
+
80
+ ## Supported Versions
81
+
82
+ The latest released version (currently 0.1.0, preview) receives security fixes.
File without changes
@@ -0,0 +1,113 @@
1
+ """Shared MCP server primitives: the FastMCP instance, manager helper,
2
+ error sanitisation, and the ``@tool_errors`` decorator.
3
+
4
+ Tool modules under ``mcp_server/tools/`` import ``mcp`` from here and register
5
+ their ``@mcp.tool()`` functions onto it. ``mcp_server/server.py`` then imports
6
+ those modules and runs the server.
7
+
8
+ Keep ``Optional[X]`` (never PEP 604 ``X | None``) in any FastMCP-reflected
9
+ tool signature — on older mcp/pydantic the union eval'd to ``types.UnionType``
10
+ crashes FastMCP's ``issubclass`` check.
11
+ """
12
+
13
+ import functools
14
+ import logging
15
+ import os
16
+ from collections.abc import Callable
17
+ from pathlib import Path
18
+ from typing import Any, Optional
19
+
20
+ from mcp.server.fastmcp import FastMCP
21
+
22
+ from network_aiops.config import load_config
23
+ from network_aiops.connection import ConnectionManager, NetworkApiError
24
+ from network_aiops.governance import sanitize
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+ _DOCTOR_HINT = "Run 'network-aiops doctor' to verify device config and reachability."
29
+
30
+ _SUPPORTED = "ios, nxos, nxos_ssh, iosxr, eos, junos"
31
+
32
+
33
+ def _safe_error(exc: Exception, tool: str) -> str:
34
+ """Return an agent-safe error string; log full detail server-side only."""
35
+ logger.error("Tool %s failed", tool, exc_info=True)
36
+ _passthrough = (
37
+ ValueError,
38
+ FileNotFoundError,
39
+ KeyError,
40
+ PermissionError,
41
+ TimeoutError,
42
+ ConnectionError,
43
+ NetworkApiError,
44
+ )
45
+ if isinstance(exc, _passthrough):
46
+ return sanitize(str(exc), 300)
47
+ return f"{type(exc).__name__}: operation failed."
48
+
49
+
50
+ def tool_errors(shape: str = "dict") -> Callable:
51
+ """Wrap a tool body in the canonical try/except → ``_safe_error`` pattern.
52
+
53
+ Place this *between* ``@governed_tool`` and the function so the audit
54
+ decorator and FastMCP still see the original signature.
55
+ """
56
+
57
+ def decorator(func: Callable) -> Callable:
58
+ name = func.__name__
59
+
60
+ @functools.wraps(func)
61
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
62
+ try:
63
+ return func(*args, **kwargs)
64
+ except Exception as e: # noqa: BLE001 — sanitised below
65
+ msg = _safe_error(e, name)
66
+ if shape == "list":
67
+ return [{"error": msg, "hint": _DOCTOR_HINT}]
68
+ if shape == "str":
69
+ return f"Error: {msg} {_DOCTOR_HINT}"
70
+ return {"error": msg, "hint": _DOCTOR_HINT}
71
+
72
+ return wrapper
73
+
74
+ return decorator
75
+
76
+
77
+ mcp = FastMCP(
78
+ "network-aiops",
79
+ instructions=(
80
+ "Governed multi-vendor network device operations (preview) over NAPALM. "
81
+ f"Officially supported drivers: {_SUPPORTED} (Cisco IOS/IOS-XE, Nexus "
82
+ "NX-OS, IOS-XR, Arista EOS, Juniper Junos). Read tools: device facts, "
83
+ "interfaces, IP addresses, BGP/LLDP neighbors, ARP table, config backup, "
84
+ "and config diff (dry-run). Write tools: config merge, config replace, "
85
+ "config rollback. An optional NetBox block adds source-of-truth device "
86
+ "lookups. A 'target' selects a device from config. Every tool runs "
87
+ "through the network-aiops governance harness (audit / budget / risk-tier "
88
+ "/ undo). Need another platform (Nokia SR OS, Huawei VRP) or action? "
89
+ "Request it via a GitHub issue or PR."
90
+ ),
91
+ )
92
+
93
+ _conn_mgr: Optional[ConnectionManager] = None
94
+
95
+
96
+ def _manager() -> ConnectionManager:
97
+ """Return the connection manager, lazily initialising it from config."""
98
+ global _conn_mgr # noqa: PLW0603
99
+ if _conn_mgr is None:
100
+ config_path_str = os.environ.get("NETWORK_AIOPS_CONFIG")
101
+ config_path = Path(config_path_str) if config_path_str else None
102
+ _conn_mgr = ConnectionManager(load_config(config_path))
103
+ return _conn_mgr
104
+
105
+
106
+ def _target(name: Optional[str] = None) -> Any:
107
+ """Resolve a device target by name (or the default device)."""
108
+ return _manager().target(name)
109
+
110
+
111
+ def _netbox() -> Any:
112
+ """Return a NetBox client (raises a teaching NetworkApiError if unconfigured)."""
113
+ return _manager().netbox()
@@ -0,0 +1,33 @@
1
+ """MCP server wrapping network-aiops operations (stdio transport).
2
+
3
+ Thin adapter layer: each ``@mcp.tool()`` function (in ``mcp_server/tools/``)
4
+ delegates to the ``network_aiops`` ops package and is wrapped with the
5
+ network-aiops ``@governed_tool`` harness (audit / budget / undo / risk-tier).
6
+
7
+ Standalone, self-governed network device operations (preview) over NAPALM —
8
+ Cisco IOS/IOS-XE, Nexus NX-OS, IOS-XR, Arista EOS, Juniper Junos, plus optional
9
+ NetBox source-of-truth.
10
+
11
+ Source: https://github.com/AIops-tools/Network-AIops
12
+ License: MIT
13
+ """
14
+
15
+ import logging
16
+
17
+ from mcp_server._shared import _safe_error, mcp, tool_errors
18
+
19
+ # Importing the tool modules registers every @mcp.tool() onto the shared
20
+ # `mcp` instance. Order does not matter; each module is self-contained.
21
+ from mcp_server.tools import ( # noqa: F401 — side effects
22
+ config_ops,
23
+ facts,
24
+ netbox,
25
+ )
26
+
27
+ __all__ = ["mcp", "main", "_safe_error", "tool_errors"]
28
+
29
+
30
+ def main() -> None:
31
+ """Run the MCP server over stdio."""
32
+ logging.basicConfig(level=logging.INFO)
33
+ mcp.run(transport="stdio")
File without changes