Juniper-MCP-v1(注:Juniper通常指一种植物或品牌名,MCP可能是一个特定项目或系统的缩写,v1表示版本1,具体翻译可能需根据上下文调整)
适用于Juniper Junos设备的模型上下文协议(MCP)服务器,支持LLM(大型语言模型)与网络设备进行交互。
目录
- 目录 - 重要安全通知 - 安全要求 - 安全最佳实践 - 重要配置通知 - 入门指南/开始使用 - 戴着紫外线灯跑步 - 文档指南 - 启动Junos MCP服务器 - 配置 - Claude Desktop 的配置(stdio 传输) - Claude 桌面版配置(使用 uv) - - - - 使用默认设置运行 - 覆盖默认参数 - Junos 设备配置 - 基于引出技术的动态设备管理 - 诱导兼容性通知 - 该(或“这个”) add_device 工具 - 它是如何工作的 - 安全提示 - 示例用法 - SSH密钥要求 - 局限性 - - 启动您的服务器 - 在你的VSCode配置中指向此URL - MCP服务器访问的身份验证 - 认证行为 - 令牌管理 - 生成一个新令牌 - 列出所有代币 - 显示代币价值(恢复) - 撤销一个令牌 - 服务器认证状态 - 带认证的客户端配置 - 带有令牌的VSCode配置 - 使用curl进行测试 - - 安全最佳实践 - 令牌文件格式 - 使用MCP服务器与瞻博网络云原生路由器(JCNR) - 开发者指南 - 架构概述 - 工具的工作原理 - 添加新工具 - 步骤1:创建一个处理函数 - 步骤2:注册处理程序 - 步骤3:定义工具元数据 - 示例:创建BGP邻居工具 - 在工具中使用引出技术 - 工具开发的最佳实践 - 使用PyEZ进行高级操作 - 测试你的工具 - 调试技巧
重要安全通知
警告: 此服务器允许大型语言模型(LLM)访问您的网络基础设施。请仔细审阅这些安全注意事项。
安全要求
- 企业政策合规性仅当贵公司政策允许将Junos设备的数据发送至LLM服务时,才可使用此服务器。
- 服务器安全在将Junos MCP服务器部署到生产环境之前,请务必确保其安全。
- 认证做 不是 在生产环境中部署时使用密码认证。我们强烈建议使用基于SSH密钥的认证方式以增强安全性。
- 部署策略在您的MCP服务器得到妥善安全保护之前,仅用于本地部署进行测试。在未采取适当安全措施的情况下,不要在生产环境中部署远程服务器。
安全最佳实践
- 使用SSH密钥认证,而非密码
- 实施适当的网络访问控制
- 监控并记录所有MCP服务器的活动
- 定期进行安全审计和更新
- 遵循您组织的安全政策
重要配置通知
警告: Junos MCP服务器支持配置更改,但请确保仅在您希望将LLM(大型语言模型)生成的配置加载并提交到您的Junos路由器时才使用此功能。
始终审查由大型语言模型(LLM)生成的配置,并且只有在该配置适合您的使用场景时才允许执行工具。
入门指南/开始使用
获取代码。
git clone https://github.com/scottcrosby-securebine/juniper-mcp-v1.git
cd juniper-mcp-v1
pip install -r requirements.txt带着紫外线(或“在紫外线环境下”)跑步
如果你正在使用 紫外线,你可以直接运行服务器:
uv run python jmcp.py -f devices.json -t stdio文档指南
我们提供了几份全面的指南来帮助您入门:
- 扭曲终端指南 - 网络工程师使用Warp AI管理Juniper设备的完整指南(无需编程经验!)
- 快速入门指南 - 5分钟内起床并开始工作
- 部署指南 - 各种环境下的详细部署指南
- 设置网络设备 - 使用Docker配置您的网络设备
- 开发者指南 - 使用自定义工具扩展MCP服务器
对终端或编程新手吗? 从……开始 扭曲终端指南 - 这是专门为网络工程师撰写的!
启动Junos MCP服务器
$ python3.11 jmcp.py --help
Junos MCP Server
options:
-h, --help show this help message and exit
-f DEVICE_MAPPING, --device-mapping DEVICE_MAPPING
the name of the JSON file containing the device mapping
-H HOST, --host HOST Junos MCP Server host
-t TRANSPORT, --transport TRANSPORT
Junos MCP Server transport
-p PORT, --port PORT Junos MCP Server portJunos MCP服务器支持流式HTTP和stdio传输方式。在使用stdio传输方式时,不要使用--host参数。
配置
Claude 桌面版配置(stdio 传输)
{
"mcpServers": {
"jmcp": {
"type": "stdio",
"command": "python3",
"args": ["jmcp.py", "-f", "devices.json", "-t", "stdio"]
}
}
}Claude 桌面版配置(使用 uv)
{
"mcpServers": {
"jmcp": {
"type": "stdio",
"command": "uv",
"args": ["run", "python", "jmcp.py", "-f", "devices.json", "-t", "stdio"]
}
}
}注: 请提供jmcp.py和devices.json文件的绝对路径。
Claude 桌面版配置(Docker 容器)
{
"mcpServers": {
"jmcp": {
"type": "stdio",
"command": "/usr/local/bin/docker",
"args": [
"run",
"--rm",
"-i",
"-v",
"devices.json:/app/network_devices/devices.json",
"-v",
"your-ssh-key.pem:/app/network_devices/keys/your-ssh-key.pem",
"juniper-mcp-v1:latest"
]
}
}
}Docker 使用方法
构建Docker容器
$ docker build -t juniper-mcp-v1:latest .使用默认设置运行
默认情况下,Docker 容器使用 stdio 传输方式运行:
$ docker run --rm -it -v /path/to/your/devices.json:/app/network_devices/devices.json juniper-mcp-v1:latest这使用的是默认命令: python jmcp.py -f /app/network_devices/devices.json -t stdio
覆盖默认参数
你可以通过指定完整命令来覆盖任何参数:
对于stdio传输:
$ docker run --rm -it -v /path/to/your/devices.json:/app/network_devices/devices.json juniper-mcp-v1:latest python jmcp.py -f /app/network_devices/devices.json -t stdio对于可流式传输的HTTP传输:
$ docker run --rm -it -v /path/to/your/devices.json:/app/network_devices/devices.json -p 30030:30030 juniper-mcp-v1:latest python jmcp.py -f /app/network_devices/devices.json -t streamable-http -H 0.0.0.0对于使用自定义端口的流式HTTP:
$ docker run --rm -it -v /path/to/your/devices.json:/app/network_devices/devices.json -p 8080:8080 juniper-mcp-v1:latest python jmcp.py -f /app/network_devices/devices.json -t streamable-http -p 8080 -H 0.0.0.0注:
- 始终使用(指定方式)挂载您的设备配置文件
-v /path/to/your/devices.json:/app/network_devices/devices.json - 对于流式HTTP传输,使用以下方式暴露端口:
-p host_port:container_port - 如果使用基于密钥的认证,请挂载任何SSH私钥文件(例如。,
-v /path/to/key.pem:/app/network_devices/keys/key.pem)
为Junos MCP服务器构建Docker容器
$ docker build -t juniper-mcp-v1:latest .注: 挂载你的配置文件 devices.json 并且挂载任何其他文件。如果您使用的是SSH密钥认证,请挂载您的私钥文件(例如。, -v /path/to/your-ssh-key.pem:/app/network_devices/keys/your-ssh-key.pem)
Junos 设备配置
Junos MCP服务器支持两者 password 基于身份的认证以及 SSH key 基于认证(参见前两个路由器的配置\[路由器-1,路由器-2\])。
{
"router-1": {
"ip": "ip-addr",
"port": 22,
"username": "user",
"auth": {
"type": "password",
"password": "pwd"
}
},
"router-2": {
"ip": "ip-addr",
"port": 22,
"username": "user",
"auth": {
"type": "ssh_key",
"private_key_path": "/path/to/private/key.pem"
}
},
"router-3": {
"ip": "ip-addr",
"port": 22,
"username": "user",
"ssh_config": "~/.ssh/config_dc",
"auth": {
"type": "ssh_key",
"private_key_path": "/path/to/private/key.pem"
}
},
"router-4": {
"ip": "ip-addr",
"port": 22,
"username": "user",
"ssh_config": "/home/user/.ssh/config_jumphost",
"auth": {
"type": "password",
"password": "pwd"
}
}
}Junos MCP服务器还提供对以下的支持: ProxyCommand(参见最后两个路由器的配置\[路由器-3,路由器-4\]),这使您能够通过一个支持的中间主机访问目标设备 netcat当你只能通过中间主机(跳板机)登录到目标设备时,这非常有用。
这是一个使用SSH配置文件的示例 .ssh/config_jumphost:
# Jumphost VM Connection
Host jumphost-vm
HostName 10.0.0.1
User admin
IdentityFile /home/user/.ssh/id_rsa
IdentitiesOnly yes
StrictHostKeyChecking no
# Target Device (via jump host)
Host target-router
HostName 192.168.1.1
User admin
IdentityFile /home/user/.ssh/id_rsa
# ProxyJump jumphost-vm # Not working with JunOS MCP
ProxyCommand ssh -l admin jumphost-vm nc %h 22 2>/dev/null
StrictHostKeyChecking no注1: Port 值应为整数(通常 22 用于SSH。
注2: IdentityFile 建议使用完整路径(例如 /home/user/.ssh/id_rsa 而不是 ~/.ssh/id_rsa)。
基于需求挖掘的动态设备管理
诱发兼容性通知
重要提示: 当前,该触发功能仅适用于 VSCode(Visual Studio Code,简称VSCode) (使用可流式传输的HTTP传输)。Claude Desktop目前还不支持引出(或探索性对话),所以 add_device 该工具无法与Claude桌面版配合使用。该 add_device 工具
Junos MCP服务器包含一个强大的 add_device 这是一款工具,允许您在不修改配置文件的情况下动态添加新的Junos设备。该工具利用MCP的引出(elicitation)功能来交互式地收集设备信息。
它是如何工作的
当你使用时 add_device 工具,它将交互式地询问:
- 设备名称您设备的唯一标识符(例如,“router1-east”)
- IP地址该设备的IP地址
- SSH 端口SSH端口(默认为22)
- 用户名用于认证的用户名
- SSH密钥路径MCP服务器上SSH私钥文件的路径
该工具对每个输入进行验证:
- 设备名称必须唯一
- IP地址必须有效
- SSH密钥文件必须存在且可读
- 在添加设备前可进行可选的连接测试
安全提示
这个(或“该”) add_device 工具 仅支持SSH密钥认证出于安全原因,以及因为VSCode的交互界面无法正确隐藏密码字段,已禁用密码认证。
示例用法
在带有GitHub Copilot的VSCode中:
@jmcp Please add a new device to the MCP server该工具随后将引导您完成整个过程:
- 输入设备名称:
vsrx-lab1 - 输入IP地址:
10.0.1.100 - 输入SSH端口:
22(或按回车键采用默认值) - 输入用户名:
admin - 输入SSH密钥路径:
/home/user/.ssh/junos_key.pem - 确认并(可选地)测试连接
添加成功后,该设备即可立即与所有其他Junos MCP工具一起使用。
SSH密钥要求
- SSH私钥文件必须存在于MCP服务器的文件系统中
- 该文件必须能够被运行MCP服务器的进程读取
- 对于Docker部署,将SSH密钥文件挂载到容器中
Docker 挂载示例:
docker run --rm -it \
-v /path/to/devices.json:/app/network_devices/devices.json \
-v /path/to/ssh_key.pem:/app/network_devices/keys/ssh_key.pem \
-p 30030:30030 \
juniper-mcp-v1:latest \
python jmcp.py -f /app/network_devices/devices.json -t streamable-http -H 0.0.0.0局限性
- 仅限VSCode在Claude Desktop中不支持提示(或引出)功能
- 仅使用SSH密钥不支持密码认证
- 无持久性添加的设备仅存储在内存中;服务器重启后,这些设备信息将会丢失
- 超时用户有5分钟的时间来回应每个提示
对于Claude Desktop用户,设备仍需在(相应平台/系统中)进行配置 devices.json 按照文中所述保存文件 Junos设备配置 部分。
VSCode + GitHub Copilot 集成
启动您的服务器
$ python3.11 jmcp.py -f devices.json
[06/11/25 08:26:11] INFO Starting MCP server 'jmcp-server' with transport 'streamable-http' on http://127.0.0.1:30030/mcp
INFO: Started server process [33512]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:30030 (Press CTRL+C to quit)在你的VSCode配置中指向这个URL
{
"mcp": {
"servers": {
"my-juniper-mcp-v1": {
"url": "http://127.0.0.1:30030/mcp/"
}
}
}
}注: 你可以使用VSCode的 Cmd+Shift+P 配置MCP服务器。
MCP服务器访问的身份验证
当使用流式HTTP传输时,Junos MCP服务器支持基于令牌的认证,以确保客户端的安全访问。这可以防止未经授权访问您的网络基础设施。
认证行为
- stdio 传输(或:标准I/O传输) (Claude Desktop):无需认证 - 由于本地运行,设计上安全可靠
- 流式传输(基于HTTP的)传输 (VSCode,网页客户端):支持基于令牌的身份验证
令牌管理
服务器包含一个专用的令牌管理命令行界面(CLI)工具: jmcp_token_manager.py
生成一个新令牌
# Basic token generation
python jmcp_token_manager.py generate --id "vscode-dev"
# With description
python jmcp_token_manager.py generate --id "vscode-dev" --description "VSCode development environment"
# Example output:
Generated new token:
ID: vscode-dev
Token: jmcp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8
Description: VSCode development environment
Save this token securely - it won't be shown again!列出所有令牌
python jmcp_token_manager.py list
# Example output:
ID Description Created
-------------------------------------------------------------------------------------
vscode-dev VSCode development environment 2025-01-28T10:30:00Z
prod-client Production client access 2025-01-28T09:15:00Z 显示代币价值(恢复)
python jmcp_token_manager.py show --id "vscode-dev"
# Example output:
Token ID: vscode-dev
Token: jmcp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8
Description: VSCode development environment
Created: 2025-01-28T10:30:00Z撤销令牌
python jmcp_token_manager.py revoke --id "vscode-dev"
# Example output:
Token 'vscode-dev' has been revoked服务器认证状态
服务器会自动检测令牌的存在,并据此启用身份验证:
已配置令牌:
$ python jmcp.py -f devices.json -t streamable-http
INFO - Token-based authentication enabled
INFO - Clients must send 'Authorization: Bearer ' header
INFO - Use jmcp_token_manager.py to manage tokens
INFO - Streamable HTTP server started on http://127.0.0.1:30030未配置令牌:
$ python jmcp.py -f devices.json -t streamable-http
WARNING - No .tokens file found - server is open to all clients
INFO - Create tokens using: python jmcp_token_manager.py generate --id
INFO - Streamable HTTP server started on http://127.0.0.1:30030带身份验证的客户端配置
使用令牌配置 VSCode
{
"mcp": {
"servers": {
"my-juniper-mcp-v1": {
"url": "http://127.0.0.1:30030/mcp/",
"headers": {
"Authorization": "Bearer jmcp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8"
}
}
}
}
}使用curl进行测试
# Test authentication with valid token
curl -X POST "http://127.0.0.1:30030/mcp/" \
-H "Authorization: Bearer jmcp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
# Test without token (should fail with 401)
curl -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":"tools/list","params":{}}'注: MCP streamable-http 需要 Accept: application/json, text/event-stream 头球
带认证的Docker
当使用 Docker 时,挂载 .tokens 启用身份验证的文件:
# Generate token first (outside container)
python jmcp_token_manager.py generate --id "docker-client"
# Run container with token file mounted
docker run --rm -it \
-v /path/to/devices.json:/app/network_devices/devices.json \
-v /path/to/.tokens:/app/.tokens \
-p 30030:30030 \
juniper-mcp-v1:latest \
python jmcp.py -f /app/network_devices/devices.json -t streamable-http -H 0.0.0.0安全最佳实践
- 代币安全:
- 安全地存储令牌(使用密码管理器、环境变量) - 使用描述性令牌ID以便于管理 - 定期通过撤销旧令牌并生成新令牌来轮换令牌 - 永远不要将令牌提交到版本控制系统中
- 访问控制:
- 为不同的客户端/环境生成独立的令牌 - 在不再需要时立即撤销令牌 - 监控服务器日志,查找未经授权的访问尝试
- 网络安全:
- 在生产环境中,通过HTTPS反向代理运行streamable-http服务器 - 使用防火墙规则限制对MCP服务器端口的访问 - 考虑为远程客户端提供VPN访问
令牌文件格式
这个(或:该) .tokens 文件以JSON格式存储令牌:
{
"vscode-dev": {
"token": "jmcp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8",
"description": "VSCode development environment",
"created": "2025-01-28T10:30:00Z"
},
"prod-client": {
"token": "jmcp_x9y8z7w6v5u4t3s2r1q0p9o8n7m6l5k4j3i2",
"description": "Production client access",
"created": "2025-01-28T09:15:00Z"
}
}重要的确保此文件的安全,不要将其提交到版本控制系统中。
使用MCP服务器与瞻博网络云原生路由器(JCNR)
JCNR是一种云原生路由器,可在多种云环境中运行。通过遵循以下步骤,您也可以将此MCP服务器与JCNR一起使用。有关配置的更多详细信息,请参阅JCNR文档。
- 在JCNR中配置SSH访问,使用除22以外的指定端口。这是必要的,因为JCNR作为一个容器在共享操作系统上运行。不建议在默认端口上运行SSH。默认情况下,SSH在24端口上启用。但是,根据您的网络需求,最好将其更改为所需的端口。
- 启用SSH的认证方法。JCNR支持基于SSH密钥和密码的认证。
- 启用基于SSH的Netconf。此功能默认已启用。
set system services netconf ssh
set system services ssh port 3030
set system services ssh root-login allow
set system root-authentication encrypted-password "$6$3vvMI$RNemhmu9izWXzO46msh38frIg4VoeFNJWJZugxgnU.NQso3OQ00QWOIZmzNePD.MWjDODxBBEYut/W7kfADdV." (or)
set system root-authentication load-key-file
开发者指南
本节介绍了Junos MCP服务器的架构以及如何通过新工具对其进行扩展。
架构概述
Junos MCP服务器使用模型上下文协议(MCP)来使大型语言模型(LLMs)能够与Juniper网络设备进行交互。服务器架构包括:
- MCP 服务器核心 (
jmcp.py): 处理MCP协议通信 - 工具处理程序实现特定网络操作的独立功能
- 工具注册表将地图工具名称映射到其处理函数
- 传输层支持stdio(Claude Desktop)和streamable-http(VSCode)
工具的工作原理
MCP服务器中的每个工具都遵循以下流程:
LLM Request → MCP Server → Tool Registry → Handler Function → PyEZ → Junos Device
↓
LLM Response ← MCP Server ← Handler Response ← PyEZ Response ←添加新工具
添加新工具是一个简单的三步流程:
步骤1:创建一个处理函数
创建一个异步处理函数 jmcp.py (在……之前 TOOL_HANDLERS (字典):
async def handle_my_new_tool(arguments: dict) -> list[types.ContentBlock]:
"""Handler for my_new_tool - describe what it does"""
# Extract arguments
router_name = arguments.get("router_name", "")
my_param = arguments.get("my_param", "default_value")
# Validate router exists
if router_name not in devices:
result = f"Router {router_name} not found in the device mapping."
else:
# Your tool logic here
log.debug(f"Executing my_new_tool on router {router_name}")
result = _run_junos_cli_command(router_name, f"show {my_param}")
return [types.TextContent(type="text", text=result)]步骤2:注册处理程序
将你的处理程序添加到 TOOL_HANDLERS 字典(大约在第330行):
TOOL_HANDLERS = {
"execute_junos_command": handle_execute_junos_command,
"get_junos_config": handle_get_junos_config,
"junos_config_diff": handle_junos_config_diff,
"gather_device_facts": handle_gather_device_facts,
"get_router_list": handle_get_router_list,
"load_and_commit_config": handle_load_and_commit_config,
"add_device": handle_add_device, # Dynamic device management with elicitation
"my_new_tool": handle_my_new_tool, # Add your tool here
}步骤3:定义工具元数据
将工具定义添加到 list_tools() 方法(大约在第410行):
types.Tool(
name="my_new_tool",
description="Brief description of what your tool does",
inputSchema={
"type": "object",
"properties": {
"router_name": {"type": "string", "description": "The name of the router"},
"my_param": {"type": "string", "description": "Description of parameter"}
},
"required": ["router_name"] # List required parameters
}
)示例:创建BGP邻居工具
以下是一个完整的示例,展示如何添加一个工具来显示BGP邻居:
# Step 1: Handler function
async def handle_show_bgp_neighbors(arguments: dict) -> list[types.ContentBlock]:
"""Handler for show_bgp_neighbors tool"""
router_name = arguments.get("router_name", "")
neighbor_address = arguments.get("neighbor_address", "")
if router_name not in devices:
result = f"Router {router_name} not found in the device mapping."
else:
log.debug(f"Getting BGP neighbors from router {router_name}")
if neighbor_address:
cmd = f"show bgp neighbor {neighbor_address}"
else:
cmd = "show bgp summary"
result = _run_junos_cli_command(router_name, cmd)
return [types.TextContent(type="text", text=result)]
# Step 2: Add to TOOL_HANDLERS
TOOL_HANDLERS = {
# ... existing tools ...
"show_bgp_neighbors": handle_show_bgp_neighbors,
}
# Step 3: Add to list_tools()
types.Tool(
name="show_bgp_neighbors",
description="Show BGP neighbor information",
inputSchema={
"type": "object",
"properties": {
"router_name": {"type": "string", "description": "The name of the router"},
"neighbor_address": {"type": "string", "description": "Optional: specific neighbor IP"}
},
"required": ["router_name"]
}
)在工具中使用引出技术
MCP服务器支持用于交互式数据收集的引出功能。要在您的工具中使用引出功能:
from mcp.server.elicitation import ElicitationResult
from pydantic import BaseModel, Field
# Define elicitation schema
class MyInputSchema(BaseModel):
user_input: str = Field(description="Enter your input")
async def handle_my_elicitation_tool(arguments: dict, context: Context) -> list[types.ContentBlock]:
"""Tool that uses elicitation to collect user input"""
# Use elicitation to ask for user input
result = await context.elicit(
message="Please provide the required input:",
schema=MyInputSchema
)
# Handle the result
match result:
case AcceptedElicitation(data=data):
user_input = data.user_input
# Process the input...
return [types.TextContent(type="text", text=f"Processing: {user_input}")]
case DeclinedElicitation() | CancelledElicitation():
return [types.TextContent(type="text", text="Operation cancelled")]注目前,提示功能仅在 VSCode 中有效(使用 streamable-http 传输)。Claude Desktop 尚不支持提示功能。
工具开发的最佳实践
- 错误处理始终优雅地处理连接错误和无效输入
- 记录日志使用全局(变量/设置/等,具体根据上下文确定)
log用于调试的日志记录器 - 验证在尝试操作之前,检查路由器是否存在
- 文档为工具和参数编写清晰的描述
- 超时支持为长时间运行的操作配置超时时间
- 返回格式总是回来
list[types.ContentBlock]带有文本内容 - 引出(信息/反应)在需要时,使用引出法进行互动式数据收集
- 上下文参数包含
context: Context如果使用引出法,则需参数
使用PyEZ进行高级操作
对于超出CLI命令范围的操作,请直接使用PyEZ:
from jnpr.junos import Device
from jnpr.junos.utils.config import Config
# Example: Using PyEZ tables
async def handle_get_interfaces(arguments: dict) -> list[types.ContentBlock]:
router_name = arguments.get("router_name", "")
if router_name not in devices:
result = f"Router {router_name} not found in the device mapping."
else:
device_info = devices[router_name]
try:
connect_params = prepare_connection_params(device_info, router_name)
with Device(**connect_params) as junos_device:
# Use PyEZ tables or other utilities
interfaces = junos_device.rpc.get_interface_information()
# Process interfaces...
result = "Interface information..."
except Exception as e:
result = f"Error: {e}"
return [types.TextContent(type="text", text=result)]测试你的工具
- 单元测试使用模拟参数测试处理函数
- 集成测试使用实际的Junos设备或vSRX进行测试
- 错误情况测试无效路由器、网络故障等情况。
示例测试:
# Test the handler directly
result = await handle_my_new_tool({
"router_name": "router-1",
"my_param": "test"
})
print(result[0].text)调试技巧
- 启用调试日志以查看详细执行情况:
logging.basicConfig(level=logging.DEBUG)- 使用stdio传输方式以便更轻松地调试:
python jmcp.py -f devices.json -t stdio- 手动测试单个命令:
result = _run_junos_cli_command("router-1", "show version")
print(result)