mcpField
C
Cisco SD-WAN MCP Server

Cisco SD-WAN MCP Server

本地服务
github.com云与基础设施19 周前更新

关于 Cisco SD-WAN MCP Server

为 MCP 客户端公开 Cisco Catalyst SD-WAN Manager(vManage)组网信息的服务。可查询设备状态、告警、路径质量、模板和策略;配置变更工具默认禁用。

主要功能

  1. 01设备与组网清单
  2. 02设备运行状况检查
  3. 03告警与事件查询
  4. 04隧道质量调查
  5. 05模板与策略查询
  6. 06可选启用并确认变更工具

适用场景

  1. 01排查无法连接的分支设备
  2. 02检查 SD-WAN 告警和事件
  3. 03定位质量下降的隧道
  4. 04变更配置前查看模板

MCP 相关

该 MCP 服务通过工具和资源提供 vManage 的设备清单、健康信息、告警、路径质量、模板及策略。启用配置变更工具后,每次操作仍需用户确认。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"pcdamasceno-cisco-sdwan": {
"command": "uvx",
"args": [
"cisco-sdwan-mcp"
],
"env": {
"SDWAN_VMANAGE_URL": "<SDWAN_VMANAGE_URL>",
"SDWAN_USERNAME": "<SDWAN_USERNAME>",
"SDWAN_PASSWORD": "<SDWAN_PASSWORD>",
"MCP_TRANSPORT": "<MCP_TRANSPORT>",
"SDWAN_VERIFY_SSL": "<SDWAN_VERIFY_SSL>",
"SDWAN_CA_BUNDLE": "<SDWAN_CA_BUNDLE>",
"SDWAN_ENABLE_WRITES": "<SDWAN_ENABLE_WRITES>"
}
}
}
}
启动命令uvx cisco-sdwan-mcp
需要配置的环境变量
SDWAN_VMANAGE_URLCisco Catalyst SD-WAN Manager URL, e.g. https://vmanage.example.com:8443
SDWAN_USERNAMEvManage username. Use a dedicated read-only account.
SDWAN_PASSWORD密钥vManage password for SDWAN_USERNAME.
MCP_TRANSPORTMust be stdio for this install. The server itself defaults to http; set http only when deploying it as a service.
SDWAN_VERIFY_SSLVerify the vManage TLS certificate. Prefer SDWAN_CA_BUNDLE over disabling this.
SDWAN_CA_BUNDLEPath to a CA bundle for a private-CA or self-signed vManage certificate.
SDWAN_ENABLE_WRITESRegister the configuration-changing tools. Read-only when unset.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypicisco-sdwan-mcp0.1.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Cisco SD-WAN MCP Server

PyPI Python License: MIT MCP Registry

cisco-sdwan-mcp 是一个面向 Cisco Catalyst SD-WAN Manager (vManage) 的 MCP 服务,基于 FastMCP 构建。

它让大模型客户端能够查看你的 SD-WAN 网络结构,包括设备清单、 设备运行状况、控制平面和数据平面状态、警报、路径质量、模板 和策略——因此你可以询问“法兰克福分支为什么宕机?”,并获得基于真实控制器数据而非猜测的回答。

默认只读。 除非你明确启用,否则不会注册会更改配置的工具; 即使启用,每次调用也都需要人工批准。


目录


你将获得什么

领域工具
设备清单list_devices、get_device、get_fabric_summary、list_inventory
设备运行状况check_device_health、get_system_status、get_control_connections、get_bfd_sessions、get_omp_peers、get_interfaces
警报和事件get_alarm_summary、list_alarms、list_events
路径质量find_degraded_tunnels、get_tunnel_statistics、get_interface_statistics
模板和策略list_device_templates、get_device_template、list_feature_templates、list_policies、get_template_input_variables
配置组和配置文件list_config_groups、get_config_group、get_device_config_group、get_config_group_device_variables、list_feature_profiles、get_feature_profile、get_parcel、get_parcel_schema、get_device_running_config
配置 (选择启用)attach_device_template、activate_vsmart_policy、update_parcel、update_cli_addon_config、deploy_config_group、get_task_status

此外还有四个工作流提示词和三个资源。

有三项设计决策值得提前了解,因为它们影响每个工具:

  • 返回的是筛选后的结果,而非原始数据。 vManage 设备记录包含 60 多个字段;200 台设备的网络会占满模型的上下文。每个工具只返回回答问题所需的字段;如果需要全部字段,可设置 detailed=true。
  • 结果始终附带计数。 每个列表都会同时报告 count(匹配数量)和 returned(返回数量),这样“有 3 台设备宕机”就不会被误解为“我查看的前 100 台设备中有 3 台宕机”。
  • 失败会以答案的形式返回。 密码错误、控制器无法访问或主机名未知时,会返回易读的消息——通常还会提供有效选项——而不是抛出异常。模型随后可以自行修正,或准确告知你需要修复什么。

快速开始

前置条件
  • Python 3.11+
  • uv(推荐)或 pip
  • 可访问的 Cisco Catalyst SD-WAN Manager(vManage)及其账号

请创建专用的 vManage 账号。 刚开始时为其分配只读角色。 账号权限才是真正的安全边界——请参阅 写入保护。

安装

如果只想运行,可从 PyPI 安装:

uvx cisco-sdwan-mcp        # no install, run it straight
pip install cisco-sdwan-mcp

如果想修改代码,可从代码库检出:

git clone https://github.com/pcDamasceno/cisco-sdwan-mcp.git
cd cisco-sdwan-mcp

# with uv (recommended)
uv sync --extra dev

# with pip
pip install -e ".[dev]"
配置
cp .env.example .env

必须填写以下三项设置:

SDWAN_VMANAGE_URL=https://vmanage.example.com:8443
SDWAN_USERNAME=automation-readonly
SDWAN_PASSWORD=...

服务启动时会从代码库根目录读取 .env——设置 SDWAN_ENV_FILE 可加载其他文件。环境中已有的变量(compose env_file、Kubernetes 密钥)不会被覆盖,启动日志会显示所用文件的名称。

运行
uv run python -m cisco_sdwan_mcp.server        # or: python -m cisco_sdwan_mcp.server

服务会通过 HTTP 在 0.0.0.0:8000 上启动。MCP 端点位于 http://localhost:8000/mcp,健康探测端点位于 http://localhost:8000/healthz, 此 README 位于 http://localhost:8000/。

在任何客户端连接之前,启动日志会确认服务将连接的目标:

INFO  cisco_sdwan_mcp.server: vManage controller: vmanage.example.com:8443 (user automation-readonly, TLS verify: True)
INFO  cisco_sdwan_mcp.server: Write tools: disabled (read-only)
首次调用

将 MCP 客户端连接到此服务(请参阅连接 MCP 客户端),并调用 get_fabric_summary。此调用只需一次往返,即可同时验证身份验证、TLS 和连通性:

{
  "total_devices": 42,
  "by_type": {"vedge": 38, "vsmart": 2, "vbond": 1, "vmanage": 1},
  "by_reachability": {"reachable": 40, "unreachable": 2},
  "unreachable_count": 2,
  "unreachable_devices": [{"host-name": "BR2-EDGE1", "system-ip": "10.0.0.12", "site-id": "1002"}]
}

配置

所有配置均通过环境变量设置;.env.example 是带注释的参考文件。

vManage 连接
变量默认值说明
SDWAN_VMANAGE_URL—控制器 URL,例如 https://vmanage.example.com:8443。必填(或使用 SDWAN_VMANAGE_HOST)
SDWAN_VMANAGE_HOST—主机名,用于替代完整 URL
SDWAN_VMANAGE_PORT443使用 SDWAN_VMANAGE_HOST 时的端口
SDWAN_USERNAME—vManage 用户名。必填
SDWAN_PASSWORD—vManage 密码。必填
SDWAN_VERIFY_SSLtrueTLS 证书验证
SDWAN_CA_BUNDLE—CA 证书包的路径——私有 CA 的正确配置方式
SDWAN_TIMEOUT60等待 vManage 的秒数
SDWAN_PAGE_SIZE100每次工具调用返回记录数的默认上限
SDWAN_ENABLE_WRITESfalse注册配置工具——见下文
服务端
变量默认值说明
MCP_SERVER_NAMEcisco-sdwan-mcp向 MCP 客户端公布的名称
MCP_TRANSPORThttphttp 或 stdio
MCP_HOST0.0.0.0绑定地址(仅限 HTTP)
MCP_PORT8000绑定端口(仅限 HTTP)
MCP_AUTHnoneMCP 客户端向此服务进行身份验证的方式
LOG_LEVELINFOPython 日志级别

SDWAN_USERNAME/SDWAN_PASSWORD 用于此服务向 vManage 进行身份验证。 MCP_AUTH 决定客户端如何向此服务进行身份验证。二者互不相关,通常两者都需要配置。

TLS

vManage 经常会提供自签名证书或私有 CA 证书。按优先顺序从高到低:

  1. 将 SDWAN_CA_BUNDLE 指向控制器的 CA——保持启用证书验证。
  2. 将 CA 添加到 certificates/,Docker 构建会自动将其安装到容器信任存储中。
  3. 只有在最后迫不得已时,才在你控制的实验环境中设置 SDWAN_VERIFY_SSL=false。 每次执行此操作时,服务都会记录一条警告并注明主机名,因为这意味着路径上的任何对象都可能读取凭据。

写入保护

更改配置的工具受到双重限制。

限制 1 — 注册。 当 SDWAN_ENABLE_WRITES 未设置或为 false 时,包含这些工具的模块永远不会被导入。它们不会出现在工具列表中,因此模型无法因误操作、误解或提示注入而调用它们。该服务从构造上就是只读的,而非依靠策略限制。

限制 2 — 确认。 启用写入后,每次调用仍会通过 MCP elicitation 向用户征求确认,明确说明模板或策略以及受影响的设备,然后才会将任何内容发送到 vManage。不支持 elicitation 的客户端无法悄悄继续操作——除非调用方传入 confirm=true,否则调用会被拒绝;无论哪种情况,决定权都在人工手中。

SDWAN_ENABLE_WRITES=true uv run python -m cisco_sdwan_mcp.server
WARNING cisco_sdwan_mcp.tools: SDWAN_ENABLE_WRITES=true — configuration-changing tools are registered.
                   Each one still requires explicit user confirmation before it runs.

vManage 账户才是真正的边界。 SDWAN_ENABLE_WRITES 控制的是此服务中有哪些工具;它无法限制该账户通过其他途径执行的操作。如果必须确保某项更改不可能发生,请使用只读 vManage 角色——不要只依赖此标志。

vManage 会异步应用配置:写入操作返回 task_id,表示已接受,而非已应用。轮询 get_task_status(task_id),直到状态显示已完成。

模板推送的预期流程,中间包含审核步骤:

list_device_templates          → find the template
get_device_template            → see what it configures and who has it
get_template_input_variables   → the exact per-device values (read-only preview)
check_device_health            → never push to an already-broken device
attach_device_template         → asks for approval, returns a task_id
get_task_status                → confirm it actually landed

对于配置组架构,编辑和部署是分开的步骤:

get_device_config_group          → which group owns the device
get_feature_profile / get_parcel → find the parcel and its current values
get_parcel_schema                → which parcel a setting lives in, and its shape
update_parcel                    → asks for approval; changes intent only
get_device_running_config        → snapshot before the push
deploy_config_group              → asks for approval, returns a task_id
get_task_status                  → confirm it landed, then re-diff the running config

工具参考

每个工具都接受 limit(记录数上限),大多数工具还接受 detailed(返回 vManage 的所有字段,而非摘要字段集)。

设备清单
工具可解答的问题
get_fabric_summary()按类型、可达性和版本统计设备数量,并列出所有不可达设备。遇到开放式问题时,从这里开始。
list_devices(device_type, reachability, site_id)vManage 当前正在与之通信的设备。
get_device(device)获取单台设备的完整记录。接受主机名、系统 IP 或机箱编号。
list_inventory(category, unattached_only)所有已置备设备,包括从未完成上线、证书无效或未关联模板的设备。
设备运行状况
工具可解答的问题
check_device_health(device)一次调用完成初步排查——系统状态、控制连接和 BFD,并提供指出问题所在的 problems 列表。
get_system_status(device)运行时间、CPU、内存、磁盘、上次重启原因。
get_control_connections(device)与 vSmart/vBond/vManage 的连接。设备无法启动时,优先检查此项。
get_bfd_sessions(device, state)到其他边缘设备的数据平面隧道。站点可以连接控制器但彼此无法通信时,检查此项。
get_omp_peers(device)OMP 对等状态——控制连接正常但 OMP 断开意味着没有覆盖网络路由。
get_interfaces(device, vpn_id, interface_name)接口状态、寻址信息和错误计数器。

这些工具通过 vManage 轮询设备,因此反映的是实时状态,但会产生一次到边缘设备的往返通信。与其分开调用 3 次,不如优先使用 check_device_health。

警报和事件
工具可解答的问题
get_alarm_summary(hours)按严重程度和组件统计数量、列出最常见规则及受影响最多的设备。开销低——列出警报前先调用。
list_alarms(hours, severity, active_only)获取警报本身。
list_events(hours, severity, component)原始事件流——噪声较多,但能显示从未升级为警报的连接抖动和状态转换。
链路质量
工具可解答的问题
find_degraded_tunnels(hours, max_loss_percent, max_latency_ms, max_jitter_ms)查找超出阈值的隧道,按问题严重程度从高到低排列,并说明各隧道超出了哪个阈值。
get_tunnel_statistics(device, hours)获取每条隧道的原始丢包、延迟、抖动和 vQoE 数据。
get_interface_statistics(device, hours, interface_name)获取历史吞吐量和错误计数器。

这些工具读取 vManage 的统计数据库——速度快,但数据新鲜度取决于上次采集周期(大多数部署中为 30 分钟)。如需查看实时状态,请使用设备运行状况工具。

模板和策略
工具说明
list_device_templates(device_type, attached_only)模板及其关联数量。
get_device_template(template_id)单个模板的定义及关联的设备。
list_feature_templates(template_type)构建模块。
list_policies(policy_scope)集中式(vSmart)或本地化策略,以及当前生效的策略。
get_template_input_variables(template_id, device_ids)只读预览关联操作将推送的值。
配置组和功能配置文件

UX-2.0 配置模型:一个配置组包含多个功能配置文件 (系统、传输、服务、CLI、策略对象),每个配置文件包含 配置块——即实际的配置负载——而一台设备最多只能属于一个 配置组。在以这种方式管理的网络结构中,模板端点不会返回有用的信息; 这些工具提供了相应的功能。vManage 会在 WAN 边缘设备清单中以 "managed-by": "Config-Group <name>" 报告成员关系,get_device 和 list_inventory 也会显示此信息。

工具说明
list_config_groups()配置组、其配置文件、设备数量及最新状态。
get_config_group(group)按名称或 ID 获取单个配置组,以及其成员设备和等待部署的设备。
get_device_config_group(device)查看管理设备的配置组,从而判断模板是否必须避开该设备。
get_config_group_device_variables(group, device_ids)部署操作将解析的各设备对应值;这是 get_template_input_variables 的配置组版本。
list_feature_profiles(profile_type)指定类型的配置文件,或全部五种类型。
get_feature_profile(profile_type, profile_id)配置块树,其中每个节点都带有可直接使用的 parcelPath。
get_parcel(profile_type, profile_id, parcel_path, parcel_id)单个配置块的负载——实际配置项。
get_parcel_schema(profile_type, parcel_path)配置块类型可包含的所有字段;编辑前请先查看。
get_device_running_config(device)设备当前的配置,用于部署前后差异对比。

启用写入后,与模板推送对应的配置组操作包括 update_parcel(编辑结构化配置项,采用读取-修改-写入方式)、update_cli_addon_config (在 CLI 附加配置文件中追加或替换原始 IOS-XE 行,并返回差异)以及 deploy_config_group(将配置组推送到指定成员设备——唯一会影响生产环境的步骤)。编辑会将成员标记为 configGroupUpToDate: false,直到完成部署。attach_device_template 会拒绝由配置组管理的设备,因此两种配置模型不会争抢同一台设备。


提示词

可重复使用的工作流,用于编码工程师实际采用的操作顺序—— 先控制平面,再数据平面;先收集证据,再得出结论。

提示词用途
troubleshoot_device(device, symptom)结构化设备排查,遇到首个真实原因时停止
fabric_health_report(hours)全网报告:设备、告警、路径质量和建议
analyse_path_quality(hours, site)隧道性能分析,按颜色/站点/设备归类,以定位原因
review_template_change(template_id)变更前审查,明确给出继续/停止建议——只提供建议,不会关联模板

资源

URI内容
sdwan://config当前生效的连接设置——控制器、用户、TLS 模式,以及是否启用了写入。绝不包含密码。
sdwan://devices当前网络结构清单,包含各设备状态
sdwan://device/{identifier}按主机名或系统 IP 查询单台设备的完整记录

连接 MCP 客户端

Claude Desktop(claude_desktop_config.json)
{
  "mcpServers": {
    "cisco-sdwan": {
      "url": "http://localhost:8000/mcp"
    }
  }
}
VS Code(GitHub Copilot)— .vscode/mcp.json
{
  "servers": {
    "cisco-sdwan": {
      "type": "http",
      "url": "http://localhost:8000/mcp"
    }
  }
}
启用令牌身份验证时
{
  "mcpServers": {
    "cisco-sdwan": {
      "url": "http://localhost:8000/mcp",
      "headers": { "Authorization": "Bearer dev-token" }
    }
  }
}

使用 OAuth 模式(github、google、oauth-proxy 等)时,无需提供标头—— MCP 客户端会自行发现身份验证流程并打开登录界面。

stdio(本地子进程)

从 PyPI 获取——无需克隆,首次运行时 uvx 会获取软件包:

{
  "mcpServers": {
    "cisco-sdwan": {
      "command": "uvx",
      "args": ["cisco-sdwan-mcp"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "SDWAN_VMANAGE_URL": "https://vmanage.example.com:8443",
        "SDWAN_USERNAME": "automation-readonly",
        "SDWAN_PASSWORD": "..."
      }
    }
  }
}

从检出目录运行:

{
  "mcpServers": {
    "cisco-sdwan": {
      "command": "uv",
      "args": ["run", "python", "-m", "cisco_sdwan_mcp.server"],
      "cwd": "/absolute/path/to/cisco-sdwan-mcp",
      "env": {
        "MCP_TRANSPORT": "stdio",
        "SDWAN_VMANAGE_URL": "https://vmanage.example.com:8443",
        "SDWAN_USERNAME": "automation-readonly",
        "SDWAN_PASSWORD": "..."
      }
    }
  }
}

传输方式:HTTP 与 stdio

  • HTTP(默认) — 用于部署的传输方式。可同时为多个客户端提供服务,支持在负载均衡器后运行,并且只有此传输方式会应用 MCP_AUTH。deploy/ 中的所有内容都以此为前提。
  • stdio — 适用于本地单用户场景,此时桌面客户端会将服务作为子进程启动。没有网络监听,因此不适用 MCP_HOST/MCP_PORT 和 MCP_AUTH;该进程由你的操作系统用户账户提供安全保护。
MCP_TRANSPORT=stdio uv run python -m cisco_sdwan_mcp.server

部署到任何地方或为多个用户提供服务 → 使用 HTTP。在自己的机器上供一个客户端使用 → 两种方式均可。


验证 MCP 客户端

默认情况下,不会验证客户端向此服务发起的请求;启动时通过 MCP_AUTH 选择验证方式。工厂函数位于 cisco_sdwan_mcp/auth.py;所有模式都基于 FastMCP 内置的提供程序。

MCP_AUTH使用场景
none(默认)本地开发,或通过网络层保护(IAM、VPN、mTLS)
static固定的 bearer 令牌——仅用于快速测试,绝不可用于生产环境
jwt你已有 IdP 用于签发 JWT(Keycloak、Okta、Entra ID、Cognito……)
introspection你的 IdP 签发不透明令牌(RFC 7662)
oauth-proxy通过任意 OAuth 提供程序实现完整的 OAuth 2.1 登录流程
github、google、azure、auth0、workos通过托管身份提供程序实现完整登录流程,且已预先配置
# Development tokens (never in production — tokens sit in plain env vars)
MCP_AUTH=static MCP_AUTH_STATIC_TOKENS=dev-token uv run python -m cisco_sdwan_mcp.server

# JWT via your IdP's JWKS endpoint
MCP_AUTH=jwt
MCP_AUTH_JWKS_URI=https://idp.example.com/realms/main/protocol/openid-connect/certs
MCP_AUTH_ISSUER=https://idp.example.com/realms/main
MCP_AUTH_AUDIENCE=cisco-sdwan-mcp

所有模式的完整变量参考请见 .env.example。

注意:

  • 验证仅适用于 HTTP 传输方式。
  • /healthz 和 / 始终公开——探针和用户不会携带令牌;MCP 端点在没有有效令牌时会返回 401。
  • 在生产环境中,OAuth 流程要求公开 URL 使用 HTTPS。
  • 如需添加自己的方案,请在 cisco_sdwan_mcp/auth.py 中编写构建器,并在 _BUILDERS 中注册(提供程序文档)。

暴露 WAN 拓扑的服务不应在可访问的网络上以 MCP_AUTH=none 运行。请参阅 deploy/README.md。


Docker

cp .env.example .env      # fill in vManage URL and credentials
docker compose up -d --build

或者手动操作:

docker build -t cisco-sdwan-mcp .
docker run -p 8000:8000 \
  -e SDWAN_VMANAGE_URL=https://vmanage.example.com:8443 \
  -e SDWAN_USERNAME=automation-readonly \
  -e SDWAN_PASSWORD=... \
  cisco-sdwan-mcp

辅助脚本会构建镜像、替换任何同名容器,并启动服务,使其可通过 http://localhost:8000/mcp 访问,同时传入你的 .env:

bash scripts/run_docker.sh          # Linux/macOS
.\scripts\run_docker.ps1            # Windows PowerShell

镜像包含针对 /healthz 的 HEALTHCHECK,因此 docker ps 开箱即用即可显示容器健康状态。

企业 CA 证书

将任意 .crt/.pem 根 CA 文件放入 certificates/。构建过程会将其添加到容器信任存储,并自动运行 update-ca-certificates——这同时适用于拦截 TLS 的代理和由内部 CA 签名的 vManage 证书。如果不需要,请将此目录留空。

使用代理时,HTTP_PROXY/HTTPS_PROXY/NO_PROXY 是预定义的 Docker 构建参数,无需修改 Dockerfile:

docker build --build-arg HTTPS_PROXY=http://proxy.example.com:8080 -t cisco-sdwan-mcp .
docker run -p 8000:8000 -e HTTPS_PROXY=http://proxy.example.com:8080 cisco-sdwan-mcp

部署

此容器是在端口 8000 上运行的普通 HTTP 服务,带有 /healthz 探针,因此可以在任何地方运行。deploy/ 提供原始 Kubernetes 清单、Helm chart、Styrmin 驱动程序和 Cloud Run 服务定义——完整操作指南请参阅 deploy/README.md,其中也包括 SD-WAN 专属内容:从云端访问管理网络控制器、处理私有 CA,以及 vManage 的每账户会话限制。

kubectl apply -k deploy/kubernetes
helm install sdwan-mcp oci://ghcr.io/pcdamasceno/charts/cisco-sdwan-mcp \
  --set sdwan.vmanageUrl=https://vmanage.example.com:8443
gcloud run services replace deploy/cloud-run-service.yaml --region europe-west3

此代码库也是一个 Styrmin 应用驱动程序——Styrmin 克隆此代码库时会读取根目录下的 driver.styrmin.yml 和 values.j2.yml。请参阅 deploy/styrmin.md。

/healthz 有意不检查 vManage。短暂的控制器故障不应导致 Pod 重启——工具会在每次调用时报告问题,服务也会自行恢复。


添加自定义工具

功能分布在三个包中,每个包对应一个关注点的模块。每个包的 __init__.py 都会导入其模块,以便运行装饰器——添加一个模块,再添加一 行导入语句。

# cisco_sdwan_mcp/tools/my_tools.py
from cisco_sdwan_mcp.sdwan.client import get_client
from cisco_sdwan_mcp.sdwan.formatting import envelope, project
from cisco_sdwan_mcp.tools._helpers import resolve_device_id, sdwan_tool


@sdwan_tool
async def get_dhcp_leases(device: str, limit: int = 100) -> dict:
    """Show DHCP leases the device is serving.

    Args:
        device: Hostname, system IP or chassis number.
        limit: Maximum leases to return.
    """
    system_ip = await resolve_device_id(device)
    client = await get_client()
    records = await client.get_data(
        "/dataservice/device/dhcp/server", {"deviceId": system_ip}
    )
    fields = ("ifname", "address", "client-id", "state", "expires")
    return envelope(project(records, fields), limit=limit, device=device)

然后将 my_tools 添加到 cisco_sdwan_mcp/tools/__init__.py 的导入列表中。

使用 @sdwan_tool,而不是 @mcp.tool——它不仅会注册工具,还会将 SD-WAN 故障转换为易读的 {"error", "message"} 结果。优先使用共享辅助函数, 而不是重新实现:

辅助函数用途
resolve_device_id(device)将主机名 / 系统 IP / 机箱转换为 vManage 实时端点所需的系统 IP
client.get_data(path, params)发起 GET 请求并解包 vManage 的 {"data": [...]} 信封
project(records, fields)将宽泛的记录精简为重要内容
envelope(records, limit=...)添加 count/returned/截断说明
build_query(hours=..., rules=...)构建告警 / 事件 / 统计数据所需的 JSON query 参数
count_by(records, field)按字段汇总计数

模型会读取文档字符串,以决定是否调用你的工具——说明它能回答什么问题, 而不只是它调用了哪个端点。将写操作放在 config_tools.py 中,以便注册 门控机制继续覆盖这些操作。


测试

uv run pytest      # or: pytest

测试套件使用伪造的 vManage(httpx.MockTransport)运行,而不是连接到 真实控制器,因此能覆盖实际部署中容易出问题的情况:

  • 登录握手,包括 vManage 使用 HTTP 200 和 HTML 正文回应失败的登录
  • CSRF 令牌处理,以及没有令牌端点的 19.2 之前版本控制器
  • 会话中途过期 → 自动重新登录并重试一次
  • 错误转换:主机无法访问、超时、403、非 JSON 响应
  • 每个读取工具的筛选、投影和截断
  • 写操作门控,在全新解释器中验证:未设置 SDWAN_ENABLE_WRITES=true 时配置工具不可用,设置后则可用
  • 写操作确认:拒绝确认,或客户端无法提示时,不得向 vManage 发起 HTTP 请求

tests/conftest.py 中包含伪造控制器;请将其作为编写自定义工具的范例。


故障排查

症状原因和解决方法
ConfigurationError: No controller configured未设置 SDWAN_VMANAGE_URL(或 SDWAN_VMANAGE_HOST)。
AuthenticationError: rejected the credentials用户名或密码错误,或者账户已锁定。密码错误时,vManage 会返回包含登录页面的 HTTP 200 响应,客户端会检测到这种情况并将其报告为身份验证失败。
AuthenticationError: may lack the required role身份验证成功,但该账户没有访问此端点的权限。模板和策略端点需要的权限不止只读角色。
AuthenticationError: issued no JSESSIONID cookieURL 指向的是会剥离 Cookie 的代理,而不是 vManage 本身。
APIError: cannot reach <host>DNS、路由、防火墙或端口错误。vManage 通常监听 8443,而不是 443。
APIError: timed out after 60s实时端点会轮询设备本身。请调高 SDWAN_TIMEOUT,或将查询范围限定为一台设备。
TLS / 证书验证失败使用的是私有 CA。请设置 SDWAN_CA_BUNDLE,或将 CA 添加到 certificates/。SDWAN_VERIFY_SSL=false 仅可作为实验环境中的最后手段。
APIError: response was not valid JSON此 vManage 版本上不存在该端点;API 路径因版本而异。
写入工具“不存在”这是预期行为:SDWAN_ENABLE_WRITES 未设置为 true。
写入返回 applied: false,并提示 confirm=True客户端不支持 MCP elicitation,因此无法请求你批准。
所有结果均为空,且没有错误该账户可能受限于没有设备的租户或设备组。请检查 sdwan://config 并尝试 list_inventory。

设置 LOG_LEVEL=DEBUG 可查看更多详情。请注意,vManage 的错误正文可能很冗长;在共享环境中启用调试日志前,请先检查实际返回的内容。


项目结构

.
├── cisco_sdwan_mcp/
│   ├── mcp.py                    ← Shared FastMCP instance, auth wiring, /healthz
│   ├── auth.py                   ← MCP client authentication factory (MCP_AUTH)
│   ├── server.py                 ← Entry point: transport selection, startup logging
│   ├── sdwan/                    ← vManage integration layer (no MCP knowledge)
│   │   ├── config.py             ← SDWAN_* settings
│   │   ├── client.py             ← Async client: login, CSRF, session recovery
│   │   ├── formatting.py         ← Projection, envelopes, vManage query builder
│   │   └── errors.py             ← Exception hierarchy
│   ├── tools/
│   │   ├── _helpers.py           ← @sdwan_tool, device resolution
│   │   ├── inventory_tools.py    ← Devices and fabric summary
│   │   ├── monitoring_tools.py   ← Control plane, BFD, OMP, interfaces, health
│   │   ├── alarm_tools.py        ← Alarms and events
│   │   ├── statistics_tools.py   ← Tunnel and interface statistics
│   │   ├── template_tools.py     ← Templates and policies (read-only)
│   │   ├── config_group_tools.py ← Config groups, feature profiles, parcels (read-only)
│   │   ├── config_tools.py       ← Template/policy writes — imported only when enabled
│   │   └── config_group_write_tools.py ← Parcel/CLI/deploy writes — same gate
│   ├── resources/sdwan_resources.py
│   └── prompts/sdwan_prompts.py
├── tests/
│   ├── conftest.py               ← Fake vManage (httpx.MockTransport)
│   ├── sample_data.py            ← Representative vManage payloads
│   ├── test_client.py            ← Login, session recovery, error translation
│   ├── test_formatting.py        ← Projection, envelopes, query building
│   ├── test_tools.py             ← Read tools via the in-memory MCP client
│   ├── test_config_tools.py      ← The write confirmation gate
│   ├── test_config_group_tools.py← Config-group reads, writes and the template guardrail
│   ├── test_server.py            ← Registration, the write gate, public routes
│   └── test_auth.py              ← MCP client auth factory
├── deploy/                       ← Kubernetes + Cloud Run
├── scripts/                      ← Docker helper scripts (bash / PowerShell)
├── certificates/                 ← Drop-in CA certificates for Docker builds
├── .env.example                  ← Annotated reference of every variable
├── docker-compose.yml
├── Dockerfile
└── pyproject.toml

资源


许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。