CLI 클라이언트
CLI 클라이언트 (CLI client)
MCP Inspector를 스크립트로 다루는 방법, 즉 메서드, 출력 형식, 종료 코드, CI 레시피를 다루는 문서예요. 각 CLI 실행은 서버에 연결하고, --method로 이름 붙인 단일 요청을 호출하며, 결과를 출력하고 종료합니다.
출처: 문서
본문
각 CLI 실행은 서버에 연결하고, --method로 이름 붙인 단일 요청을 호출하며, 결과를 출력하고 종료해요. 그래서 서버 변경을 즉시 검증해야 하는 CI 파이프라인, 셸 원라이너, 코딩 에이전트에 잘 맞습니다.
npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list
아래 예시는 설치된 mcp-inspector 바이너리를 사용해요. 전역 설치가 없다면 위와 같이 각 명령 앞에 npx @modelcontextprotocol/inspector를 붙이세요.
서버 선택
CLI는 위치 인수 명령(stdio), --server-url(HTTP/SSE), 또는 카탈로그·구성 파일에서 이름 붙은 서버를 받아요.
# stdio: everything positional is the command to spawn
mcp-inspector --cli node build/index.js --method tools/list
# HTTP
mcp-inspector --cli https://api.example.com/mcp --transport http --method tools/list
# From a file
mcp-inspector --cli --config ./mcp.json --server myserver --method tools/list
서버가 파일에서 오면 그 서버별 설정(헤더, 타임아웃, OAuth, 프로토콜 시대, roots)이 TUI와 web 클라이언트가 해석하는 것과 정확히 동일하게 연결에 적용돼요. --header 플래그는 그 실행 동안 파일의 헤더를 덮어쓰면서 타임아웃과 OAuth는 그대로 둡니다.
이후 예시는 사용하는 형식 중 어떤 것이든, 그 --transport 또는 --config/--server 플래그와 함께 <server>로 줄여 쓸게요.
구성 파일이 실행에 roots를 주는 유일한 지속적 방법입니다. roots 플래그는 없고,
--method roots/set은 그 하나의 단명 연결에만 적용돼요. 서버에 구성된 roots는 연결 시 광고되므로,roots/list를 호출하는 서버(@modelcontextprotocol/server-filesystem이 허용 디렉터리를 배우려고 하는 것처럼)는 그것을 받습니다.
--catalog 대 --config, -- 구분자, 공유 서버 선택 플래그는 구성과 플래그를 참고하세요.
메서드
--method |
필수 동반 | 참고 |
|---|---|---|
initialize |
없음 | 연결 전용 프로브: {serverInfo, protocolVersion, capabilities, instructions}. |
tools/list |
없음 | |
tools/call |
--tool-name, 그리고 --tool-arg / --tool-args-json |
|
resources/list |
없음 | |
resources/read |
--uri |
|
resources/templates/list |
없음 | |
prompts/list |
없음 | |
prompts/get |
--prompt-name, --prompt-args |
|
logging/setLevel |
--log-level |
레거시 시대 전용. 현대 서버는 대신 요청별 옵트인. |
servers/list, servers/show |
없음 | 아무것에도 연결하지 않고 카탈로그를 읽음. |
스트림·세션 전용 메서드(logging/tail 같은)는 거부돼요. 종료하는 프로세스가 스트림을 열어 둘 수 없기 때문이죠.
인수 전달
--tool-arg는 key=value를 받고 값을 JSON 파싱으로 강제 변환해서, count=1은 숫자가 되고 "012"는 12가 됩니다.
mcp-inspector --cli <server> --method tools/call --tool-name mytool \
--tool-arg key=value --tool-arg count=1 --tool-arg 'options={"format":"json"}'
--tool-args-json은 전체 인수 객체를 한 번에 받아 강제 변환 없이 그대로 전달해서, "012"는 문자열 012로 유지됩니다. 둘은 상호 배타적이에요.
mcp-inspector --cli <server> --method tools/call --tool-name mytool \
--tool-args-json '{"zip":"10001"}'
출력
--format text(기본값)는 사람을 위해 예쁘게 출력해요. --format json은 배너 없이 stdout에 단일 JSON 객체를 내보내서, 전체 출력이 깔끔하게 파이프됩니다.
mcp-inspector --cli <server> --method tools/list --format json | jq '.result.tools[].name'
MCP Apps 프로빙
--app-info는 도구를 호출하지 않고 도구가 MCP App UI(ui:// 리소스, CSP, 권한)를 동봉하는지 보고해요. 그래서 파이프라인이 무엇을 호출하기 전에 브라우저가 필요한지 결정할 수 있습니다.
# One tool -> one JSON line
mcp-inspector --cli <server> --method tools/call --tool-name my_tool --app-info
# {"hasApp":true,"toolName":"my_tool","resourceUri":"ui://...","csp":{...},"permissions":{...}}
# Every tool -> NDJSON, one line each, over a single connection
mcp-inspector --cli <server> --method tools/list --app-info | jq -c 'select(.hasApp)'
종료 코드가 결과를 구분해요. 앱이 있는 도구는 0으로, 없는 도구는 2로, 없는 도구는 5로 종료해서 오타가 "앱 없음"으로 오인되지 않게 합니다. 프로브 실패(읽을 수 없는 UI 리소스, 잘못된 resourceUri)는 중단 대신 resourceError 필드로 보고되어, 나쁜 도구 하나가 전체 목록을 죽이지 않아요.
tools/list --app-info는--format에 관계없이 항상 NDJSON(도구당 한 줄)을 내보냅니다.--format json은tools/call --app-info의 단일 도구 출력만 재구성해요.
종료 코드와 오류 엔벨로프
모든 0이 아닌 종료는 안정적인 실패 클래스에 매핑되어, 호출자가 산문을 긁지 않고 왜를 기준으로 분기할 수 있어요.
| 코드 | 의미 |
|---|---|
0 |
성공. |
1 |
사용법 또는 예기치 않은 오류(포괄). |
2 |
도구에서 MCP App을 찾지 못함(--app-info 프로브). |
3 |
서버가 인증을 요구(401/403, WWW-Authenticate, OAuth). |
4 |
서버에 도달 불가(DNS, 연결 거부, 타임아웃, fetch failed). |
5 |
도구 오류: tools/call이 isError: true를 반환했거나 도구를 찾지 못함. |
0이 아닌 종료 시 CLI는 stderr에 단일 JSON 줄도 씁니다.
{
"error": {
"code": "auth_required",
"message": "Unauthorized",
"status": 401,
"url": "https://api.example/mcp"
}
}
한 줄이므로 호출자는 2>&1 | tail -1 | jq .error로 파싱할 수 있어요.
isError: true를 반환하는 tools/call은 여전히 페이로드를 출력하지만 5로 종료해서, 실패한 호출에서 && 체인이 진행되지 않습니다.
스크립트에서의 인증
기본적으로 CLI는 TUI와 같은 루프백 OAuth 흐름을 실행해요. 브라우저를 열고 CI 작업이 완료할 수 없는 localhost 콜백을 기다리죠. 두 플래그가 비상호작용 실행을 예측 가능하게 만들어요.
--stored-auth-only: 상호작용 OAuth나 스텝업을 시작하지 않고 브라우저를 자동으로 열지 않아요. 공유 저장소의 토큰이 있으면 사용하고, 없으면 즉시auth_required로 실패해요. CI가 원하는 플래그입니다.--use-stored-auth: web Inspector가 이미 이 머신에서 얻은 토큰을 재사용하고, 리프레시 토큰이 저장되어 있으면 먼저 갱신해요.
둘 다 없고 stdin이나 stderr에 TTY도 없으면, CLI는 아무도 완료하지 않을 콜백에서 15분간 매달리지 않고 auth_required로 빠르게 실패해요.
전체 흐름, web-to-CLI 핸드오프, --print-handoff는 인증을 참고하세요.
레시피
CI에서 서버 검증
set -euo pipefail
# Fail the build if the server can't be reached or doesn't expose the tool
mcp-inspector --cli --config ./ci-servers.json --server my-server \
--stored-auth-only --method tools/list --format json \
| jq -e '.result.tools | map(.name) | index("get_weather")' > /dev/null
실패 클래스로 분기
if out=$(mcp-inspector --cli "$URL" --transport http --method tools/list 2>err.json); then
echo "$out"
else
case $? in
3) echo "needs auth: run the web inspector once to sign in" ;;
4) echo "server unreachable" ;;
*) jq .error < err.json ;;
esac
fi
UI가 있는 모든 도구 스모크 테스트
mcp-inspector --cli "$URL" --transport http --method tools/list --app-info \
| jq -r 'select(.hasApp) | .toolName'
연결하지 않고 카탈로그 검사
mcp-inspector --cli --catalog ~/.mcp-inspector/mcp.json --method servers/list
mcp-inspector --cli --catalog ~/.mcp-inspector/mcp.json --method servers/show --server my-server
servers/show는 비밀을 담은 필드(env값, 민감한 헤더, OAuth 클라이언트 시크릿)를 편집하지만, 서버url(userinfo나 쿼리 토큰)이나 stdioargs에 내장된 자격 증명은 씻어내지 않아요. 이슈에 붙여넣기 전에 원시 URL과detail필드를 민감한 것으로 취급하세요.
프록시
원격 HTTP/SSE 서버로의 연결은 관례적인 프록시 변수를 존중합니다. HTTPS_PROXY/HTTP_PROXY(소문자도)는 프록시를 선택하고 NO_PROXY는 호스트를 면제해요. Inspector 특정 플래그는 필요 없고, 프록시 에이전트는 지연 로드되므로 프록시 없이 실행하는 것은 아무 비용도 들지 않습니다. web 클라이언트의 백엔드에도 동일하게 적용됩니다.