주요 변경 사항

주요 변경 사항 (Key Changes)

이전 개정 2025-11-25 이후 Model Context Protocol (MCP) 사양에 적용된 변경 사항을 정리한 페이지예요. 프로토콜이 무상태(stateless)로 바뀌고, 다중 왕복 요청(MRTR) 패턴이 도입되는 등 핵심적인 변화가 많아요.

출처: 문서

본문

이 문서는 이전 개정 2025-11-25 이후 Model Context Protocol (MCP) 사양에 적용된 변경 사항을 나열해요.

주요 변경 사항 (Major changes)

  1. 프로토콜 수준 세션과 Streamable HTTP 트랜스포트의 Mcp-Session-Id 헤더를 제거한다. 목록 엔드포인트(tools/list, resources/list, prompts/list)는 더 이상 연결별로 달라지지 않아요. 호출 간 상태가 필요한 서버는 서버가 발행한 명시적 핸들(server-minted handles)을 일반 도구 인자로 전달해서 사용해요 (SEP-2567).

  2. MCP를 무상태로 만든다: initialize/notifications/initialized 핸드셰이크를 제거한다. 이제 모든 요청이 _meta에 프로토콜 버전과 클라이언트 기능을 담는다 (io.modelcontextprotocol/protocolVersion, io.modelcontextprotocol/clientCapabilities). 클라이언트는 각 요청에서 자신을 식별해야 SHOULD 하고(io.modelcontextprotocol/clientInfo), 서버는 각 결과의 _meta에서 자신을 식별해야 SHOULD 한다(io.modelcontextprotocol/serverInfo). 버전 불일치는 UnsupportedProtocolVersionError를 반환한다 (SEP-2575).

  3. server/discover를 추가한다: 서버는 지원 프로토콜 버전·기능·정체성을 광고하기 위해 이 RPC를 반드시(MUST) 구현해야 한다. 클라이언트는 MAY 다른 어떤 요청보다 먼저 호출해 미리 버전을 선택하거나, STDIO에서 하위 호환성 조사용으로 사용할 수 있다 (SEP-2575).

  4. HTTP GET 엔드포인트와 resources/subscribe/resources/unsubscribe를 subscriptions/listen으로 대체한다: 서버에서 클라이언트로의 변경 알림을 위한 단일 장수명(long-lived) POST-응답 스트림이에요. 클라이언트는 특정 유형(toolsListChanged, promptsListChanged, resourcesListChanged, resourceSubscriptions)에 옵트인하고, 서버는 알림을 수신 확인하고 io.modelcontextprotocol/subscriptionId로 태그를 단다. notifications/progress, notifications/message 같은 요청 범위 알림은 subscriptions/listen 스트림이 아니라 관련 요청의 응답 스트림으로 계속 흐른다 (SEP-2575).

  5. ping, logging/setLevel, notifications/roots/list_changed를 제거한다. 로그 레벨은 이제 _meta의 io.modelcontextprotocol/logLevel로 요청별 설정한다. 서버는 이 필드를 포함하지 않은 요청에 대해 notifications/message를 방출해서는 MUST NOT 안 된다 (SEP-2575).

  6. 실험적 tasks를 핵심 프로토콜에서 공식 확장(io.modelcontextprotocol/tasks)으로 옮긴다. 재설계된 확장은 블로킹 tasks/result 메서드를 tasks/get을 통한 폴링과 클라이언트→서버 입력용 tasks/update로 대체하고, tasks/list를 제거하며, 서버가 요청별 옵트인 없이 작업 핸들을 무단으로(unsolicited) 반환할 수 있게 한다 (SEP-2663).

  7. MRTR (Multi Round-Trip Requests) 패턴을 도입한다. 이 패턴은 roots/list, sampling/createMessage, elicitation/create 같은 서버 발신 요청을 보내던 이전 방식을 대체해요. 서버는 inputRequests 필드에 요청 처리에 필요한 추가 정보를 담은 InputRequiredResult (resultType: "input_required")를 반환한다. 클라이언트는 원래 요청을 재시도하면서 inputResponses로 응답한다 (SEP-2322).

  8. 모든 결과가 이제 필수 resultType 필드를 담는다: 일반 결과는 "complete", 다중 왕복 요청 중간 결과는 "input_required". 클라이언트는 필드가 없는 이전 프로토콜 서버의 결과를 "complete"로 취급해야 MUST 한다 (SEP-2322).

  9. Streamable HTTP 트랜스포트에서 SSE 스트림 재개 가능성과 메시지 재전송(Last-Event-ID 헤더와 SSE 이벤트 ID)을 제거한다. 끊긴 응답 스트림은 진행 중이던 요청을 잃어버리며, 클라이언트는 MUST 이를 새 요청 ID로 새 요청으로 다시 발행해야 한다 (SEP-2575).

사소한 변경 사항 (Minor changes)

  1. 핵심 프로토콜을 넘어선 선택적 확장을 지원하기 위해 ClientCapabilities와 ServerCapabilities에 extensions 필드를 추가한다.
  2. _meta 키(traceparent, tracestate, baggage)에 대한 OpenTelemetry 추적 컨텍스트 전파 규칙을 문서화한다 (SEP-414).
  3. 서버는 클라이언트 측 캐싱을 가능하게 하고 LLM 프롬프트 캐시 히트율을 높이기 위해 tools/list에서 도구를 결정적 순서로 반환해야 SHOULD 한다.
  4. Streamable HTTP POST 요청에 표준 MCP 요청 헤더(Mcp-Method, Mcp-Name)를 요구하고, x-mcp-header를 통한 도구 파라미터의 커스텀 헤더 지원을 추가한다 (SEP-2243).
  5. 새 CacheableResult 인터페이스를 통해 tools/list, prompts/list, resources/list, resources/read, resources/templates/list가 반환하는 결과에 ttlMs와 cacheScope 필드를 요구한다. ttlMs는 클라이언트가 응답을 캐시하고 폴링을 줄일 수 있게 하는 신선도 힌트(밀리초)이고, cacheScope("public" 또는 "private")는 공유 중간자(intermediaries)가 응답을 캐시할 수 있는지 제어한다. 두 필드 모두 기존 listChanged 알림을 보완한다 (SEP-2549).
  6. 리소스 없음 오류 코드를 JSON-RPC 사양에 맞춰 -32002에서 -32602 (Invalid Params)로 변경한다.
  7. 인증 서버는 RFC 9207에 따라 인증 응답에 iss 파라미터를 포함해야 SHOULD 하고, MCP 클라이언트는 인증 코드를 교환하기 전에 기록된 issuer에 대해 있는 그대로의 iss를 검증해야 MUST 한다 (SEP-2468).
  8. OpenID Connect 리다이렉트 URI 충돌을 피하기 위해 MCP 클라이언트가 Dynamic Client Registration 중 적절한 application_type을 지정하도록 요구한다 (SEP-837).
  9. 클라이언트 자격 증명이 이를 발행한 인증 서버에 바인딩된다고 명확히 한다: 클라이언트는 MUST 지속된 자격 증명을 issuer 식별자로 키를 잡고, MUST NOT 다른 인증 서버와 재사용하며, 인증 서버가 바뀌면 MUST 재등록해야 한다 (SEP-2352).
  10. inputSchema와 outputSchema는 모든 JSON Schema 2020-12 키워드를 허용하도록 느슨하게 하고, structuredContent는 모든 JSON 값을 허용하도록 느슨하게 한다. $ref 해석 요구사항과 composition 키워드 리소스 경계를 추가한다 (SEP-2106).
  11. notifications/elicitation/complete 알림과 2025-11-25에서 도입된 URL 모드 elicitation 요청의 elicitationId 필드를 제거한다. Multi Round-Trip Requests 패턴 아래에서 클라이언트는 원래 요청을 재시도함으로써 대역 외(out-of-band) 상호작용의 결과를 알게 되므로, 서버 발신 완료 신호와 이를 상관시키는 데 쓰던 식별자는 더 이상 프로토콜에 맞지 않아요. 재시도에 걸쳐 elicitation을 상관시켜야 하는 서버는 자신의 식별자를 requestState에 인코딩한다.
  12. JSON-RPC 서버 오류 범위를 분할하는 오류 코드 할당 정책을 정의한다: -32000 ~ -32019는 구현 정의로 유지(기존 SDK 사용은 그대로 인정)되고, -32020 ~ -32099는 MCP 사양에 예약된다. 이 초안에서 도입된 오류 코드를 그에 맞춰 재번호한다 — HeaderMismatch -32001 → -32020, MissingRequiredClientCapability -32003 → -32021, UnsupportedProtocolVersion -32004 → -32022 — 그리고 기존에 트랜스포트 산문에만 있었던 HeaderMismatchError를 스키마에 추가한다.

폐기됨 (Deprecated)

여기에 나열된 기능은 사양의 일부로 남아 있지만 기능 수명주기와 폐기 정책 아래에서 제거가 예정되어 있어요. 새 구현은 이를 채택하지 말아야 해요. 폐기 기능 레지스트리가 현재 Deprecated 상태인 모든 기능을 추적해요.

  1. Roots, Sampling, Logging 기능을 폐기한다 (SEP-2577). 이 기능들은 폐기 기간 동안 완전히 동작하지만, 새 구현은 지원을 추가하지 말아야 해요. 제안된 이전 경로: Roots 대신 도구 파라미터·리소스 URI·서버 설정으로 디렉터리나 파일을 전달하고, Sampling 대신 LLM 제공자 API에 직접 통합하고, Logging 대신 stderr(stdio)로 로깅하거나 OpenTelemetry를 사용한다.

  2. HTTP+SSE 트랜스포트(프로토콜 버전 2025-03-26부터 폐기)를 기능 수명주기 정책 아래에서 Deprecated로 재분류한다 (SEP-2596). Streamable HTTP로 이전한다.

  3. includeContext 값 "thisServer"와 "allServers"(프로토콜 버전 2025-11-25부터 소프트 폐기)를 Deprecated로 재분류한다 (SEP-2596). 필드를 생략하거나 "none"을 사용한다. 이 값들은 Sampling 기능 자체보다 늦어도 함께 제거될 것이다.

  4. 클라이언트 등록 메커니즘으로 OAuth 2.0 Dynamic Client Registration Protocol (RFC7591)을 Client ID Metadata Documents에 유리하게 폐기한다 (PR #2858). Client ID Metadata Documents를 지원하지 않는 인증 서버와의 하위 호환성을 위해 계속 사용 가능하다.

기타 스키마 변경 (Other schema changes)

  1. schema.json이 이제 minimum/maximum/default의 TypeScript 정의가 정수뿐 아니라 number임을 올바르게 반영한다. 이는 --defaultNumberType integer로 생성기를 실행한 데서 비롯됐다 (PR#2710).

거버넌스와 프로세스 업데이트 (Governance and process updates)

  1. Active, Deprecated, Removed 기능 상태를 정의하고, 최소 12개월 폐기 기간을 두며, 폐기 기능 레지스트리를 갖춘 사양 기능 수명주기와 폐기 정책을 채택한다 (SEP-2596).

프로세스 변경 (Process changes)

  1. seps/ 디렉터리의 마크다운 파일, PR 기반 번호 부여, 스폰서 책임, PR 레이블을 통한 상태 관리를 갖춘 PR 기반 SEP 워크플로를 공식화한다 (SEP-1850).

전체 변경 로그 (Full changelog)

마지막 프로토콜 개정 이후 적용된 모든 변경 사항의 전체 목록은 GitHub에서 볼 수 있어요.

더 알아보기 (Learn more)