🌐 Nornir MCP 服务器

这台服务器充当桥梁,将Nornir/NAPALM网络操作作为大规模并发处理(MCP)工具暴露出来,使得兼容的MCP客户端能够轻松访问这些操作。
✨ 主要特点
- 并发与多供应商利用Nornir进行库存管理,并通过NAPALM实现对多厂商网络设备的并发任务执行。
- 扩展工具集提供超过20种工具,包括一系列广泛的NAPALM获取器(
get_facts,get_interfaces), 执行命令 (ping,traceroute),以及库存管理(list_all_hosts)。 - 健壮的输入验证用途 Pydantic 为工具验证所有传入数据的模型,确保类型安全并防止无效输入导致的错误。
- 安全命令执行具有可配置功能 命令黑名单 (
conf/blacklist.yaml) 以防止意外或恶意执行危险命令,如reload或者erase startup-config通过send_command工具。 - 集装箱化且快速使用 Docker🐳 进行容器化,便于设置和使用
uv在容器内实现闪电般的Python依赖管理⚡。
🔧 前提条件
在开始之前,请确保已安装以下内容:
- (通常随Docker Desktop一起提供)
⚙️ 配置
在运行服务器之前,您 必须 配置您的网络资产清单和设备凭据:
- 导航至
conf/项目中的目录。 - 编辑
hosts.yaml定义您的网络设备,包括它们的管理IP、平台、凭据以及所属组。 - 编辑
groups.yaml定义具有共享属性的设备组。 - 编辑
defaults.yaml设置默认凭据和连接选项。
- ⚠️ 重要安全提示: 对于生产环境,强烈建议使用Nornir的密钥管理功能,以避免在YAML文件中存储明文凭证。
- 评论
blacklist.yaml自定义被阻止命令和模式的列表,以符合您的安全策略。
▶️ 运行服务器
配置完成后,您可以轻松地使用 Docker Compose 运行服务器:
docker-compose up --build -d此命令在Docker容器中启动Nornir MCP服务器,可通过端口访问 8000 在您的主机上。现在,容器使用的是 run.py 将其作为入口点,该入口点同时支持开发模式和生产模式。
要在本地运行服务器(不使用 Docker),请使用:
python run.py --dev或者简而言之:
python run.py这将使用新的入口点逻辑在 0.0.0.0:8000 上启动服务器。
🔌 如何连接MCP客户端
此项目通过流式HTTP传输方式,使FastMCP可通过HTTP暴露。服务器提供了两个有用的端点:
- HTTP API终端点:http://:
/mcp(这个指令或缩写在中文中没有直接对应的翻译,它可能是一个特定上下文中的命令或缩写,如在编程、游戏或特定软件中,需要根据具体上下文来解释。如果仅从字面来看,可以保留原样或解释为“/mcp(特定指令/缩写)”。)
- SSE 端点(事件):http://:
/服务器发送事件(Server-Sent Events)
关于传输和客户端设置的说明:
- MCP服务器本身是一个由Uvicorn服务的HTTP应用程序(基于FastAPI/Starlette)。您应该直接将MCP客户端连接到
/mcp使用支持流式HTTP传输的客户端来访问(主要)终点。 - 对于典型的HTTP或SSE客户端,你无需以stdio模式运行此项目。之前包含的关于以“stdio模式”运行服务器并使用Supergateway进行代理的说明,对于本仓库的正常使用来说是不准确的。
示例 MCP 客户端 JSON 配置(HTTP/可流式传输的 HTTP):
{
"name": "Nornir MCP (HTTP)",
"url": "http://localhost:8000/mcp",
"transport": "http"
}🧠 提示(自定义提示功能)
此服务器支持注册自定义提示函数,这些函数返回一个消息列表(MCP 提示格式)。提示允许您预定义对话输入,MCP 客户端或由大型语言模型(LLM)驱动的代理可以按名称调用这些提示 FastMCP API暴露了一个 @server.prompt() 装饰器用于注册函数。
主要特点:
- 使用(该工具)注册同步或异步提示函数
@server.prompt(). - 可选择性地提供一个
name,title,以及description使提示在MCP客户端中可被发现。 - 提示可以返回结构化消息,包括资源引用(对于返回文件内容或库存片段非常有用)。
如何添加提示(示例):
@server.prompt(name="list-host-names", title="List Host Names", description="Return a short list of host names from inventory")
def prompt_list_hosts() -> list:
hosts = nr_mgr.list_hosts()
return [{"role": "user", "content": f"Available hosts: {', '.join(h['device_name'] for h in hosts)}"}]带有资源的异步示例:
@server.prompt()
async def show_topology() -> list:
topo = await server.read_resource("resource://topology")
return [{"role": "user", "content": {"type": "resource", "resource": topo}}]使用说明:
- 注册提示后,客户端可以通过MCP发现它们
ListPrompts请求并按名称调用它们。 - 保持提示功能简洁且确定性;避免在提示中执行长时间运行的操作。如果需要从设备收集数据,请考虑注册一个工具并从提示中调用它,或者返回一个短的资源引用,以便客户端可以获取数据。
安全:
- 提示在服务器进程内部运行;不要在提示函数中执行不安全的文件操作或运行不可信的代码。
快速入门 — Docker(推荐)
- 使用docker-compose构建并运行(在仓库根目录下):
docker-compose up --build -d这会在容器中启动服务器,并默认将其暴露在8000端口上。
快速入门 — 本地
- 创建并激活一个虚拟环境。
& .venv\Scripts\Activate.ps1
# or on Unix: python -m venv .venv; source .venv/bin/activate- 安装运行时依赖项(示例):
pip install -U pip
pip install nornir==3.5.0 nornir-napalm mcp[cli]==1.15.0 sse-starlette- 在本地运行服务器(默认绑定到0.0.0.0:8000):
python run.py或者与 uv (使用随附的运行程序时推荐):
uv run .\run.py如果你需要更改主机/端口,请使用 --host 并且 --port 运行时的标志 run.py。
Resources provided by the server
- `resource://inventory/hosts` — returns JSON array of hosts with sanitized fields (name, hostname, platform, groups, data). Sensitive keys such as `username`, `password`, and `secret` are removed.
- `resource://inventory/hosts/{keyword}` — same output filtered by a keyword (case-insensitive) that matches name, hostname, platform, group names, or data values.
- `resource://inventory/groups` — returns groups mapping (sanitized).
- `resource://topology` — parsed `resources/topology.json`.
- `resource://cisco_ios_commands` — parsed `resources/cisco_ios_commands.json`.
How to add your own resources
1. Edit `resources.py` and add a function named `resource_` (e.g., `resource_my_tools`).
2. If your function needs the Nornir manager, accept a single parameter named `nr_mgr`.
3. Add an entry to `RESOURCE_MAP` if you want a custom URI; otherwise a default URI `resource://user/` is used.
Example `resources.py` snippet
def resource_my_static(): return {"hello": "world"}
def resource_my_hosts(nr_mgr): # returns a JSON-serializable list of hosts return nr_mgr.list_hosts()
安全注意事项
- 库存YAML文件可能包含凭据。在生产环境中,建议使用密钥管理(如Vault、环境变量或Nornir密钥插件)来替代明文YAML。
- 服务器会移除常见的敏感键(`username`, `password`, `secret`) 来自通过以下方式提供的资源: `resource://inventory/*`。
做出贡献
- 为更改提交一个问题或拉取请求。保持更改的小规模,并在适当的地方包含测试。
许可证
- 麻省理工学院(MIT)