본문 바로가기
C.W.K.
Stream
Lesson 04 of 05 · published

Lifecycle 과 Capability Negotiation

~22 min · initialize, lifecycle, capabilities, handshake

Level 0호기심 많은 독자
0 XP0/48 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

MCP session 은 네 단계로 굴러가. connect, initialize, operate, shutdown. 첫 단계는 transport 마다 달라 (stdio pipe 를 열거나 HTTP 연결을 열거나), 마지막 단계는 얌전히 닫는 일이고. 가운데 둘이 protocol 의 무게를 다 짊어져.

Initialize 가 handshake 야. Client 가 initialize request 를 보내면서 protocolVersioncapabilities (sampling, roots, elicitation 같은 거), clientInfo 를 밝혀. Server 도 같은 봉투로 답해. 양쪽이 다 아는 것 중 가장 높은 합의된 version, 자기 capability, 그리고 serverInfo. 이 한 번의 주고받음으로, 이번 session 에서 뭘 쓸 수 있는지에 대한 정밀한 합의문이 양쪽 손에 남아.

Handshake 가 중요한 이유는 protocol 이 발맞춰 올리지 않고도 진화할 수 있게 해주기 때문이야. 새 client 가 옛 server 와도 대화할 수 있어 — 양쪽이 밝힌 capability 안에서만 움직이니까. 새 server 는 실험적인 capability 를 얹어 내보내도 돼 — 옛 client 는 그냥 무시하거든. HTTP 나 REST 에서 version 번호가 하던 역할을 MCP 에서는 capability 가 해. 부품들이 서로를 안 깨뜨리면서 각자 다른 속도로 움직이게 해주는 장치지.

Operate 는 handshake 뒤에 벌어지는 전부야. Tool 호출, resource 읽기, prompt 요청, sampling 왕복, log 메시지, 진행 상황 알림. Shutdown 은 양쪽이 자원을 정리하는 작별 인사고. Server 는 shutdown 을 log 를 비우고 파일 손잡이를 놓는 기회로 삼아야 해.

Code

Wire 위 initialize handshake·json
// Client -> Server
{
  "jsonrpc": "2.0", "id": 1, "method": "initialize",
  "params": {
    "protocolVersion": "2025-11-25",
    "capabilities": {
      "sampling": {},
      "roots": { "listChanged": true }
    },
    "clientInfo": { "name": "claude-code", "version": "1.42.0" }
  }
}

// Server -> Client
{
  "jsonrpc": "2.0", "id": 1, "result": {
    "protocolVersion": "2025-11-25",
    "capabilities": {
      "tools": { "listChanged": true },
      "resources": {},
      "prompts": {}
    },
    "serverInfo": { "name": "github-mcp", "version": "0.4.0" }
  }
}
Capability 읽고 동작 gate·python
async with ClientSession(read, write) as session:
    init_result = await session.initialize()
    if "tools" not in init_result.capabilities:
        raise RuntimeError("이 server 는 tool 광고 안 함 — 잘못된 server?")
    if init_result.capabilities.get("logging"):
        await session.set_logging_level("info")  # 광고됐을 때만 안전
    tools = await session.list_tools()

External links

Exercise

아무 MCP server 나 하나 띄워 (SDK 의 'echo' 예제도 좋고 커뮤니티 server 도 좋아). Transport sniffer 나 debug logger 로 initialize request 와 response 를 잡아. 합의된 capability 를 읽고 머릿속으로 따져봐. 어떤 method 는 불러도 안전하고, 어떤 건 광고가 안 돼서 405 를 받게 될까?

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.