프로토콜 시대

프로토콜 시대 (Protocol eras)

Inspector가 레거시 대 현대 MCP를 어떻게 협상하고, 각 프로토콜 시대에서 모든 기능이 어떻게 처리되는지 다루는 문서예요. MCP의 2026-07-28 개정은 프로토콜에 상당한 변경을 가져왔습니다.

출처: 문서

본문

MCP의 2026-07-28 개정은 프로토콜에 상당한 변경을 가져왔어요. 그래서 Inspector는 프로토콜 시대(protocol era)(레거시 또는 현대, 즉 그 개정 이전 또는 그 시점 이후)를 전송과 직교하는 일급 서버별 설정으로 취급합니다. 같은 HTTP URL도 레거시 서버 또는 현대 서버로 검사할 수 있죠. 여러 탭이 어떤 시대가 적용되는지에 따라 의미 있게 다른 UI와 트래픽을 렌더링해요.

Protocol Era 설정

각 서버는 legacy, auto, modern 중 하나의 protocolEra를 지녀요. Web 클라이언트에서는 Server Settings에 있고, 카탈로그나 구성 파일에서는 protocolEra 필드이며, CLI와 TUI에서는 같은 파일에서 나옵니다.

시대 연결 시 Inspector가 하는 일
legacy 기본값. 일반 initialize만, 전혀 프로빙하지 않음.
auto 먼저 server/discover를 프로브하고, 비현대 결과에 대해선 initialize로 폴백.
modern 정확히 2026-07-28로 고정. 폴백이 없으므로 비현대 서버는 크게 실패.

auto가 아니라 legacy가 기본인 이유. 디버깅 도구는 자동 프로브를 하지 않아야 해요. server/discover 프로브는 조용한 레거시 stdio 서버에서 멈춰 버리고, 여러분이 보러 온 기록된 트랜스크립트를 오염시킵니다. auto나 modern으로 선택하는 것은 의도적 행위라서, Protocol 탭에서 보는 것이 바로 여러분이 구성한 대로 동작하는 클라이언트의 서버가 본 것과 같아요.

시대 선택은 세 클라이언트 모두에서 같은 방식으로 동작해요.

연결되면 협상된 시대가 연결 헤더와 Connection Info에 보고됩니다. 현대 연결에서는 server/discover가 capabilities(extensions 포함), instructions, supportedVersions 목록도 제공해요. 서버의 이름과 버전은 결과 _meta의 io.modelcontextprotocol/serverInfo 아래에 도착합니다.

각 시대를 로컬에서 재현하기

아래의 각 섹션은 "Reproduce with ..." 포인터로 끝나며, Inspector 저장소에 딸려 있는 조합 가능한 테스트 서버 중 하나의 JSON 구성을 가리켜요. 저장소를 복제하고 테스트 서버를 빌드한 다음, 섹션이 이름 붙인 구성으로 Inspector를 가리키세요.

git clone https://github.com/modelcontextprotocol/inspector
cd inspector && npm install && npm run build
cd clients/web && npm run test-servers:build

로깅 (Logging)

Legacy

로깅은 세션 범위예요. 클라이언트가 logging/setLevel을 한 번 보내고, 서버는 나머지 세션 동안 그 수준 이상의 notifications/message를 내보냅니다.

Logs 탭은 Set Active Level 선택기와 Set 버튼을 보여 줍니다. 수준을 고르고 Set을 클릭하면 이후 서버 로그가 패널로 스트리밍됩니다.

test-servers/configs/logging-legacy-http.json으로 재현하세요.

Modern

logging/setLevel은 사라졌어요. 대신 클라이언트가 요청별로 각 나가는 요청에 _meta["io.modelcontextprotocol/logLevel"]을 찍어 선택합니다. 서버는 옵트인하지 않은 요청에 대해 notifications/message를 내보내면 안 됩니다(MUST NOT).

따라서 Logs 탭은 Log Level per Request 컨트롤을 보여 줍니다. 수준을 고르면 이후의 모든 요청이 도장을 지니며, Network 탭의 요청 본문에서 볼 수 있어요. 요청을 처리하는 동안 내보낸 로그는 그 요청의 SSE 응답 스트림을 타고 갑니다.

컨트롤을 Off로 설정하면 logLevel 키가 완전히 빠져서, 같은 도구 호출이 어떤 로그도 만들지 않아요. 그 침묵은 버그가 아니라 올바른 동작입니다.

서버별 기본값은 debug예요(Inspector가 디버깅 도구이므로 가장 상세한 수준에서 옵트인). 서버에서 modernLogLevel: "off"를 설정하면 기본적으로 다시 옵트아웃할 수 있어요.

test-servers/configs/logging-modern-http.json으로 재현하세요.


리소스 구독 (Resource subscriptions)

Legacy

리소스에서 Subscribe를 클릭하면 resources/subscribe를 보내요. Subscriptions 섹션은 스트림 장식 없이 URI를 나열합니다. 리소스가 변경되면 서버가 notifications/resources/updated를 내보내고 구독 타일의 마지막 업데이트 시간이 찍혀요.

test-servers/configs/subscriptions-legacy-http.json으로 재현하세요. 이 구성은 또한 update_resource 도구를 서빙해서 알림 왕복을 직접 구동할 수 있게 합니다.

Modern

같은 Subscribe 버튼이 대신 subscriptions/listen 을 보내는데, 필터에 resourceSubscriptions와 resourcesListChanged 옵트인을 담아요. 서버가 notifications/subscriptions/acknowledged를 보내면 구독이 확인됩니다.

구독이 이제 세션 플래그가 아닌 장기 연결 스트림이므로, Subscriptions 섹션은 헤더에 스트림 상태 배지가 생겨 Connecting...에서 Listening으로 이동해요. 스트림이 끊기면 Inspector는 subscriptions/listen을 다시 보내 재연결합니다.

test-servers/configs/subscriptions-modern-http.json으로 재현하세요.


Tasks

Tasks는 프로토콜 시대 사이에서 가장 크게 변하고, Inspector UI 탭이 게이트되는 방식도 포함해요.

Legacy

Tasks 탭은 서버가 capabilities.tasks를 광고할 때 나타납니다. Run as task를 켜고 도구를 실행하면, 탭이 tasks/list로 채워지고 tasks/get으로 폴링됩니다. 완료된 페이로드는 차단 tasks/result 로 가져오고, Cancel은 tasks/cancel을 보냅니다.

test-servers/configs/tasks-legacy-http.json으로 재현하세요.

Modern

Tasks는 확장 (io.modelcontextprotocol/tasks, SEP-2663)이라서, 탭은 capabilities.tasks가 아니라 협상된 확장에 게이트됩니다.

도구를 task로 실행하면 tools/call이 CreateTaskResult(resultType: "task", Protocol과 Network 탭에서 볼 수 있음)를 반환해요. Inspector는 tasks/get만 폴링해요. tasks/list는 없으므로 Refresh는 클라이언트가 이미 아는 핸들을 다시 폴링합니다. 완료된 task는 차단 tasks/result 호출 없이 결과를 인라인해요.

더 많은 정보가 필요한 task는 input_required로 이동하고, 보류 요청 모달(web 클라이언트가 요청이 사용자를 기다릴 때마다 여는 대화 상자)에 내장된 elicitation을 표면화해요. 답하면 inputResponses를 담은 tasks/update 를 보내고 다음 폴링이 완료됩니다.

test-servers/configs/tasks-modern-http.json(도구 modern_task와 modern_input_task)으로 재현하세요.


다중 왕복 도구 결과 (Multi-round tool results / MRTR)

현대 시대에서 도구는 최종 결과 대신 input_required를 반환할 수 있어요. elicitation, sampling 요청, 또는 roots/list 요청을 내장하죠. 클라이언트는 그 내장 요청에 답하고, 호출이 complete에 도달할 때까지 새 JSON-RPC id 아래에서 tools/call을 재시도합니다.

Inspector는 MRTR을 수동으로 구동해서, 각 라운드가 input_required로 태그된 보류 요청 모달에서 멈춰 여러분이 답하기를 기다려요. Protocol 보기는 전체 교환을 별개의 호출이 아니라 하나의 MRTR 대화로 그룹화합니다.

test-servers/configs/mrtr-showcase-http.json은 모든 형태를 하나의 현대 서버에 묶습니다.

도구 검증 내용
mrtr_confirm 단일 elicitation 라운드.
mrtr_two_step requestState로 이어지는 두 개의 elicitation 라운드.
mrtr_sample Sampling 패널로 라우팅되는 내장 sampling 요청.
mrtr_roots 구성된 roots에서 조용히 답하는 내장 roots/list(모달 없음).
mrtr_edge inputRequests 전용 라운드 후 requestState 전용 라운드.
mrtr_loop 결코 완료되지 않아 클라이언트가 MRTR_MAX_ROUNDS 한계에서 멈춤.

레거시 collect_elicitation 패턴(서버가 server.elicitInput을 호출하는 것)은 서버-클라이언트 요청이 허용되지 않는 2026-07-28 연결에서 오류가 나요. MRTR이 그것의 현대 대체물입니다.


도구: 미러링 헤더와 제외 도구

SEP-2243은 도구가 인수를 x-mcp-header로 어노테이션해, Streamable HTTP 클라이언트가 그 인수 값을 Mcp-Param-* 요청 헤더로 미러링하도록 요청할 수 있게 해줍니다.

Inspector는 그 계약의 양면을 Tools 탭에서 표면화해요.

  • 유효한 어노테이션이 있는 도구는 상세 패널에 "Mirrored request headers (SEP-2243)" 섹션을 보여 줍니다. 예: city -> Mcp-Param-City.
  • 유효하지 않은 어노테이션이 있는 도구(예: 공백이 있어 RFC 9110 토큰으로 유효하지 않은 헤더 이름 "Bad Header")는 사이드바에서 "Excluded (SEP-2243)" 구분선 아래에 취소선으로 나타나고, 호버 시 이유를 보여 줍니다. 준수하는 클라이언트는 tools/list에서 그런 도구를 반드시 제거해야 해요. Inspector는 조용히 숨기지 않고 왜 제거됐는지 보여 줍니다.

test-servers/configs/xmcpheader-modern-http.json으로 재현하세요.

Mcp-Param-* 미러링은 브라우저에서 SDK에 의해 건너뜁니다. web 클라이언트에서 미러된 도구를 호출하면 헤더가 빠져서, 엄격한 서버는 -32020(HeaderMismatch, 아래 오류 분류 참고)으로 답합니다. 같은 도구를 CLI나 TUI(둘 다 Node에서 실행)에서 호출하면 올바르게 미러링돼요. 헤더는 Inspector 통제 밖인 SDK 내부의 환경 검사에 의해 버려집니다.

-32602 오류 패널

현대 시대에서 -32602로 거부하는 tools/call은 별개의 오류 패널로 렌더링됩니다.

  • Unknown Tool: 메시지가 서버가 나열하지 않는 도구를 이름 붙일 때. 서버의 tools/list에 없는 어떤 이름을 호출해 재현하세요.
  • Invalid Parameters: 다른 모든 -32602. 위 구성의 trigger_invalid_params 도구로 재현하세요.

두 시대 모두 -32602로 거부해요. 바뀌는 것은 Inspector의 표시 방식뿐입니다. 레거시 연결에서는 일반 JSON-RPC 실패 하나를 얻고, 어느 경우에 걸렸는지 알려면 메시지를 읽어야 해요.


Network와 Protocol: 헤더와 오류 분류

현대 시대는 일련의 Mcp-* HTTP 헤더를 표준화하고 더 풍부한 JSON-RPC 오류 분류(SEP-2243 / SEP-2575)를 도입해요. 두 모니터링 탭이 작업을 나눕니다.

  • Network 탭은 HTTP 보기입니다. 미러된 Mcp-* 헤더가 강조되고 센티널 값이 디코딩돼요.
  • Protocol 탭은 JSON-RPC 보기입니다. 각 사양 오류가 일반 실패가 아닌 구별되게 렌더링돼요.

test-servers/configs/modern-network-http.json은 실제 HTTP 상태와 JSON-RPC 오류 본문을 함께 만드는 네 도구를 서빙합니다. 각 클래스당 하나씩이죠.

도구 HTTP JSON-RPC 코드 의미
trigger_header_mismatch 400 -32020 필수 미러링 헤더가 없거나 잘못됨.
trigger_missing_capability 400 -32021 요청이 서버가 요구하는 클라이언트 기능을 생략함.
trigger_unsupported_version 400 -32022 지원되지 않는 버전. 지원 버전은 data.supported.
trigger_method_not_found 404 -32601 메서드를 찾을 수 없음.

세션 (Sessions)

레거시 Streamable HTTP 연결은 서버가 할당한 세션 ID(Mcp-Session-Id)를 지닐 수 있으며, 클라이언트는 이를 HTTP DELETE로 해체해요. 현대 연결은 세션리스이고 요청별입니다. 세션 ID가 없으면 클라이언트 SDK는 서버에 DELETE를 보내지 않아서, 연결 해제는 순전히 로컬입니다.

이것은 여러분 자신의 테스트 서버에 실질적인 결과를 가져와요. 요청별로 구성되는 무상태 현대 핸들러는 호출 사이에 상태를 잡을 수 없어서, test-servers/configs/subscriptions-modern-http.json이 레거시 대응물과 달리 update_resource 도구를 생략한 이유가 됩니다. 그 변형은 일회용 서버 인스턴스에 대해 실행되어 다음 읽기에는 보이지 않을 것이기 때문이죠.

더 알아보기 (Learn more)