전체 회차
C-0252026-08-13

MCP 신규 스펙 해설: 세션에서 스테이트리스 프로토콜로

MCP가 세션 기반에서 스테이트리스 요청-응답 구조로 바뀐 이유와 MRTR 방식을 정리한다.

#mcp#modelcontextprotocol#statelessprotocol#mrtr#python-sdk#llm-agent#api-design
01

영상

· video
3:58youtu.be/sY1cTlzH9kw
03

학습 자료

· material

요지

  • MCP는 초기화 후 세션을 유지하며 통신하는 세션 중심 프로토콜에서, 요청마다 필요한 정보를 자체 포함하는 스테이트리스 프로토콜로 바뀌었다.
  • 스테이트리스 전환은 MCP 서버가 로컬 환경을 넘어 여러 대로 로드밸런싱되는 원격·클라우드 환경에서 쓰이기 시작했기 때문에 필요해졌다.
  • 기존에는 서버가 처리 중 추가 정보가 필요하면 클라이언트를 역호출할 수 있었지만, 신규 스펙은 MRTR(Multi-Round Trip Request) 구조로 이를 대체했다.
  • MRTR에서는 서버가 정보 부족을 응답으로 알리고 요청을 종료하면, 클라이언트가 필요한 정보를 확보한 뒤 다시 요청을 보낸다.
  • 공식 파이썬 SDK v2의 FastMCP → MCPServer 이름 변경은 표면적 변화일 뿐, 실질은 프로토콜이 stateful에서 request-response 기반 stateless로 성숙한 것이다.
  • 이 변화는 MCP가 로컬 툴 연결 규격을 넘어 클라우드 환경에서 대규모로 동작하는 에이전트 인프라를 위한 웹 프로토콜로 발전하고 있음을 보여준다.

개요

MCP(Model Context Protocol)는 LLM 애플리케이션이 외부 툴·데이터 소스와 통신하기 위한 표준 프로토콜이다. 2026년 7월 28일 공개된 신규 스펙과 공식 파이썬 SDK v2 업데이트는 단순한 클래스명 변경(FastMCP → MCPServer)처럼 보이지만, 실제로는 프로토콜이 세션 기반 구조에서 스테이트리스 구조로 전환되는 근본적인 변화를 담고 있다. MCP가 로컬 컴퓨터에서 툴 몇 개를 연결하는 용도를 넘어, 클라우드 환경에서 대규모로 운영되는 에이전트 인프라의 일부로 쓰이기 시작하면서 이런 변화가 필요해졌다.

이 변화를 이해하면 MCP 서버를 설계할 때 왜 세션 상태에 의존하면 안 되는지, 그리고 서버가 클라이언트에게 추가 정보를 요청하는 방식이 왜 달라졌는지 알 수 있다. 특히 원격·클라우드 환경에서 MCP 서버를 여러 대 운영할 계획이 있다면 이 변화는 필수적으로 알아야 할 내용이다.

배경 / 사전 지식

  • MCP(Model Context Protocol): LLM이 외부 툴·리소스에 접근하도록 표준화한 프로토콜. 클라이언트(LLM 애플리케이션)와 서버(툴 제공자)로 구성된다.
  • FastMCP: MCP 서버를 쉽게 만들 수 있게 해주는 파이썬 프레임워크. 공식 SDK에 흡수되며 v2에서 클래스명이 MCPServer로 바뀌었다.
  • 세션(session): 클라이언트와 서버가 연결을 맺은 뒤 유지하는 상태. 세션이 있으면 서버는 "이 클라이언트가 누구인지, 지금까지 무엇을 주고받았는지"를 기억한다.
  • 스테이트리스(stateless) 프로토콜: 각 요청이 처리에 필요한 모든 정보를 자체적으로 포함해서, 서버가 이전 요청 상태를 기억하지 않아도 되는 구조. HTTP REST API가 대표적이다.
  • 로드밸런싱: 여러 대의 서버 인스턴스에 요청을 분산시키는 기법. 서버가 상태를 유지하면(stateful) 특정 클라이언트의 요청이 항상 같은 서버 인스턴스로 가야 하므로 로드밸런싱이 어려워진다.

핵심 개념

세션 중심 프로토콜에서 스테이트리스 프로토콜로

기존 MCP는 클라이언트가 서버에 처음 연결되면 initialize 과정을 거쳤다. 클라이언트와 서버가 서로 지원하는 기능(capability)을 교환하고 연결을 초기화한 뒤, 그 연결(세션) 위에서 툴 목록 조회·툴 실행 같은 요청을 처리했다. 즉 클라이언트-서버 사이에 세션이라는 다리가 만들어지고, 그 상태를 유지하면서 요청을 주고받는 구조였다.

신규 스펙은 이 initialize·세션 개념을 크게 단순화했다. 프로토콜 차원에서 서버가 클라이언트별 세션 상태를 계속 들고 있을 필요 없이, 각 요청이 처리에 필요한 정보를 스스로 포함해 독립적으로 전달되는 구조로 바뀌었다.

MRTR (Multi-Round Trip Request)

기존 MCP에는 서버가 작업 도중 추가 정보(예: 사용자 확인)가 필요하면 클라이언트를 역으로 호출해 "이걸 사용자에게 물어봐 달라"고 요청할 수 있는 구조가 있었다. 클라이언트→서버 단방향 호출이 아니라 서버도 클라이언트를 부를 수 있는 양방향 구조였던 것이다.

신규 스펙은 이를 MRTR(Multi-Round Trip Request) 구조로 대체했다. 서버는 정보가 부족하면 클라이언트를 역호출하는 대신 "정보가 더 필요하다"는 응답을 반환하며 요청을 일단 종료한다. 클라이언트는 그 응답을 받아 필요한 정보를 확보한 뒤, 다시 서버에 요청을 보낸다. 이 방식은 웹에서 일반적으로 쓰이는 HTTP request-response 구조와 훨씬 잘 맞는다.

작동 원리

  1. (기존) 클라이언트가 서버에 연결 → initialize로 capability 교환 → 세션 생성.
  2. (기존) 세션 위에서 클라이언트가 툴 목록 조회·툴 실행 요청 → 서버가 처리 중 추가 정보가 필요하면 클라이언트를 역호출해 값을 얻고 계속 처리.
  3. (신규) 클라이언트가 요청을 보낼 때 필요한 컨텍스트를 요청 자체에 포함 → 서버는 세션 상태 없이 그 요청만으로 처리 가능.
  4. (신규) 서버가 처리 중 정보가 부족하면 "정보 필요" 응답을 반환하고 요청 종료(1차 round trip).
  5. (신규) 클라이언트가 필요한 정보를 확보한 뒤 그 정보를 포함해 다시 요청 전송(2차 round trip) → 서버가 필요한 정보를 모두 갖췄으므로 처리 완료.
  6. 이 구조 덕분에 서버를 여러 대로 복제해 로드밸런서 뒤에 두어도, 각 요청이 어느 서버 인스턴스로 가든 독립적으로 처리할 수 있다.

코드 예시

영상은 개념 설명 위주라 실제 코드를 보여주지는 않는다. 아래는 파이썬 SDK v2에서 이름이 바뀐 MCPServer(구 FastMCP)로 스테이트리스 툴을 정의하는 전형적인 형태를, 공식 SDK의 일반적인 사용 패턴에 맞춰 정리한 예시다.

from mcp.server import MCPServer  # v2: 구 FastMCP

server = MCPServer("my-tool-server")

@server.tool()
def search_docs(query: str, max_results: int = 5) -> list[str]:
    """요청 하나에 필요한 정보(query, max_results)가 모두 담겨 있어
    서버가 이전 요청 상태를 기억하지 않아도 독립적으로 처리할 수 있다."""
    return run_search(query, limit=max_results)

if __name__ == "__main__":
    # 여러 인스턴스를 띄워 로드밸런서 뒤에 둬도
    # 요청 단위로 스테이트리스하게 처리되므로 문제없이 확장된다.
    server.run(transport="http")
  • MCPServer: v2에서 FastMCP를 대체한 클래스명. 이름만 바뀐 게 아니라 내부적으로 세션 관리 로직이 단순화됐다.
  • search_docs 같은 툴 함수는 호출마다 필요한 인자를 모두 받으므로, 서버가 별도로 "이 클라이언트가 이전에 뭘 물어봤는지" 기억할 필요가 없다.
  • 정보가 더 필요한 경우(MRTR) SDK는 "추가 입력 필요" 상태를 응답으로 반환하는 방식을 지원하며, 클라이언트가 이를 받아 다시 요청하는 흐름으로 처리된다.

함정·실수

  • 기존 코드에서 세션 상태에 의존하고 있었다면 그대로 마이그레이션이 안 된다. 이전 요청에서 저장해 둔 값을 다음 요청에서 꺼내 쓰는 방식으로 짠 서버 로직은, 스테이트리스 구조에서는 각 요청에 필요한 값을 명시적으로 다시 전달해야 한다.
  • FastMCP → MCPServer 이름만 바꾸고 넘어가면 안 된다. 클래스명만 바꾸는 마이그레이션은 컴파일은 되지만, 세션 의존적으로 짠 로직(예: 서버가 클라이언트를 역호출해 값을 받아오는 패턴)은 신규 스펙에서 더 이상 보장되지 않는다.
  • 서버의 클라이언트 역호출을 기대하고 설계하면 안 된다. 신규 스펙에서는 서버가 클라이언트를 직접 부르는 대신 "정보 필요" 응답으로 요청을 끝내야 한다. 기존 방식을 그대로 쓰면 최신 클라이언트와 호환되지 않을 수 있다.
  • 로드밸런싱 환경을 고려하지 않고 세션을 계속 유지하는 서버를 배포하면 확장성 문제가 재발한다. 특정 클라이언트의 요청이 항상 같은 서버 인스턴스로 가야 한다는 가정은 신규 스펙의 취지와 정반대다.

베스트 프랙티스

  • 새 MCP 서버를 만든다면 처음부터 각 요청이 필요한 컨텍스트를 스스로 담도록 설계한다. 서버 쪽에 클라이언트별 상태를 보관하지 않는다.
  • 서버가 처리 중 추가 정보가 필요한 상황을 MRTR 패턴으로 설계한다 — "정보 필요" 응답을 명확히 정의하고, 클라이언트가 그 응답을 받아 재요청할 수 있는 흐름을 마련한다.
  • 여러 서버 인스턴스를 로드밸런서 뒤에 두는 배포 구조를 염두에 두고 있다면, 스테이트리스 전환을 미루지 말고 신규 스펙 기준으로 마이그레이션한다.
  • 공식 파이썬 SDK v2로 갈아탈 때는 클래스명 치환(FastMCP → MCPServer)뿐 아니라, 세션·역호출에 의존하던 로직이 있는지 코드 전체를 점검한다.
  • MCP를 로컬 툴 연결 용도로만 쓰고 있다면 당장 문제되지 않을 수 있지만, 향후 원격·클라우드 배포를 고려한다면 신규 스펙의 스테이트리스 설계를 미리 반영해 두는 것이 낫다.

참고

(영상 내 명시 없음 — 영상 설명란 고정 댓글에 추가 자료 링크가 있다고 언급되었으나 URL 자체는 자막에 포함되어 있지 않음)