MCP 클라이언트 이해하기
MCP 클라이언트 이해하기 (Understanding MCP clients)
MCP 클라이언트는 호스트 애플리케이션이 특정 MCP 서버와 통신하기 위해 인스턴스화하는 구성 요소예요. 호스트(Claude.ai나 IDE 같은)가 전체 사용자 경험을 관리하고 여러 클라이언트를 조정하며, 각 클라이언트는 하나의 서버와 한 번의 직접 통신을 처리합니다.
출처: 문서
본문
MCP 클라이언트는 호스트 애플리케이션이 특정 MCP 서버와 통신하기 위해 인스턴스화하는 구성 요소예요. 호스트 애플리케이션(Claude.ai나 IDE 같은)은 전체 사용자 경험을 관리하고 여러 클라이언트를 조정합니다. 각 클라이언트는 하나의 서버와의 한 번의 직접 통신을 처리해요.
이 구분을 이해하는 게 중요해요. 호스트는 사용자가 상호작용하는 애플리케이션이고, 클라이언트는 서버 연결을 가능하게 하는 프로토콜 수준의 구성 요소랍니다.
핵심 클라이언트 기능 (Core Client Features)
서버가 제공하는 컨텍스트를 활용하는 것 외에도, 클라이언트는 서버에 여러 기능을 제공할 수 있어요. 이런 클라이언트 기능 덕분에 서버 작성자는 더 풍부한 상호작용을 만들 수 있죠.
| 기능 | 설명 | 예시 |
|---|---|---|
| Elicitation | Elicitation은 서버가 상호작용 중 사용자에게 특정 정보를 요청할 수 있게 해 줘요. 서버가 필요할 때 구조적으로 정보를 수집하는 방식을 제공하죠. | 여행 예약 서버가 항공 좌석, 객실 유형, 연락처에 대한 사용자 선호를 물어 예약을 완료하는 경우 |
| Roots | Roots는 클라이언트가 서버가 집중해야 할 디렉터리를 지정할 수 있게 해 주고, 조정 메커니즘을 통해 의도된 범위를 전달해요. Roots는 프로토콜 버전 2026-07-28부터 폐기 예정입니다. |
여행 예약 서버가 특정 디렉터리에 접근 권한을 받아, 그 안에서 사용자의 달력을 읽을 수 있는 경우 |
| Sampling | Sampling은 서버가 클라이언트를 통해 LLM 완성을 요청할 수 있게 해 줘서 에이전트형 워크플로를 가능하게 해요. 이 방식은 클라이언트가 사용자 권한과 보안 조치를 완전히 통제하게 합니다. Sampling은 프로토콜 버전 2026-07-28부터 폐기 예정입니다. |
여행 예약 서버가 항공편 목록을 LLM에 보내고, 사용자에게 가장 좋은 항공편을 고르라고 요청하는 경우 |
Elicitation
Elicitation은 서버가 상호작용 중 사용자에게 특정 정보를 요청할 수 있게 해 주며, 더 동적이고 반응적인 워크플로를 만들어요.
개요
Elicitation은 서버가 필요할 때 필요한 정보를 구조적으로 수집할 수 있는 방식을 제공해요. 모든 정보를 미리 요구하거나 데이터가 없을 때 실패하는 대신, 서버는 작업을 잠시 멈추고 사용자에게 특정 입력을 요청할 수 있어요. 이렇게 하면 서버가 고정된 패턴을 따르기보다 사용자 요구에 적응하는 더 유연한 상호작용을 만들 수 있죠.
Elicitation은 두 가지 모드를 지원해요.
- Form 모드: 서버가 클라이언트에게 사용자로부터 구조화된 데이터를 수집하도록 요청해요. 요청에는 클라이언트가 입력 폼을 만들고 응답을 검증하는 데 사용하는 스키마가 포함됩니다.
- URL 모드: 서버가 사용자가 열어 볼 URL을 제공해요. 상호작용은 밴드 밖(out of band)에서 일어나고 그 데이터는 결코 클라이언트를 통과하지 않아요. 그래서 자격 증명 입력이나 제3자 OAuth 인증 같은 민감한 흐름에 적합하죠.
Elicitation은 Multi Round-Trip Requests(MRTR) 패턴을 따라요. 서버가 tools/call 같은 요청을 처리하는 동안 사용자 입력이 필요하면, inputRequests 필드에 하나 이상의 elicitation/create 요청을 담은 InputRequiredResult로 응답해요. 클라이언트는 입력을 수집하고, 수집한 inputResponses를 붙이고 서버가 포함한 requestState를 그대로 되돌려 보내며 원래 요청을 재시도합니다.
Elicitation 흐름:
sequenceDiagram
participant User
participant Client
participant Server
Client->>Server: tools/call (id: 1)
Note over Server: Server needs more information
Server-->>Client: InputRequiredResult with elicitation/create request
Note over Client,User: Human interaction
Client->>User: Present elicitation UI
User-->>Client: Provide requested information
Note over Client,Server: Retry request with user input
Client->>Server: tools/call (id: 2, inputResponses)
Note over Server: Continue processing with new information
Server-->>Client: Final result
이 흐름은 동적 정보 수집을 가능하게 해요. 서버는 필요할 때 특정 데이터를 요청하고, 사용자는 적절한 UI를 통해 정보를 제공하며, 서버는 새로 얻은 컨텍스트로 재시도된 요청을 완료합니다.
Elicitation 요청 예시(InputRequiredResult.inputRequests 안에 전달됨):
{
method: "elicitation/create",
params: {
mode: "form",
message: "Please confirm your Barcelona vacation booking details:",
requestedSchema: {
type: "object",
properties: {
confirmBooking: {
type: "boolean",
description: "Confirm the booking (Flights + Hotel = $3,000)"
},
seatPreference: {
type: "string",
enum: ["window", "aisle", "no preference"],
description: "Preferred seat type for flights"
},
roomType: {
type: "string",
enum: ["sea view", "city view", "garden view"],
description: "Preferred room type at hotel"
},
travelInsurance: {
type: "boolean",
default: false,
description: "Add travel insurance ($150)"
}
},
required: ["confirmBooking"]
}
}
}
예시: 휴가 예약 승인 (Holiday Booking Approval)
여행 예약 서버는 최종 예약 확인 과정에서 elicitation의 힘을 보여 줍니다. 사용자가 바르셀로나로의 이상적인 휴가 패키지를 선택하면, 서버는 진행하기 전에 최종 승인과 누락된 세부 사항을 수집해야 해요.
서버는 여행 요약(바르셀로나 항공편 6월 15~22일, 비치프런트 호텔, 총 $3,000)과 좌석 선택, 객실 유형, 여행 보험 옵션 같은 추가 선호 필드를 포함한 구조화된 요청으로 예약 승인을 elicitation 합니다.
예약이 진행되면서 서버는 예약 완료에 필요한 연락처 정보를 elicitation 해요. 항공 예약을 위한 여행자 세부 사항, 호텔을 위한 특별 요청, 비상 연락처 정보를 물어볼 수 있죠.
사용자 상호작용 모델
Elicitation 상호작용은 명확하고, 문맥에 맞고, 사용자 자율성을 존중하도록 설계됐어요.
요청 표시: 클라이언트는 어떤 서버가 묻는지, 왜 정보가 필요한지, 어떻게 사용될지에 대한 명확한 컨텍스트와 함께 elicitation 요청을 표시해요. 요청 메시지가 목적을 설명하고, 스키마가 구조와 검증을 제공해요.
응답 옵션: 사용자는 적절한 UI 컨트롤(텍스트 필드, 드롭다운, 체크박스)로 요청된 정보를 제공하거나, 선택적 설명과 함께 정보 제공을 거부하거나, 전체 작업을 취소할 수 있어요. 클라이언트는 서버에 반환하기 전에 제공된 스키마에 대해 응답을 검증해요.
URL 처리: URL 모드에서는 클라이언트가 전체 URL을 보여 주고 열기 전에 명시적 동의를 받으며, 절대 URL을 자동으로 가져오지 않아요. 클라이언트는 사용자가 동의했는지 여부만 알 수 있어요. 상호작용 자체는 사용자와 대상 사이트 사이에서만 이뤄집니다.
개인정보 고려 사항: 서버는 비밀번호, API 키, 접근 토큰, 결제 자격 증명 같은 민감한 정보를 요청하는 데 form 모드를 사용하면 안 돼요. 그런 상호작용은 URL 모드에 속하며, 데이터가 밴드 밖에 있으므로 클라이언트나 LLM 컨텍스트를 결코 통과하지 않아요. 클라이언트는 의심스러운 요청에 대해 경고하고, 사용자가 보내기 전에 폼 데이터를 검토하게 해 줍니다.
Roots
Roots는 프로토콜 버전
2026-07-28부터 폐기 예정이며 제거 예정이에요. 새 구현은 대신 디렉터리나 파일을 도구 매개변수, 리소스 URI, 또는 서버 설정으로 전달해야 합니다.
Roots는 서버 작업의 파일시스템 경계를 정의해서, 클라이언트가 서버가 집중해야 할 디렉터리를 지정할 수 있게 해 줘요.
개요
Roots는 클라이언트가 파일시스템 접근 경계를 서버에 전달하는 메커니즘이에요. 서버가 작업할 수 있는 디렉터리를 나타내는 파일 URI로 구성되며, 서버가 사용 가능한 파일과 폴더의 범위를 이해하도록 도와줘요. Roots가 의도된 경계를 전달하지만, 보안 제한을 강제하지는 않는다는 점에 유의하세요. 실제 보안은 운영 체제 수준에서 파일 권한 및/또는 샌드박싱을 통해 강제돼야 해요.
Root 구조:
{
"uri": "file:///Users/agent/travel-planning",
"name": "Travel Planning Workspace"
}
Roots는 전적으로 파일시스템 경로이며 항상 file:// URI 스킴을 사용해요. 서버가 프로젝트 경계, 작업 공간 구성, 접근 가능한 디렉터리를 이해하도록 도와줘요. 사용자가 다른 프로젝트나 폴더로 작업하면 roots 목록이 바뀔 수 있어요. 서버는 다음에 roots 목록을 요청할 때 업데이트된 경계를 알게 됩니다.
예시: 여행 계획 작업 공간
여러 고객 여행을 다루는 여행 에이전트는 roots를 통해 파일시스템 접근을 체계화하는 혜택을 보게 돼요. 여행 계획의 여러 측면을 위한 각기 다른 디렉터리가 있는 작업 공간을 생각해 보세요.
클라이언트는 여행 계획 서버에 파일시스템 roots를 제공해요.
file:///Users/agent/travel-planning— 모든 여행 파일이 있는 메인 작업 공간file:///Users/agent/travel-templates— 재사용 가능한 일정 템플릿과 리소스file:///Users/agent/client-documents— 고객 여권과 여행 문서
에이전트가 바르셀로나 일정을 만들 때, 잘 동작하는 서버는 이 경계를 존중합니다. 지정된 roots 안에서 템플릿에 접근하고, 새 일정을 저장하고, 고객 문서를 참조하죠. 서버는 보통 root 디렉터리의 상대 경로를 사용하거나 root 경계를 존중하는 파일 검색 도구를 활용해 roots 안의 파일에 접근해요.
에이전트가 file:///Users/agent/archive/2023-trips 같은 아카이브 폴더를 열면, 클라이언트는 이를 roots 목록에 추가하고, 서버는 다음 roots/list 요청에서 새 경계를 보게 됩니다.
roots를 존중하는 서버의 완전한 구현은 공식 서버 저장소의 filesystem 서버를 참고하세요.
설계 철학
Roots는 보안 경계가 아니라 클라이언트와 서버 사이의 조정 메커니즘이에요. 사양은 서버가 "root 경계를 존중해야 한다(SHOULD respect)"고 요구하지, "강제해야 한다(MUST enforce)"고 요구하지 않아요. 서버가 클라이언트가 통제할 수 없는 코드를 실행하기 때문이죠.
Roots는 서버가 신뢰되거나 검증됐고, 사용자가 그 권고적 성격을 이해하며, 목표가 악의적인 행동을 막는 것이 아니라 사고를 예방하는 것일 때 가장 잘 동작해요. 컨텍스트 범위 지정(서버가 어디에 집중해야 하는지 알려주기), 사고 예방(잘 동작하는 서버가 경계 안에 머물도록 돕기), 워크플로 구성(프로젝트 경계 자동 관리 같은)에 탁월합니다.
사용자 상호작용 모델
Roots는 보통 호스트 애플리케이션이 사용자 동작에 따라 자동으로 관리하며, 일부 애플리케이션은 수동 root 관리를 노출할 수 있어요.
자동 root 감지: 사용자가 폴더를 열면 클라이언트가 자동으로 이를 root로 노출해요. 여행 작업 공간을 열면 클라이언트가 그 디렉터리를 root로 노출해서, 서버가 현재 작업에서 어떤 일정과 문서가 범위 안인지 이해하도록 돕죠.
수동 root 구성: 고급 사용자는 설정을 통해 roots를 지정할 수 있어요. 예를 들어 재사용 가능한 리소스를 위한 /travel-templates를 추가하면서 재무 기록이 있는 디렉터리는 제외할 수 있어요.
Sampling
Sampling은 프로토콜 버전
2026-07-28부터 폐기 예정이며 제거 예정이에요. 새 구현은 대신 LLM 제공자 API에 직접 통합해야 합니다.
Sampling은 서버가 클라이언트를 통해 언어 모델 완성을 요청할 수 있게 해 주며, 보안과 사용자 통제를 유지하면서 에이전트 같은 동작을 가능하게 해요.
개요
Sampling은 서버가 AI 모델에 직접 통합하거나 비용을 지불하지 않고도 AI 의존 작업을 수행할 수 있게 해 줘요. 대신 서버는 이미 AI 모델 접근 권한이 있는 클라이언트에게 그 작업을 대신 처리해 달라고 요청할 수 있어요. 이 방식은 클라이언트가 사용자 권한과 보안 조치를 완전히 통제하게 합니다. sampling 요청은 다른 작업(예: 데이터를 분석하는 도구)의 컨텍스트 안에서 발생하고 별도의 모델 호출로 처리되므로, 서로 다른 컨텍스트 사이에 명확한 경계가 유지되고 컨텍스트 윈도우를 더 효율적으로 사용할 수 있어요.
Sampling은 elicitation 아래에 설명된 것과 같은 Multi Round-Trip Requests 흐름을 따르며, InputRequiredResult가 sampling/createMessage 요청을 담아요.
서버는 sampling 중 도구 사용도 요청할 수 있는데, 요청에 tools 배열과 선택적 toolChoice 필드를 포함하면 돼요. 도구 정의는 그 sampling 요청에 한정되며 서버가 노출하는 도구와 일치할 필요가 없어요. 클라이언트는 sampling.tools 기능으로 지원을 선언하고, 서버는 이를 선언하지 않은 클라이언트에 도구 지원 sampling 요청을 보내면 안 됩니다. 자세한 내용은 사양의 sampling을 참고하세요.
Sampling 흐름:
sequenceDiagram
participant LLM
participant User
participant Client
participant Server
Client->>Server: tools/call (id: 1)
Note over Server: Server needs an LLM completion
Server-->>Client: InputRequiredResult with sampling/createMessage request
Note over Client,User: Human-in-the-loop review
Client->>User: Present request for approval
User-->>Client: Review and approve/modify
Note over Client,LLM: Model interaction
Client->>LLM: Forward approved request
LLM-->>Client: Return generation
Note over Client,User: Response review
Client->>User: Present response for approval
User-->>Client: Review and approve/modify
Note over Client,Server: Retry request with approved response
Client->>Server: tools/call (id: 2, inputResponses)
Server-->>Client: Final result
이 흐름은 여러 인간 개입(human-in-the-loop) 체크포인트를 통해 보안을 보장해요. 사용자는 클라이언트가 원래 요청을 재시도하기 전에 초기 요청과 생성된 응답을 모두 검토하고 수정할 수 있어요.
요청 매개변수 예시:
{
messages: [
{
role: "user",
content: {
type: "text",
text: "Analyze these flight options and recommend the best choice:\n" +
"[47 flights with prices, times, airlines, and layovers]\n" +
"User preferences: morning departure, max 1 layover"
}
}
],
modelPreferences: {
hints: [{
name: "claude-sonnet-4-20250514" // Suggested model
}],
costPriority: 0.3, // Less concerned about API cost
speedPriority: 0.2, // Can wait for thorough analysis
intelligencePriority: 0.9 // Need complex trade-off evaluation
},
systemPrompt: "You are a travel expert helping users find the best flights based on their preferences",
maxTokens: 1500
}
예시: 항공편 분석 도구
여행 예약 서버에 sampling을 사용해 이용 가능한 항공편을 분석하고 최적의 선택을 추천하는 findBestFlight 도구가 있다고 생각해 보세요. 사용자가 "다음 달 바르셀로나로 가는 최고의 항공편을 예약해 줘"라고 요청하면, 이 도구는 복잡한 트레이드오프를 평가할 AI 지원이 필요해요.
도구는 항공사 API를 조회해 47개의 항공편 옵션을 모읍니다. 그런 다음 이 옵션들을 분석해 달라고 AI 지원을 요청합니다. "이 항공편 옵션을 분석하고 최선의 선택을 추천해 줘: [가격, 시간, 항공사, 경유지가 있는 47개 항공편] 사용자 선호: 오전 출발, 경유 최대 1회."
클라이언트는 sampling 요청을 시작해, AI가 저렴한 레드아이(red-eye) 항공편과 편리한 오전 출발 같은 트레이드오프를 평가하게 해 줘요. 도구는 이 분석을 사용해 상위 3개 추천을 제시합니다.
사용자 상호작용 모델
요구 사항은 아니지만, sampling은 인간 개입 통제를 가능하게 설계돼 있어요. 사용자는 여러 메커니즘으로 감독을 유지할 수 있어요.
승인 통제: sampling 요청은 명시적 사용자 동의를 요구할 수 있어요. 클라이언트는 서버가 무엇을 분석하려 하는지, 왜인지를 보여 줄 수 있어요. 사용자는 요청을 승인하거나, 거부하거나, 수정할 수 있어요.
투명성 기능: 클라이언트는 정확한 프롬프트, 모델 선택, 토큰 한도를 표시해서, 사용자가 서버로 반환되기 전에 AI 응답을 검토할 수 있게 해 줘요.
구성 옵션: 사용자는 모델 선호를 설정하고, 신뢰하는 작업에 자동 승인을 구성하거나, 모든 것에 승인을 요구할 수 있어요. 클라이언트는 민감한 정보를 편집하는 옵션을 제공할 수도 있어요.
보안 고려 사항: 클라이언트와 서버 모두 sampling 중 민감한 데이터를 적절히 처리해야 해요. 클라이언트는 속도 제한을 구현하고 모든 메시지 콘텐츠를 검증해야 합니다. 인간 개입 설계는 서버가 요청한 AI 상호작용이 명시적 사용자 동의 없이 보안을 손상시키거나 민감한 데이터에 접근할 수 없도록 보장해요.