Netdisco MCP

Netdisco MCP

Enables AI agents to interact with the Netdisco network management platform through its complete REST API, supporting device inspection, port queries, VLAN searches, and job management.

Category
访问服务器

README

<div align="center">

Netdisco MCP

The complete Netdisco REST API, translated into an agent-native MCP server

Python 3.11+ CI FastMCP MCP Docker License: MIT

81 tools · dynamic Swagger discovery · stdio + Streamable HTTP · guidance-first agent UX · bearer authentication

</div>


Netdisco MCP turns a live Netdisco swagger.json document into a complete, searchable MCP tool surface. It does not maintain a fragile handwritten subset of endpoints. At startup it discovers the connected Netdisco version, upgrades Swagger 2.0 to OpenAPI 3, repairs schema incompatibilities, assigns stable tool names, and publishes every supported operation through FastMCP.

The result is an MCP server that can answer operational questions, inspect devices and switch ports, search nodes and VLANs, run inventory reports, and— when explicitly enabled—submit or remove Netdisco jobs.

[!IMPORTANT] The live API is the source of truth. Tool counts can increase when Netdisco adds endpoints. The catalog in this README is a verified snapshot of Netdisco 2.103000.

Contents

Why this project exists

Capability What it means
Complete API coverage Every operation advertised by the connected Netdisco instance becomes an MCP tool.
Upgrade-aware A container restart reloads the live specification and discovers new endpoints.
Agent-first guidance get_guidance is intentionally the first tool, and middleware redirects agents that skip it.
Capability discovery find_capability searches names, routes, tags, methods, and descriptions.
Safer exploration Read-only mode removes POST, PUT, PATCH, and DELETE operations before tool generation.
Context protection Oversized responses are truncated with a clear hint to narrow the request.
Flexible transport Run locally over stdio or remotely over MCP Streamable HTTP.
Remote authentication Streamable HTTP can require a deployment-specific bearer token.
Container hardened The supplied Compose service uses a read-only filesystem, no-new-privileges, and no host port.

Architecture

flowchart LR
    subgraph Clients["MCP clients"]
        ChatGPT["ChatGPT / OpenAI"]
        Codex["Codex"]
        ClaudeCode["Claude Code"]
        ClaudeDesktop["Claude Desktop"]
    end

    Proxy["TLS reverse proxy"]

    subgraph Server["Netdisco MCP"]
        Auth["Bearer authentication"]
        Guide["Guidance gate"]
        Catalog["FastMCP tool catalog"]
        Limit["Response limiter"]
        Adapter["Swagger 2 → OpenAPI 3 adapter"]
    end

    Spec["Netdisco swagger.json"]
    API["Netdisco REST API"]

    ChatGPT --> Proxy
    Codex --> Proxy
    ClaudeCode --> Proxy
    ClaudeDesktop --> Proxy
    Proxy --> Auth
    Auth --> Guide --> Catalog --> Limit
    Adapter --> Catalog
    Spec --> Adapter
    Catalog --> API

Startup pipeline

sequenceDiagram
    participant S as Netdisco MCP
    participant N as Netdisco
    participant A as Swagger adapter
    participant F as FastMCP

    S->>N: GET /swagger.json
    N-->>S: Swagger 2.0 document
    S->>A: Normalize schemas and references
    A->>A: Assign stable operation IDs
    A->>A: Remove mutations when read-only
    A-->>S: OpenAPI 3.0.3 document
    S->>F: Generate and mount tools
    F-->>S: MCP server ready

A productive agent workflow

The server is deliberately opinionated about how an AI agent should approach a network-management task.

flowchart TD
    Start["Start a Netdisco task"] --> Guidance["Call get_guidance"]
    Guidance --> Known{"Know the exact tool?"}
    Known -- No --> Find["Call find_capability"]
    Known -- Yes --> Read["Use search or object GET"]
    Find --> Read
    Read --> Evidence["Inspect current state"]
    Evidence --> Change{"Is a change required?"}
    Change -- No --> Report["Return evidence"]
    Change -- Yes --> Confirm["Confirm target and scope"]
    Confirm --> Mutate["Call mutation tool"]
    Mutate --> Verify["Read current state again"]
    Verify --> Report
  1. Call get_guidance once at the start of the working session.
  2. Use find_capability when the correct tool is not obvious.
  3. Prefer search and object tools before broad reports.
  4. Inspect the current state before any mutation.
  5. Verify the resulting state instead of interpreting a timeout as failure.

Complete tool catalog

The verified Netdisco 2.103000 surface contains:

Category Tools
Agent assistance 2
Objects 31
Reports 34
Queue 5
Search 4
User 2
General 3
Total 81

Seven generated API tools use POST, PUT, or DELETE and are treated as mutations. Set NETDISCO_READ_ONLY=1 to remove those seven tools.

[!CAUTION] Netdisco exposes GET /logout, which destroys the current API key and session despite using HTTP GET. Method-based read-only filtering cannot classify that endpoint as a mutation. Treat get_logout as destructive.

Agent-assistance tools

Tool Purpose
get_guidance Returns the bundled Netdisco operating guide and can highlight a topic-specific section.
find_capability Searches the complete generated catalog by task, route, tag, HTTP method, or description.

<details> <summary><strong>Objects — 31 tools</strong></summary>

Method Tool Netdisco route Purpose
DELETE delete_device_jobs /api/v1/object/device/{ip}/jobs Delete jobs and clear the skiplist for a device, optionally filtered by fields.
GET get_device /api/v1/object/device/{ip} Return a row from the device table.
GET get_device_device_ips /api/v1/object/device/{ip}/device_ips Return device_ips rows for a device.
GET get_device_modules /api/v1/object/device/{ip}/modules Return module rows for a device.
GET get_device_neighbors /api/v1/object/device/{ip}/neighbors Return layer-2 neighbor relationships for a device.
GET get_device_nodes /api/v1/object/device/{ip}/nodes Return nodes found on a device.
GET get_device_port /api/v1/object/device/{ip}/port/{port} Return a row from the device_port table.
GET get_device_port_active_nodes /api/v1/object/device/{ip}/port/{port}/active_nodes Return active-node rows for a port.
GET get_device_port_active_nodes_with_age /api/v1/object/device/{ip}/port/{port}/active_nodes_with_age Return active-node rows with age data for a port.
GET get_device_port_agg_master /api/v1/object/device/{ip}/port/{port}/agg_master Return the aggregation-master entry for a port.
GET get_device_port_last_node /api/v1/object/device/{ip}/port/{port}/last_node Return the last-node entry for a port.
GET get_device_port_logs /api/v1/object/device/{ip}/port/{port}/logs Return log rows for a port.
GET get_device_port_neighbor /api/v1/object/device/{ip}/port/{port}/neighbor Return the neighbor entry for a port.
GET get_device_port_nodes /api/v1/object/device/{ip}/port/{port}/nodes Return node rows for a port.
GET get_device_port_nodes_with_age /api/v1/object/device/{ip}/port/{port}/nodes_with_age Return node rows with age data for a port.
GET get_device_port_port_vlans /api/v1/object/device/{ip}/port/{port}/port_vlans Return port_vlans rows for a port.
GET get_device_port_power /api/v1/object/device/{ip}/port/{port}/power Return the power entry for a port.
GET get_device_port_properties /api/v1/object/device/{ip}/port/{port}/properties Return the properties entry for a port.
GET get_device_port_ssid /api/v1/object/device/{ip}/port/{port}/ssid Return the SSID entry for a port.
GET get_device_port_vlans /api/v1/object/device/{ip}/port/{port}/vlans Return VLAN rows for a port.
GET get_device_port_wireless /api/v1/object/device/{ip}/port/{port}/wireless Return the wireless entry for a port.
GET get_device_port_vlans_cd8cf56 /api/v1/object/device/{ip}/port_vlans Return port_vlans rows for a device.
GET get_device_ports /api/v1/object/device/{ip}/ports Return port rows for a device.
GET get_device_power_modules /api/v1/object/device/{ip}/power_modules Return PoE module status and aggregated port statistics.
GET get_device_powered_ports /api/v1/object/device/{ip}/powered_ports Return powered-port rows for a device.
GET get_device_ssids /api/v1/object/device/{ip}/ssids Return SSID rows for a device.
GET get_device_vlans /api/v1/object/device/{ip}/vlans Return VLAN rows for a device.
GET get_device_wireless_ports /api/v1/object/device/{ip}/wireless_ports Return wireless-port rows for a device.
GET get_vlan_nodes /api/v1/object/vlan/{vlan}/nodes Return nodes found in a VLAN.
PUT update_device_arps /api/v1/object/device/{ip}/arps Queue a job to store ARP entries found on a device.
PUT update_device_nodes /api/v1/object/device/{ip}/nodes Queue a job to store nodes found on a device.

</details>

<details> <summary><strong>Reports — 34 tools</strong></summary>

Method Tool Netdisco route Report
GET get_report_device_deviceaddrnodns /api/v1/report/device/deviceaddrnodns IP addresses without DNS entries.
GET get_report_device_devicebylocation /api/v1/report/device/devicebylocation Inventory grouped by location.
GET get_report_device_devicednsmismatch /api/v1/report/device/devicednsmismatch Device name and DNS mismatches.
GET get_report_device_deviceinventory /api/v1/report/device/deviceinventory Device inventory.
GET get_report_device_devicemultipleaddresses /api/v1/report/device/devicemultipleaddresses Devices with multiple addresses.
GET get_report_device_devicepoestatus /api/v1/report/device/devicepoestatus Power over Ethernet status.
GET get_report_device_devicesharedaddresses /api/v1/report/device/devicesharedaddresses IP addresses found on multiple devices.
GET get_report_device_devicesmissingmodeloros /api/v1/report/device/devicesmissingmodeloros Devices missing model or operating-system data.
GET get_report_device_portutilization /api/v1/report/device/portutilization Port utilization.
GET get_report_device_recentlyaddeddevices /api/v1/report/device/recentlyaddeddevices Recently added devices.
GET get_report_ip_duplicateprivatenetworks /api/v1/report/ip/duplicateprivatenetworks Duplicate private networks.
GET get_report_ip_ipinventory /api/v1/report/ip/ipinventory IP inventory.
GET get_report_ip_subnets /api/v1/report/ip/subnets Subnet utilization.
GET get_report_node_nodemultiips /api/v1/report/node/nodemultiips Nodes with multiple active IP addresses.
GET get_report_node_nodesdiscovered /api/v1/report/node/nodesdiscovered Nodes discovered through LLDP or CDP.
GET get_report_port_duplexmismatch /api/v1/report/port/duplexmismatch Mismatched duplex settings.
GET get_report_port_halfduplex /api/v1/report/port/halfduplex Ports operating in half-duplex mode.
GET get_report_port_portadmindown /api/v1/report/port/portadmindown Administratively disabled ports.
GET get_report_port_portblocking /api/v1/report/port/portblocking Ports blocked by spanning tree.
GET get_report_port_portmultinodes /api/v1/report/port/portmultinodes Ports with multiple attached nodes.
GET get_report_port_portserrordisabled /api/v1/report/port/portserrordisabled Error-disabled ports.
GET get_report_port_portssid /api/v1/report/port/portssid Port SSID inventory.
GET get_report_port_portswithmostvlans /api/v1/report/port/portswithmostvlans Ports carrying the most VLANs.
GET get_report_port_portvlanmismatch /api/v1/report/port/portvlanmismatch Mismatched VLAN configurations.
GET get_report_vlan_devicevlancount /api/v1/report/vlan/devicevlancount VLAN count per device.
GET get_report_vlan_vlaninventory /api/v1/report/vlan/vlaninventory VLAN inventory.
GET get_report_vlan_vlanmultiplenames /api/v1/report/vlan/vlanmultiplenames VLANs with multiple names.
GET get_report_vlan_vlansneverconfigured /api/v1/report/vlan/vlansneverconfigured VLANs known but never configured.
GET get_report_vlan_vlansonlyuplinks /api/v1/report/vlan/vlansonlyuplinks VLANs found only on uplinks.
GET get_report_vlan_vlansunused /api/v1/report/vlan/vlansunused VLANs no longer in use.
GET get_report_wireless_apchanneldist /api/v1/report/wireless/apchanneldist Access-point channel distribution.
GET get_report_wireless_apclients /api/v1/report/wireless/apclients Access-point client counts.
GET get_report_wireless_apradiochannelpower /api/v1/report/wireless/apradiochannelpower Access-point radio channel and power.
GET get_report_wireless_ssidinventory /api/v1/report/wireless/ssidinventory SSID inventory.

</details>

<details> <summary><strong>Queue — 5 tools</strong></summary>

Method Tool Netdisco route Purpose
GET get_queue_backends /api/v1/queue/backends List active Netdisco backend names.
GET get_queue_jobs /api/v1/queue/jobs Return queued jobs with optional filters.
GET get_queue_status /api/v1/queue/status Return job counts grouped by status.
POST create_queue_jobs /api/v1/queue/jobs Submit jobs to the Netdisco queue.
DELETE delete_queue_jobs /api/v1/queue/jobs Delete queue jobs and skiplist entries with optional filters.

</details>

<details> <summary><strong>Search — 4 tools</strong></summary>

Method Tool Netdisco route Purpose
GET search_device /api/v1/search/device Search devices by identity, address, location, model, OS, vendor, and other attributes.
GET search_node /api/v1/search/node Search nodes, including active and archived observations.
GET search_port /api/v1/search/port Search switch ports by description and port characteristics.
GET search_vlan /api/v1/search/vlan Search VLANs.

</details>

<details> <summary><strong>User — 2 tools</strong></summary>

Method Tool Netdisco route Purpose
GET get_users /api/v1/users List users with roles and token status.
POST create_user /api/v1/user Provision a token-only service account and issue or revoke its API token.

</details>

<details> <summary><strong>General — 3 tools</strong></summary>

Method Tool Netdisco route Purpose
GET get_statistics /api/v1/statistics Return the latest Netdisco statistics row.
GET get_logout /logout Destroy the current API key and session cookie; this has a destructive side effect.
POST create_login /login Obtain a Netdisco API key.

</details>

Quick start

Requirements

  • Python 3.11 or newer
  • A reachable Netdisco instance with swagger.json
  • A permanent Netdisco API token or supported username/password credential
  • Docker and Docker Compose for container deployment

Local development

git clone https://github.com/omichelbraga/netdisco-mcp.git
cd netdisco-mcp
cp .env.example .env

Set the required values in .env:

NETDISCO_URL=https://netdisco.example.net
NETDISCO_API_TOKEN=replace-with-a-permanent-netdisco-token

Install, validate the live specification, and run:

uv sync --extra dev
uv run netdisco-mcp --check
uv run netdisco-mcp

The default transport is stdio.

Docker Compose

The supplied Compose file expects the shared external network mcp-edge and does not publish a host port.

docker network create mcp-edge
docker compose up --build -d

A reverse proxy on mcp-edge can reach the service at:

http://netdisco-mcp:8000/mcp

Configuration reference

Setting Default Purpose
NETDISCO_URL required Base URL of the Netdisco instance.
NETDISCO_SPEC_URL $NETDISCO_URL/swagger.json Override the live Swagger/OpenAPI URL.
NETDISCO_API_TOKEN unset Netdisco API credential sent to the upstream API.
NETDISCO_AUTH_SCHEME Bearer Authorization scheme; use raw for an unprefixed token.
NETDISCO_USERNAME unset Optional Netdisco Basic-auth username.
NETDISCO_PASSWORD unset Optional Netdisco Basic-auth password.
NETDISCO_TLS_VERIFY 1 Validate the Netdisco TLS certificate.
NETDISCO_TIMEOUT 30 Upstream request timeout in seconds.
NETDISCO_READ_ONLY 0 Remove POST, PUT, PATCH, and DELETE tools when set to 1.
NETDISCO_GUIDANCE_GATE 1 Require guidance before normal tool use.
NETDISCO_GUIDANCE_TTL 1800 Guidance activity window in seconds.
NETDISCO_MAX_RESPONSE_CHARS 50000 Maximum tool-response size before truncation.
NETDISCO_MCP_TRANSPORT stdio stdio or streamable-http; stdin and http are accepted aliases.
NETDISCO_MCP_HTTP_HOST 127.0.0.1 Bind address for Streamable HTTP.
NETDISCO_MCP_HTTP_PORT 8000 Listening port inside the process or container.
NETDISCO_MCP_BEARER_TOKEN unset Static bearer token required by the HTTP transport when configured.

[!WARNING] NETDISCO_API_TOKEN authenticates the server to Netdisco. NETDISCO_MCP_BEARER_TOKEN authenticates MCP clients to this server. They protect different trust boundaries and should never share the same value.

Connect MCP clients

Claude Code

claude mcp add --transport http --scope user \
  netdisco-mcp https://netdisco-mcp.example.net/mcp \
  --header "Authorization: Bearer <mcp-bearer-token>"

Verify the connection:

claude mcp get netdisco-mcp

Codex

Store the MCP bearer token in NETDISCO_MCP_BEARER_TOKEN, then add this entry to ~/.codex/config.toml:

[mcp_servers."netdisco-mcp"]
url = "https://netdisco-mcp.example.net/mcp"
bearer_token_env_var = "NETDISCO_MCP_BEARER_TOKEN"
default_tools_approval_mode = "prompt"

See the official Codex MCP configuration for additional timeout, allow-list, and approval controls.

Claude Desktop

Claude Desktop can use the included authenticated stdio proxy. The proxy keeps the remote bearer token out of the MCP protocol messages sent by Desktop and adds it only when connecting upstream.

fastmcp install claude-desktop \
  src/netdisco_mcp/desktop_proxy.py:mcp \
  --name netdisco-mcp \
  --with-editable . \
  --env NETDISCO_MCP_URL=https://netdisco-mcp.example.net/mcp \
  --env NETDISCO_MCP_BEARER_TOKEN=<mcp-bearer-token>

Restart Claude Desktop after installation.

OpenAI Responses API

import os

from openai import OpenAI

client = OpenAI()

response = client.responses.create(
    model="gpt-5.6",
    input="Call get_guidance, then summarize the Netdisco device inventory.",
    tools=[
        {
            "type": "mcp",
            "server_label": "netdisco",
            "server_url": "https://netdisco-mcp.example.net/mcp",
            "authorization": os.environ["NETDISCO_MCP_BEARER_TOKEN"],
            "require_approval": "always",
        }
    ],
)

print(response.output_text)

The authorization field follows the official remote MCP tool contract. Keeping require_approval set to always is appropriate for this server because its live catalog can include mutation tools.

Generic MCP client

{
  "mcpServers": {
    "netdisco-mcp": {
      "type": "http",
      "url": "https://netdisco-mcp.example.net/mcp",
      "headers": {
        "Authorization": "Bearer <mcp-bearer-token>"
      }
    }
  }
}

Security model

flowchart LR
    Client["Authenticated MCP client"]
    Edge["TLS reverse proxy"]
    MCP["Netdisco MCP bearer verifier"]
    Credential["Internal Netdisco credential"]
    Netdisco["Netdisco authorization"]

    Client -- "MCP bearer token" --> Edge
    Edge -- "preserved Authorization header" --> MCP
    MCP -- "approved tool call" --> Credential
    Credential -- "separate API token" --> Netdisco

Security controls provided by the project:

  • Constant-time comparison for the configured MCP bearer token.
  • Separate MCP-client and Netdisco-upstream credentials.
  • Optional method-based read-only tool filtering.
  • Guidance middleware before operational tool use.
  • Response-size limiting to protect model context.
  • TLS verification for Netdisco by default.
  • No host port in the supplied Compose file.
  • Read-only container filesystem and no-new-privileges.

Recommended production controls:

  • Terminate trusted TLS at the reverse proxy.
  • Store both credentials in a secret manager or Portainer secret environment.
  • Rotate credentials on a defined schedule and after accidental disclosure.
  • Restrict the Netdisco credential to the minimum required role.
  • Keep approval prompts enabled for mutation tools.
  • Review reverse-proxy access logs and Netdisco job history.
  • Use NETDISCO_READ_ONLY=1 for discovery-only deployments.

How tool generation works

Netdisco 2.103000 publishes Swagger 2.0 while FastMCP consumes OpenAPI 3. The adapter performs the following transformations without removing supported operations:

  1. Rewrites Swagger references into OpenAPI components references.
  2. Converts body and form parameters into OpenAPI request bodies.
  3. Moves parameter type information into schemas.
  4. Repairs Netdisco property-level required flags.
  5. Normalizes boolean, integer, and array defaults.
  6. Converts response schemas into media-type content entries.
  7. Assigns deterministic, human-readable operation IDs.
  8. Adds the original HTTP method and route to every tool description.
  9. Removes write methods when read-only mode is enabled.

If two routes would receive the same friendly name, a deterministic seven- character digest is appended. This explains names such as get_device_port_vlans_cd8cf56 and keeps the full API surface collision-free.

Repository layout

netdisco-mcp/
├── src/netdisco_mcp/
│   ├── __main__.py          # CLI and transport startup
│   ├── auth.py              # MCP bearer-token verification
│   ├── config.py            # Environment-driven settings
│   ├── desktop_proxy.py     # Authenticated Claude Desktop proxy
│   ├── guidance.py          # Guidance loading and enforcement
│   ├── server.py            # FastMCP assembly and tool mounting
│   ├── spec.py              # Swagger normalization and tool catalog
│   └── data/GUIDANCE.md     # Operating instructions for AI agents
├── tests/                   # Configuration, auth, and spec tests
├── compose.yaml             # Internal-network container deployment
├── Dockerfile
└── pyproject.toml

Development and testing

Run the test suite:

uv run pytest

Validate the connected live API without starting a transport:

NETDISCO_URL=https://netdisco.example.net \
NETDISCO_API_TOKEN=<netdisco-api-token> \
uv run netdisco-mcp --check

The check reports API version coverage, read/write operation counts, total MCP tools, and tags. Tests cover transport aliases, bearer verification, Swagger- to-OpenAPI conversion, stable names, request bodies, schema repair, read-only filtering, and capability discovery.

Contributing

  1. Fork the repository and create a focused branch.
  2. Add tests for behavioral changes.
  3. Run the full test suite against a representative Swagger fixture.
  4. Run netdisco-mcp --check against an authorized Netdisco instance.
  5. Open a pull request describing the user-visible behavior and verification.

Please do not commit Netdisco credentials, MCP bearer tokens, internal URLs, or captured infrastructure data.

License

Released under the MIT License.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选