콘텐츠로 이동

Inspector 레시피 (Recipes)

원문 출처: Model Context Protocol 공식 문서 — Recipes

서버 연결(stdio·HTTP), 기존 클라이언트 설정 가져오기, MCP App 검토, Docker, 네트워크 호스팅에 이르기까지 실무에서 바로 쓸 수 있는 Inspector 활용 가이드예요.

stdio 서버 vs HTTP 서버 연결

stdio

stdio 서버는 Inspector가 (프로세스로) 직접 띄우는 서버예요. 위치 인자(positional argument)가 곧 명령줄이 됩니다.

mcp-inspector node build/index.js -- --verbose --config /etc/myserver.conf

서버 쪽으로 넘기고 싶은 인자 앞에는 반드시 -- 를 붙여주세요. 구분자 없이 쓰면 --verbose 를 Inspector가 자기 것으로 해석해 버려서 서버까지 전달되지 않아요.

프로세스에 환경 변수를 줄 때는 -e, 작업 디렉터리는 --cwd 로 지정합니다.

mcp-inspector -e API_KEY=abc123 -e REGION=us-east-1 --cwd ~/projects/my-server \
  node build/index.js

서버의 stderr 는 웹의 Console 탭(또는 TUI의 Console 탭, o)에 출력돼요. 대부분의 stdio 서버는 진단 메시지를 여기로 보내기 때문에, 뚜렷한 이유 없이 연결이 실패하면 제일 먼저 이 탭을 확인해 보세요.

HTTP와 SSE

mcp-inspector --server-url https://api.example.com/mcp --transport http \
  --header "X-Tenant: acme"

--transporthttp(Streamable HTTP)와 sse 를 받습니다. 서버가 보호되어 있다면 Authorization 문서를 참고하세요. 미리 준비할 건 없어요. 서버가 401 로 응답하면 Inspector가 그 문서에 설명된 OAuth 흐름을 직접 진행하고 연결을 재시도해 주니까요.

HTTP 서버라면 프로토콜 시대(protocol era)도 정해줘야 해요. 기본값은 legacy 이고, Server Settings(또는 카탈로그 파일의 protocolEra)에서 modern 이나 auto 를 지정하면 2026-07-28 행동을 쓸 수 있어요. 자세한 내용은 protocol eras 문서를 참고하세요.

기존 클라이언트 설정 가져오기

Servers 화면의 Add Servers는 이미 다른 곳에서 설정해 둔 MCP 서버를 다시 입력하지 않고 가져올 수 있어요. Claude Desktop, Cursor, Cline, VS Code 클라이언트 설정을 직접 파싱하고, 서버 자체의 MCP Registry server.json 도 읽어요.

가져오기는 활성 카탈로그(Inspector가 쓰고 수정할 수 있는 서버 목록)에 병합되기 때문에 기존 항목이 덮어써지지 않아요. 카탈로그를 건드리고 싶지 않다면 외부 파일을 읽기 전용으로 그대로 띄우면 됩니다.

mcp-inspector --config ~/Library/Application\ Support/Claude/claude_desktop_config.json

--config 는 파일을 있는 그대로 제공할 뿐, 절대 쓰기·시드·마이그레이션을 하지 않는다는 걸 보장해 줘요.

MCP App 검토하기

MCP App은 UI 위젯을 갖춘 도구예요. 자동화된 검토(CI나 에이전트)에는 JSON을 반환하는 모든 검사를 CLI로 처리하고, 브라우저는 렌더링된 위젯을 확인할 때만 여는 게 좋습니다.

1. 도구를 호출하지 않고 보안 자세 파악하기

mcp-inspector --cli --transport http --server-url https://example.com/mcp \
  --method tools/call --tool-name <tool> --app-info

stdout에 JSON 한 줄이 나오고, 도구에 앱이 있으면 exit 0, 없으면 2 를 반환해요. 그래서 && 체인으로 바로 분기할 수 있습니다.

{
  "hasApp": true,
  "toolName": "get_pros",
  "resourceUri": "ui://pros/view.html",
  "csp": { "connectDomains": ["https://api.example.com"] },
  "permissions": { "clipboard": false },
  "prefersBorder": true,
  "resourceMimeType": "text/html"
}

csppermissions(그리고 리소스가 선언한 경우 domain)는 도구가 아니라 UI 리소스에 있으므로, --app-info 는 그 리소스를 읽어와요. 도구 자체는 절대 호출되지 않습니다.

2. 브라우저 없이 전체 결과 페이로드 얻기

mcp-inspector --cli --transport http --server-url https://example.com/mcp \
  --method tools/call --tool-name <tool> --tool-args-json '{"zip":"10001"}' --format json

3. 웹 Inspector를 루프백 전용으로 한 번 띄우기

TOKEN="$(openssl rand -hex 24)"
HOST=127.0.0.1 CLIENT_PORT=6274 MCP_SANDBOX_PORT=6275 \
MCP_AUTO_OPEN_ENABLED=false MCP_INSPECTOR_API_TOKEN="$TOKEN" \
mcp-inspector --web &

여기서 MCP_SANDBOX_PORT 를 고정하는 게 중요해요. 앱의 UI는 기본적으로 동적으로 정해지는 별도의 샌드박스 포트에서 제공되는데, 자동화가 고정된 주소로 접근해야 하기 때문이에요.

4. 렌더링된 위젯으로 딥 링크 하나 열기

http://127.0.0.1:6274/?serverUrl=<encoded url>&transport=http&autoConnect=<TOKEN>&openApp=<tool>&appArgs=<base64url(JSON)>&autoOpen=<TOKEN>

appArgs 는 도구의 인자를 base64url 인코딩한 JSON이에요. 딥 링크의 각 매개변수는 Deep links 문서에 설명되어 있어요. autoOpen 은 URL에서 바로 도구 호출을 실행하기 때문에 autoConnect 와 같은 게이트를 거쳐야 해요. 그래서 autoConnectautoOpen 은 둘 다 세션 토큰과 값이 같아야 합니다.

5. 슬립 대신 결정적인 신호 기다리기

Apps 화면은 안정적인 자동화 계약을 노출합니다. sleep 대신 아래 속성을 폴링하세요.

셀렉터 속성
[data-testid="apps-form"] data-app-status ready (실패 시 data-app-error 에 원인이 담김)
[data-testid="connection-status"] data-status connecting, 그다음 connected 또는 error (data-error-message 에 상세)
[data-testid="connection-status"] data-deeplink parsed, rejected, 또는 none (none 은 딥 링크가 없었다는 뜻, rejected 는 거부됐다는 뜻)

Docker

linux/amd64linux/arm64 용 컨테이너 이미지가 GitHub Container Registry에 배포돼 있어요.

docker run --rm -p 6274:6274 ghcr.io/modelcontextprotocol/inspector

컨테이너 로그에서 세션 토큰을 읽거나 -e MCP_INSPECTOR_API_TOKEN=<value> 로 직접 고정하면 됩니다. 이미지는 기본적으로 --web 모드로, 0.0.0.0:6274 에 바인딩하고 브라우저 자동 열기는 꺼져 있으며, 비-root 사용자로 실행돼요. 컨테이너는 -p 로 도달 가능하려면 와일드카드 주소에 바인딩해야 하므로 DANGEROUSLY_BIND_ALL_INTERFACES=true 를 설정합니다. HEALTHCHECK 는 웹 UI를 검사하므로 --cli--tui(둘 다 웹 서버가 없음)로 실행할 때는 --no-healthcheck 를 붙여주세요. 아래 <target>ad-hoc target으로, 위치 인자 stdio 명령 또는 --server-url <url> --transport http 형태예요.

docker run --rm --no-healthcheck ghcr.io/modelcontextprotocol/inspector --cli <target> --method tools/list

게시된 포트를 바꾸면 ALLOWED_ORIGINS 를 설정하세요. -p 8080:6274 로 실행하면 브라우저의 origin이 http://localhost:8080 이 되는데, 이는 컨테이너 안의 포트와 더 이상 일치하지 않아 연결이 403 으로 거부돼요. -e CLIENT_PORT=8080 -p 8080:8080 으로 실행하거나, -e ALLOWED_ORIGINS=http://localhost:8080,http://127.0.0.1:8080 을 설정하세요.

네트워크에서 호스팅하기

Inspector는 기본적으로 localhost 에 바인딩되고 백엔드가 프로세스를 띄우기 때문에, 네트워크에 노출하는 일은 신중한 결정으로 다뤄야 해요. Inspector는 DANGEROUSLY_BIND_ALL_INTERFACES=true 를 설정하지 않는 한 와일드카드 전체 인터페이스 주소(0.0.0.0, ::, 그리고 그 모든 동등한 표기) 바인딩을 거부합니다. 특정 주소에 바인딩하는 것은 옵트인 없이 허용돼요. 이는 모든 인터페이스를 한꺼번에 노출하는 게 아니라 의도적인 노출 하나일 뿐이고, DNS 리바인딩 공격이 노리는 형태가 바로 이 주소이기 때문이에요.

목표 해야 할 일
LAN의 다른 머신에서 접근 HOST=192.168.1.50. 기본 origin 허용 목록이 바인딩 호스트를 따라가므로 추가 설정 없이 http://192.168.1.50:6274 가 허용돼요.
TLS 또는 리버스 프록시 뒤에서 브라우저의 Origin 이 공개 origin이 되는데, 이는 바인딩 호스트와 일치하지 않아요. ALLOWED_ORIGINS=https://inspector.example.com 을 설정하세요.
와일드카드 바인딩(컨테이너) DANGEROUSLY_BIND_ALL_INTERFACES=true 를 설정하세요. 루프백 접근은 기본적으로 여전히 동작하고, 루프백이 아닌 주소로 접근하려면 ALLOWED_ORIGINS 가 필요해요.

ALLOWED_ORIGINS 는 기본 목록에 병합하지 않고 대체합니다. 접속할 모든 origin을 나열하되, 유지하고 싶은 루프백 형태도 포함하세요.

ALLOWED_ORIGINS=http://localhost:6274,http://127.0.0.1:6274,http://192.168.1.50:6274

각 항목은 스킴(scheme)을 꼭 포함해야 해요. 스킴이 없는 값은 경고와 함께 버려집니다. 빈 값은 검사를 비활성화하지 않고 기본값으로 폴백해요. origin 검증을 끌 수 있는 손잡이는 존재하지 않습니다.

루프백을 벗어날 때 두 가지 주의사항이 더 있어요.

  • MCP App은 자기 샌드박스 포트도 도달 가능해야 해요. 샌드박스 포트는 기본적으로 동적으로 정해지는 별도 포트라서, MCP_SANDBOX_PORT 로 고정하고 노출하거나 포워딩해 주세요. Docker 이미지는 6274 만 게시합니다.
  • MCP App은 TLS 위나 bare IPv6 리터럴에서는 렌더링할 수 없어요. 샌드박스 URL은 항상 평문 http 라서 https:// 페이지에서는 iframe을 혼합 콘텐츠로 차단해요. 또 괄호로 감싼 IPv6 리터럴은 유효한 CSP 호스트 소스가 아니므로, 이름이나 IPv4 주소로 접속하세요.

어떤 형태든: 인증을 계속 켜두세요. 스스로 외에는 누구에게도 닿는 곳이라면 DANGEROUSLY_OMIT_AUTH 를 설정하지 마세요.

개발 워크플로

실제로 잘 맞는 루프는 이렇습니다.

1. CLI로 시작하기

--method initialize 는 서버가 시작하고, 핸드셰이크하고, 기대하는 capabilities를 보고하는지 1초 안에 기계가 읽을 수 있는 답변으로 확인해 줘요. "안 되는" 일의 대부분이 여기서 드러나요.

2. 탐색은 웹 클라이언트로

스키마 기반 폼, 렌더링된 결과, 그리고 그 옆의 Protocol 탭 덕분에 도구가 잘못 동작하는 사례를 빠르게 찾을 수 있어요.

3. 경계값을 테스트하기

잘못된 입력, 빠진 필수 프롬프트 인자, 동시 호출, 그리고 HTTP 서버라면 두 프로토콜 시대 모두를 확인하세요. 실패도 성공만큼 의도적이어야 하는지 검증해 봐요.

4. CLI로 확정하기

발견한 내용을 CI 단언으로 바꾸세요. CLI의 --format json 출력을 --stored-auth-only 와 함께 jq -e 에 연결하면, 토큰이 없을 때 인터랙티브 OAuth를 시작하는 대신 즉시 실패해요. 전체 명령은 Verify a server in CI 문서를 참고하세요.