Skip to main content
Glama

nautobot-mcp

CI Python License

一个用于 Nautobot 的 MCP 服务器,专为 API 过大而无法枚举的实例构建:Nautobot 3.2 提供了 477 个路径上的 1,673 个 REST 操作,而且每个已安装的应用都会增加更多。此服务器暴露 15 个由模式驱动的工具,而不是每个端点一个工具,因此整个 API——包括核心和插件——都可以访问,而不会淹没代理的上下文。

它的工作原理

构建步骤,而非运行时解析。 Nautobot 的 OpenAPI 文档为 18 MB,其 GraphQL introspection 另有 10 MB。一个构建脚本将它们融合成一个约 1.1 MB 的 SQLite 索引,并带有一个 FTS5 搜索表。服务器以只读方式打开它,并在微秒内回答查询;启动不依赖于 API 的大小。

从 GraphQL 恢复外键。 仅靠 OpenAPI 无法描述 Nautobot 的关系——每个相关字段都序列化为一个相同的透明对象:

// dcim.device: device_type, role, status and location are indistinguishable here
"device_type": { "id": {...}, "object_type": {"pattern": "^[a-z]+\\.[a-z]+$"}, "url": {...} }

GraphQL 的类型系统直接命名了目标(device_type → DeviceTypeType),因此两者在 OpenAPI 组件名称上连接,以恢复 441 条类型化的外键边。正是这个图使得依赖规划成为可能。

压缩过滤器。 dcim.device 暴露了 250 个过滤器参数,这些参数实际上是约 74 个基础字段乘以一系列查找后缀(__ic、__n、__isnull、__gte、……)。索引存储基础字段及其后缀集,并一次性描述该词汇表。

Related MCP server: mcp-graphql

安装

uv venv && uv pip install -e ".[dev]"
cp .env.example .env        # then set NAUTOBOT_URL and NAUTOBOT_TOKEN
cp .mcp.json.example .mcp.json   # optional: for stdio-based clients
python -m nautobot_mcp.schema.build --probe

或者完全跳过检出,在容器中运行——参见 Docker。

构建步骤会获取模式并写入 var/index.sqlite。在安装或升级 Nautobot 应用后重新运行它——或者调用 nautobot_refresh_schema 工具。

配置

变量

默认值

用途

NAUTOBOT_URL

—

基础 URL,例如 http://nautobot.example.com:8080

NAUTOBOT_TOKEN

—

API 令牌

NAUTOBOT_ALLOW_WRITE

false

创建/更新/删除的主开关

NAUTOBOT_VERIFY_SSL

true

TLS 验证

NAUTOBOT_TIMEOUT

30

每个请求的超时时间(秒)

NAUTOBOT_CACHE_DIR

./var

模式源和索引所在的位置

NAUTOBOT_MAX_PAGE

1000

fetch_all 分页的上限

仅限容器的旋钮,由入口点而非服务器读取:

变量

默认值

用途

MCP_TRANSPORT

streamable-http

容器提供的传输方式(对于客户端生成的容器为 stdio)

MCP_HOST

0.0.0.0

HTTP 传输的绑定地址

MCP_PORT

8000

HTTP 传输的绑定端口

NAUTOBOT_AUTO_INDEX

true

在启动时构建缺失的模式索引,而不是拒绝运行

向客户端注册

{
  "mcpServers": {
    "nautobot": {
      "command": "/path/to/nautobot-mcp/.venv/bin/python",
      "args": ["-m", "nautobot_mcp"],
      "env": {
        "NAUTOBOT_URL": "http://nautobot.example.com:8080",
        "NAUTOBOT_TOKEN": "...",
        "NAUTOBOT_CACHE_DIR": "/path/to/nautobot-mcp/var"
      }
    }
  }
}

HTTP 传输也可用:python -m nautobot_mcp --transport streamable-http --port 8000。

Docker

cp .env.example .env        # then set NAUTOBOT_URL and NAUTOBOT_TOKEN
docker compose up -d        # or: make docker-up

首次启动会针对你的实例构建模式索引,并将其存储在 index 卷上;后续启动会复用该索引。服务器监听 127.0.0.1:8000/mcp。

索引并未烘焙到镜像中,也无法烘焙:它是由特定 Nautobot 实例的模式(包括该实例已安装的任何应用)融合而成的。在安装或升级应用后重新构建它——make docker-index,或 nautobot_refresh_schema 工具,该工具会写入同一卷。

make docker-index                 # rebuild the index in place
make docker-logs                  # follow the server log
make docker-down                  # stop; VOLUMES=1 also drops the index
docker compose run --rm server index --offline   # rebuild from cached sources only

向客户端注册容器

通过 HTTP,将客户端指向已发布的端口:

{
  "mcpServers": {
    "nautobot": { "url": "http://127.0.0.1:8000/mcp" }
  }
}

或者让客户端通过 stdio 为每个会话生成一个容器,复用相同的索引卷:

{
  "mcpServers": {
    "nautobot": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "--env-file", "/path/to/nautobot-mcp/.env",
        "-e", "MCP_TRANSPORT=stdio",
        "-v", "nautobot-mcp_index:/data",
        "nautobot-mcp:latest"
      ]
    }
  }
}

镜像名称之后传递的任何内容都会直接传递给 python -m nautobot_mcp,因此 docker run ... nautobot-mcp:latest --transport sse --host 0.0.0.0 --port 8000 也可以。

compose 文件的假设

  • 端口仅在回环上发布。 安全 部分完全适用:这是一个未认证的代理,持有具有你权限的令牌,因此从其他主机访问它意味着在其前面放置认证,而不是扩大端口映射。

  • 写入保持关闭,除非 .env 中有 NAUTOBOT_ALLOW_WRITE=true。

  • 容器默认已加固——非 root(uid 1000)、只读根文件系统、所有能力被丢弃、no-new-privileges。唯一可写的路径是 /data 卷,索引及其缓存的源就位于那里。

  • 健康检查是 TCP 连接,而不是 MCP 请求:对 /mcp 的未会话请求会使会话管理器分配一个无人回收的传输,因此每 30 秒探测协议会导致每次探测泄漏一个会话。

  • .env 由 compose 原样读取。 将注释保留在自己的行上;尾随的 # comment 不会可靠地从值中剥离。

工具

工具

用途

nautobot_search_schema

按名称、描述或字段名查找模型

nautobot_describe_model

字段、必填字段、外键目标、过滤器、操作

nautobot_list_apps

应用命名空间(核心和插件)、版本、索引状态

nautobot_plan_create

创建对象的有序先决条件

nautobot_resolve

人类可读名称 → UUID,限定于引用模型

nautobot_list / nautobot_get

读取任何模型,精简或投影

nautobot_create / nautobot_update / nautobot_delete

受控写入

nautobot_graphql

任意 GraphQL 查询

nautobot_graphql_schema

内省,一次一个类型

nautobot_model_actions

非 CRUD 端点(trace、napalm、notes、……)

nautobot_call

任何 REST 端点——插件、批量操作、自定义操作

nautobot_refresh_schema

重新获取模式并重建索引

模型引用是宽容的:dcim.device、device、devices、Device、/dcim/devices/ 和 DeviceType 都能解析,并且拼写错误会得到建议(dvice → “你的意思是:dcim.device?”)。

依赖规划

在空实例上创建 Device 意味着首先创建其他四个对象。nautobot_plan_create("dcim.device") 遍历外键图,检查实时实例中已存在的内容,并按顺序返回它们:

dcim.manufacturer → dcim.devicetype → dcim.locationtype → dcim.location → extras.role → dcim.device

它还处理 Nautobot 的 内容类型作用域。Role、Status 和 Tag 只能分配给其 content_types 中列出的模型。全局计数是错误的问题——一个实例可以包含 20 个 Role,而 没有 一个适用于 Device:

{
  "model": "extras.role",
  "action": "create",                      // not "use_existing", despite 20 existing
  "content_type_scoped": true,
  "by_referrer": { "dcim.device": { "valid_count": 0 } },
  "note": "No extras.role is assignable to dcim.device yet. Create one with
           content_types including ['dcim.device'] ..."
}

哪些模型以这种方式作用域是发现的,而不是硬编码的:content_types 在 LocationType 上表示“什么可以在这里”,在 Role 上表示“谁可以引用我”。规划器尝试作用域查询,并将 400 视为作用域不适用的证据——因此插件模型无需额外代码即可正确运行。

写入

在 NAUTOBOT_ALLOW_WRITE=true 之前,写入是关闭的。即便如此,变更也是两步的:第一次调用返回预览和 confirm_token,然后使用该令牌重复调用以应用它。令牌是从负载派生的,因此为一个请求体签发的令牌不能针对另一个请求体重放。nautobot_update 预览字段级差异;nautobot_delete 预览对象及其引用的所有内容。

安全

此服务器是 Nautobot 的未认证特权代理。 它持有一个 API 令牌,并且不执行自身的认证:任何能够访问它的客户端都可以使用该令牌的全部权限,而无需拥有该令牌。

默认设置是刻意安全的——--host 绑定 127.0.0.1,NAUTOBOT_ALLOW_WRITE 为 false。风险配置是将非回环绑定与启用写入相结合,这会将未认证的创建/更新/删除授予任何能够路由到该端口的内容,从而影响你的真实来源。

确认令牌流程是意外防护,而不是访问控制——任何客户端都可以从预览响应中读取令牌并立即确认。

如果服务器必须被其他主机访问,请在其前面放置认证(带有 mTLS 的反向代理、支持 OAuth 的网关或 SSH 隧道),并为其提供一个仅包含代理所需权限的 Nautobot 令牌。参见 SECURITY.md。

响应性

  • 一个池化的 HTTP/2 客户端在工具之间共享;规划器并发地扇出存在性检查。

  • 响应在到达代理之前被精简。Nautobot 不支持稀疏字段集(?fields= 被拒绝为未知过滤器),因此 url、natural_slug、notes_url、时间戳和空的自定义字段块在客户端被丢弃,嵌套的相关对象被简化为身份。传递 fields=[...] 以投影,或 full=true 以选择退出。

扩展

每个工具集都是一个模块,暴露 register(server, ctx),列在 tools/__init__.py::TOOLSETS 中。注册被包装,以便每个工具返回结构化错误而不是抛出异常——未捕获的异常会作为不透明的“执行工具 X 时出错”到达代理。

插件端点不需要代码:它们出现在 /api/swagger.json 中,因此重建索引使它们对所有工具可用。

测试

pytest

82 个测试针对从实时模式中提取的夹具运行,HTTP 通过 respx 模拟。它们固定了构建过程中发现的陷阱:将 virtualization.vminterface 映射到 DCIM 的 InterfaceType 的 slug 冲突、静默产生不可用计划的 content_types 作用域,以及将 DynamicGroupMembership.group 解析为 Django 的 auth.Group 而不是 extras.DynamicGroup 的外键启发式。

代理配置

AGENT.md 包含一个即用型系统提示和注册表描述,用于驱动此服务器的代理,包括写入协议和最常见的导致创建失败的内容类型作用域规则。

贡献

欢迎提交问题和拉取请求。pytest 必须通过,ruff check / ruff format --check 必须干净;CI 在 Python 3.11-3.13 上强制执行两者。该套件不需要 Nautobot 实例,也不需要网络——它针对 tests/fixtures 中的模式夹具运行,HTTP 由 respx 模拟。

许可证

Apache 2.0 - 参见 LICENSE。

布局

src/nautobot_mcp/
  schema/build.py     fuses OpenAPI + GraphQL + content types into the index
  schema/index.py     read-only query layer (lookup, FTS search, graph)
  client.py           pooled async HTTP, slimming, error normalisation
  depgraph.py         creation planning and reference resolution
  safety.py           write gate, confirm tokens, diffs
  tools/              one module per toolset, registered through a guard
  server.py           MCP server assembly

Related MCP Connectors

Related MCP Servers