
MCP 이행 전에 세션 의존성을 검출하는 Python
요약
MCP 프로토콜의 스테이트리스(Stateless) 전환에 대비하여, 세션 의존성을 검출하고 상태 핸들(Handle)을 명시적으로 관리하는 방법을 다룹니다. Python을 이용해 툴 호출 트레이스에서 상태 생성과 전달이 적절히 이루어지는지 감사하는 코드를 제안합니다.
핵심 포인트
- MCP 프로토콜 업데이트로 인한 세션 ID 제거 및 스테이트리스화 대응 필요
- 상태 유지를 위해 basket_id와 같은 핸들을 툴 인자로 명시적 전달 권장
- Python을 활용해 툴 호출 트레이스 내 상태 핸들의 생성 및 전달 여부 검증 가능
- 상태 핸들은 식별 용도이며, 보안을 위해 별도의 인가(Authorization) 프로세스 병행 필수
스테이트리스(Stateless)화된 MCP 서버에서, 어디에 남아있던 상태가 사라지는가. 로드 밸런서(Load Balancer) 설정만 고치고 끝내면, 여기서 사고가 난다.
7월 28일에 정식화 예정인 MCP 2026-07-28은, 프로토콜 계층의 initialize / initialized와 Mcp-Session-Id를 제거한다. RC 단계에서는 능력 확인은 server/discover로 옮겨지며, 각 요청이 자신의 프로토콜 정보를 가지는 형태가 된다. 일반적인 라운드 로빈(Round Robin) 하에 배치하기 쉬워지는 것은 확실하다. 다만, 장바구니나 편집 중인 문서까지 사라지는 것은 아니다.
상태를 필요로 한다면, 툴의 반환값으로 basket_id와 같은 핸들(Handle)을 반환하고, 다음 호출에서 인자(Argument)로 전달한다. 이행의 본체는 "세션을 버리는" 작업보다, 이 계약(Contract)을 겉으로 드러내는 작업이라고 생각한다.
구 구성에서는 클라이언트가 어느 서버로 왔는지와 어떤 작업의 연속인지가 Mcp-Session-Id 뒤에 숨기 쉽다. 스테이트리스화 후에도 애플리케이션의 상태는 가질 수 있지만, 툴 호출만을 보고 추적할 수 있는 형태로 만들 필요가 있다.
구 구성과 이행 후의 구성을 도식화하면, 차이점은 여기에 집약된다.
나는 이런 종류의 이행에서 먼저 Ingress의 Sticky 설정을 찾곤 했다. 하지만 먼저 조사해야 할 것은, 후속 툴이 아무런 ID도 받지 않고 동작하고 있지 않은가였다. add_item이나 checkout에 작업 대상의 인자가 없다면, 접속 대상을 아무리 깔끔하게 관리해도 상태는 승계되지 않는다.
이하는 JSON화한 툴 실행 trace에 대해, 핸들의 생성과 전달을 검사하는 최소한의 Python이다. contracts를 자신의 툴 이름과 ID 이름으로 교체하여 사용한다.
from __future__ import annotations
def audit_state_handles(calls: list[dict], contracts: dict[str, dict]) -> list[str]:
known_handles: set[str] = set()
...
Python 3.12.13에서 실행한 출력은 다음과 같았다.
[]
["#2 add_item: basket_id='b-999' 는, 이 trace에서 생성되지 않았다"]
처음에는 "필수 인자가 있는가"만을 보고 있었다. 이렇게 하면 basket_id="적당한 문자열"이 통과된다. 생성 툴의 반환값과 대조하는 검사까지 넣으면, 적어도 테스트용 trace에서 상태의 출처를 추적할 수 있다. 실운용에서는 로그에 툴 이름, 인자의 핸들, 결과의 핸들을 남기면 동일한 검사를 CI로 보낼 수 있다.
이 부분은 섞지 않는 것이 좋다. basket_id는 대상을 가리키기 위한 값이지, 액세스 권한(Access Right)이 아니다. checkout 측에서는 해당 핸들의 소유자나 테넌트(Tenant)를 인증된 주체와 대조한다. ID를 명시함으로써 다른 사용자의 ID를 전달할 수 있게 해서는 안 된다.
또 하나, 서버에서 임의의 타이밍에 통지하는 설계, 구독(Subscription), 접속에 묶인 분리가 필요하다면 스테이트리스화를 서두르지 마라. 2026-07-28 대응 SDK와 클라이언트가 혼재하는 기간은 구 프로토콜을 남겨두는 경로도 필요하다. RC는 최종 사양이 아니므로, 고정된 날짜로 구현을 단정 짓지 않는 것도 중요하다.
이번 변경으로 사라지는 것은 MCP가 관리하던 접속 단위의 상태다. 업무상의 상태까지 없앨 필요는 없다. 오히려 basket_id나 draft_id를 툴 계약으로서 드러내는 편이 trace도 테스트도 장애 조사도 쉬워진다.
이행 전에 상태를 만드는 툴, 상태를 사용하는 툴, 인가를 확인하는 곳을 한 장에 써 내려간다. 이 감사를 수행한 뒤에 Sticky Session을 제거하면, 스테이트리스화는 인프라의 모양 바꾸기로 끝나지 않고, MCP의 툴 설계를 조금 제대로 할 수 있게 된다.
참고:
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기