Junos-MCP-小型堡垒服务器
通过MCP+HTTP集中Junos CLI\*
Linux Bastion上的Junos MCP服务器
通过MCP+HTTP集中Junos CLI
此README描述了如何设置 Junos MCP服务器 在Linux主机(通常是堡垒/跳转服务器)上,操作团队可以:
- 发送 Junos CLI命令 通过MCP连接到路由器
- 使用 HTTP+JSON (或一个简单的shell助手)获取实时输出
- 避免单独使用SSHing到每个路由器
本文件 不 涵盖任何编辑器/IDE集成——它纯粹专注于直接在Linux主机上运行所有内容。
______________________________________________________________________
1.架构概述
- 堡垒主机 (Linux):
- 运行Junos MCP服务器(jmcp.py)在Python虚拟环境中。 - 在本地公开HTTP MCP端点 127.0.0.1:30030. - 提供shell帮助程序 jmcp_cli 让运维工程师通过MCP运行Junos CLI命令。
- Junos路由器:
- 可从堡垒访问(例如管理IP)。 - 定义于a devices.json 包含凭据和连接详细信息的文件。
高水位流量:
- 行动工程师SSHe前往堡垒。
- 跑
jmcp_cli "show bgp summary | no-more". - Bastion发送MCP
tools/call通过HTTP向MCP服务器发送请求。 - MCP服务器连接到Junos路由器,运行CLI命令并返回输出。
- 辅助函数将CLI文本打印回操作员。
2.先决条件
在堡垒主机上,您需要:
- Linux(以下示例使用Ubuntu 22.04)
- python 3.11
python3-pip和python3.11-venvgitcurljq(用于解析JSON并提取CLI输出)
安装核心工具(根据需要调整您的环境/存储库):
apt update
apt install -y \
git \
python3.11 \
python3-pip \
python3.11-venv \
curl \
jq如果您的环境使用内部镜像(例如。repo.juniper.net),确保apt相应地进行配置。
______________________________________________________________________
3.克隆Junos MCP服务器存储库
为工具选择一个目录,例如。 /root:
cd /root
git clone https://github.com/Juniper/junos-mcp-server.git
cd junos-mcp-server
ls
# CLAUDE.md Dockerfile jmcp.py jmcp_token_manager.py pyproject.toml
# devices-template.json requirements.txt ...______________________________________________________________________
4.创建并激活Python虚拟环境
为MCP服务器创建隔离环境:
cd /root/junos-mcp-server
python3.11 -m venv .venv
source .venv/bin/activate
which python
# /root/junos-mcp-server/.venv/bin/python升级 pip (可选但推荐):
python -m pip install --upgrade pip______________________________________________________________________
5.安装MCP服务器依赖项
虚拟环境处于活动状态时:
cd /root/junos-mcp-server
pip install -r requirements.txt如果您稍后看到以下错误:
ModuleNotFoundError: No module named 'pydantic'这通常意味着你不在虚拟环境中。重新运行:
cd /root/junos-mcp-server
source .venv/bin/activate______________________________________________________________________
6.配置设备(devices.json)
从提供的模板开始:
cd /root/junos-mcp-server
cp devices-template.json devices.json编辑 devices.json:
vi devices.json单个路由器的示例:
{
"vmx101": {
"ip": "10.38.171.252",
"port": 22,
"username": "ken",
"auth": {
"type": "password",
"password": "junos123"
}
}
}替换为您自己的详细信息:
"ip"–Junos设备的管理IP/主机名"port"SSH端口(通常22)"username"/"password"–Junos以适当的权限登录
您可以将多个路由器定义为:
{
"vmx101": { ... },
"vmx102": { ... },
"core-mx1": { ... }
}______________________________________________________________________
7.启动MCP服务器(HTTP/Streamable)
当venv处于活动状态时:
cd /root/junos-mcp-server
source .venv/bin/activate
python jmcp.py -f devices.json -t streamable-http -H 127.0.0.1您应该看到类似以下内容的日志:
WARNING - No .tokens file found - server is open to all clients
INFO - All 1 device(s) validated successfully
INFO - Successfully loaded and validated 1 device(s)
INFO - Streamable HTTP server started on http://127.0.0.1:30030
Uvicorn running on http://127.0.0.1:30030 (Press CTRL+C to quit)让此进程在该终端中运行。
🔐 安全说明: 没有.tokens文件,任何可以访问的进程127.0.0.1:30030可以与此MCP服务器通信。 在单用户堡垒上,这通常很好。在共享环境中,考虑使用以下配置令牌jmcp_token_manager.py.
______________________________________________________________________
8.初始化MCP会话并捕获会话ID
打开A 第二 SSH会话到同一堡垒主机。
运行MCP initialize 呼叫:
curl -i \
-X POST "http://127.0.0.1:30030/mcp/" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": { "name": "curl", "version": "1.0" }
}
}'您应该看到这样的响应:
HTTP/1.1 200 OK
date: ...
server: uvicorn
content-type: text/event-stream
mcp-session-id: f98a307fce164ec2af8c49e43b1fc664
...
event: message
data: {"jsonrpc":"2.0","id":1,"result":{...}}关键部分是标题:
mcp-session-id: f98a307fce164ec2af8c49e43b1fc664将其作为环境变量导出到shell中:
export MCP_SESSION=f98a307fce164ec2af8c49e43b1fc664
echo "$MCP_SESSION"
# f98a307fce164ec2af8c49e43b1fc664🔁 重要提示: 每次重新启动时jmcp.py,您必须: 1. 呼叫initialize再次,以及 1. 更新MCP_SESSION随着新mcp-session-id.
______________________________________________________________________
9.创建一个 jmcp_cli 辅助功能
为了使MCP服务器易于运维团队使用,添加一个shell函数:
- 发送MCP
tools/call请求通过curl - 剥去
data:来自服务器发送事件(SSE)的前缀 - 用途
jq仅提取Junos CLI文本
此功能的作用
在较高层次上,jmcp_cli:
- 接受Junos CLI命令作为参数
- 例如jmcp_cli“显示bgp摘要|不再显示”
- 完整字符串存储在cmd中并传递给MCP服务器。
- 确保命令和MCP会话有效
- 如果你忘记传递命令,它会打印: 用法:jmcp_cli
- 如果未设置MCP_SESSION(您尚未运行初始化调用),它会提醒您这样做。
- 通过HTTP调用MCP服务器
- 向发送JSON-RPC工具/调用请求http://127.0.0.1:30030/mcp/.
- 对路由器vmx101(在devices.json中定义)使用execute_junos_command工具。
- 包含Mcp会话Id:$Mcp_Session标头,以便服务器知道要使用哪个Mcp会话。
- 清理响应并仅打印CLI文本
- 服务器响应为服务器发送事件(SSE),行类似于event:。..和数据:{…}。
- sed去掉了前导数据:所以我们只剩下纯JSON。
- jq选取.result.content\[0\].text(Junos CLI输出)并将其作为普通文本打印出来。
从操作员的角度来看,所有这些都是隐藏的。一旦设置了MCP_SESSION并加载了jmcp_cli,它们就会运行:
jmcp_cli "show chassis routing-engine | no-more"
jmcp_cli "show bgp summary | no-more"
jmcp_cli "show interfaces terse | no-more"编辑您的bash配置:
vi ~/.bashrc附上以下内容:
jmcp_cli() {
local cmd="$*"
if [ -z "$cmd" ]; then
echo "Usage: jmcp_cli "
return 1
fi
if [ -z "$MCP_SESSION" ]; then
echo "Error: MCP_SESSION not set. Run the MCP initialize curl and export MCP_SESSION first."
return 1
fi
curl -s "http://127.0.0.1:30030/mcp/" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "Mcp-Session-Id: $MCP_SESSION" \
-d "{
\"jsonrpc\": \"2.0\",
\"id\": 10,
\"method\": \"tools/call\",
\"params\": {
\"name\": \"execute_junos_command\",
\"arguments\": {
\"router_name\": \"vmx101\",
\"command\": \"${cmd}\"
}
}
}" \
| sed -n 's/^data: //p' \
| jq -r '.result.content[0].text // .data.result.content[0].text'
}输出示例如下
root@ansible:~# curl -i \
-X POST "http://127.0.0.1:30030/mcp/" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": { "name": "curl", "version": "1.0" }
}
}'
HTTP/1.1 200 OK
date: Wed, 03 Dec 2025 16:04:58 GMT
server: uvicorn
cache-control: no-cache, no-transform
connection: keep-alive
content-type: text/event-stream
mcp-session-id: f98a307fce164ec2af8c49e43b1fc664
x-accel-buffering: no
Transfer-Encoding: chunked
event: message
data: {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"experimental":{},"prompts":{"listChanged":false},"resources":{"subscribe":false,"listChanged":false},"tools":{"listChanged":false}},"serverInfo":{"name":"jmcp-server","version":"1.0.0"}}}
重新加载shell配置:
source ~/.bashrc
type jmcp_cli
# jmcp_cli is a function📝 上面的示例被硬编码为router_name: "vmx101". 如果你有多个路由器,你可以创建一个jmcp_cli_r ""稍后的变体。
______________________________________________________________________
10.使用 jmcp_cli 运行Junos CLI命令
一次:
jmcp.py正在堡垒上奔跑MCP_SESSION已设置jmcp_cli已装入您的壳中
…你可以运行这样的命令:
输出示例:
root@ansible:~# jmcp_cli "show chassis routing-engine | no-more"
Routing Engine status:
Slot 0:
Current state Master
Election priority Master (default)
DRAM 4042 MB (4096 MB installed)
Memory utilization 11 percent
5 sec CPU utilization:
User 1 percent
Background 0 percent
Kernel 1 percent
Interrupt 1 percent
Idle 97 percent
1 min CPU utilization:
User 1 percent
Background 0 percent
Kernel 2 percent
Interrupt 1 percent
Idle 96 percent
5 min CPU utilization:
User 1 percent
Background 0 percent
Kernel 2 percent
Interrupt 1 percent
Idle 96 percent
15 min CPU utilization:
User 1 percent
Background 0 percent
Kernel 2 percent
Interrupt 1 percent
Idle 96 percent
Model RE-VMX
Serial ID 907311d8-cf
Start time 2025-12-02 06:49:05 PST
Uptime 1 day, 1 hour, 33 minutes, 3 seconds
Last reboot reason Router rebooted after a normal shutdown.
Load averages: 1 minute 5 minute 15 minute
0.06 0.17 0.16
root@ansible:~# jmcp_cli "show bgp summary "
Threading mode: BGP I/O
Default eBGP mode: advertise - accept, receive - accept
Groups: 1 Peers: 6 Down peers: 0
Table Tot Paths Act Paths Suppressed History Damp State Pending
inet.0
36 36 0 0 0 0
bgp.l3vpn.0
12 12 0 0 0 0
bgp.l2vpn.0
4 4 0 0 0 0
bgp.evpn.0
0 0 0 0 0 0
Peer AS InPkt OutPkt OutQ Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped...
11.0.0.102 11 3413 3412 0 0 1d 1:56:26 Establ
inet.0: 6/6/6/0
bgp.l3vpn.0: 4/4/4/0
bgp.l2vpn.0: 0/0/0/0
bgp.evpn.0: 0/0/0/0
vpn_0.inet.0: 4/4/4/0
l2vpn_3.l2vpn.0: 0/0/0/0
vpn_200.l2vpn.0: 0/0/0/0
11.0.0.103 11 3385 3382 0 0 1d 1:42:55 Establ
inet.0: 6/6/6/0
bgp.l3vpn.0: 4/4/4/0
bgp.l2vpn.0: 1/1/1/0
bgp.evpn.0: 0/0/0/0
vpn_0.inet.0: 4/4/4/0
l2vpn_3.l2vpn.0: 0/0/0/0
vpn_200.l2vpn.0: 1/1/1/0
11.0.0.104 11 3385 3381 0 0 1d 1:42:37 Establ
inet.0: 6/6/6/0
bgp.l3vpn.0: 4/4/4/0
bgp.l2vpn.0: 2/2/2/0
bgp.evpn.0: 0/0/0/0
vpn_0.inet.0: 4/4/4/0
l2vpn_3.l2vpn.0: 1/1/1/0
vpn_200.l2vpn.0: 1/1/1/0
11.0.0.105 11 3411 3413 0 0 1d 1:57:31 Establ
inet.0: 6/6/6/0
bgp.l2vpn.0: 0/0/0/0
bgp.evpn.0: 0/0/0/0
l2vpn_3.l2vpn.0: 0/0/0/0
vpn_200.l2vpn.0: 0/0/0/0
11.0.0.106 11 3377 3377 0 0 1d 1:41:19 Establ
inet.0: 6/6/6/0
bgp.l2vpn.0: 1/1/1/0
bgp.evpn.0: 0/0/0/0
l2vpn_3.l2vpn.0: 0/0/0/0
vpn_200.l2vpn.0: 1/1/1/0
11.0.0.107 11 3377 3379 0 0 1d 1:42:05 Establ
inet.0: 6/6/6/0
bgp.l3vpn.0: 0/0/0/0
bgp.l2vpn.0: 0/0/0/0
l2vpn_3.l2vpn.0: 0/0/0/0
vpn_200.l2vpn.0: 0/0/0/0
从运营商的角度来看,他们只是:
- SSH到堡垒
- 确保
MCP_SESSION已设置(或运行执行此操作的包装器) - 使用
jmcp_cli ""与路由器交互
______________________________________________________________________
______________________________________________________________________
11.总结
这种设置将Linux堡垒变成了 Junos的中央MCP网关:
- 单个SSH入口点 对于运营团队
- HTTP+JSON 通往朱诺庄园的北行接口
- 简单
jmcp_clishell助手,以便操作员可以:
- 避免直接SSH到每个路由器 - 运行标准显示命令 - 在MCP之上构建小脚本/健康检查
此README有意停留在CLI+HTTP层。
同一个MCP服务器以后可以与IDE、聊天代理或其他工具集成,但“堡垒MCP服务器”的核心模式+ jmcp_cli“已经提供了强大的操作流程。
