List
이전 글에서는 MCP(Model Context Protocol)가 무엇인지, 그리고 Python SDK로 간단한 MCP 서버를 만들고 연동하는 방법을 정리했습니다. MCP 서버를 한 번이라도 실행해 보면 자연스럽게 이런 질문이 따라옵니다. “내가 만든 이 파이썬 MCP 서버를 Claude나 ChatGPT는 어떻게 찾고, 어떤 방식으로 대화할까?”
이 질문의 답은 MCP에서 말하는 Transport(전송 방식) 에 있습니다. 이번 글에서는 MCP에서 가장 많이 쓰이는 두 가지 전송 방식인 Stdio와 SSE(Server-Sent Events) 를 중심으로 정리해 보려고 합니다.
MCP에서 Transport란 무엇인가
MCP 관점에서 우리가 준비하는 것은 크게 두 가지입니다.
1.
무엇을 할 수 있는지
•
툴, 리소스(resources), 프롬프트(prompts) 등 “기능” 정의
2.
어떻게 연결할지
•
AI 클라이언트와 MCP 서버가 메시지를 주고받는 통로(Transport) 정의
Transport는 쉽게 말해서 AI 클라이언트
MCP 서버 사이에서 JSON 메시지가 오가는 통로라고 볼 수 있습니다.
MCP에서 대표적으로 쓰이는 Transport 방식은 다음 두 가지입니다.
•
Stdio (Standard I/O): 같은 머신 안에서 프로세스끼리 통신
•
SSE (Server-Sent Events): HTTP 위에서 이벤트 스트림을 흘리는 방식
두 방식 모두 JSON-RPC 메시지를 주고받는다는 점은 같습니다. 각 방식의 특징을 자세히 살펴보겠습니다.
Stdio - 같은 컴퓨터 안에서 바로 연결하기
Stdio는 MCP를 로컬에서 사용할 때 기본으로 쓰는 방식이라고 생각하면 이해가 쉽습니다. Stdio는 이름 그대로 표준 입출력(Standard Input / Output) 을 사용합니다.
•
터미널에 입력하면 프로그램은 이를 stdin으로 읽기
•
프로그램이 출력하면 터미널에 stdout으로 보내기
MCP에서는 이 stdin/stdout 채널을 이용해 AI 클라이언트와 MCP 서버가 JSON 메시지를 주고받습니다. 같은 컴퓨터 안에서 AI 클라이언트가 MCP 서버 프로세스를 직접 실행하고 그 프로세스의 stdin/stdout에 JSON을 쓰고 읽는 구조라고 볼 수 있습니다. 별도의 포트나 HTTP 서버 없이도 동작합니다.
장점
•
구성이 단순
◦
네트워크, 포트, 도메인 같은 걸 몰라도 동작
◦
MCP 지원 클라이언트에서 “이 바이너리를 Stdio MCP로 실행해줘” 정도의 설정이면 충분
•
기본적으로 로컬에만 열려 있어서 보안 측면에서 안전
◦
외부에서 바로 접속할 수 있는 엔드포트가 없음
단점
•
원격에서 접근하기 어려움
◦
같은 머신에서 돌아가는 클라이언트만 이 MCP 서버를 사용할 수 있음
◦
팀원들과 공유하거나, 서버에 올려서 여러 사람이 쓰는 구조에는 맞지 않음
FastMCP로 Stdio 기반 MCP 서버 실행하기
FastMCP는 별도 옵션 없이 실행하면 기본적으로 Stdio 기반 MCP 서버로 동작합니다
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-local-tool")
@mcp.tool()
def add(a: int, b: int) -> int:
"""두 숫자를 더합니다."""
return a + b
if __name__ == "__main__":
# 기본: Stdio 기반 MCP 서버 실행
mcp.run()
Python
복사
위 코드를 실행해 두고, MCP를 지원하는 클라이언트(예: 데스크톱 앱)에서 이 바이너리를 Stdio MCP 서버로 등록해 두면, 클라이언트는 이 프로세스의 stdin/stdout을 통해 add 툴을 호출할 수 있습니다. 로컬에서 “일단 MCP를 써보고 싶다”라면 대부분 이 방식으로 시작하게 됩니다.
SSE - HTTP 위에서 지속적으로 메시지 흘리기
로컬 실험을 넘어서 서버에 배포해서 여러 사람이 공유하는 MCP 서버를 만들고 싶다면 SSE(Server-Sent Events) 방식을 쓰게 됩니다
일반적인 HTTP와 뭐가 다른 점
일반적인 HTTP 요청/응답 패턴은 다음과 같습니다. 클라이언트가 요청(Request)을 한 번 보내고 서버가 응답(Response)을 한 번 보내고 연결이 끝납니다.
그런데 MCP 서버 입장에서는 이런 요구가 생길 수 있습니다.
•
긴 작업을 수행하면서 중간 진행 상황을 흘려보내고 싶거나
•
응답을 한 번에 보내지 않고 여러 조각으로 스트리밍하고 싶거나
SSE는 이런 요구를 위해 만들어진 방식입니다. 핵심 아이디어는 다음과 같습니다
•
클라이언트가 SSE 엔드포인트에 한 번 연결(구독) 하면
•
서버는 그 연결을 유지한 채 텍스트 기반의 이벤트 스트림을 계속 흘려보낼 수 있습니다.
MCP에서의 전형적인 흐름은 다음과 같이 이해할 수 있습니다
1.
클라이언트가 SSE 엔드포인트에 접속해서 서버가 보내는 이벤트 스트림을 수신
2.
별도의 HTTP 요청으로 “툴 실행 요청” 같은 명령을 서버에 전달
3.
서버는 실행 결과나 중간 상태를 SSE 스트림을 통해 클라이언트로 전송
즉, HTTP 연결은 유지한 채로 서버→클라이언트 방향의 이벤트를 계속 보내는 채널을 하나 열어두는 것이 SSE입니다
장점
•
원격 환경에 적합
◦
인터넷이나 사내 네트워크에서 접근할 수 있는 MCP 서버를 만들 수 있음
◦
여러 사용자가 같은 MCP 서버를 공유할 수 있음
•
일반적인 웹 서비스 운영 패턴과 적합
◦
도메인, HTTPS, 로깅, 모니터링, 스케일 아웃 등 기존 웹 서비스 운영 경험을 그대로 가져올 수 있음
◦
Nginx, Traefik 같은 리버스 프록시 뒤에 붙여서 운영하기도 좋음
단점
•
인프라/네트워크 설정이 필요
◦
포트, 도메인, HTTPS, 방화벽, 인증/인가 등을 직접 설계 필요
•
구성이 Stdio에 비해 복잡
◦
“내 로컬에서 혼자 쓰는 도구”라면 오버엔지니어링
FastMCP로 SSE/HTTP 서버 실행하기
FastMCP는 Stdio뿐 아니라 HTTP 기반 Transport도 지원합니다
실제 실행 방법은 환경마다 다르지만, 흔히 Docker나 CLI에서 이런 식으로 실행하게 됩니다
# 예시: Docker 컨테이너에서 HTTP/SSE 모드 MCP 서버 실행
CMD ["--transport", "streamable-http", "--port", "8000", "-v"]
Bash
복사
코드 구조 자체는 Stdio 모드와 거의 동일합니다
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-remote-tool")
@mcp.tool()
def get_server_status() -> str:
return "Server is running"
if __name__ == "__main__":
# Stdio 모드로 실행하려면: mcp.run()
# SSE 모드는 보통 uvicorn 등으로 실행하지만, FastMCP의 명령어를 사용할 수도 있습니다.
mcp.run(transport="sse") # 예시
Python
복사
즉, MCP 서버 코드는 그대로 두고 실행 커맨드/환경만 바꿔서 개발 단계/운영 단계로 전환하는 패턴을 생각하면 이해가 편합니다.
Stdio vs SSE 한 번에 정리
항목 | Stdio (Standard I/O) | SSE (Server-Sent Events / HTTP) |
연결 대상 | 같은 머신에서 실행 중인 MCP 서버 | 네트워크 상의 서버 (온프렘 / 클라우드) |
통신 경로 | 프로세스 stdin / stdout | HTTP(S) + SSE 스트림 |
주요 사용처 | 로컬 개발, 개인용 자동화, 데스크톱 앱 연동 | 팀 공유 툴, 사내 공용 MCP 서버, 실서비스 환경 |
보안 관점 | 외부 포트 노출 없음, 로컬에 한정 | 인증/인가 설계 필요, 방화벽/HTTPS 고려 |
구현 난이도 | 낮음 (코드 + 실행만으로 구성 가능) | 상대적으로 높음 (인프라, 네트워크 지식 필요) |
확장성 | 단일 사용자/단일 클라이언트에 적합 | 여러 사용자/여러 클라이언트에 적합 |
마무리
MCP에서 Transport는 AI 클라이언트와 MCP 서버 사이에 JSON 메시지가 오가는 방식입니다. Stdio는 같은 머신 안에서 MCP를 쓸 때 가장 단순한 방식이고 네트워크 설정 없이 바로 시작하기 좋습니다. SSE/HTTP는 서버에 올려서 여러 클라이언트가 공유하는 MCP 환경을 만들 때 필요하고 인프라/보안/운영까지 함께 고민해야 하지만, 실서비스 수준의 MCP를 만들 수 있습니다.
이제 Stdio와 SSE의 역할과 차이를 감으로라도 잡았다면, 다음 단계에서는 실제로 SSE 모드 MCP 서버를 띄우고, MCP Inspector나 클라이언트에서 연결 테스트, 툴 호출 흐름, 스트리밍 응답 형태까지 따라가 보는 실습을 해 보는 것이 좋습니다.