Post

MCP 개요

MCP 구성 요소와 기본 개념

MCP 개요

참조 문서 (스펙 버전: 2025-11-25)

  • 아키텍처(규범): https://modelcontextprotocol.io/specification/2025-11-25/architecture
  • 아키텍처(개요·학습): https://modelcontextprotocol.io/docs/learn/architecture
  • 라이프사이클: https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle
  • MCP Server Primitives: https://modelcontextprotocol.io/specification/2025-11-25/server
  • MCP Client Primitives: https://modelcontextprotocol.io/specification/2025-11-25/client
  • 보안 모범사례: https://modelcontextprotocol.io/specification/2025-11-25/basic/security_best_practices

아키텍처 레이어 (누가 누구와 통신하는가)

  • MCP Host: LLM과 MCP Client를 포함하는 AI 애플리케이션 (Claude Desktop, Claude Code, Cursor, Cline 등 MCP 구현체 전반)
    • LLM:
      • Host 내부에서 컨텍스트를 처리하고 응답을 생성하는 언어 모델
      • Tools 호출 여부를 자율 결정
    • MCP Client:
      • MCP Host가 MCP Server 하나당 하나씩 생성하는 컴포넌트
      • MCP Server와 1:1 전용 연결 유지
      • MCP Server 개발자가 직접 구현하지 않으며, Claude Desktop·Claude Code 등 MCP Host 담당
  • MCP Server: MCP Client에게 컨텍스트를 제공하는 프로그램
  • 기반 프로토콜: 모든 통신은 JSON-RPC 2.0 위에서 동작

“Host”는 MCP 프로토콜상의 역할 명칭임

  • MCP Client를 품고(host) MCP Server에 연결하는 앱을 가리킴
  • 네트워크의 “호스팅 서버”가 아니라 사용자가 직접 쓰는 사용자 측 앱(Claude Desktop·Code 등)임
  • 이 앱이 “에이전트”인지 여부는 MCP가 규정하지 않는 별개 축임

기본 호출 흐름 (해피패스)

sequenceDiagram
    participant Customer as 고객
    participant LLM as LLM [Host]
    participant Client as MCP Client [Host]
    participant Server as MCP Server

    Note over Client,Server: (사전) 초기화 + tools/list·resources/list·prompts/list 로 목록 확보

    Customer->>LLM: 프롬프트 입력
    LLM->>Client: Tool 호출 결정
    Client->>Server: tools/call
    Server-->>Client: 실행 결과
    Client-->>LLM: 결과 전달
    LLM-->>Customer: 최종 응답
  • MCP 프로토콜 공식 범위: MCP Client ↔ MCP Server 구간 (MCP Client는 MCP Host 내부 컴포넌트)
  • 고객 ↔ MCP Host 흐름: MCP 범위 밖이나 전체 시스템 이해를 위해 포함
  • 화살표: ->> 실선: 요청(응답 기대) · -->> 점선: 응답 · -) 실선+open: 단방향 알림(notification, 응답 없음)

Primitives 분류

  • MCP Server Primitives (Tools · Resources · Prompts): 개발자가 MCP Server에 직접 구현
  • MCP Client Primitives (Roots · Sampling · Elicitation): MCP Server는 요청만 가능, 구현은 MCP Host 담당
  • MCP Server 유틸리티 (Logging 등): primitive와 별개로 MCP Server가 선언·구현하는 보조 기능
  • 각 Primitive의 발동 주체·시점: 각 상세 절의 미니 시퀀스 Note·주체 줄에 표기
  • “순서 무관”의 의미: Tools 실행 중 위 항목들은 MCP Server 내부 로직이 필요할 때 각각 독립 발동되므로 고정 순서 없음

Transport 레이어 (어떻게 연결하는가)

Transport사용 시나리오
stdio로컬 프로세스 간 통신, 네트워크 오버헤드 없음
HTTP+SSE (구 transport)2024-11-05 버전의 별도 transport로, Streamable HTTP로 대체·deprecated됨 (하위호환용 선택적 지원만 존속함)
Streamable HTTP현재 표준 (HTTP POST·GET 기반, 선택적 SSE 스트리밍, OAuth 인증 지원)
  • SSE(Server-Sent Events) 자체는 제거된 것이 아니라 Streamable HTTP의 선택적 스트리밍 메커니즘으로 존속함
  • deprecated된 것은 standalone HTTP+SSE transport임

인증 (Authorization) — 원격 서버 한정

  • stdio 서버는 OS 프로세스 신뢰 경계 안이라 이 절이 불필요함
  • Streamable HTTP(원격) 서버에만 해당
  • 기반: OAuth 2.1
  • MCP Server는 OAuth Resource Server 역할이며, 인증 자체는 별도 Authorization Server(AS)에 위임 가능
  • AS 디스커버리 (2단계): ① MCP Server가 Protected Resource Metadata(RFC 9728)로 AS의 위치를 알림 — WWW-Authenticate 헤더(401 응답)의 resource_metadata 또는 .well-known/oauth-protected-resource 폴백 / ② 클라이언트가 그 AS의 메타데이터를 OAuth 2.0 AS Metadata(RFC 8414) 또는 OpenID Connect Discovery 1.0으로 조회
  • 클라이언트는 발급받은 Bearer 토큰을 매 요청 Authorization 헤더에 실음
  • 서버는 토큰의 audience가 자신인지 반드시 검증
  • 2025-11-25 신규:
    • OpenID Connect Discovery 1.0 지원 (AS 디스커버리 강화)
    • WWW-Authenticate 기반 incremental scope consent(필요한 scope를 점진적으로 동의 요청)
    • OAuth Client ID Metadata Documents(CIMD) — 사전 관계 없는 클라이언트 등록의 권장 1순위 방식(동적 클라이언트 등록(DCR)은 하위호환용 폴백으로 강등)
  • token passthrough 금지(핵심 보안 원칙): MCP Server가 받은 클라이언트 토큰을 제3자 API에 그대로 넘기면 안 됨
  • 제3자 인증이 필요하면 Elicitation url 모드(아래)로 서버가 별도 OAuth 클라이언트가 되어 토큰을 자체 보관

보안 · 신뢰와 안전 (Security & Trust/Safety)

  • 출처: 스펙 개요 페이지의 “Security and Trust & Safety” 절(4원칙) + Security Best Practices 페이지(공격·완화)
  • 아래는 두 원문의 요약·인용이며 별도 추정 없음
  • 4원칙: https://modelcontextprotocol.io/specification/2025-11-25
  • 공격·완화: https://modelcontextprotocol.io/specification/2025-11-25/basic/security_best_practices

핵심 4원칙 (스펙이 모든 구현자 대상으로 명시)

  1. 사용자 동의·통제 (User Consent and Control): 사용자는 모든 데이터 접근·작업에 명시적으로 동의·이해해야 하며, 무엇을 공유하고 어떤 행동을 할지에 대한 통제권을 유지해야 함
  2. 데이터 프라이버시 (Data Privacy): Host는 사용자 데이터를 Server에 노출하기 전 명시적 동의를 받아야 하고, 동의 없이 리소스 데이터를 외부로 전송하면 안 됨
  3. 툴 안전성 (Tool Safety):
    • Tool은 임의 코드 실행으로 취급해야 함
    • tool 동작 설명·annotation은 신뢰할 수 있는 서버 출처가 아니면 untrusted로 간주
    • Host는 어떤 tool이든 호출 전 명시적 동의 필요
  4. LLM 샘플링 통제 (LLM Sampling Controls):
    • 사용자가 샘플링 요청을 명시 승인해야 하며, 샘플링 수행 여부·실제 전송 프롬프트·서버가 볼 수 있는 결과를 통제
    • 프로토콜은 서버의 프롬프트 가시성을 의도적으로 제한

스펙 명시: MCP는 이 원칙들을 프로토콜 차원에서 강제할 수 없으므로 구현자는 SHOULD — 견고한 동의·인가 흐름 구축 / 보안 영향 문서화 / 적절한 접근 통제·데이터 보호 구현 / 보안 모범사례 준수 / 기능 설계 시 프라이버시 고려.

주요 공격·완화 (Security Best Practices 페이지가 명시한 것)

  • 각 항목은 문서가 밝힌 적용 맥락을 그대로 표기함
  • 우리 서버는 원격(Streamable HTTP)이므로 앞쪽 4개가 직접 해당
  • Token Passthrough: MCP Server가 자신에게 발급되지 않은 토큰을 받아 하위 API로 그대로 전달하는 안티패턴
    • 완화: 인가 스펙에서 금지 — “MCP servers MUST NOT accept any tokens that were not explicitly issued for the MCP server.”
  • Confused Deputy: MCP 서버가 제3자 API에 대해 OAuth 프록시(static client ID) 역할을 하면서 MCP 클라이언트의 동적 등록을 허용할 때, 제3자 AS의 consent 쿠키를 악용해 사용자 동의 없이 인가 코드가 탈취될 수 있음
    • 완화(MUST): 제3자 인가로 넘기기 전에 클라이언트별(per-client) 동의를 받고(승인된 client_id 레지스트리를 사전 확인), redirect_uri를 등록값과 정확히 문자열 일치로 검증, OAuth state를 난수 생성·콜백에서 일치 검증·단회용 처리
  • Session Hijacking: 다중 stateful HTTP 서버 환경에서 세션 ID가 탈취되면 사칭·이벤트 주입이 가능
    • 완화(MUST): 인가를 구현하는 서버는 모든 인바운드 요청을 검증하고 세션을 인증 수단으로 사용 금지(MUST NOT), 안전한 비결정적 세션 ID 사용
    • 완화(SHOULD): 세션 ID를 사용자 식별 정보에 바인딩(<user_id>:<session_id> 형태) — user_id는 토큰에서 유도하므로 세션 ID를 추측해도 타인 사칭 불가
  • Scope Minimization: 광범위 scope를 미리 부여하면 토큰 탈취 시 피해 범위가 커짐
    • 완화: 점진적 최소권한 모델 — 최소 초기 scope만 부여하고 권한이 필요할 때 WWW-Authenticatescope= 챌린지로 점증
    • 와일드카드/omnibus scope(*, full-access 등) 금지
    • 주의(Common Mistakes): 토큰의 claimed scope만 믿고 서버측 인가 로직 없이 처리하는 것은 실수
  • SSRF (문서상 주로 MCP 클라이언트 측 위험): 악의적 서버가 OAuth 메타데이터 URL로 내부 자원(http://169.254.169.254/ 등)을 가리켜 클라이언트가 요청하도록 유도
    • 완화(MUST): 서버에 배포되는 MCP 클라이언트는 SSRF 위험을 고려
    • 완화(SHOULD): HTTPS 강제·사설 IP 대역 차단·리다이렉트 대상 검증·egress 프록시 사용
  • Local MCP Server Compromise (문서상 로컬/stdio 서버 한정): 로컬 서버는 임의 코드 실행 위험
    • 완화(MUST): 클라이언트가 원클릭 설정을 지원하면 실행 전 동의(실행될 명령 전체 표시)
    • 완화(SHOULD): 로컬 실행을 의도한 서버는 stdio로 접근을 MCP 클라이언트로 제한하거나, HTTP 사용 시 인가 토큰·유닉스 도메인 소켓으로 접근 제한

라이프사이클 · Capability Negotiation (연결 후 무엇부터 하는가)

Transport로 연결돼도 곧바로 Primitive를 쓸 수는 없음:

  • 먼저 초기화 핸드셰이크로 프로토콜 버전을 맞추고 서로의 capability를 교환해야 함
  • 아래 시퀀스가 이 단계를 보여줌

세 단계로 구성됨:

  1. Initialization (초기화): 버전 합의 + capability 협상 + 구현 정보 교환
    • 반드시 첫 상호작용이어야 함
  2. Operation (운영): 협상된 버전·capability 범위 안에서만 정상 통신
  3. Shutdown (종료): 별도 메시지 없이 transport 종료로 신호 (stdio는 입력 스트림 종료→SIGTERM→SIGKILL, HTTP는 연결 종료)
sequenceDiagram
    participant Client as MCP Client [Host]
    participant Server as MCP Server

    Note over Client,Server: 1. Initialization (반드시 첫 상호작용)
    Client->>Server: initialize (protocolVersion · client capabilities)
    Server-->>Client: 응답 (협상된 version · server capabilities)
    Client-)Server: notifications/initialized

    Note over Client,Server: 2. Operation (협상된 범위 내 통신)
    Note over Client,Server: 3. Shutdown (transport 종료로 신호)

버전 협상:

  • MCP Client가 지원 버전(보통 최신)을 보내고, MCP Server가 그 버전을 지원하면 같은 값으로, 아니면 자신이 지원하는 다른 버전으로 응답함
  • MCP Client가 응답 버전을 지원하지 않으면 연결을 끊어야 함
  • HTTP transport는 이후 모든 요청에 MCP-Protocol-Version 헤더 필수

Capability 협상:

  • 양측이 지원 기능을 명시 선언해 세션에서 쓸 선택 기능을 확정함
  • 이 선언이 앞서 본 각 Primitive의 “~ capability 선언 시에만 사용 가능”의 근거임
주체주요 capability
MCP Clientroots · sampling(+tools) · elicitation(form/url)
MCP Serverprompts · resources(+subscribe) · tools · logging · completions
공통 하위listChanged(목록 변경 알림, prompts·resources·tools) · subscribe(개별 항목 구독, resources 한정)
  • 위 표 외: 양측 모두 experimental(비표준 실험 기능 선언용) capability를 가짐
  • tasks(durable 요청 — 폴링·지연 결과 회수)도 양측 capability이나 2025-11-25 기준 experimental이라 본 문서 범위에서 의도적으로 제외함(정식화 시 추가)

핸드셰이크 전 제약(SHOULD NOT): MCP Client는 initialize 응답 전 ping 외 요청을 보내지 않아야 하고, MCP Server는 notifications/initialized 수신 전 ping·logging 외 요청을 보내지 않아야 함.

MCP Server Primitives 상세

MCP Server가 노출하는 핵심 3가지

요소Python SDK설명
Tools@mcp.tool()LLM이 자율 호출하는 실행 함수
Resources@mcp.resource()MCP Host가 LLM에게 제공하는 데이터/컨텍스트
Prompts@mcp.prompt()고객이 명시 선택하는 프롬프트 템플릿
  1. Tools (@mcp.tool()): LLM이 호출을 결정하는 실행 함수

    1
    2
    3
    
    @mcp.tool()
    async def get_user(user_id: str) -> dict:
        """사용자 정보를 조회한다."""
    
    sequenceDiagram
        participant LLM
        participant Client as MCP Client
        participant Server
        Note over LLM,Server: 고객 프롬프트 입력 후, LLM이 행동 필요 시 발동
        LLM->>Client: Tool 호출 결정
        Client->>Server: tools/call
        Server-->>Client: 실행 결과
        Client-->>LLM: 결과 전달
    
    • 주체: 구현은 MCP Server(개발자), 호출 결정은 LLM (model-controlled), 전송은 MCP Client
    • 외부 API 호출, DB 쿼리, 파일 쓰기 등 부수 효과(side effect)가 있는 작업
    • 스키마: 프로토콜상 inputSchema는 JSON Schema 객체임 — Python SDK(FastMCP)가 함수 시그니처에서 inputSchema를, docstring에서 tool description을 자동 생성해 LLM에 노출
    • 출력: 기본은 비구조화 content(text/image/audio/resource_link/embedded resource)
    • outputSchema를 선언하면 structuredContent(JSON)로 구조화 결과를 반환·검증 가능 (하위호환 위해 같은 JSON을 text content에도 함께 실음)
    • 메타데이터: title(표시명)·icons·annotations(readOnlyHint/destructiveHint/idempotentHint/openWorldHint 등 동작 힌트) — 단 클라이언트는 신뢰 서버가 아니면 annotations를 untrusted로 취급
    • 에러 처리 (2종 구분):
      • Tool Execution Error: 결과에 isError: true + 설명 텍스트로 LLM이 self-correction 가능
      • 입력 검증 오류도 2025-11-25부터 이쪽으로 반환 권장(JSON-RPC protocol error 아님)
      • Protocol Error: 알 수 없는 도구·요청 구조 위반 등 JSON-RPC 에러(-32xxx) → 모델이 스스로 고치기 어려움
  2. Resources (@mcp.resource()): MCP Host가 LLM에게 제공하는 컨텍스트 데이터

    1
    2
    3
    
    @mcp.resource("users://{user_id}")
    async def user_resource(user_id: str) -> str:
        """사용자 데이터를 리소스로 노출한다."""
    
    sequenceDiagram
        participant LLM
        participant Client as MCP Client
        participant Server
        Note over Client,Server: 입력 전후, MCP Host가 컨텍스트로 주입할 때
        Client->>Server: resources/read
        Server-->>Client: contents(text/blob)
        Client->>LLM: 컨텍스트 데이터로 포함
    
    • 주체: 구현은 MCP Server(개발자), 포함 결정은 MCP Host 앱(LLM 아님), 읽기는 MCP Client (application-controlled)
    • URI로 식별되는 읽기 전용 데이터 소스
    • 파일, DB 레코드, 웹페이지 같은 컨텍스트 정보
    • Tool과의 차이: Tool은 LLM이 실행을 호출, Resource는 컨텍스트로 주입 (호출 아님)
    • URI 템플릿으로 동적 리소스 정의 가능 (예: users://{user_id})
  3. Prompts (@mcp.prompt()): 재사용 가능한 프롬프트 템플릿

    1
    2
    3
    4
    
    @mcp.prompt()
    def analyze_user(user_id: str) -> str:
        """사용자 분석을 요청하는 프롬프트 템플릿."""
        return f"user_id={user_id}의 데이터를 분석하고 인사이트를 제공해줘."
    
    sequenceDiagram
        participant Customer as 고객
        participant LLM
        participant Client as MCP Client
        participant Server
        Note over Customer,Server: 고객이 입력 전 명시 선택할 때
        Customer->>Client: 프롬프트 선택
        Client->>Server: prompts/get
        Server-->>Client: 프롬프트 메시지(role 포함)
        Client->>LLM: 대화 메시지로 삽입
    
    • 주체: 구현은 MCP Server(개발자), 선택은 고객 (user-controlled), 요청 전송은 MCP Client
    • 슬래시 커맨드 등으로 노출
    • 반복적으로 쓰는 업무 지시문, 분석 요청 포맷 등을 표준화
    • 세 가지 중 가장 선택적: 없어도 MCP Server 동작에 지장 없음

MCP Server 유틸리티

  • 대표 항목은 Logging — MCP Server 동작을 디버깅·모니터링 목적으로 MCP Client에 전달

Logging (ctx.info() 등)

  • 주체: 선언·구현·발신은 MCP Server, 수신은 MCP Client
  • logging capability 선언 시 사용 가능 (SDK 사용 시 자동 선언되어 코드에 드러나지 않을 수 있음)
  • primitive와 달리 요청-응답이 아닌 MCP Server→MCP Client 단방향 알림(notifications/message)으로 전송
  • 로그 수준: 프로토콜은 8단계(debug/info/notice/warning/error/critical/alert/emergency), Python SDK는 ctx.debug/info/warning/error 4종 노출
1
2
3
4
5
@mcp.tool()
async def process_data(data: str, ctx: Context) -> str:
    await ctx.info("처리 시작")
    await ctx.warning("대용량 데이터 감지")
    return "완료"
sequenceDiagram
    participant Client as MCP Client
    participant Server
    Note over Client,Server: 처리 중 MCP Server가 로그 발신 (순서 무관)
    Server-)Client: notifications/message

기타 기본 유틸리티 (간략)

  • Completion (completions capability, completion/complete): prompt 인자·resource URI 템플릿 입력값의 자동완성 후보 제공
  • Pagination: tools/list·resources/list·prompts/list 등 목록 조회는 cursor 기반 페이지네이션(cursor 요청 / nextCursor 응답). 커서는 불투명 토큰으로 취급
  • Progress (notifications/progress): 장시간 작업 진행률을 progressToken으로 보고
  • Cancellation (notifications/cancelled): 진행 중 요청을 취소 통지
  • Ping (ping): 연결 생존 확인용 요청/응답 (핸드셰이크 전에도 허용)

MCP Client Primitives 상세

  • MCP Server는 이 셋을 직접 구현하지 못하고 ctx로 MCP Client에 요청만 가능 — 선언·구현은 MCP Client 몫

MCP Server에서 요청 가능한 3가지

요소Python SDK설명
Rootsctx.session.list_roots()MCP Client가 노출한 작업 경계 조회
Samplingctx.session.create_message()MCP Host의 LLM에 완성 요청
Elicitationctx.elicit()고객에게 추가 입력 요청
  1. Roots (ctx.session.list_roots()): MCP Server가 MCP Client의 작업 경계(roots)를 조회하는 방법

    1
    2
    3
    4
    5
    6
    7
    
    @mcp.tool()
    async def summarize_roots(ctx: Context) -> str:
        """클라이언트가 노출한 작업 경계(roots)를 요약."""
        result = await ctx.session.list_roots()
        if not result.roots:
            return "노출된 roots 없음"
        return "\n".join(f"- {r.name or r.uri}" for r in result.roots)
    
    sequenceDiagram
        participant Client as MCP Client
        participant Server
        Note over Server,Client: tool 실행 중 MCP Server가 작업 경계 필요 시 (순서 무관)
        Server->>Client: roots/list
        Client-->>Server: 노출된 roots 목록
        Client-)Server: notifications/roots/list_changed
    
    • 주체: roots 선언·응답은 MCP Client, 조회 요청은 MCP Server (roots/list)
    • MCP Client가 노출한 작업 디렉터리·파일 경계 (URI는 file:// 한정)
    • 변경 시 notifications/roots/list_changed 알림 수신 가능
    • Resources와의 차이: Resources는 MCP Server가 노출하는 데이터, Roots는 MCP Client가 노출하는 접근 경계
    • MCP Client가 roots capability(+listChanged)를 선언한 경우에만 사용 가능
  2. Sampling (ctx.session.create_message()): MCP Server가 MCP Host의 LLM을 호출하는 방법

    1
    2
    3
    4
    5
    6
    7
    
    @mcp.tool()
    async def analyze_with_llm(query: str, ctx: Context) -> str:
        result = await ctx.session.create_message(
            messages=[{"role": "user", "content": {"type": "text", "text": query}}],
            max_tokens=200
        )
        return result.content.text
    
    sequenceDiagram
        participant LLM
        participant Client as MCP Client
        participant Server
        Note over LLM,Server: tool 실행 중 MCP Server가 LLM 완성 필요 시 (순서 무관)
        Server->>Client: sampling/createMessage
        Client->>LLM: 완성 요청
        LLM-->>Client: 완성 응답
        Client-->>Server: 완성 결과
    
    • 주체: 요청은 MCP Server (sampling/createMessage), 수신·중개는 MCP Client, 완성 생성은 LLM, 모델 선택·승인은 MCP Host (휴먼인더루프 권장)
    • MCP Server 개발자가 LLM SDK를 직접 포함하지 않고도 LLM 호출 가능
    • LLM 힌트(claude-sonnet-4-6 등) 요청 가능
    • MCP Client가 sampling capability를 선언한 경우에만 사용 가능
    • Tool calling (2025-11-25 신규): 요청에 tools 배열과 toolChoice(객체 형태 {mode: "auto"|"required"|"none"}, 생략 시 auto)를 실어 LLM이 도구를 호출하게 할 수 있음
      • 응답이 stopReason: "toolUse"로 오면 MCP Server가 도구를 실행하고 tool_result를 덧붙여 재요청하는 멀티턴 루프를 돎
      • 별도 sampling.tools 하위 capability를 MCP Client가 선언해야 함
      • 메시지 제약: tool_result를 담은 user 메시지는 오직 tool_result만 포함해야 하며(text/image 혼합 금지), 직전 assistant의 모든 tool_use는 같은 toolUseId를 가진 tool_result와 1:1로 짝이 맞아야 함 — 위반 시 -32602
  3. Elicitation (ctx.elicit()): MCP Server가 고객에게 추가 입력을 요청하는 방법

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    from pydantic import BaseModel
    
    class ConfirmDelete(BaseModel):
        confirmed: bool
    
    @mcp.tool()
    async def confirm_delete(resource_id: str, ctx: Context) -> str:
        result = await ctx.elicit(
            message=f"{resource_id}를 삭제할까요?",
            schema=ConfirmDelete,
        )
        if result.action == "accept" and result.data and result.data.confirmed:
            return f"{resource_id} 삭제 완료"
        return "취소됨"
    
    sequenceDiagram
        participant Customer as 고객
        participant Client as MCP Client
        participant Server
        Note over Customer,Server: tool 실행 중 MCP Server가 고객 입력 필요 시 (LLM 우회)
        Server->>Client: elicitation/create
        Client->>Customer: 입력 요청 (LLM 우회)
        Customer-->>Client: accept / decline / cancel
        Client-->>Server: 입력 결과
    
    • 주체: 요청은 MCP Server (elicitation/create), UI 표시·중개는 MCP Client (LLM 우회), 응답은 고객 (accept/decline/cancel)
    • MCP Server 처리 중 고객 확인이나 추가 정보가 필요한 시점에 활용
    • 위 세 응답은 form·url 두 모드 공통
    • MCP Client가 elicitation capability를 선언한 경우에만 사용 가능
    • 두 가지 모드 (2025-11-25):
      • form (기존·기본): requestedSchema로 구조화 입력 수집
        • 위 예시가 이에 해당
        • 비밀번호·API 키·결제정보 같은 민감정보 요청 금지
      • url (신규): 고객을 외부 URL로 보내 MCP 클라이언트를 거치지 않는 대역외(out-of-band) 상호작용
        • OAuth·결제·민감정보 입력용
        • url+elicitationId를 보내고 입력 데이터는 MCP Client에 노출되지 않음
        • 완료 시 MCP Server가 notifications/elicitation/complete(선택적)로 통지
        • URL elicitation 완료 전엔 진행 불가한 요청에 대해 MCP Server가 URLElicitationRequiredError(-32042)를 반환할 수 있음
    • capability도 모드를 구분: elicitation: { form: {}, url: {} } (빈 객체 {}는 form만 지원과 동치)

MCP Host surface별 MCP 지원 범위

  • MCP 지원은 surface(앱)마다 다름
    • Tools는 사실상 모든 MCP Host가 지원하는 공통 분모임
    • Resources · Prompts · Sampling · Roots · Elicitation 등은 surface마다 지원 여부가 갈림
  • 특정 MCP Server가 어떤 MCP Host에 붙는지는 두 축으로 결정됨
    • MCP Server의 transport (stdio / Streamable HTTP)
    • 그 MCP Host 앱의 지원 범위 (아래 표)
  • MCP Server 설계 함의: Tools만 노출하면 호환 surface가 가장 넓고, 다른 primitive에 의존할수록 붙는 MCP Host가 줄어듦
  • 아래는 2026-05-26 기준 스냅샷이며 문서가 다루는 핵심 primitive만 표기 (출처: https://modelcontextprotocol.io/clients)
  • 벤더 업데이트로 수시 변동되므로 최신·전체 기능은 위 목록에서 확인
Surface지원하는 핵심 primitive (스냅샷)
VS Code (GitHub Copilot)Tools · Resources · Prompts · Sampling · Roots · Elicitation
Claude CodeTools · Resources · Prompts · Roots · Elicitation
Claude.aiTools · Resources · Prompts
CursorTools · Prompts · Roots · Elicitation
ClineTools · Resources
Gemini CLITools · Prompts
ZedTools · Prompts
ChatGPTTools (원격 HTTP MCP Server 한정, developer mode 필요)
This post is licensed under CC BY 4.0 by the author.