MCP 전송 방식 Stdio와 Streamable HTTP
로컬 도구에는 클라이언트가 실행하는 Stdio, 원격 서버에는 단일 엔드포인트에 POST하는 Streamable HTTP가 적합하다.
전송 방식 비교
MCP 메시지는 전송 방식과 무관하게 동일한 JSON-RPC이다. 전송 방식은 메시지를 전달하는 경로만 규정한다. 표준 전송 방식은 stdio와 Streamable HTTP 두 가지이다.
| stdio | Streamable HTTP | |
|---|---|---|
| 서버 실행 | 클라이언트가 자식 프로세스로 실행 | 독립적으로 실행되는 프로세스 |
| 메시지 전달 경로 | 표준 입력·표준 출력 | 단일 HTTP 엔드포인트에 POST |
| 적합한 환경 | 같은 장비의 로컬 도구 | 원격 서버 |
Stdio
메시지 하나는 한 줄을 차지한다. 서버는 표준 입력에서 메시지를 읽고 표준 출력에 기록한다. 표준 출력에는 MCP 메시지만 기록해야 한다. print()로 출력한 로그가 섞이면 메시지 스트림이 손상된다. 로그는 표준 오류(stderr)로 출력한다.
import logging
from mcp.server import MCPServer
mcp = MCPServer("Stock")
log = logging.getLogger("stock")
@mcp.tool()
def get_stock(part_id: str) -> int:
"""부품의 현재 재고 수량을 돌려준다."""
log.info("get_stock %s", part_id) # print() 대신 쓴다. stderr로 나간다
return 420
if __name__ == "__main__":
mcp.run() # 기본값이 stdio
Streamable HTTP
mcp.run(transport="streamable-http", port=8000)
Python SDK 2.x의 기본 주소는 http://127.0.0.1:8000/mcp이다. 클라이언트는 메시지마다 POST를 전송하고, 서버는 단일 JSON 또는 해당 요청에 속한 SSE 스트림으로 응답한다.
- 서버는
Origin헤더를 검증하여 DNS rebinding 공격을 방지한다. - 로컬에서만 사용하는 경우
0.0.0.0이 아니라127.0.0.1에 바인드한다. - 외부에 공개할 때는 인증을 적용한다.
개정 이력
2024-11-05 개정의 HTTP+SSE 전송은 2025-03-26 개정에서 Streamable HTTP로 대체되었으며, 현재는 폐기 예정(deprecated)이다. Streamable HTTP에서도 2026-07-28 개정에서 세션(Mcp-Session-Id)과 GET 스트림이 제거되었다.