MCP 서버 연결 확인법: 목록 표시와 실제 도구 호출 구별
코딩 에이전트 CLI에서 MCP 서버가 목록에 보여도 그것만으로 도구가 작동한다고 판정할 수는 없다. macOS의 로컬 stdio 서버 하나를 기준으로 하면 설정 읽기, 서버 초기화, 실제 도구 호출은 서로 다른 출력으로 확인해야 한다. 실측과 공식 문서 확인은 모두 2026-11-03에 했다.
Codex에서는 없는 경로를 준 고장 설정도 enabled로 표시됐다. 성공 여부는 mcp_tool_call 이벤트의 도구 이름과 반환값으로 판정해야 했다.
MCP 서버가 목록에 있는데 왜 도구는 작동하지 않을까
MCP 공식 아키텍처·전송 문서에 따르면 로컬 stdio 연결에서 클라이언트는 서버를 자식 프로세스로 실행한다. 설정에 명령이 적혀 있는 것과 그 프로세스가 살아서 응답하는 것은 별개다.
그래서 이 글은 확인 과정을 등록·읽기, 시작·초기화, 실제 호출 세 단계로 나눈다. MCP 공식 명칭은 아니다. 실패 지점을 좁히려고 이 글에서 정한 진단 분류다.
설정 읽기가 통과해도 초기화나 도구 호출에서 멈출 수 있으므로 단계마다 다른 증거를 봐야 한다.
다른 폴더에서 서버가 보이지 않는 이유
Claude Code 공식 문서는 등록 범위를 local, project, user로 나눈다. 기본값 local은 현재 프로젝트에만 적용되며 ~/.claude.json의 프로젝트 경로별 항목에 저장된다.
Claude Code 2.1.274와 codex-cli 0.161.0으로 ~/workspace에서 직접 실행해 봤다. claude mcp list와 codex mcp list 모두 서버가 없다고 나왔다.
~/.claude.json에서 프로젝트 키와 서버 이름만 뽑아 보니 홈 폴더(~) 항목에는 chrome-devtools가 있었고 ~/workspace 항목에는 서버가 없었다. local 범위에 등록한 서버를 전역 설정으로 오해하면 다른 폴더에서 서버가 사라진 것처럼 보인다.
설정 등록과 실제 도구 호출은 어떤 출력으로 구별하는가
OpenAI Codex 공식 문서는 ~/.codex/config.toml의 [mcp_servers.<name>] 테이블로 서버를 구성한다고 설명한다. 이번에는 설정 파일을 쓰지 않으려고 실행별 -c 오버라이드만 썼다. 실험 전후 이 파일의 SHA-256 해시는 같았다.
실험 대상은 공식 저장소가 학습용 예제로 소개하는 참조 구현 @modelcontextprotocol/server-filesystem@2.1.0이다. 쓰기 도구도 있는 서버라서 <폴더>/data만 허용하고 읽기만 요청했다.
아래가 정상 설정의 목록 조회다. NPM_CONFIG_* 두 변수는 MCP 요구사항이 아니다. 이 컴퓨터의 npm 인증 오류(E401)를 피하려고 서버 프로세스에만 넘긴 값이다.
codex -c 'mcp_servers.demo.command="npx"' -c 'mcp_servers.demo.args=["-y","@modelcontextprotocol/server-filesystem@2.1.0","<폴더>/data"]' -c 'mcp_servers.demo.env.NPM_CONFIG_USERCONFIG="/dev/null"' -c 'mcp_servers.demo.env.NPM_CONFIG_REGISTRY="https://registry.npmjs.org"' -c 'mcp_servers.demo.startup_timeout_sec=30' mcp list
경로 인수만 없는 경로 <폴더>/does-not-exist로 바꿔 mcp list와 mcp get demo --json을 다시 실행했다. 정상 설정과 고장 설정 모두 list의 Status는 enabled, get의 JSON은 "enabled": true였다. 이 표시는 설정을 읽었다는 뜻일 뿐, 서버가 기동했다는 증거는 되지 못한다.
Claude Code 문서에 따르면 claude mcp list와 claude mcp get은 Connected 같은 연결 상태도 보여 준다. 이 상태를 Codex의 enabled와 같은 신호로 보면 안 된다.
고장 설정으로 에이전트를 실행하자 실패가 드러났다.
codex (같은 -c 옵션, 경로만 <폴더>/does-not-exist) exec --json --skip-git-repo-check -s read-only 'Use only the demo MCP server to read <폴더>/data/proof.txt. … If demo is unavailable report that fact and stop.'
JSON 이벤트에는 mcp_tool_call, tool: list_mcp_resources, status: failed와 함께 다음 오류가 남았다.
resources/list failed: failed to get client: MCP startup failed: handshaking with MCP server failed: connection closed: initialize response: connection closed: initialize response
read_text_file이 실행된 흔적은 없다. 에이전트는 서버를 쓸 수 없다고 보고한 뒤 턴을 끝냈고, 그래서 CLI 종료 코드는 0이었다.
정상 경로에서는 도구 이름까지 지정해 실행했다.
codex (같은 -c 옵션) exec --json --skip-git-repo-check -s read-only 'Call the demo MCP server read_text_file tool on <폴더>/data/proof.txt. … return its full exact content without commentary.'
이번에는 mcp_tool_call에 tool: "read_text_file", status: "completed", error: null이 찍혔다. 반환 본문에는 테스트 파일 두 줄이 끝 줄바꿈까지 그대로 있었다. 모델의 마지막 답변에서는 그 줄바꿈이 빠졌다. 그러니 판정은 도구 응답 이벤트로 해야 한다.
| 확인 단계 | 판정 근거 | 실패 시 현상 |
|---|---|---|
| 등록·읽기 | mcp list의 enabled | 이름이 없거나 다른 폴더에서만 보임 |
| 시작·초기화 | initialize 응답, tools/list 도구 14개 | MCP startup failed |
| 실제 호출 | mcp_tool_call의 tool, status, 반환 본문 | 종료 코드 0인데 사용 불가 보고, isError: true |
초기화와 도구 호출은 왜 실패하는가
원인을 보려고 고장 설정의 서버 명령을 셸에서 직접 실행했다.
env NPM_CONFIG_USERCONFIG=/dev/null NPM_CONFIG_REGISTRY=https://registry.npmjs.org npx -y @modelcontextprotocol/server-filesystem@2.1.0 <폴더>/does-not-exist
Error: None of the specified directories are accessible
stderr에 이 오류가 나오고 종료 코드 1로 끝났다. 서버가 허용 경로 검사에서 바로 종료하는 바람에 initialize에 응답하지 못한 것으로 본다. 시작 제한 시간 startup_timeout_sec을 늘려도 풀리지 않는 실패다.
원시 stdio 테스트는 protocolVersion: "2025-06-18"을 썼다. initialize, tools/list(도구 14개), 허용 경로 안의 파일 읽기가 모두 성공했다. 2026-07-28 규격에는 초기 핸드셰이크가 없는 방식과 server/discover가 있다. 따라서 이 순서를 모든 MCP 연결로 일반화하지 않는다.
허용 경로 밖 파일을 tools/call로 요청하자 연결은 유지된 채 isError: true와 Access denied - path outside allowed directories 문구가 돌아왔다. 접근 거부는 시작 실패가 아니다. 연결이 성립한 뒤 서버가 정상적으로 처리한 결과다.
설정 파일을 직접 고치지 않고 확인하는 절차
<폴더>/data/proof.txt에 고유 문자열 두 줄을 저장한다. 이 내용은 프롬프트에 알려 주지 않는다.- 작업 폴더에서
claude mcp list또는codex mcp list로 기존 등록 상태와 범위를 확인한다. - Codex에서
-c옵션으로 서버 버전과 허용 경로를 지정하고mcp get demo --json으로 설정이 읽히는지 본다. - 셸과 기본 파일 도구를 쓰지 말고
read_text_file만 호출하라고 지시해exec --json을 실행한다. mcp_tool_call의tool,status,error와 반환 본문을 원본 파일과 대조한다. 초기화에서 막히면 서버 명령을 셸에서 직접 실행해 stderr를 본다.
이번 검증의 한계
Claude Code의 --mcp-config, --strict-mcp-config를 쓴 호출 세션과 /mcp 화면은 문서로만 확인했고 직접 실행하지 않았다. 원격 HTTP/SSE 서버, OAuth, Windows 인용부호, 느린 네트워크에서의 시간 초과도 측정하지 않았다.
MCP의 기본 개념은 MCP란 무엇인가에서 다뤘다. 다른 폴더에서 서버가 빠졌던 경험은 MCP vs CLI에 정리했다.
결론
MCP 서버가 목록에 보이거나 CLI 종료 코드가 0이어도 도구가 작동했다고 볼 수 없다. 기준은 설정 읽기, 초기화, 실제 호출 중 어디까지 증거가 남았는지다. 최종 성공은 mcp_tool_call 이벤트의 도구 이름과 반환값으로 판정한다. 지금 쓰는 서버가 의심스럽다면 작은 텍스트 파일 하나로 JSON 호출 로그에 도구 이름과 파일 내용이 찍히는지부터 확인해 보자.

댓글
댓글 쓰기