로드 중

MCP 클라이언트와 서버는 JSON 메시지를 주고받으며 통신하지만, 이러한 메시지는 실제로 어떻게 전송될까요? 이때 사용되는 통신 채널을 전송 방식(transport)이라고 하며, 이를 구현하는 방법에는 여러 가지가 있습니다 - HTTP 요청부터 WebSocket, 심지어 엽서에 JSON을 적는 방법까지 있습니다(다만 마지막 방법은 프로덕션 환경에서 사용하는 것을 권장하지 않습니다).

Stdio 전송 방식

MCP 서버나 클라이언트를 처음 개발할 때 가장 흔히 사용되는 전송 방식은 stdio 전송 방식입니다. 이 방식은 간단합니다: 클라이언트가 MCP 서버를 서브프로세스로 실행하고, 표준 입력 및 출력 스트림을 통해 통신합니다.

stdio 전송 방식 다이어그램: MCP 클라이언트가 서버의 stdin을 통해 MCP 서버로 메시지를 보내고, 서버는 stdout을 통해 메시지를 다시 보냅니다. 양쪽 모두 언제든지 메시지를 보낼 수 있으며, 클라이언트와 서버가 같은 머신에서 실행될 때만 작동합니다

작동 방식은 다음과 같습니다:

  • 클라이언트는 서버의 stdin을 사용하여 서버로 메시지를 보냅니다
  • 서버는 stdout에 씀으로써 응답합니다
  • 서버나 클라이언트 모두 언제든지 메시지를 보낼 수 있습니다
  • 클라이언트와 서버가 같은 머신에서 실행될 때만 작동합니다

실제로 Stdio 동작 확인하기

별도의 클라이언트를 작성하지 않고도 터미널에서 직접 MCP 서버를 테스트할 수 있습니다. uv run server.py로 서버를 실행하면 서버는 stdin을 수신 대기하고 stdout에 응답을 씁니다. 즉, JSON 메시지를 터미널에 직접 붙여넣어 서버의 응답을 즉시 확인할 수 있습니다.

터미널 출력에는 초기화 및 도구 호출에 대한 예시 메시지를 포함하여 전체 메시지 교환 과정이 표시됩니다.

MCP 연결 시퀀스

모든 MCP 연결은 특정한 세 단계의 메시지 핸드셰이크로 시작해야 합니다:

MCP 핸드셰이크 시퀀스 다이어그램: 클라이언트가 서버로 Initialize Request를 보내고, 서버는 Initialize Result로 응답한 다음, 클라이언트가 Initialized Notification을 보내며 이에 대한 응답은 돌아오지 않습니다

  1. Initialize Request - 클라이언트가 먼저 이를 보냅니다
  2. Initialize Result - 서버가 기능(capabilities)으로 응답합니다
  3. Initialized Notification - 클라이언트가 확인합니다(응답은 예상되지 않음)

이 핸드셰이크가 끝난 후에만 도구 호출이나 프롬프트 목록 조회 같은 다른 요청을 보낼 수 있습니다.

메시지 유형과 흐름

MCP는 양방향으로 흐르는 다양한 메시지 유형을 지원합니다:

클라이언트와 서버 간 MCP 메시지 유형 차트: Call Tool Request → Call Tool Result와 같은 클라이언트 주도 요청/결과 쌍, Create Message Request 및 List Roots Request와 같은 서버 주도 쌍, 그리고 응답이 필요 없는 양쪽의 단방향 알림

핵심은 일부 메시지는 응답이 필요하지만(요청 → 결과) 다른 메시지는 그렇지 않다는 점입니다(알림). 클라이언트와 서버 모두 언제든지 통신을 시작할 수 있습니다.

네 가지 통신 시나리오

어떤 전송 방식을 사용하든, 네 가지 서로 다른 통신 패턴을 처리해야 합니다:

"이 각각을 stdio로 어떻게 구현할 수 있을까요?"라는 제목의 다이어그램으로, 클라이언트에서 서버로의 최초 요청, 서버에서 클라이언트로의 응답, 서버에서 클라이언트로의 최초 요청, 클라이언트에서 서버로의 응답이라는 네 가지 패턴을 나열하고, 그 옆에 MCP 클라이언트가 MCP 서버의 stdin 및 stdout에 연결된 모습을 보여줍니다

  • 클라이언트 → 서버 요청: 클라이언트가 stdin에 씁니다
  • 서버 → 클라이언트 응답: 서버가 stdout에 씁니다
  • 서버 → 클라이언트 요청: 서버가 stdout에 씁니다
  • 클라이언트 → 서버 응답: 클라이언트가 stdin에 씁니다

stdio 전송 방식의 묘미는 그 단순함에 있습니다 - 이 두 채널을 사용하면 어느 쪽이든 언제든지 통신을 시작할 수 있습니다.

왜 중요한가

stdio 전송 방식을 이해하는 것이 중요한 이유는, 이것이 양방향 통신이 매끄럽게 이루어지는 "이상적인" 경우를 나타내기 때문입니다. HTTP와 같은 다른 전송 방식으로 넘어가면, 서버가 항상 클라이언트로 요청을 시작할 수는 없는 제약을 마주하게 됩니다. stdio 전송 방식은 다른 전송 방식의 제약을 다루기 전에, 완전한 MCP 통신이 어떤 모습인지 이해하기 위한 기준선 역할을 합니다.

개발 및 테스트 용도로는 stdio 전송 방식이 완벽합니다. 클라이언트와 서버가 서로 다른 머신에서 실행되어야 하는 프로덕션 배포 환경에서는, 각기 다른 장단점을 가진 다른 전송 방식 옵션을 고려해야 합니다.