Skip to main content

Agentic Model Context Protocol server for NetBox — read-only, tool-rich, built for LLM reasoning workflows

Project description

NetBox Agent MCP

PyPI Docs CI Python License: MIT pre-commit Ruff

A read-only Model Context Protocol server for NetBox, designed for agentic LLM workflows.

The server is built around four patterns agents need most:

  • Deep relational queries via GraphQL selection paths (site.region.name)
  • Pre-computed follow-up filters in search and list responses (no hand-parsing IDs)
  • Live schema introspection so agents don't guess at field names
  • Hard-capped auto-pagination — no "partial-result hallucinations"

Requirements

  • Python 3.11+, < 3.15
  • uv (recommended) or pipx
  • A NetBox instance (4.x recommended) with a read-only API token

Install

Two end-user options. Pick one.

Option A — uvx (zero install, always latest). Nothing to install; your MCP client invokes uvx netbox-agent-mcp, which fetches the latest published wheel into uv's cache on first use and re-runs from cache afterwards. Best for casual use.

Option B — persistent install.

uv tool install netbox-agent-mcp         # preferred
# or
pipx install netbox-agent-mcp            # if you don't have uv

Either puts a netbox-agent-mcp executable on your PATH. Upgrade with uv tool upgrade netbox-agent-mcp / pipx upgrade netbox-agent-mcp.

See Development install below if you want to hack on the code.

Run

The server reads configuration from environment variables or CLI flags (flags win). Minimum: NETBOX_URL + NETBOX_TOKEN.

stdio transport (default — used by MCP clients like Claude Code):

NETBOX_URL=https://netbox.example.com/ \
NETBOX_TOKEN=<your-token> \
netbox-agent-mcp

HTTP transport:

netbox-agent-mcp --transport http --host 127.0.0.1 --port 8000

See netbox-agent-mcp --help for the full flag list.

Claude Code integration

Register the server with uvx (no prior install needed):

claude mcp add --transport stdio netbox \
  --env NETBOX_URL=https://netbox.example.com/ \
  --env NETBOX_TOKEN=<your-token> \
  -- uvx netbox-agent-mcp

If you used uv tool install / pipx install instead, drop uvx — the binary is already on PATH:

claude mcp add --transport stdio netbox \
  --env NETBOX_URL=... --env NETBOX_TOKEN=... \
  -- netbox-agent-mcp

After registering, start a Claude Code session — the netbox_* tools will be available. See also docs/SYSTEM_PROMPT.md for a recommended agent system prompt that unlocks the server's follow-up hints.

LM Studio integration

LM Studio supports MCP servers via mcp.json. Open Program → Install → Edit mcp.json, or edit the file directly:

  • macOS / Linux: ~/.lmstudio/mcp.json
  • Windows: %USERPROFILE%\.lmstudio\mcp.json

Merge this block into your mcpServers map:

{
  "mcpServers": {
    "netbox": {
      "command": "uvx",
      "args": ["netbox-agent-mcp"],
      "env": {
        "NETBOX_URL": "https://netbox.example.com/",
        "NETBOX_TOKEN": "<your-token>"
      }
    }
  }
}

Save and either restart LM Studio or toggle the server off/on in the Program panel. Tool calling requires a tool-capable model — look for the tool icon in LM Studio's model list.

Troubleshooting LM Studio:

  • "Disconnected": check the MCP log (Program panel → log icon). Most common cause: uvx (or netbox-agent-mcp) not on the PATH LM Studio inherits, or missing NETBOX_URL / NETBOX_TOKEN.
  • uvx / netbox-agent-mcp not found: LM Studio does not inherit your shell PATH. Use the absolute path to the binary — e.g. /opt/homebrew/bin/uvx on macOS, /usr/local/bin/uvx on Linux — as the command value.
  • Tools never get called: confirm the model supports tool use, then ask explicitly ("Use netbox_search to find…").

Development install

Contributors, or anyone who wants to run integration tests against a local NetBox:

git clone https://github.com/magicboxlab-ai/netbox-agent-mcp.git
cd netbox-agent-mcp
uv sync
uv run pre-commit install

Invoke the checked-out copy from an MCP client by swapping uvx netbox-agent-mcp for uv --directory /absolute/path/to/netbox-agent-mcp run netbox-agent-mcp. See CONTRIBUTING.md and docs/DEVELOPMENT.md for the full development workflow.

Tools

Ten read-only tools are exposed.

netbox_query(graphql, variables=None)

Raw GraphQL escape hatch. Use when you need fragments, deep hydration, or cross-entity joins not expressible via netbox_get.

netbox_query("""
  query {
    device_list(filters: {site_id: {in_list: [8, 12]}}, limit: 5) {
      id name site { name region { name } } primary_ip4 { address }
    }
  }
""")

netbox_get(object_type, filters, select=None, limit=10, offset=0)

High-level list/filter. Compiles to GraphQL internally.

  • filters: REST-style grammar (site_id__in, name__ic, vid__gte, etc.)
  • select: dotted paths for arbitrary-depth field selection (["name", "site.name", "site.region.name"])
  • Returns {results, total_count, has_more, suggested_next}suggested_next contains pre-built filter blocks for common follow-ups.

netbox_get_all(object_type, filters, select=None, max_records=10000)

Paginated variant of netbox_get. Loops internally; fails loud if total_count > max_records. Never silently truncates. max_records may be raised up to 100,000.

netbox_search(query, object_types=None, limit=25)

Text search across NetBox objects via REST ?q=. Returns matches, match_counts (per-type total/returned/truncated so agents can detect silent caps), and suggested_filters — ready-to-use filter dicts the agent can paste into netbox_get without re-parsing.

{
  "matches": {"dcim.site": [{"id": 8, "name": "london-dc1"}]},
  "match_counts": {
    "dcim.site": {"total": 1, "returned": 1, "truncated": false}
  },
  "suggested_filters": {
    "devices_at_these_sites": {
      "object_type": "dcim.device",
      "filters": {"site_id__in": [8]}
    }
  }
}

suggested_filters is a base filter — merge your other constraints (e.g. role_id=3) before calling netbox_get.

netbox_inspect_type(object_type)

Live GraphQL schema introspection. Returns the type's full field list with types and relations. Call this before constructing filters or select paths against unfamiliar types.

netbox_trace_path(endpoint_type, endpoint_id)

Cable path tracing. endpoint_type is one of interfaces, console-ports, console-server-ports, power-ports, power-outlets, power-feeds.

netbox_get_available(resource_type, parent_id, count=1)

Free-capacity queries. resource_type is one of:

  • prefix.available-ips
  • prefix.available-prefixes
  • ip-range.available-ips
  • vlan-group.available-vlans
  • asn-range.available-asns

netbox_aggregate_by_device(relation, top_n=10, filters=None, max_scan=10000)

Server-side "top N devices by X" aggregation. Scans the junction/direct endpoint with a cheap projection, counts in-process, returns ONLY the top N — never ships 1000s of raw rows through the MCP wire.

Supported relations:

  • tunnel_terminations — top devices by VPN tunnel count
  • cable_terminations — top devices by cable count
  • interfaces — top devices by interface count
  • inventory_items — top devices by inventory item count
  • ip_addresses — top devices by assigned IP count

Scope via filters (standard NetBox REST filter grammar): {"role_id": 3} → top firewalls only, {"site_id__in": [8, 17]} → scope by site. Safety-capped at max_scan=10000 rows by default.

netbox_device_profile(device_id, include=None, max_per_category=100)

Composite one-shot view of a device: the full device record plus interfaces, IP addresses, tunnel terminations, and inventory items (plus optional cable terminations, console/power ports, module bays). Related items are returned in ?brief=1 shape. Hints (auto-computed): interface type breakdown, and the "N tunnel-named interfaces vs M structural tunnel terminations" gap that commonly shows up after firewall imports.

Pass max_per_category=0 for summary mode — counts and hints only, no item bodies.

netbox_find_ip_references(ip)

Fan-out lookup for every place an IP is referenced. Checks the structured IPAM record (ipam.ipaddress with assigned_object) and does case-insensitive description searches across vpn.tunnel, dcim.interface, and ipam.prefix.

Use when a straight netbox_get("ipam.ipaddress", ...) doesn't find a structural assignment — common for tunnel peer IPs that live only in free-text descriptions (e.g. Palo Alto imports).

Returns {query, ipam_record, text_references, summary} with a hint in summary that tells you which sub-result to follow.

Environment variables

Variable Default Purpose
NETBOX_URL (required) Base URL of the NetBox instance (e.g. https://netbox.example.com/)
NETBOX_TOKEN (required) API token. Read-only strongly recommended.
NETBOX_VERIFY_SSL true Verify TLS certificates
LOG_LEVEL INFO DEBUG / INFO / WARNING / ERROR / CRITICAL
TRANSPORT stdio stdio or http
HOST 127.0.0.1 HTTP bind address (when TRANSPORT=http)
PORT 8000 HTTP port (when TRANSPORT=http)
MAX_RECORDS_CEILING 100000 Absolute ceiling for netbox_get_all

Tokens starting with nbt_ use Bearer auth; other token formats use Token auth. Detection is automatic.

Supported object types

Ships with ~48 curated types across dcim, ipam, circuits, virtualization, tenancy, vpn, wireless, extras, and core. See schema/object_types.py for the full registry. Plugin types are out of scope.

Read-only by design

No create/update/delete tools are exposed. Writes are deliberately excluded to keep the attack surface minimal. For writes, use NetBox's web UI or REST API directly.

Troubleshooting

"Configuration error: … missing NETBOX_URL / NETBOX_TOKEN" Set both environment variables before running the server.

"UnknownObjectType: 'dcim.wizard'" The type is not in the registry. Call netbox_inspect_type after listing valid types in the error message.

"CapExceeded: Query would return 45230 records, exceeds max_records=10000" Either narrow your filters (e.g. add site_id or status) or pass max_records=50000 on netbox_get_all. The absolute ceiling is 100,000.

"SchemaIntrospectionError: GraphQL error: Cannot query field 'X' on type 'Y'" The field doesn't exist on that type, or NetBox's schema has changed. Call netbox_inspect_type('Y') to see the current field list.

Connection refused / TLS errors Verify NETBOX_URL is reachable and includes the scheme (https://). For self-signed certs in dev, set NETBOX_VERIFY_SSL=false (not recommended for production).

Further reading

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

netbox_agent_mcp-0.1.3.tar.gz (184.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

netbox_agent_mcp-0.1.3-py3-none-any.whl (49.5 kB view details)

Uploaded Python 3

File details

Details for the file netbox_agent_mcp-0.1.3.tar.gz.

File metadata

  • Download URL: netbox_agent_mcp-0.1.3.tar.gz
  • Upload date:
  • Size: 184.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for netbox_agent_mcp-0.1.3.tar.gz
Algorithm Hash digest
SHA256 8428900414bb5936f25f1386568d41a700feed119732c542b8c09814a00fbe41
MD5 8a5d25b216f6b08a1219eddf9277f052
BLAKE2b-256 edb0ead718fba9760a5b81fb2cf63f84d9aca5b9d93af595723efedbc41d4bb0

See more details on using hashes here.

Provenance

The following attestation bundles were made for netbox_agent_mcp-0.1.3.tar.gz:

Publisher: publish.yml on magicboxlab-ai/netbox-agent-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file netbox_agent_mcp-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for netbox_agent_mcp-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f3b5aea9202b968bdfc53365d1cb74b7799ded0d9a5787130fc9419b88994f19
MD5 186eb4c02055d267545af0c05cce7320
BLAKE2b-256 8432a589c303a7c4dcd6afe1837ef4668f7924e9c963580d48b498f8e13b573c

See more details on using hashes here.

Provenance

The following attestation bundles were made for netbox_agent_mcp-0.1.3-py3-none-any.whl:

Publisher: publish.yml on magicboxlab-ai/netbox-agent-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page