Skip to main content
Glama

claude-project — netmiko MCP 서버 + 스킬

AI 에이전트가 SSH를 통해 라우터, 스위치, 방화벽에 읽기 전용으로 접근할 수 있도록 하는 바로 복사해서 사용할 수 있는 프로젝트입니다. Model Context Protocol을 통해 동작합니다.

이 프로젝트는 두 가지 구성 요소와 그 연결을 제공합니다:

  • mcps/mcp_server_netmiko.py — 독립형 MCP 서버. 9개의 도구, 모든 명령은 운영자가 정의한 허용/거부 목록에 대해 검증되며, 출력은 ntc-templates로 JSON으로 파싱되고, 모든 시도에 대해 실패 시 폐쇄 감사 추적이 기록됩니다.

  • .claude/skills/netmiko/SKILL.md — 에이전트가 언제 이러한 도구를 사용해야 하는지, 각 플랫폼의 CLI 방언이 어떻게 생겼는지, 거부 메시지를 읽는 방법을 가르치는 스킬입니다.

여기서는 장치에 아무것도 쓰지 않습니다. 허용 목록은 기본 거부(default-deny)입니다. 빈 목록은 아무것도 허용하지 않으며, 거부 측이 항상 허용 측보다 우선합니다.

작성자 및 출처

이 프로젝트는 Ed Scrimagliaedgardo.scrimaglia@gmail.com, Octupus가 작성했습니다. 서버, 스킬, 구성 모델 및 문서는 그의 작업이며, Niko 에이전트를 위해 작성되어 독립형 프로젝트로 패키징되었습니다.

이 프로젝트는 포크에서 시작되었으며, 그 기원을 숨기지 않고 인정합니다: 출발점은 Kirk Byers의 작업이었고, 프로젝트는 그 이상으로 성장했습니다. 현재 여기에 있는 것 — 진실 공급원 기반 인벤토리, 자격 증명 해결, 세 가지 배포 방식, 출력 페이지 매김, 감사 추적, 스킬 및 이 문서 — 는 업스트림에서 온 것이 아닙니다.

Kirk Byers의 두 업스트림 프로젝트:

  • Netmiko — 실제로 장치와 통신하는 다중 벤더 SSH 라이브러리.

  • netmiko_mcp — 이 서버가 포크된 MCP 서버. 그 중 한 부분은 거의 원래 그대로 유지됩니다: 보안 핵심(명령 검증, glob 처리, 허용/거부 비대칭)은 의도적으로 충실하게 포팅되어 업스트림 패치를 계속 diff할 수 있습니다. 이는 엔지니어링 결정이었으며, 나머지 작업에 대한 제한이 아닙니다.

Niko 소개

이 서버는 Niko, Neural Intelligence Knowledge Orchestrator AI 에이전트를 위해 작성되었습니다. Ed Scrimaglia가 Octupus에서 구축했습니다. Niko는 일련의 MCP 서버(진실 공급원 서버, 이 서버, Jira, 이메일 전송, 파일 생성 등)를 앞에 두고 있어, 운영자가 평문으로 질문하면 부동산에서 답을 얻을 수 있습니다: SoT는 있어야 하는 것, 장치 자체는 실제로 있는 것.

Niko 내부에서 동일한 파일은 약간 다르게 실행됩니다. 이는 코드의 몇 가지 사항을 설명하기 때문에 알아두는 것이 좋습니다:

  • 서버는 루프백에서 HTTP로 실행되며, 각각 하나의 포트를 사용하고 mcps/mcp_config.jsonurl / transport / local / env로 선언됩니다 — 아래 설명된 동일한 두 축 구성이 Niko 자체 형식으로 표현됩니다.

  • 설치를 위해 파일을 복사하는 대신 앱을 통해 진행됩니다: 업로드가 검증되고, 종속성이 코드 자체에서 해결되며, 설치 실패 시 서버의 절반을 남기지 않고 롤백됩니다.

이러한 통합 각각은 대체 기능이 있는 선택적 임포트이므로 niko를 설치할 필요가 없습니다. 네 가지가 있으며, 각각 임포트 실패 시 어떻게 저하되는지는 다음과 같습니다:

Import

라인

독립형 대체

niko.srvclass_logging.MCPLogging

60

NIKO_AVAILABLE = False; 서버가 자체 logging을 구성함

niko.niko_paths.NikoPaths

68

None; 경로는 NETMIKO_MCP_* 변수에서 가져오며, 이것이 이 프로젝트가 명시적으로 설정하는 이유임

niko.srvclass_logging.SyncedConcurrentTimedRotatingFileHandler

436

FailClosedFileHandler — 여전히 실패 시 폐쇄되지만, 다중 프로세스에 안전하지는 않음

niko.srvclass_list_budget.apply_budget_to_payload

2709

페이로드를 변경하지 않고 반환하는 no-op

Niko 외부에서 중요한 것은 손실되지 않습니다: 동시 핸들러는 여기서 발생하지 않는 여러 프로세스-하나의 파일 문제를 해결하며, 목록 예산은 자체 컨텍스트 회계가 있는 에이전트를 위해 긴 페이로드를 자릅니다. 하나의 파일, 두 개의 집, 포크 없음.

Fedele은 Niko의 진실 공급원이며, 이것이 SoT 변수가 NetBox 인스턴스를 가리키더라도 FEDELE_ 접두사를 갖는 이유입니다.

라이선스

이 프로젝트 자체 코드는 MIT입니다 — LICENSE 참조.

파생 작업이므로 두 가지 라이선스가 적용되며 두 파일 모두 함께 제공됩니다:

라이선스

파일

이 프로젝트의 코드, 문서 및 스킬

MIT

LICENSE

ktbyers/netmiko_mcp에서 포팅된 부분

Apache-2.0

LICENSE-APACHE-2.0

NOTICE는 Apache-2.0 §4(b)에서 요구하는 저작자 표시 및 수정 사항 설명을 포함합니다. Netmiko는 일반적인 MIT 종속성입니다: 임포트되었으며, 벤더링되지 않았고, 재배포할 것이 없습니다.


레이아웃

claude-project/
├── .mcp.json                     # declares the server (project scope)
├── .env.example                  # → copy to .env with the SSH credentials
├── .claude/skills/netmiko/
│   └── SKILL.md                  # one directory per skill, file named SKILL.md
├── mcps/
│   └── mcp_server_netmiko.py     # NOT at the root: the server reads ../.env
├── config/netmiko/
│   ├── commands.yml              # allow/deny list — without it, a 16-command fallback applies
│   └── inventory.yml             # inventory in netmiko_tools format
├── logs/                         # netmiko-mcp.log + netmiko-audit.jsonl
├── mcpr/netmiko/                 # created on demand (0700): large outputs
├── LICENSE  LICENSE-APACHE-2.0  NOTICE
└── pyproject.toml

두 가지 규칙은 협상 불가입니다:

  1. 스킬은 .claude/skills/<name>/SKILL.md에 위치합니다. Claude Code는 skills/netmiko.md를 읽지 않습니다: 디렉토리와 정확한 파일 이름이 필요합니다.

  2. 서버는 루트가 아닌 mcps/에 위치합니다. PARENT_DIR.py(mcp_server_netmiko.py:62)를 포함하는 디렉토리의 상위 디렉토리이며, .env가 여기서 가져옵니다. 서버가 루트에 있으면 .env는 프로젝트 한 단계 위에서 조회됩니다.

실행하기

uv venv --python 3.12
uv pip install -r <(uv pip compile pyproject.toml)   # or: uv sync
cp .env.example .env && $EDITOR .env                 # SSH credentials
# .mcp.json needs no editing: its paths are project-relative
claude                                               # approve the project server

세션 내부: /mcp는 9개의 도구를 나열하고, /skills는 스킬이 로드되었는지 확인합니다. 네트워크에 접촉하지 않고 첫 번째 확인:

netmiko MCP가 시행하는 명령 정책은 무엇인가요?


세 가지 방식

인벤토리가 어디에서 오는지와 자격 증명이 어디에서 오는지는 두 개의 독립적인 축입니다. 이것이 하나의 서버로 세 가지 배포를 만드는 이유이며, 서버가 그들 사이를 이동하기 위해 수정될 필요가 없는 이유입니다: 두 개의 환경 변수가 결정합니다.

인벤토리

자격 증명

필요한 것

사용 시기

A — SoT 모든 것

Fedele

Fedele

API 토큰 + Fernet 키

SoT가 권위적이며 이미 장치 자격 증명을 보유하고 있음

B — SoT 인벤토리, 로컬 자격 증명

Fedele 또는 NetBox

.env

API 토큰

SoT는 있지만 자격 증명 플러그인이 없음. 일반적인 시작점

C — 자체 포함

로컬 YAML

.env

외부 없음

실험실, 에어갭, 데모, 또는 SoT가 다운되었을 때의 저하 모드

netmiko.get_metadata는 실제로 실행 중인 방식을 보고합니다. 구성 파일에서 추측하지 마십시오:

{
  "inventory": {"backend": "fedele", "scope_filter": {"tag": "lab"}, "available": true},
  "credential_source": "env",
  "device_types_in_inventory": ["cisco_ios", "huawei_vrp", "…"]
}

A — 진실 공급원으로서의 Fedele, 자격 증명 포함

에이전트가 장치 이름으로 요청하면, 서버는 호출 시점에 SoT에 대해 주소, 플랫폼 및 자격 증명을 해결합니다. 에스테이트에 대한 어떤 것도 이 프로젝트에 저장되지 않습니다: SoT에 장치를 추가하면 다음 호출에서 파일을 편집하거나 재시작할 필요 없이 접근 가능합니다.

// .mcp.json → env
"NETMIKO_MCP_INVENTORY_TYPE": "fedele",
"NETMIKO_MCP_CREDENTIAL_SOURCE": "fedele",
"NETMIKO_MCP_FEDELE_GROUP_SOURCE": "tags",        // tags | device_roles | sites
"NETMIKO_MCP_FEDELE_DEVICE_FILTER": "tag=lab",    // the scope filter — read the warning
"NETMIKO_MCP_FEDELE_CACHE_TTL": "60"
# .env
FEDELE_URL=https://fedele.example.com
FEDELE_TOKEN=<API token>
FEDELE_CREDENTIALS_KEY=<Fernet key of the fedele_credentials plugin>

파일: 필수는 없습니다. commands.yml권장됩니다 — 없으면 내장된 대체 정책이 적용됩니다. 로컬 인벤토리는 관련되지 않으며, NETMIKO_USERNAME / NETMIKO_PASSWORD도 없습니다. credential_source=fedele인 경우 NETMIKO_SECRET무시됩니다 — enable 비밀번호도 SoT에서 가져옵니다.

자격 증명 조회 방법, 세 단계:

GET dcim/devices/?name=<name>                          → device.id
GET plugins/credentials/devicecredentials/?device=<id> → credential id
GET plugins/credentials/networkcredentials/<id>/       → username + encrypted password
                                                          decrypted locally with the Fernet key

이 방식을 선택하기 전에 알아야 할 사항:

  • Fernet 키는 전체 보안 경계입니다. 서버 메모리에서 장치 비밀번호를 해독합니다. 비밀번호 자체처럼 취급하십시오.

  • FEDELE_CREDENTIALS_KEY가 없으면 서버는 여전히 시작되지만, 모든 도구는 누락된 변수를 명명하는 동일한 Startup Error를 반환합니다. 조용히 실패하지 않고 크게 실패합니다.

  • 범위 필터를 설정하십시오. NETMIKO_MCP_FEDELE_DEVICE_FILTER가 없으면 인벤토리는 SoT가 알고 있는 전체 에스테이트이며, 이는 에이전트가 접근할 수 있는 전체 장치 집합이기도 합니다. 서버는 누락 시 경고를 기록합니다. 필터는 쿼리 구문 tag=lab&status=active를 사용합니다.

  • primary_ip가 없거나, platform이 없거나, 플랫폼이 Netmiko device_type이 아닌 장치는 인벤토리에서 제외됩니다 — SoT는 카메라, 배지 리더기, 섀시도 인벤토리합니다. 제외는 계산되어 보고되므로 에이전트가 하위 집합에 대해 "이것들이 모든 장치입니다"라고 주장하지 않습니다.

  • 회로 차단기가 있습니다: 전송 오류 또는 5xx 이후 클라이언트는 30초 동안 SoT 호출을 중단합니다. SoT가 다운된 상태에서 40개 장치에 대한 그룹 명령은 40번이 아닌 한 번 실패합니다.

B — 인벤토리는 SoT, 자격 증명은 .env

A와 동일하지만 하나의 변수가 반전됨:

"NETMIKO_MCP_CREDENTIAL_SOURCE": "env",
# .env
FEDELE_URL=https://sot.example.com
FEDELE_TOKEN=<API token>
NETMIKO_USERNAME=<service account>
NETMIKO_PASSWORD=<password>
NETMIKO_SECRET=<enable password, if any device asks for it>

동적 인벤토리(그 자체로 가치 있는 부분)를 자격 증명 플러그인과 Fernet 키 없이 얻을 수 있습니다. 모든 장치에 대해 하나의 서비스 계정이 사용됩니다.

NetBox 또는 NetBox 형태의 SoT

인벤토리 백엔드는 NetBox REST 방언을 사용하므로 NetBox 자체가 이 방식에서 수정 없이 작동합니다:

백엔드가 호출하는 것

읽는 것

dcim/devices/

범위 필터로 필터링되고 페이지 매김된 장치 목록

extras/tags/, dcim/device-roles/, dcim/sites/

FEDELE_GROUP_SOURCE가 선택한 것이 장치 그룹이 됨

device.primary_ip.address

SSH 호스트, 마스크 제거

device.platform.name

Netmiko device_type, CLASS_MAPPER에 대해 검증됨

FEDELE_URL을 NetBox 인스턴스로 지정하고(생략하면 /api가 추가됨) FEDELE_TOKEN을 NetBox API 토큰으로 지정합니다. 클라이언트는 NetBox가 기대하는 Authorization: Token … 헤더로 인증합니다. 변수는 FEDELE_ 접두사를 유지합니다. 이는 제품 요구 사항이 아닌 명명 유산입니다.

NetBox가 기본적으로 충족하지 않는 한 가지 요구 사항: platform.name은 정확히 Netmiko device_type 이어야 합니다 — cisco_ios, arista_eos, huawei_vrp, juniper_junos. "Cisco IOS 15.2"라는 플랫폼은 device_type이 아니므로, 해당 플랫폼을 가진 모든 장치는 인벤토리에서 제외됩니다. NetBox에서 플랫폼 이름을 바꾸거나 보고되는 제외를 수용하십시오.

자격 증명은 NetBox가 다루지 않는 부분입니다: plugins/credentials/… 엔드포인트는 Fedele의 플러그인에 속합니다. 일반 NetBox를 사용하면 방식 A를 사용할 수 없습니다. B를 유지하십시오.

C — 자체 포함: SoT 없음

모든 것이 이 프로젝트에 있습니다. 외부 서비스에 전혀 접촉하지 않습니다.

// .mcp.json → env
"NETMIKO_MCP_INVENTORY_TYPE": "yaml",
"NETMIKO_MCP_CREDENTIAL_SOURCE": "env",
"NETMIKO_MCP_INVENTORY_FILE": "/abs/path/claude-project/config/netmiko/inventory.yml"
# .env
NETMIKO_USERNAME=<service account>
NETMIKO_PASSWORD=<password>
NETMIKO_SECRET=<enable password, if any device asks for it>

파일: inventory.yml은 여기서 필수입니다 — 장치가 존재하는 유일한 곳입니다. commands.yml은 여전히 권장되며 필수는 아닙니다. 인벤토리는 netmiko_tools 형식입니다 — 이름과 연결 데이터의 평면 매핑에 그룹 키가 추가됩니다:

CORE-RTR-01:
  device_type: cisco_xr        # must be a Netmiko device_type, verbatim
  host: 192.0.2.11

CORE-SW-01:
  device_type: arista_eos
  host: 192.0.2.21

core:                          # a group is a list of device names
- CORE-RTR-01
- CORE-SW-01

이 프로젝트가 제공하는 파일은 예시 데이터입니다: RFC 5737 문서 범위에 있는 12개의 가상 장치, 7개의 그룹, 그리고 허용 목록에 언급된 모든 CLI 방언이 대표되도록 선택된 플랫폼입니다. 여러분의 실제 환경으로 교체하세요.

이것은 이 프로젝트가 기본으로 구성된 형태이며, 동시에 저하된 모드이기도 합니다: SoT(신뢰 정보 출처)가 다운되면, 두 개의 변수와 재시작만으로 flavor-A 또는 flavor-B 배포를 이 파일로 이동시킵니다. 실제로 필요해지기 전에 이 과정을 연습해두는 것이 좋습니다.

단점은 파일이 오래된 정보가 될 수 있다는 것입니다. 상위 저장소의 scripts/export_inventory.py 스크립트가 SoT로부터 이 파일을 다시 생성하므로, 정기적으로 실행하세요. 6개월 전 주소가 담긴 백업 인벤토리는 전혀 없는 것보다 나쁩니다. 운영 중에야 알게 되기 때문입니다.

세 가지 flavor에서 동일한 부분

명령어 정책, 감사 추적, 출력 페이지 매김, 도구 표면은 flavor 간에 변경되지 않습니다. 에이전트가 마주하는 계약은 동일하므로, 스킬에 flavor별 변형이 필요하지 않습니다.

commands.yml은 권장 사항이지 필수 사항이 아닙니다.

서버는 이 파일 없이도 실행됩니다. 파일이 없으면 모든 것을 거부하지도 않고 시작을 거부하지도 않습니다. 대신 내장된 대체 폴백 16개의 읽기 전용 명령어가 적용됩니다 — show version, show ip interface brief, display version 및 그에 상응하는 Junos/VRP 명령어입니다. 일부러 이렇게 설계되었습니다. 빈 정책은 서버가 정상 상태라고 보고하면서도 모든 명령어를 거부하게 되는데, 이는 운영자에게 "장치가 거부했다"가 아니라 "정책을 작성한 사람이 없다"로 읽힙니다. 폴백은 시작 시 알려지며, netmiko.get_command_policypolicy_source: "fallback"을 보고하고, 모든 감사된 시도는 출처를 기록합니다.

따라서 이 파일은 설치 단계가 아니라 정책 결정입니다. 폴백을 사용하면 처음 시도에 서버를 실행할 수 있으며, 보수적인 기본값 대신 실제 환경의 정책을 원할 때 commands.yml을 작성합니다. 선택하지 않은 정책을 모르는 상태로 가질 수는 없습니다 — 서버는 요청을 받을 때마다 어떤 정책이 적용 중인지 알려줍니다.


.mcp.json 파일

프로젝트 루트의 .mcp.json이 프로젝트에 대한 MCP 서버를 선언합니다. Claude Code는 파일을 처음 볼 때 승인을 요청하며, 이 파일은 커밋되어야 합니다. 전체 팀이 동일한 서버를 사용하는 방법입니다.

동일한 서버 정의에 대해 두 가지 다른 범위가 있습니다:

범위(scoped)

위치

누가 보는지

project

프로젝트 루트의 .mcp.json

프로젝트를 여는 모든 사람 (승인 후)

user

~/.claude.json

해당 사용자의 모든 프로젝트, 해당 머신에서

local

~/.claude.json, 프로젝트 경로별 키 지정

해당 사용자만, 해당 프로젝트에서만

claude mcp add --scope project netmiko -- /path/to/python /path/to/server.py 명령어가 project 항목을 대신 작성해줍니다. JSON을 직접 수정해도 동일합니다.

파일의 구조

{
  "mcpServers": {           // ← the top-level key. Not "servers", not "mcp".
    "netmiko": {            // ← the server name; it becomes the tool prefix
      ...                   //    mcp__netmiko__<tool>
    }
  }
}

서버 이름은 단순히 보여주기 위한 것이 아닙니다: Claude Code는 각 도구를 mcp__<server-name>__<tool-name> 형태로 노출합니다. 이름이 netmiko이고 서버가 등록한 도구 netmiko.get_metadata의 경우, Claude가 실제로 보는 도구는 mcp__netmiko__netmiko.get_metadata입니다. /mcp를 실행하여 정확한 이름을 확인한 후 allowed-tools 목록이나 권한 규칙에 작성하세요.

필드 참조

필드

전송 방식

의미

type

둘 다

"stdio" (생략 시 기본값), "http", 또는 "sse"

command

stdio

실행할 실행 파일. 절대 경로 — cwd를 가정하지 마세요

args

stdio

인수 목록, 각 요소는 분리

env

stdio

자식 프로세스의 환경 변수. 상속받은 환경에 병합됨

url

http / sse

전체 엔드포인트 URL, 경로 포함

headers

http / sse

추가 요청 헤더, 일반적으로 Authorization

값은 환경 변수 확장을 지원합니다: ${VAR}${VAR:-default}. 커밋된 파일에 토큰을 보관하지 않는 데 유용합니다:

"headers": { "Authorization": "Bearer ${NETMIKO_MCP_TOKEN}" }

전송 방식 1 — stdio (이 프로젝트가 사용하는 방식)

Claude Code는 서버를 자식 프로세스로 생성하고 stdin/stdout을 통해 JSON-RPC를 주고받습니다. 포트를 수신하거나 네트워크에서 접근 가능한 것이 없으며, 프로세스 수명은 세션과 같습니다. 이는 SSH 자격 증명을 보유하는 서버에 적합한 기본값입니다.

{
  "mcpServers": {
    "netmiko": {
      "type": "stdio",
      "command": "${CLAUDE_PROJECT_DIR:-.}/.venv/bin/python",
      "args": ["${CLAUDE_PROJECT_DIR:-.}/mcps/mcp_server_netmiko.py"],
      "env": {
        "NETMIKO_MCP_INVENTORY_TYPE": "yaml",
        "NETMIKO_MCP_INVENTORY_FILE": "${CLAUDE_PROJECT_DIR:-.}/config/netmiko/inventory.yml",
        "NETMIKO_MCP_COMMAND_FILE": "${CLAUDE_PROJECT_DIR:-.}/config/netmiko/commands.yml",
        "NETMIKO_MCP_CREDENTIAL_SOURCE": "env",
        "NETMIKO_MCP_SAVE_OUTPUT_DIR": "${CLAUDE_PROJECT_DIR:-.}/mcpr/netmiko",
        "NETMIKO_MCP_AUDIT_LOG_FILE": "${CLAUDE_PROJECT_DIR:-.}/logs/netmiko-audit.jsonl",
        "LOG_FILE": "${CLAUDE_PROJECT_DIR:-.}/logs/netmiko-mcp.log",
        "LOG_LEVEL": "INFO"
      }
    }
  }
}

주의해야 할 두 가지 사항:

  • 하드코딩된 경로는 사용하지 말아야 하며, 작업 디렉터리에 의존해서는 안 됩니다. ${CLAUDE_PROJECT_DIR:-.}이 파일을 수정 없이 커밋 가능하게 유지하는 요소입니다. 다음 섹션에서 전체 설명을 다룹니다. 직관적인 해석이 틀릴 수 있기 때문입니다.

  • 서버는 stdout에 출력하면 안 됩니다. stdout은 프로토콜 채널이며, 한 줄의 잘못된 출력이 세션을 망가뜨립니다. 로깅은 stderr와 LOG_FILE에 있는 순환 파일(5MB × 3, 0600 권한 생성 — DEBUG 수준에서는 장치 출력 포함)로 보내집니다. Niko 내부에서는 동일한 변수가 MCPLogging에 의해 처리됩니다.

${CLAUDE_PROJECT_DIR:-.}의 출처

하나의 문자열에 두 가지 다른 것이 포함되어 있습니다: 구문과 변수.

구문. ${VAR}${VAR:-default}는 POSIX 매개변수 대체("VAR 사용; 설정되지 않았거나 비어 있으면 default 사용")이지만, 셸이 개입하는 것은 아닙니다 — JSON 파일은 셸을 거치지 않습니다. Claude Code가 파일을 읽을 때 command, args, env, urlheaders에서 확장을 직접 구현합니다. 이는 그 클라이언트의 규칙이며, MCP 사양의 일부가 아닙니다: 다른 클라이언트는 이를 구현하지 않을 수 있으며(경로가 리터럴이어야 하는 Non-Claude agents 참조), VS Code는 자체 표기법인 ${workspaceFolder}를 사용합니다.

변수. CLAUDE_PROJECT_DIR은 Claude Code가 프로젝트 루트로 설정하며, 훅이 받는 값과 동일합니다. 세션 중간에 --add-dir로 추가 작업 디렉터리를 허용해도 변경되지 않습니다.

직관에 반하는 부분이자 :-.이 장식이 아닌 이유는: Claude Code는 해당 변수를 서버의 환경에 설정하며, 자신의 환경에는 설정하지 않습니다. 그러나 확장은 스폰 전에, Claude Code의 환경을 대상으로 발생합니다 — 그 환경에는 변수가 존재하지 않습니다. 따라서 bare ${CLAUDE_PROJECT_DIR}은 아무것도 확장되지 않고 /config/netmiko/inventory.yml을 남겨 파일 시스템 루트의 절대 경로가 됩니다.

따라서 프로젝트 범위의 .mcp.json에서 기본값은 어떤 경계 조건에 대한 폴백이 아닙니다: 매번 사용되는 값입니다. 프로세스에 전달되는 것은 ./config/netmiko/inventory.yml입니다. 유일한 예외는 플러그인이 제공하는 MCP 구성입니다. 이 경우 Claude Code가 변수를 직접 대체하며 기본값이 필요하지 않습니다.

이것이 서버의 처리를 강제합니다. 상대 경로는 자식 프로세스의 cwd를 기준으로 해석되며, cwd는 클라이언트의 선택이지 프로젝트의 선택이 아닙니다. 따라서 resolve_project_path()가 있습니다: 모든 상대 경로 설정은 설정이 로드될 때 PARENT_DIRmcps/의 상위 디렉터리이자 .env가 있는 동일한 루트 — 에 고정됩니다. 어디서 시작된 세션이든 config/netmiko/를 찾으며, validate_startup()은 파일이 누락된 경우 절대 경로 파일을 명시합니다. ~는 여전히 운영자의 홈 디렉터리를 의미하며, 프로젝트 내부 파일을 의미하지 않습니다.

변수는 문서가 의도한 대로 서버 내부에서 (os.environ["CLAUDE_PROJECT_DIR"]) 읽을 때 유용하며, 여기서 설정됩니다. 이 서버는 필요하지 않습니다: PARENT_DIR__file__에서 파생되므로 클라이언트에 전혀 의존하지 않습니다 — HTTP 전송 방식에서 해당 변수를 설정하는 사람이 없으므로 특별한 처리가 필요하지 않은 것과 같은 이유입니다.

출처: Claude Code — MCP, Add a local stdio serverEnvironment variable expansion in .mcp.json 섹션.

전송 방식 2 — HTTP (streamable HTTP)

Claude Code가 지원하며, 다른 MCP 클라이언트도 지원합니다. 서버가 다른 곳에서 실행될 때 사용하는 전송 방식입니다: 다른 호스트, 컨테이너, 여러 에이전트가 공유하는 서비스, 또는 Claude가 아닌 에이전트.

서버 파일은 항상 __main__ 가드 아래에서 mcp.run(transport="stdio")를 호출하므로, HTTP는 FastMCP CLI를 통해 제공됩니다 — 코드 변경 없음:

.venv/bin/fastmcp run mcps/mcp_server_netmiko.py \
  --transport http --host 127.0.0.1 --port 8123
# endpoint: http://127.0.0.1:8123/mcp/

NETMIKO_MCP_* 변수는 더 이상 클라이언트 구성의 일부가 아닙니다: 서버 프로세스는 사용자가 시작하므로, 서버의 환경에 속합니다 (셸 export, systemd 유닛, 컨테이너의 environment: 블록).

클라이언트 측:

{
  "mcpServers": {
    "netmiko": {
      "type": "http",
      "url": "http://127.0.0.1:8123/mcp/",
      "headers": {
        "Authorization": "Bearer ${NETMIKO_MCP_TOKEN}"
      }
    }
  }
}

또는 동등하게 claude mcp add --transport http netmiko http://127.0.0.1:8123/mcp/.

--transport sse"type": "sse"도 작동합니다. SSE는 더 오래된 원격 전송 방식이며, streamable HTTP로 전환하지 않은 클라이언트를 위해 유지됩니다.

보안. FastMCP CLI는 인증 없이 이 서비스를 제공합니다: 포트에 접근할 수 있는 사람은 서버 환경에 있는 자격 증명을 사용하여 인벤토리의 모든 장치에 대해 show 명령어를 실행할 수 있습니다. 로컬 테스트를 위해 127.0.0.1에 바인딩하고, 공유되는 모든 것은 TLS를 종료하고 Authorization 헤더를 확인하는 리버스 프록시 뒤에 배치하세요. 위의 headers 블록은 클라이언트가 보내는 것이며, 프록시가 이를 확인해야 합니다.

Non-Claude 에이전트

여기에 표시된 mcpServers 객체는 사실상의 표준 형태입니다: Claude Code, Claude Desktop, Cursor, Windsurf 모두 stdio에 대해 동일한 세 개의 필드(command / args / env)와 원격에 대해 동일한 두 개의 필드(url / headers)를 읽습니다. 항목을 그대로 복사하면 일반적으로 작동합니다.

복사하기 전에 확인해야 할 알려진 차이점:

  • VS Codemcp.json을 사용하며, "mcpServers" 대신 최상위 "servers" 키를 사용하고 "type"을 명시적으로 요구합니다.

  • 일부 클라이언트는 ${VAR} 확장을 구현하지 않습니다. 이 경우 값은 리터럴이어야 하며, 이는 커밋된 파일에 토큰을 붙여넣는 대신 HTTP 전송 방식과 프록시를 사용해야 하는 이유가 됩니다.

  • 구성 파일이 전혀 없는 에이전트도 HTTP 엔드포인트에 직접 연결할 수 있습니다 — URL과 Authorization 헤더가 전체 계약입니다.

env 블록

NETMIKO_MCP_* 항목은 모든 YAML 구성 파일보다 우선합니다. Niko 외부에는 NikoPaths가 없으므로 기본값은 ~/commands.yml~/.netmiko_mcp_tmp로 폴백되기 때문에 명시적으로 설정됩니다.

여기의 모든 경로는 프로젝트 루트를 기준으로 작성될 수 있습니다: 서버는 설정 로드 시 상대 값을 PARENT_DIR에 고정하므로, 생성된 프로세스의 cwd가 인벤토리나 감사 추적의 위치를 결정하지 않습니다. 절대 경로나 ~는 그대로 사용됩니다.

변수

기본값

목적

NETMIKO_MCP_INVENTORY_TYPE

netmiko_tools

yaml (로컬 파일) 또는 fedele (SoT)

NETMIKO_MCP_INVENTORY_FILE

(netmiko-tools lookup)

유형이 yaml일 때의 인벤토리 경로

NETMIKO_MCP_CREDENTIAL_SOURCE

env

env (.env 파일을 읽음) 또는 fedele

NETMIKO_MCP_FEDELE_GROUP_SOURCE

tags

그룹을 정의하는 항목: tags, device_roles, sites

NETMIKO_MCP_FEDELE_DEVICE_FILTER

(none)

범위 필터, tag=lab&status=active. 이 값이 없으면 전체 자산 대상

NETMIKO_MCP_FEDELE_CACHE_TTL

60

SoT 해결 캐시 (초 단위)

NETMIKO_MCP_COMMAND_FILE

Niko 외부의 ~/commands.yml

허용/거부 목록

NETMIKO_MCP_ALLOW_PIPE

false

명령어에서 파이프 사용 활성화

NETMIKO_MCP_SSH_CONFIG_FILE

(none)

OpenSSH ssh_config. 점프호스트에 필수 — Netmiko는 자체적으로 ~/.ssh/config를 읽지 않음

NETMIKO_MCP_MAX_WORKERS

10

그룹 명령어의 동시 연결 수

NETMIKO_MCP_SAVE_OUTPUT_DIR

Niko 외부의 ~/.netmiko_mcp_tmp

대용량 출력을 위한 버퍼

NETMIKO_MCP_SAVE_THRESHOLD

1000

이 줄 수를 초과하면 출력이 인라인 대신 저장됨

NETMIKO_MCP_AUDIT_LOG_FILE

(상위 README 참조)

감사 추적 (JSON, fail-closed)

NETMIKO_MCP_CONFIG

~/.netmiko-mcp.yml

동일한 설정을 포함하는 YAML 구성 파일의 경로

LOG_FILE / LOG_LEVEL

Niko.log / INFO

운영 로그: 항상 stderr에 기록되며, 이 순환 파일(5 MB × 3, 0600)에도 기록됨. LOG_LEVEL은 기본값으로 명시되어 있어 설정을 쉽게 찾을 수 있음 — DEBUG로 설정하면 장치 출력이 로그에 기록됨

자격 증명은 여기서 설정되지 않습니다. NETMIKO_USERNAME, NETMIKO_PASSWORD, NETMIKO_SECRETFEDELE_* 변수는 <project-root>/.env에서 읽어오므로, 커밋된 JSON 파일에 포함되지 않습니다. 우선순위: env 블록에 있는 값이 .env보다 조용히 우선합니다 — 각 변수는 정확히 한 곳에서 정의하세요.

다른 모든 변수는 상위 저장소의 README에 문서화되어 있습니다.

작동 확인

claude mcp list          # netmiko: ✓ connected

세션 내에서 /mcp는 도구를 나열하고 /skills는 스킬이 로드되었음을 확인합니다. 어떤 정책이 적용 중인지 물어보면 netmiko.get_command_policy가 읽고 있는 파일을 알려주거나 — "fallback"을 보고합니다. 이는 파일을 찾지 못하여 기본 제공 16개 명령어로 실행 중임을 의미합니다.


저자: Ed Scrimaglia edgardo.scrimaglia@gmail.com — 마지막 업데이트: 2026-08-18.

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.

  • Read-only bank access for your AI agent. Connects Claude, ChatGPT, Cursor, Gemini, Codex.

  • Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/escrimaglia/netmiko-mcp-claude'

If you have feedback or need assistance with the MCP directory API, please join our Discord server