본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 20. 00:24

2026-07-28 MCP 명세: 서버 준비 상태 체크리스트

요약

Model Context Protocol(MCP)의 2026-07-28 개정 명세에 따른 서버 준비 체크리스트를 안내합니다. 이번 업데이트는 전송 계층의 무상태(stateless) 전환, 핸드셰이크 제거, 필수 라우팅 헤더 도입 등 파괴적 변경 사항을 포함합니다.

핵심 포인트

  • MCP 프로토콜이 상태가 없는(stateless) 방식으로 전환됨
  • 기존 initialize 핸드셰이크가 제거되고 모든 요청의 _meta 필드로 정보 전달
  • 세션 ID가 제거되어 수평적 배포 및 스티키 라우팅 요구사항 해소
  • 라우팅 효율을 위해 Mcp-Method, Mcp-Name 등 필수 헤더 도입
  • 상태 유지가 필요한 경우 도구 인자를 통한 명시적 핸들 관리 권장

다음 Model Context Protocol (MCP) 명세인 2026-07-28은 프로토콜 출시 이후 가장 큰 규모의 개정판입니다. 2026년 5월 21일에 출시 후보(release candidate)가 확정되었으며, 최종 명세는 7월 28일에 발행됩니다. 여기에는 전송(transport), 권한 부여(authorization), 그리고 도구 스키마(tool schemas) 처리 방식에 대한 파괴적 변경 사항(breaking changes)이 포함되어 있습니다.

오늘날 2025-11-25 버전에 맞춰 올바르게 작동하는 서버가 당장 고장 나는 것은 아닙니다. 여기에 언급된 내용 중 현재 시점의 취약점은 없습니다. 하지만 이러한 변경 사항 중 여러 가지는 단순한 호환성 문제를 넘어 보안 속성(security properties)에 해당합니다. 요청 라우팅 무결성(request routing integrity), 교차 사용자 캐시 범위(cross-user cache scope), 스키마 기반 페치 동작(schema-driven fetch behavior)이 모두 이번 개정판에서 다뤄집니다. 이 체크리스트는 서버 운영자가 7월 28일 이전에 처리해야 할 변경 사항을 안내하며, 보안상의 영향이 있는 곳마다 이를 지적합니다.

아래의 모든 내용은 출시 후보(release candidate)를 기준으로 설명합니다. 세부 사항은 7월 28일 최종 확정 전까지 변경될 수 있으므로, 배포 전 공식 명세를 통해 검증하십시오.

전송 (Transport): 상태가 없는(stateless) 핵심

이것이 가장 주요한 변경 사항입니다. MCP는 프로토콜 계층에서 상태가 없는(stateless) 방식으로 변하며, 대부분의 마이그레이션 작업이 이 부분에 집중되어 있습니다.

핸드셰이크(handshake)와 세션의 제거

initialize/initialized 핸드셰이크가 제거되었습니다 (SEP-2575). 프로토콜 버전, 클라이언트 정보, 클라이언트 기능(capabilities)은 더 이상 연결 시점에 한 번 교환되지 않으며, 모든 요청의 _meta 필드에 포함되어 전달됩니다. 동일한 SEP는 새로운 탐색 앵커(discovery anchor)로 server/discover를 추가합니다. 서버는 이를 반드시 구현해야 하며, 클라이언트는 사전에 필요한 경우 이를 통해 서버의 기능을 가져옵니다. 핸드셰이크가 사라짐에 따라, server/discover에 응답할 수 없는 서버와는 협상(negotiation)을 진행할 수 없습니다.

Mcp-Session-Id 헤더와 해당 헤더가 담고 있던 프로토콜 수준의 세션 또한 제거되었습니다 (SEP-2567). 이제 어떤 요청이든 어떤 서버 인스턴스로든 도달할 수 있습니다. 수평적 배포(horizontal deployments)가 의존했던 스티키 라우팅(sticky routing) 및 공유 세션 저장소는 더 이상 프로토콜 계층에서 요구되지 않습니다.

만약 서버가 호출 간에 상태(state)를 유지해야 한다면, 도구(tool)로부터 명시적인 핸들(handle) — 예: basket_id, browser_id — 을 생성하고, 모델이 이를 일반적인 인자(argument)로 다시 전달하도록 하세요. 이렇게 하면 상태는 전송 메타데이터(transport metadata)에 숨겨진 것이 아니라, 가시적인 도구 입력(tool input)이 됩니다.

필수 라우팅 헤더 (Required routing headers)

Streamable HTTP 전송 계층은 이제 로드 밸런서(load balancers), 게이트웨이(gateways), 속도 제한기(rate-limiters)가 본문(body)을 읽지 않고도 작업을 기반으로 라우팅할 수 있도록 Mcp-MethodMcp-Name 헤더(SEP-2243)를 요구합니다. 또한 요청에는 MCP-Protocol-Version이 포함됩니다.

서버는 헤더와 본문이 일치하지 않는 요청을 거부해야 합니다. 이는 단순한 편의를 위한 것이 아니라 요청 무결성(request-integrity) 체크입니다. 라우팅 헤더와 본문의 실제 메서드(method) 간의 불일치는 스머글링(smuggling) 및 혼란 라우팅(confused-routing) 공격이 악용하는 바로 그 모호함의 유형입니다. 일치 여부를 강제하세요. 헤더를 기준으로 라우팅하고 본문을 실행하는 방식을 취해서는 안 됩니다.

체크리스트 (Checklist)

  • _meta에 프로토콜 버전, 클라이언트 정보 및 기능(capabilities)을 포함하는 자립형(self-contained) 요청을 수락할 것
  • 기능 협상(capability negotiation)을 위한 server/discover를 구현할 것
  • Mcp-Session-Id에 대한 의존을 중단하고 스티키 세션(sticky sessions) 요구를 중단할 것
  • Mcp-MethodMcp-Name을 요구하고, 헤더와 본문의 불일치를 거부할 것
  • 호출 간의 모든 상태를 모델이 볼 수 있는 명시적인 핸들(handles)로 이동할 것

서버-클라이언트 요청 (Server-to-client requests)

상태가 없는(stateless) 프로토콜이라 하더라도, 서버가 호출 중간에 클라이언트에게 무언가를 요청할 수 있는 방법은 여전히 필요합니다. 두 가지 변경 사항을 통해 지속적인 연결(persistent connection) 없이도 해당 흐름을 재구축할 수 있습니다.

활성 처리 중에만 유도 (Elicitation only during active processing)

서버가 시작하는 요청(Server-initiated requests)은 이제 서버가 클라이언트의 요청을 활발하게 처리하는 동안에만 발행될 수 있습니다 (SEP-2260). 이전 버전에서는 이를 권장했으나, 이제는 필수 사항입니다.

보안 가치는 구체적입니다. 사용자는 갑작스럽게 프롬프트(prompt)를 받게 되지 않으며, 모든 유도(elicitation)는 사용자나 그들의 에이전트(agent)가 시작한 동작으로 거슬러 올라갑니다. 요청되지 않은 서버 주도형 프롬프트는 이제 명세 위반(spec violation)이며, 이는 프롬프트를 통한 사회 공학적 공격(social-engineering-via-prompt)이라는 일련의 행위들을 모호한 것이 아닌 탐지 가능한 것으로 만듭니다.

멀티 라운드 트립(Multi round-trip) 결과

서버 전송 이벤트(Server-Sent Events, SSE) 스트림을 계속 열어두는 대신, 서버는 불투명한 requestState를 포함하는 InputRequiredResult를 반환합니다 (SEP-2322). 클라이언트는 답변을 수집하고 inputResponses와 에코(echoed)된 requestState를 포함하여 원래의 호출을 재발행하며, 어떤 인스턴스라도 이 재시도(retry)를 이어받을 수 있습니다.

requestState가 다시 돌아올 때는 신뢰할 수 없는 것으로 취급하십시오. 이는 서버를 떠나 클라이언트 측에 머물다가 다시 돌아옵니다. 수정된 requestState가 미완료된 작업을 재실행(replay)하거나 권한을 상승(escalate)시키지 못하도록 무결성을 보호(Integrity-protect)하십시오 — 즉, 서명(sign)하거나 암호화(encrypt)해야 합니다. 검증 없이 이를 신뢰할 수 있는 서버 상태로 역직렬화(deserialize)하지 마십시오.

체크리스트

  • 클라이언트 호출을 처리하는 동안에만 서버 주도형 요청을 발행할 것
  • SSE 스트림을 열어두는 대신 InputRequiredResult를 반환할 것
  • requestState의 무결성을 보호하고 재시도 시 이를 검증할 것

캐싱(Caching) 및 트레이싱(Tracing)

세 가지 작은 변경 사항은 결과적인 트래픽을 운영하기 더 쉽게 만들며, 그중 두 가지는 주의를 기울여야 할 경계를 가로지르는 데이터를 포함합니다.

캐시 범위(Cache scope)는 테넌시(tenancy) 경계입니다

목록(List) 및 리소스 읽기(resource-read) 결과에는 이제 HTTP Cache-Control을 모델로 한 ttlMscacheScope가 포함됩니다 (SEP-2549). 클라이언트는 tools/list 응답이 정확히 얼마나 오랫동안 최신 상태를 유지하는지, 그리고 사용자 간에 공유해도 안전한지 알 수 있습니다.

cacheScope는 이것이 보안 결정이 되는 지점입니다. 만약 서버가 사용자별 또는 테넌트별 도구 인터페이스를 노출하면서 결과를 공유 가능하다고 표시하면, 클라이언트가 한 사용자의 도구 목록을 다른 사용자에게 제공할 수 있습니다. cacheScope를 응답이 드러내는 실제 민감도와 일치하도록 설정하고, 불확실할 때는 더 좁은 범위(narrower scope)를 기본값으로 설정하십시오.

트레이스 컨텍스트 전파(Trace context propagation)

_meta 내의 W3C Trace Context 전파(propagation)가 문서화되었으며, traceparent, tracestate, baggage 키 이름이 수정되었습니다 (SEP-414). 트레이스(trace)는 클라이언트 SDK, 서버, 그리고 서버가 호출하는 하위 시스템(downstream)을 거쳐 호출을 따라갈 수 있으며, OpenTelemetry 호환 백엔드에서 하나의 스팬 트리(span tree)로 나타납니다.

baggage는 주의 깊게 살펴봐야 할 필드입니다. 설계상 임의의 키-값(key-value) 데이터를 하위 시스템으로 전파하므로 유용하지만, 민감한 값이 보아서는 안 될 시스템으로 넘어가는 경로가 될 수도 있습니다. baggage에 무엇을 넣을지 신중하게 결정하고, 모든 것을 전달하기보다는 신뢰 경계(trust boundaries)에서 이를 제거하거나 세척(scrub)하십시오.

체크리스트 (Checklist)

  • 목록(list) 및 리소스 읽기(resource-read) 결과에 정확한 ttlMs를 발행할 것
  • 사용자별 또는 테넌트별(per-tenant) 민감도에 맞춰 cacheScope를 설정할 것
  • 수정된 트레이스 키 이름을 사용하고, baggage가 경계를 넘어 무엇을 운반할지 제어할 것

권한 부여 강화 (Authorization hardening)

6개의 SEP가 권한 부여(authorization) 명세를 OAuth 2.0 및 OpenID Connect가 배포되는 방식과 더 밀접하게 일치하도록 조정합니다. 이는 자체 권한 부여 서버를 운영하거나 서버 앞단에서 인증을 중개(broker auth)하는 운영자들에게 가장 중요합니다.

권한 부여 서버는 RFC 9207에 따라 권한 부여 응답 시 iss 파라미터를 제공해야 합니다 (SEP-2468). 이제 클라이언트는 이를 검증할 것으로 예상되며, 향후 버전에서는 이를 누락한 응답을 거부할 것입니다. 이는 MCP의 단일 클라이언트-다중 서버(single-client, many-server) 패턴에서 발생할 가능성이 높은 혼동 공격(mix-up attack)에 대한 저비용 완화책입니다. 따라서 아직 제공하고 있지 않다면 지금부터 iss를 제공하기 시작하십시오.

남은 변경 사항들은 규모는 작지만 함께 처리할 가치가 있습니다: 동적 클라이언트 등록 (Dynamic Client Registration) 시 OpenID Connect의 application_type을 지원하여 데스크톱 및 CLI 클라이언트가 기본값인 "web"으로 설정되어 거부되지 않도록 합니다 (SEP-837); 등록된 자격 증명(credentials)을 발급 권한 서버의 issuer에 바인딩하고 리소스가 마이그레이션될 때 재등록합니다 (SEP-2352); OIDC 스타일의 서버로부터 리프레시 토큰 (refresh tokens)을 요청하는 방법을 문서화합니다 (SEP-2207); 그리고 명확해진 범위 누적 (scope-accumulation) 및 .well-known 디스커버리 (discovery) 규칙을 따릅니다 (SEP-2350, SEP-2351).

체크리스트

  • 권한 부여 응답 (authorization responses) 시 iss 제공
  • 동적 클라이언트 등록 (Dynamic Client Registration) 시 application_type 준수
  • 자격 증명을 발급자 (issuer)에 바인딩하고 리소스 마이그레이션 시 재등록
  • 문서화된 리프레시 토큰 (refresh-token), 범위 누적 (scope-accumulation), 디스커버리 (discovery) 규칙 준수

도구 스키마 (Tool schemas)

도구의 inputSchemaoutputSchema가 완전한 JSON Schema 2020-12로 격상되었습니다 (SEP-2106). 입력 스키마 (Input schemas)는 type: "object" 루트를 유지하지만, 이제 합성 (oneOf, anyOf, allOf), 조건문 (conditionals), 그리고 참조 ($ref, $defs)를 허용합니다. 출력 스키마 (Output schemas)는 제한이 없으며, structuredContent는 객체뿐만 아니라 모든 JSON 값일 수 있습니다.

이 변경 사항에는 두 가지 보안 제약 사항이 포함되어 있으며, 명세는 이를 요구 사항으로 규정합니다. 구현체는 외부 $ref URI를 자동으로 역참조 (auto-dereference)해서는 안 됩니다. $ref가 외부 URL을 가리키는 스키마를 그대로 따르면 SSRF 및 무제한 페치 (unbounded-fetch) 벡터가 됩니다. 또한, 구현체는 스키마 깊이와 검증 시간을 제한해야 합니다. 깊게 중첩되거나 재귀적인 스키마는 서비스 거부 (denial-of-service) 입력이 될 수 있기 때문입니다. 서버가 클라이언트가 제공하거나 제3자가 제공한 스키마를 검증한다면, 두 가지 모두를 강제하십시오.

이와 별개로, 리소스 누락에 대한 에러 코드(error code)가 MCP 커스텀 코드인 -32002에서 JSON-RPC 표준인 -32602 Invalid Params로 변경됩니다 (SEP-2164). 코드 내에 리터럴 -32002와 일치하는 부분이 있다면 업데이트하십시오.

체크리스트

  • JSON Schema 2020-12 입출력 스키마 (input and output schemas) 수용
  • 외부 $ref URI를 자동으로 역참조 (auto-dereference) 하지 말 것
  • 스키마 깊이 (schema depth) 및 검증 시간 (validation time) 제한
  • 리소스 누락 시 -32602를 반환하고, -32002와 일치하는 모든 항목을 업데이트할 것

Deprecations (중단 예정 기능)

새로운 기능 라이프사이클 정책 (SEP-2577)에 따라 Roots, Sampling, Logging 기능이 중단 예정 (deprecated) 상태가 됩니다. 이는 주석(annotation) 기반의 중단 예정 사항입니다. 즉, 이번 릴리스와 향후 1년 이내에 발표되는 모든 명세 버전에서 계속 작동하며, 제거를 위해서는 별도의 SEP가 필요합니다. 7월 28일에 강제 전환이 이루어지는 것은 아니지만, 지금부터 대체 방안을 계획하십시오.

문서화된 대체 방안은 다음과 같습니다: Roots 대신 도구 파라미터 (tool parameters), 리소스 URI (resource URIs) 또는 서버 설정 (server configuration)을 사용하십시오. Sampling 대신 LLM 제공업체 API와의 직접 통합을 사용하십시오. Logging 대신 stderr (stdio 전송 방식의 경우) 또는 OpenTelemetry를 사용하십시오.

Checklist (체크리스트)

  • Roots, Sampling 또는 Logging의 사용 현황을 조사하십시오.
  • 라이프사이클 제한 시간이 만료되기 전에 문서화된 대체 방안으로의 마이그레이션 (migration)을 계획하십시오.

Extensions (확장 기능)

확장 기능 (Extensions)이 이제 일급 객체 (first-class)가 되었습니다 (SEP-2133). 확장 기능은 역도메인 ID (reverse-DNS IDs)로 식별되며, 클라이언트와 서버의 기능 (capabilities) 내 extensions 맵을 통해 협상되고, 명세와는 독립적으로 버전이 관리됩니다.

이번 릴리스에는 두 가지 공식 확장 기능이 포함됩니다. Tasks 기능은 실험적인 핵심 기능에서 재설계된 상태 비저장 라이프사이클 (stateless lifecycle)을 가진 확장 기능으로 승격되었습니다. 서버는 tools/call에 대해 태스크 핸들 (task handle)로 응답하고, 클라이언트는 tasks/get, tasks/update, tasks/cancel을 통해 이를 제어합니다. tasks/list는 세션 없이 안전하게 범위를 지정할 수 없기 때문에 제거되었습니다 (SEP-2663). 2025-11-25 실험적 Tasks API를 기반으로 구축한 모든 사용자는 마이그레이션이 필요합니다.

MCP Apps (SEP-1865)를 통해 서버는 호스트가 샌드박스 처리된 iframe에서 렌더링할 수 있는 대화형 HTML 인터페이스를 제공할 수 있습니다. 도구 (Tools)는 UI 템플릿을 사전에 선언하므로, 호스트는 실행 전 템플릿을 프리페치 (prefetch), 캐싱 및 보안 검토를 수행할 수 있습니다. 또한 UI를 통해 시작된 모든 작업은 직접적인 도구 호출과 동일한 감사 (audit) 및 동의 경로를 거칩니다.

Checklist (체크리스트)

  • extensions 기능 맵 (capability map)을 통해 확장 기능 (extensions) 협상
  • 실험적인 Tasks 사용 사례를 확장 라이프사이클 (extension lifecycle)로 마이그레이션
  • UI를 출시하는 경우, 호스트 검토를 위해 MCP Apps 템플릿을 사전에 선언

지금 해야 할 일 (What to do now)

5월 21일 잠금 (lock)과 7월 28일 최종 확정 사이의 10주 기간은 정확히 이 목적을 위해 존재합니다: 변경 사항이 규범 (normative)이 되기 전에 실제 워크로드 (workloads)를 대상으로 검증하는 것입니다. 원격 MCP 서버를 운영하거나, 자체 권한 부여 (authorization)를 실행하거나, 실험적인 Tasks API를 기반으로 구축하고 있다면 마이그레이션 브랜치 (migration branch)를 시작하십시오. 전송 (transport) 재작업이 가장 큰 부분이며, 인증 (auth) 및 스키마 (schema) 제약 조건은 보안 측면에서 실질적인 영향력을 가집니다.

이 중 대부분은 서버 외부에서 확인 가능합니다 — 라우팅 헤더 (routing-header) 강제 적용, 목록 응답 (list responses)의 캐시 범위 (cache scope), $ref 처리, iss 파라미터 등이 이에 해당합니다. Gated는 배포된 MCP 서버를 이러한 항목 및 기타 체크 라이브러리를 기준으로 검사하며, 각 항목을 준수 (conformance)보안 (security) 제품군에 매핑하고, 모든 발견 사항에 대해 재현 방법을 제공합니다. 이는 네트워크 내부에서 접근 가능한 프라이빗 및 내부 서버를 포함합니다. 보안 팀이 7월 28일 이전에 서버의 상태를 서면으로 확인하고자 한다면, 바로 이러한 결과물을 얻게 될 것입니다.

— Gustavo, Gated

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0