콘텐츠로 이동

02-구조

02 — 구조: 호스트, 클라이언트, 서버

섹션 제목: “02 — 구조: 호스트, 클라이언트, 서버”

MCP는 호스트-클라이언트-서버(host-client-server) 구조를 따른다. 한 호스트가 여러 클라이언트를 띄우고, 각 클라이언트는 서버 한 개와 1:1 세션을 유지한다 — mcp-architecture.

┌─────────────────── Host (예: Claude Code, Claude Desktop) ───────────────────┐
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Client1 │ │ Client2 │ │ Client3 │ ← 호스트가 생성·관리, 보안 경계 │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
└───────┼───────────┼────────────┼─────────────────────────────────────────────┘
│ JSON-RPC │ JSON-RPC │ JSON-RPC (1 client : 1 server)
┌────┴────┐ ┌────┴────┐ ┌────┴───────┐
│ Filesys │ │ GitHub │ │ Postgres │ ← 각 서버는 독립 프로세스
│ MCP │ │ MCP │ │ MCP │
└─────────┘ └─────────┘ └────────────┘
  • 클라이언트 인스턴스를 만들고 수명 주기 관리
  • 사용자 동의(consent), 권한, 보안 정책 강제
  • 모델 호출(샘플링) 및 컨텍스트 통합
  • 서버 한 개와 상태 있는(stateful) 세션 유지
  • 프로토콜 협상(capability negotiation), 메시지 라우팅, 구독·알림 처리
  • 다른 서버를 들여다볼 수 없음(격리)
  • 자신이 잘하는 일에만 집중(좁은 책임)
  • 리소스/도구/프롬프트를 노출
  • 호스트 너머의 대화 전체를 볼 수 없음 — 격리가 곧 보안

“Servers should not be able to read the whole conversation, nor ‘see into’ other servers.”

의역: 서버는 대화 전체를 읽을 수도, 다른 서버를 들여다볼 수도 없어야 한다. — mcp-architecture

이게 함수 호출과의 결정적 차이다. 함수 호출은 “모델이 다 본다”가 전제지만 MCP는 **“호스트만 다 본다”**가 전제다.

서버가 노출할 수 있는 것은 정확히 세 종류다 — mcp-quickstart-server.

원시누가 부르나비유
리소스(Resources)클라이언트가 읽음파일·API 응답 — “GET”
도구(Tools)모델이 호출(사용자 승인 후)함수 — “POST”
프롬프트(Prompts)사용자가 선택미리 작성된 템플릿

대부분의 서버는 도구만으로 시작한다. 리소스와 프롬프트는 점진적으로 추가하면 된다(“Features can be added progressively” — 설계 원칙).

표준 전송 두 가지 — mcp-transports:

  • 클라이언트가 서버를 자식 프로세스로 띄움
  • stdin/stdout으로 JSON-RPC, stderr는 로깅
  • 로컬 서버 기본값. Claude Desktop·Code의 npm/uv 패키지가 다 이 방식
  • 규칙: “서버는 stdout에 MCP 메시지가 아닌 것을 절대 쓰지 말 것” — print 디버깅이 즉시 프로토콜을 깨뜨린다
  • 서버가 독립 프로세스로 떠 있고 HTTP POST/GET로 통신
  • 응답은 단일 JSON 또는 SSE 스트림
  • 원격(SaaS) MCP 서버 기본값. Notion·Stripe·Asana 등 호스팅된 MCP가 이 방식
  • 보안 경고: Origin 헤더 검증 필수, 로컬에서는 127.0.0.1에만 바인딩(DNS 리바인딩 방지)

이전 사양의 HTTP+SSE 전송은 폐기되고 Streamable HTTP로 대체됐다(2024-11-05 → 2025-06-18). 옛 글이 알려주는 SSE-only 패턴은 지금 쓰지 말 것.

세션 시작 시 클라이언트와 서버는 서로 무엇을 지원하는지 선언한다. 서버는 도구/리소스/프롬프트/구독 지원 여부를, 클라이언트는 샘플링/알림 처리 여부를 알린다. 선언하지 않은 기능은 사용하지 않는다. 이게 점진 확장(progressive enhancement)의 토대다.

  • 03-실전 — Claude Code에 실제로 붙여보기