Model Context Protocol의 연결 생명주기와 두 가지 표준 Transport(stdio, Streamable HTTP)의 동작 방식을 공식 문서 기준으로 분석합니다.
“이 글은 MCP 공식 문서에 근거하며, MCP 서버를 AI 애플리케이션의 하나의 모듈로 바라보는 관점에서 설명합니다. Client는 AI 애플리케이션(또는 그 안의 MCP Client 모듈), Server는 MCP Server를 의미합니다.
일반적인 웹 애플리케이션이 TCP 커넥션 이후 곧바로 통신에 진입하는 것과 달리, MCP는 연결 전에 서로의 기능을 파악하고 협상하는 구조화된 생명주기를 가집니다.
클라이언트와 서버의 첫 상호작용이자 필수 단계입니다. 이 단계에서 다음 세 가지가 이루어집니다.
클라이언트가 initialize 요청을 전송하며 시작합니다.
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {
"roots": { "listChanged": true },
"sampling": {},
"elicitation": { "form": {}, "url": {} },
"tasks": {
"requests": {
"elicitation": { "create": {} },
"sampling": { "createMessage": {} }
}
}
},
"clientInfo": {
"name": "ExampleClient",
"title": "예시 클라이언트 표시 이름",
"version": "1.0.0",
"description": "예시 MCP 클라이언트 애플리케이션",
"websiteUrl": "https://example.com"
}
}
}
초기화가 완료되면 클라이언트는 initialized 알림을 전송해 운영 준비가 되었음을 알립니다.
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
initialize 요청에 응답하기 전에 ping 외의 요청을 보내선 안 됩니다.initialized 알림을 수신하기 전에 ping과 로깅 외의 요청을 보내선 안 됩니다.클라이언트는 자신이 지원하는 최신 프로토콜 버전을 initialize 요청에 담아 보냅니다.
| 상황 | Server 응답 |
|---|---|
| 동일 버전 지원 | 같은 버전으로 응답 |
| 미지원 버전 | 자신이 지원하는 버전으로 응답 |
| Client가 Server 버전 미지원 | Client가 연결 종료 |
Client와 Server가 서로 어떤 기능을 지원하는지 선언합니다. 이후 Operation 단계에서는 협상된 Capability 범위 안에서만 통신해야 합니다.
| 선언 주체 | Capability | 의미 |
|---|---|---|
| Server | tools | Tool 호출 기능 제공 |
| Server | resources | Resource 읽기 기능 제공 |
| Server | prompts | 프롬프트 템플릿 제공 |
| Server | logging | 로그 스트리밍 지원 |
| Client | sampling | LLM 샘플링 요청 지원 |
| Client | roots | 파일시스템 루트 제공 |
초기화와 협상이 완료되면 협상된 Capability 범위 안에서 자유롭게 통신합니다.
tools/call, resources/read 같은 요청들이 이 구간에서 발생합니다.
초기화 단계에서 선언되지 않은 Capability는 Operation 중에 요청할 수 없습니다.
별도의 종료 메시지 없이, 전송 레이어를 닫는 것으로 종료를 신호합니다. 전송 방식에 따라 처리 방법이 다릅니다.
| Transport | 종료 방식 |
|---|---|
stdio (로컬 프로세스) | 입력 스트림 닫기 → SIGTERM → SIGKILL 순서 |
HTTP | HTTP 커넥션 닫기 |
REST API에서 HTTP / WebSocket / gRPC 중 선택하듯, MCP는 현재 두 가지 표준 Transport를 정의합니다.
MCP Server가 로컬 머신에서 실행되는 경우 사용합니다.
AI 애플리케이션이 MCP 서버 프로세스를 직접 실행시키고, 표준 입출력(stdin / stdout)으로 JSON-RPC 메시지를 주고받습니다.
AI Application
┌───────────────────────────────────┐
│ │
│ ┌─────────────┐ stdin/stdout ┌─────────────┐
│ │ MCP Client │ ◄────────────► │ MCP Server │
│ └─────────────┘ └─────────────┘
│ (동일 프로세스 또는 서브프로세스) │
└───────────────────────────────────┘
Streamable HTTP에서 Server가 상태를 유지하고 싶을 경우 Session을 사용할 수 있습니다.
Server가 initialize 응답 헤더에 MCP-Session-Id를 포함해 반환합니다.
Client는 이후 모든 요청 헤더에 MCP-Session-Id를 포함합니다.
Session이 만료되면 Server는 404를 반환합니다.
Client가 404를 받으면 initialize부터 다시 시작합니다.
Client가 Session을 끝내고 싶으면 DELETE /mcp 요청을 전송합니다.
네트워크 불안정으로 SSE 연결이 끊어질 수 있습니다.
“DB의 커서 기반 페이지네이션과 동일한 원리입니다. 어디까지 전송했는지 기억한 뒤 이어서 전송합니다.
Server는 SSE 이벤트마다 고유 id를 부여합니다.
연결이 끊어지면 Client는 Last-Event-ID 헤더와 함께 GET /mcp으로 재연결합니다.
Server는 해당 ID 이후 이벤트부터 재전송합니다.
SSE 연결이 끊어졌다고 해서 진행 중인 요청이 취소된 것으로 취급하지 않습니다. 명시적으로 취소하려면 취소 알림(cancellation notification) 을 별도로 전송해야 합니다.
Streamable HTTP 사용 시 Origin 헤더 검증을 반드시 수행해야 합니다.
검증하지 않으면 DNS rebinding 공격에 취약해집니다.
외부 사이트가 브라우저를 통해 로컬의 MCP Server를 호출할 수 있기 때문입니다.
Origin이 유효하지 않으면 403 Forbidden으로 차단해야 합니다.
HTTP 사용 시 모든 요청 헤더에 다음을 포함해야 합니다.
MCP-Protocol-Version: 2025-11-25
핸드셰이크에서 협상된 버전을 사용하면 됩니다.
2025-03-26 버전으로 간주합니다.400 Bad Request를 반환합니다.