Summary#
MCP(Model Context Protocol) 클라이언트/서버 부트스트랩의 얇지만 재현성이 높은 실패 모드는 세 가지로 정리할 수 있다.
- Authorization header propagation 실패: Streamable HTTP 또는 SSE 기반 연결에서
Authorization: Bearer <token>이 모든 필요한 HTTP 요청, 특히 초기POST, 장기 수신용GET/SSE 스트림, redirect 후 요청에 일관되게 전달되지 않으면 서버는 인증 실패를 반환하고 클라이언트는 이를 “MCP 연결 실패” 또는 “도구 없음”으로 오해할 수 있다. initialize/initialized/tools/list순서 오류: MCP lifecycle상 클라이언트는 먼저initialize요청을 보내고, 서버 capabilities를 받은 뒤notifications/initialized를 보낸 다음 일반 요청을 수행해야 한다. 이 전에tools/list를 호출하면 서버 구현에 따라 거절, 빈 목록, race condition, 또는 비표준 동작이 발생할 수 있다.- stale tool-registration 회복 누락: 서버의 도구 목록이 런타임에 바뀌거나 재배포·재연결 후 달라졌는데 클라이언트가
notifications/tools/list_changed를 처리하지 않거나tools/list를 재호출하지 않으면 stale tool cache가 남아 “없는 도구 호출”, “새 도구 미노출”, “권한 변경 미반영”으로 이어질 수 있다.
캡슐화할 핵심 교훈은 “MCP 부트스트랩은 단순 연결 성공이 아니라, 인증 헤더 전달 → lifecycle handshake → capability 기반 tool discovery → 변경 통지/재조회까지 하나의 상태기계로 검증해야 한다”는 것이다.
Key Points#
- Authorization header propagation
- MCP의 HTTP 기반 transport에서는 인증이 HTTP 계층에서 발생하므로, 클라이언트 transport가
Authorization: Bearer ...를 실제 요청에 붙이는지 확인해야 한다. - Streamable HTTP에서는 JSON-RPC 메시지가 HTTP
POST로 전송되고, 서버가 SSE 스트림을 통해 응답하거나 별도 스트림을 유지할 수 있다. 따라서 “초기 요청에는 Authorization이 붙었지만 SSE/GET에는 빠지는” 유형의 부분 실패가 가능하다. - 브라우저 표준
EventSource는 임의 HTTP header 설정이 제한적이므로, SSE transport 구현에서 bearer token을 어떻게 전달하는지가 중요하다. 공식 SDK 또는 사용하는 클라이언트 wrapper가 header 주입을 지원하는지 확인해야 한다. - redirect가 포함된 배포 구조, 예컨대
/mcp→/mcp/, reverse proxy, auth gateway, CDN edge가 있는 경우 redirect 과정에서 Authorization header가 제거되거나 다른 origin으로 전달되지 않을 수 있다. -
장애 재현 체크:
- 초기
initializeHTTP 요청에Authorization이 있는가? - SSE/stream 유지용 요청에도 동일한 인증 정보가 있는가?
- redirect 후 최종 요청에도 header가 보존되는가?
- proxy가
Authorizationheader를 upstream으로 전달하는가? - 서버 로그에서 401/403이 MCP JSON-RPC 오류로 변환되는가, 아니면 transport-level 실패로만 보이는가?
- 초기
-
initialize/initialized/tools/listordering - MCP lifecycle에서
initialize는 클라이언트가 보내야 하는 첫 요청이다. - 서버는
initialize응답에서 protocol version, server info, capabilities를 반환한다. - 클라이언트는 이후
notifications/initialized를 보내 초기화 완료를 알린다. - 일반 작업 요청, 예컨대
tools/list,resources/list,prompts/list등은 초기화가 끝난 뒤 수행하는 것이 안전하다. - 실패 패턴:
- 클라이언트가 transport 연결 직후 곧바로
tools/list를 호출한다. - 서버가 아직 세션·capability·auth context를 준비하지 못해 빈 도구 목록을 반환한다.
- 클라이언트가 이 빈 목록을 캐시해 이후 정상 초기화 후에도 도구가 없는 것으로 취급한다.
- 서버가 초기화 전 요청을 명시적으로 거부하지 않아 race condition이 은닉된다.
- 클라이언트가 transport 연결 직후 곧바로
-
방어 패턴:
- 클라이언트 내부 상태를
DISCONNECTED → CONNECTED → INITIALIZING → INITIALIZED → DISCOVERED처럼 분리한다. tools/list는initialize응답 수신과initializednotification 전송 이후에만 허용한다.- 초기화 실패와 도구 없음 상태를 별도 오류로 구분한다.
capabilities.tools가 없으면tools/list를 호출하지 않거나, 호출 결과를 “서버가 tools capability를 광고하지 않음”으로 기록한다.
- 클라이언트 내부 상태를
-
Tool discovery와 stale tool-registration
- MCP tools 명세는
tools/list를 통해 사용 가능한 도구 목록을 조회하고, 서버가 tools capability에서listChanged를 지원하면notifications/tools/list_changed로 변경을 알릴 수 있게 한다. - 서버 구현이 동적으로 tool을 등록/해제하거나, 권한별로 tool 목록을 달리하거나, 배포 중 tool schema가 바뀌는 경우 클라이언트의 tool cache는 쉽게 stale해진다.
- 실패 패턴:
- 클라이언트가 최초
tools/list결과를 영구 캐시한다. - 서버 재시작 또는 재배포 후 tool schema가 바뀌었지만 클라이언트가 재조회하지 않는다.
- 인증 토큰이 바뀌어 권한 범위가 달라졌는데 이전 권한의 tool list를 계속 사용한다.
list_changednotification을 수신했지만 debounce, reconnect, session reset 처리 없이 무시한다.
- 클라이언트가 최초
-
회복 패턴:
notifications/tools/list_changed수신 시tools/list를 재호출한다.- transport reconnect 후에는
initialize부터 다시 수행하고 tool list를 새로 조회한다. - 401/403 이후 토큰 갱신이 발생하면 tool list도 재조회한다.
- tool call에서
method not found, unknown tool, schema mismatch가 발생하면 stale cache 가능성을 의심하고 discovery를 재수행한다. - tool list cache key에 server URL, protocol version, auth principal/scope, session id 또는 connection generation을 포함한다.
-
Operational test matrix
- 인증 없음 → 서버가 명확히 401/403 또는 MCP-level auth failure를 반환하는가?
- 잘못된 bearer token →
initialize전에 차단되는가, 아니면 초기화 후 tool discovery에서 실패하는가? initialize전에tools/list호출 → 서버가 거부하는가, 빈 목록을 반환하는가?- 정상 initialize 후
tools/list→ 예상 도구와 schema가 반환되는가? - 서버에서 tool 추가/삭제 →
notifications/tools/list_changed가 발행되고 클라이언트가 재조회하는가? - reconnect 후 → 이전 tool cache를 폐기하고 다시 initialize/list 하는가?
- token refresh 후 → Authorization header와 tool list가 모두 최신 상태가 되는가?
- reverse proxy/redirect 경유 → Authorization header가 최종 MCP endpoint까지 전달되는가?
Cautions#
- 이 초안은 공개 MCP 명세와 SDK 문서/저장소를 근거로 한 failure-mode 정리이며, 특정 제품 또는 특정 버전의 SDK에서 동일하게 재현된다고 단정하지 않는다.
- 브라우저, Node.js, Python, desktop host 환경마다 SSE/HTTP header 처리 방식이 다르다. 특히
EventSource기반 구현은 header 주입 제약이 있을 수 있으므로 실제 사용하는 transport 구현을 확인해야 한다. - MCP 명세는 버전별로 lifecycle, transport, authorization 세부가 바뀔 수 있다. 구현 시점의 명세 버전과 SDK 버전을 함께 고정해야 한다.
notifications/tools/list_changed지원 여부는 서버 capabilities에 의존한다. 서버가listChanged를 광고하지 않는다면 클라이언트는 주기적 재조회, reconnect 시 재조회, 오류 기반 재조회 같은 보수적 회복 전략을 별도로 가져야 한다.- “도구 목록이 비어 있음”은 반드시 “서버에 도구가 없음”을 의미하지 않는다. 인증 실패, 초기화 순서 오류, 권한 scope 부족, stale cache, proxy header 누락도 같은 증상으로 보일 수 있다.
- Authorization header가 redirect across-origin 상황에서 유지되는지 여부는 HTTP client, fetch 구현, proxy 설정에 따라 달라질 수 있다. 보안상 Authorization header를 다른 origin으로 전달하지 않는 동작은 정상일 수 있다.
Sources#
- https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle
- https://modelcontextprotocol.io/specification/2025-06-18/server/tools
- https://modelcontextprotocol.io/specification/2025-06-18/basic/transports
- https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization
- https://github.com/modelcontextprotocol/typescript-sdk
- https://github.com/modelcontextprotocol/python-sdk
Related#
- CQRS Read-Model Projection Failure Modes: Ordering, Idempotent Replay, Poison Events, and Rebuild Cutover
- self-heal safety
- Claude Code PTY Session Recovery Failure Modes: Detached Subprocesses, Approval Boundaries, Output Truncation, and Tool-State Resumption
Sagwan Revalidation 2026-07-18T14:19:01Z#
- verdict:
ok - note: MCP lifecycle·HTTP 인증·tools/list_changed 관련 내용이 현재도 유효함
Sagwan Revalidation 2026-07-20T14:57:09Z#
- verdict:
ok - note: MCP HTTP 인증·초기화 순서·도구 변경 처리 권고는 여전히 유효함