본문으로 건너뛰기

아키텍처 개요

이 Model Context Protocol(MCP) 개요에서는 MCP의 범위핵심 개념을 살펴보고, 각 핵심 개념을 보여주는 예제를 제공합니다.

MCP SDK가 여러 고려 사항을 추상화하므로 대부분의 개발자에게는 데이터 계층 프로토콜 섹션이 가장 유용할 것입니다. 이 섹션에서는 MCP 서버가 AI 애플리케이션에 컨텍스트를 제공하는 방법을 설명합니다.

구체적인 구현 세부 사항은 사용하는 언어의 언어별 SDK 문서를 참고하세요.

범위

Model Context Protocol에는 다음 프로젝트가 포함됩니다.

  • MCP 명세: 클라이언트와 서버의 구현 요구 사항을 설명하는 MCP 명세입니다.
  • MCP SDK: 여러 프로그래밍 언어로 MCP를 구현하는 SDK입니다.
  • MCP 개발 도구: MCP Inspector를 비롯하여 MCP 서버와 클라이언트를 개발하기 위한 도구입니다.
  • MCP 참조 서버 구현: MCP 서버의 참조 구현입니다.

MCP의 개념

참여자

MCP는 Claude CodeClaude Desktop 같은 AI 애플리케이션인 MCP 호스트가 하나 이상의 MCP 서버와 연결을 설정하는 클라이언트-서버 아키텍처를 따릅니다. MCP 호스트는 각 MCP 서버마다 하나의 MCP 클라이언트를 만들어 이를 수행합니다. 각 MCP 클라이언트는 해당 MCP 서버와 전용 연결을 유지합니다.

STDIO 전송을 사용하는 로컬 MCP 서버는 일반적으로 하나의 MCP 클라이언트에 서비스를 제공하지만, Streamable HTTP 전송을 사용하는 원격 MCP 서버는 대개 여러 MCP 클라이언트에 서비스를 제공합니다.

MCP 아키텍처의 주요 참여자는 다음과 같습니다.

  • MCP 호스트: 하나 이상의 MCP 클라이언트를 조정하고 관리하는 AI 애플리케이션
  • MCP 클라이언트: MCP 서버와 연결을 유지하며 MCP 호스트가 사용할 컨텍스트를 MCP 서버에서 가져오는 구성 요소
  • MCP 서버: MCP 클라이언트에 컨텍스트를 제공하는 프로그램

예시: Visual Studio Code는 MCP 호스트로 작동합니다. Visual Studio Code가 Sentry MCP 서버 같은 MCP 서버에 연결할 때 Visual Studio Code 런타임은 Sentry MCP 서버와의 연결을 유지하는 MCP 클라이언트 객체를 생성합니다. 이후 Visual Studio Code가 로컬 파일 시스템 서버 같은 다른 MCP 서버에 연결하면 Visual Studio Code 런타임은 이 연결을 유지할 MCP 클라이언트 객체를 추가로 생성합니다.

graph TB
subgraph "MCP Host (AI Application)"
Client1["MCP Client 1"]
Client2["MCP Client 2"]
Client3["MCP Client 3"]
Client4["MCP Client 4"]
end

ServerA["MCP Server A - Local<br/>(e.g. Filesystem)"]
ServerB["MCP Server B - Local<br/>(e.g. Database)"]
ServerC["MCP Server C - Remote<br/>(e.g. Sentry)"]

Client1 ---|"Dedicated<br/>connection"| ServerA
Client2 ---|"Dedicated<br/>connection"| ServerB
Client3 ---|"Dedicated<br/>connection"| ServerC
Client4 ---|"Dedicated<br/>connection"| ServerC

MCP 서버는 실행 위치와 관계없이 컨텍스트 데이터를 제공하는 프로그램을 의미합니다. MCP 서버는 로컬 또는 원격에서 실행할 수 있습니다. 예를 들어 Claude Desktop이 파일 시스템 서버를 실행하면 이 서버는 STDIO 전송을 사용하므로 같은 컴퓨터에서 로컬로 실행됩니다. 이를 일반적으로 "로컬" MCP 서버라고 합니다. 공식 Sentry MCP 서버는 Sentry 플랫폼에서 실행되며 Streamable HTTP 전송을 사용합니다. 이를 일반적으로 "원격" MCP 서버라고 합니다.

계층

MCP는 두 계층으로 구성됩니다.

  • 데이터 계층: 기능 및 버전 탐색과 도구, 리소스, 프롬프트, 알림 같은 핵심 프리미티브를 포함하여 클라이언트-서버 통신을 위한 JSON-RPC 기반 프로토콜을 정의합니다.
  • 전송 계층: 전송 방식별 연결 설정, 메시지 프레이밍, 권한 부여를 포함하여 클라이언트와 서버 간 데이터 교환을 지원하는 통신 메커니즘과 채널을 정의합니다.

개념적으로 데이터 계층은 내부 계층이고 전송 계층은 외부 계층입니다.

데이터 계층

데이터 계층은 메시지 구조와 의미 체계를 정의하는 JSON-RPC 2.0 기반 교환 프로토콜을 구현합니다. 이 계층에는 다음 항목이 포함됩니다.

  • 탐색: 클라이언트가 server/discover 요청을 통해 서버가 지원하는 프로토콜 버전, 기능, 식별 정보를 조회할 수 있게 합니다.
  • 서버 기능: AI 작업을 위한 도구, 컨텍스트 데이터용 리소스, 클라이언트와 주고받는 상호작용 템플릿용 프롬프트 등 핵심 기능을 서버가 제공할 수 있게 합니다.
  • 클라이언트 기능: 서버가 사용자에게 입력을 요청할 수 있게 합니다. 샘플링은 프로토콜 버전 2026-07-28부터 지원 중단되었습니다.
  • 유틸리티 기능: 실시간 업데이트 알림과 장기 실행 작업의 진행 상황 추적 같은 추가 기능을 지원합니다.

전송 계층

전송 계층은 클라이언트와 서버 사이의 통신 채널과 인증을 관리합니다. MCP 참여자 사이의 연결 설정, 메시지 프레이밍, 보안 통신을 처리합니다.

MCP는 두 가지 전송 메커니즘을 지원합니다.

  • Stdio 전송: 같은 컴퓨터의 로컬 프로세스 사이에서 직접 통신하도록 표준 입출력 스트림을 사용하며, 네트워크 오버헤드 없이 최적의 성능을 제공합니다.
  • Streamable HTTP 전송: 클라이언트에서 서버로 보내는 메시지에는 HTTP POST를 사용하고, 스트리밍 기능에는 선택적으로 Server-Sent Events를 사용합니다. 이 전송 방식은 원격 서버 통신을 지원하며 전달자 토큰, API 키, 사용자 지정 헤더를 포함한 표준 HTTP 인증 방식을 지원합니다. MCP는 인증 토큰을 얻을 때 OAuth를 사용할 것을 권장합니다.

전송 계층은 프로토콜 계층에서 통신 세부 사항을 추상화하여 모든 전송 메커니즘에서 동일한 JSON-RPC 2.0 메시지 형식을 사용할 수 있게 합니다.

데이터 계층 프로토콜

MCP의 핵심은 MCP 클라이언트와 MCP 서버 사이의 스키마와 의미 체계를 정의하는 것입니다. 개발자에게는 데이터 계층, 특히 프리미티브 집합이 MCP에서 가장 흥미로운 부분일 것입니다. 이 계층은 개발자가 MCP 서버의 컨텍스트를 MCP 클라이언트와 공유하는 방법을 정의합니다.

MCP는 기반 RPC 프로토콜로 JSON-RPC 2.0을 사용합니다. 클라이언트와 서버는 서로 요청을 보내고 이에 응답합니다. 응답이 필요하지 않을 때는 알림을 사용할 수 있습니다.

무상태성과 탐색

MCP는 무상태 프로토콜입니다. 모든 요청은 해당 요청과 관련된 프로토콜 버전과 기능_meta 필드에 담으므로 서버가 각 요청을 독립적으로 처리할 수 있습니다. 별도로 설정하지 않았다면 클라이언트도 같은 필드에 자신의 식별 정보를 포함해야 합니다. 서버는 필수 server/discover 요청을 통해 지원하는 버전과 기능을 알리며, 클라이언트는 다른 요청보다 먼저 이 요청을 보낼 수 있습니다. 자세한 내용은 명세에서 확인할 수 있으며 예제에서는 요청별 메타데이터와 탐색 순서를 보여줍니다.

프리미티브

MCP 프리미티브는 MCP에서 가장 중요한 개념입니다. 프리미티브는 클라이언트와 서버가 서로 제공할 수 있는 항목을 정의합니다. 또한 AI 애플리케이션과 공유할 수 있는 컨텍스트 정보의 유형과 수행할 수 있는 작업의 범위를 지정합니다.

MCP는 _서버_가 노출할 수 있는 세 가지 핵심 프리미티브를 정의합니다.

  • 도구: AI 애플리케이션이 작업을 수행하기 위해 호출할 수 있는 실행 가능한 함수(예: 파일 작업, API 호출, 데이터베이스 쿼리)
  • 리소스: AI 애플리케이션에 컨텍스트 정보를 제공하는 데이터 소스(예: 파일 내용, 데이터베이스 레코드, API 응답)
  • 프롬프트: 언어 모델과의 상호작용을 구조화하는 데 도움이 되는 재사용 가능한 템플릿(예: 시스템 프롬프트, 퓨샷 예제)

각 프리미티브 유형에는 탐색(*/list), 조회(*/get), 경우에 따라 실행(tools/call)을 위한 메서드가 연결되어 있습니다. MCP 클라이언트는 */list 메서드로 사용 가능한 프리미티브를 탐색합니다. 예를 들어 클라이언트는 먼저 사용 가능한 모든 도구 목록(tools/list)을 조회한 다음 해당 도구를 실행할 수 있습니다. 이러한 설계 덕분에 목록을 동적으로 구성할 수 있습니다.

구체적인 예로 데이터베이스에 관한 컨텍스트를 제공하는 MCP 서버를 살펴보겠습니다. 이 서버는 데이터베이스를 조회하는 도구, 데이터베이스 스키마를 포함하는 리소스, 도구와 상호작용하는 퓨샷 예제가 포함된 프롬프트를 노출할 수 있습니다.

서버 프리미티브에 대한 자세한 내용은 서버 개념을 참고하세요.

MCP는 _클라이언트_가 노출할 수 있는 프리미티브도 정의합니다. 이러한 프리미티브를 통해 MCP 서버 개발자는 더욱 풍부한 상호작용을 구축할 수 있습니다.

  • 정보 요청: 서버가 사용자에게 추가 정보를 요청할 수 있게 합니다. 서버 개발자가 사용자로부터 더 많은 정보를 얻거나 작업 확인을 요청할 때 유용합니다. 서버는 elicitation/create 메서드로 사용자 입력을 요청합니다.

정보 요청은 다중 왕복 요청 패턴을 통해 전달되며, 이 패턴은 정보 요청 개요에서 설명합니다.

지원 중단: 다음 클라이언트 프리미티브는 프로토콜 버전 2026-07-28부터 지원 중단되었습니다.

  • 샘플링: 서버가 클라이언트의 AI 애플리케이션에 언어 모델 완성을 요청할 수 있게 합니다. 서버 개발자가 언어 모델을 사용하면서도 특정 모델에 종속되지 않고 MCP 서버에 언어 모델 SDK를 포함하지 않으려 할 때 유용합니다. 서버는 sampling/createMessage 메서드로 완성을 요청하며, 이 요청 역시 다중 왕복 요청 패턴을 통해 전달됩니다. 새로운 구현은 LLM 제공업체 API와 직접 통합해야 합니다.
  • 로깅: 서버가 디버깅과 모니터링을 위해 클라이언트에 로그 메시지를 보낼 수 있게 합니다. 새로운 구현은 stderr(stdio 전송)에 기록하거나 OpenTelemetry를 사용해야 합니다.

클라이언트 프리미티브에 대한 자세한 내용은 클라이언트 개념을 참고하세요.

서버 및 클라이언트 프리미티브 외에도 프로토콜은 핵심 프로토콜을 기반으로 하는 선택적 확장을 지원합니다. 예를 들어 Tasks 확장을 사용하면 서버가 장기 실행 요청에 대한 지속 가능한 핸들을 반환할 수 있으므로 클라이언트가 상태를 폴링하고 나중에 결과를 가져올 수 있습니다.

알림

프로토콜은 서버와 클라이언트 사이의 동적 업데이트를 지원하기 위해 실시간 알림을 제공합니다. 예를 들어 서버에서 사용 가능한 도구가 변경되면(새 기능을 사용할 수 있게 되거나 기존 도구가 수정되는 경우 등) 서버는 연결된 클라이언트에 이러한 변경 사항을 알리는 도구 업데이트 알림을 보낼 수 있습니다. 알림은 응답을 기대하지 않는 JSON-RPC 2.0 알림 메시지로 전송됩니다. 변경 알림은 옵트인 방식입니다. 클라이언트는 수신하려는 알림 유형을 지정하여 장기 실행 subscriptions/listen 스트림을 열고, 서버는 해당 스트림으로 일치하는 알림을 전달합니다.

예제

데이터 계층

이 섹션에서는 데이터 계층 프로토콜을 중심으로 MCP 클라이언트-서버 상호작용을 단계별로 살펴봅니다. JSON-RPC 2.0 메시지를 사용하여 탐색, 도구 작업, 알림을 설명합니다.

탐색

무상태성과 탐색 섹션에서 설명했듯이 모든 MCP 요청은 _meta 필드에 프로토콜 버전과 클라이언트 기능을 담으며, 클라이언트는 이 필드에 식별 정보도 포함해야 합니다. 다른 요청을 보내기 전에 서버가 지원하는 기능을 확인하려는 클라이언트는 모든 서버가 반드시 구현해야 하는 server/discover 요청을 보냅니다. 탐색 응답은 일반적으로 캐시할 수 있으므로 재사용할 수 있으며, 모든 요청마다 탐색 흐름을 수행할 필요가 없습니다.

{
"jsonrpc": "2.0",
"id": 1,
"method": "server/discover",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "example-client",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": {}
}
}
}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"supportedVersions": ["2026-07-28"],
"capabilities": {
"tools": {
"listChanged": true
},
"resources": {}
},
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "example-server",
"version": "1.0.0"
}
},
"ttlMs": 3600000,
"cacheScope": "public"
}
}

탐색 교환 이해하기

_meta 필드와 탐색 응답은 함께 다음과 같은 여러 목적을 수행합니다.

  1. 프로토콜 버전 선택: io.modelcontextprotocol/protocolVersion 필드는 클라이언트가 이 요청에서 사용하는 버전을 선언하고, 응답의 supportedVersions는 서버가 허용하는 버전 목록을 제공합니다. 서버가 요청된 버전을 지원하지 않으면 지원하는 버전 목록이 담긴 UnsupportedProtocolVersionError로 요청을 거부하며, 클라이언트는 양쪽이 모두 지원하는 버전으로 다시 시도합니다.

  2. 기능 탐색: 클라이언트는 모든 요청의 io.modelcontextprotocol/clientCapabilities에 자신의 기능을 선언하고, 서버는 server/discover에서 자체 capabilities 객체를 반환합니다. 이를 통해 양측은 상대방이 처리할 수 있는 프리미티브(도구, 리소스, 프롬프트)와 변경 알림 지원 여부를 파악하므로 지원되지 않는 작업을 시도하지 않습니다.

  3. 식별 정보 교환: 요청의 _meta에 있는 io.modelcontextprotocol/clientInfo 필드와 결과의 _meta에 있는 io.modelcontextprotocol/serverInfo 필드는 디버깅과 호환성을 위한 식별 및 버전 정보를 제공합니다.

이 예제의 교환 과정에서는 MCP 기능을 선언하는 방법을 보여줍니다.

클라이언트 기능:

  • "elicitation": {} - 서버가 요청할 때 클라이언트가 사용자로부터 추가 입력을 받을 수 있음을 선언합니다.

서버 기능:

  • "tools": {"listChanged": true} - 서버가 도구 프리미티브를 지원하며 subscriptions/listentoolsListChanged 필터를 처리할 수 있습니다. 이 필터를 요청한 클라이언트는 도구 목록이 변경될 때 notifications/tools/list_changed를 받습니다.
  • "resources": {} - 서버가 리소스 프리미티브도 지원합니다(resources/listresources/read 메서드를 처리할 수 있음).

server/discover 호출은 선택 사항입니다. 모든 요청에 같은 _meta 필드가 포함되므로 클라이언트는 어떤 요청이든 바로 보내고 버전 오류가 반환되면 이를 처리할 수 있습니다. 탐색은 서버의 식별 정보, 기능, 지원 버전을 한 번의 요청으로 가져오는 편리한 방법입니다.

AI 애플리케이션에서의 작동 방식

AI 애플리케이션의 MCP 클라이언트 관리자는 구성된 서버에 연결하고 탐색한 기능을 나중에 사용할 수 있도록 저장합니다. 애플리케이션은 이 정보를 사용하여 특정 유형의 기능(도구, 리소스, 프롬프트)을 제공할 수 있는 서버와 실시간 업데이트 지원 여부를 판단합니다. Python SDK에서는 클라이언트가 연결되는 동안 탐색이 수행되며, 이후 클라이언트 객체에서 결과를 사용할 수 있습니다.

# Pseudo Code
async with Client(stdio_client(server_config)) as client:
if client.server_capabilities.tools:
app.register_mcp_server(client, supports_tools=True)
app.set_server_ready(client)

도구 탐색(프리미티브)

클라이언트는 tools/list 요청을 보내 사용 가능한 도구를 탐색할 수 있습니다. 이 요청은 MCP 도구 탐색 메커니즘의 핵심으로, 클라이언트가 도구를 사용하기 전에 서버에서 사용할 수 있는 도구를 파악할 수 있게 합니다.

{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "example-client",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": {}
}
}
}
}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"tools": [
{
"name": "calculator_arithmetic",
"title": "Calculator",
"description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
"inputSchema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
}
},
"required": ["expression"]
}
},
{
"name": "weather_current",
"title": "Weather Information",
"description": "Get current weather information for any location worldwide",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, address, or coordinates (latitude,longitude)"
},
"units": {
"type": "string",
"enum": ["metric", "imperial", "kelvin"],
"description": "Temperature units to use in response",
"default": "metric"
}
},
"required": ["location"]
}
}
],
"ttlMs": 300000,
"cacheScope": "public"
}
}

도구 탐색 요청 이해하기

tools/list 요청에는 모든 MCP 요청에 포함되는 표준 _meta 필드 외에 다른 매개변수가 필요하지 않습니다. 페이지네이션을 위한 선택적 cursor 매개변수도 받을 수 있지만 위 예제에서는 생략했습니다.

도구 탐색 응답 이해하기

응답에는 사용 가능한 각 도구의 종합적인 메타데이터를 제공하는 tools 배열이 포함됩니다. 이 배열 기반 구조를 통해 서버는 서로 다른 기능 사이의 명확한 경계를 유지하면서 여러 도구를 동시에 노출할 수 있습니다.

응답의 각 도구 객체에는 다음과 같은 주요 필드가 포함됩니다.

  • name: 서버 네임스페이스 안에서 도구를 식별하는 고유 식별자입니다. 도구 실행을 위한 기본 키 역할을 하며 명확한 이름 지정 패턴을 따라야 합니다(예: 단순히 calculate가 아닌 calculator_arithmetic).
  • title: 클라이언트가 사용자에게 표시할 수 있는 사람이 읽기 쉬운 도구 이름입니다.
  • description: 도구가 수행하는 작업과 사용 시점에 대한 자세한 설명입니다.
  • inputSchema: 예상 입력 매개변수를 정의하는 JSON Schema로, 타입 검증을 지원하고 필수 및 선택 매개변수에 관한 명확한 문서를 제공합니다.

결과에는 "resultType": "complete"가 표시되고 두 개의 캐싱 필드가 포함됩니다. ttlMs는 밀리초 단위의 최신성 힌트이므로 이 도구 목록을 5분 동안 캐시할 수 있습니다. cacheScope는 응답을 재사용할 수 있는 주체를 나타냅니다. 전체 규칙은 명세의 캐싱 유틸리티에 정의되어 있습니다.

AI 애플리케이션에서의 작동 방식

AI 애플리케이션은 연결된 모든 MCP 서버에서 사용 가능한 도구를 가져와 언어 모델이 접근할 수 있는 통합 도구 레지스트리로 결합합니다. 이를 통해 LLM은 수행할 수 있는 작업을 파악하고 대화 중 적절한 도구 호출을 자동으로 생성할 수 있습니다.

# Pseudo-code using MCP Python SDK patterns
available_tools = []
for client in app.mcp_clients():
tools_response = await client.list_tools()
available_tools.extend(tools_response.tools)
conversation.register_available_tools(available_tools)

여러 서버를 연합하는 클라이언트는 모든 도구를 처음부터 불러오는 대신 점진적 도구 탐색을 사용할 수 있습니다.

도구 실행(프리미티브)

이제 클라이언트는 tools/call 메서드로 도구를 실행할 수 있습니다. 이는 MCP 프리미티브를 실제로 사용하는 방식을 보여줍니다. 클라이언트는 사용 가능한 도구를 탐색한 후 적절한 인수와 함께 도구를 호출할 수 있습니다.

도구 실행 요청 이해하기

tools/call 요청은 타입 안전성과 클라이언트-서버 간 명확한 통신을 보장하는 구조화된 형식을 따릅니다. 단순화한 이름이 아니라 탐색 응답에 있는 정확한 도구 이름(weather_current)을 사용한다는 점에 유의하세요.

{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "weather_current",
"arguments": {
"location": "San Francisco",
"units": "imperial"
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "example-client",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": {}
}
}
}
}
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"resultType": "complete",
"content": [
{
"type": "text",
"text": "Current weather in San Francisco: 68°F, partly cloudy with light winds from the west at 8 mph. Humidity: 65%"
}
]
}
}

도구 실행의 핵심 요소

요청 구조에는 다음과 같은 중요한 구성 요소가 포함됩니다.

  1. name: 탐색 응답의 도구 이름(weather_current)과 정확히 일치해야 합니다. 이를 통해 서버가 실행할 도구를 올바르게 식별할 수 있습니다.

  2. arguments: 도구의 inputSchema에 정의된 입력 매개변수를 포함합니다. 이 예제에서는 다음과 같습니다.

    • location: "San Francisco"(필수 매개변수)
    • units: "imperial"(선택적 매개변수, 지정하지 않으면 기본값은 "metric")
  3. _meta: 모든 MCP 요청에 포함해야 하는 프로토콜 버전 및 클라이언트 기능과, 별도로 설정하지 않았다면 포함해야 하는 클라이언트 식별 정보 등 요청별 표준 필드를 담습니다.

  4. JSON-RPC 구조: 요청과 응답을 연결하는 고유 id가 포함된 표준 JSON-RPC 2.0 형식을 사용합니다.

도구 실행 응답 이해하기

응답은 MCP의 유연한 콘텐츠 시스템을 보여줍니다.

  1. content 배열: 도구 응답은 콘텐츠 객체 배열을 반환하므로 텍스트, 이미지, 리소스 등 다양한 형식의 풍부한 응답을 제공할 수 있습니다.

  2. 콘텐츠 유형: 각 콘텐츠 객체에는 type 필드가 있습니다. 이 예제에서 "type": "text"는 일반 텍스트 콘텐츠를 나타내지만 MCP는 다양한 사용 사례를 위해 여러 콘텐츠 유형을 지원합니다.

  3. 구조화된 출력: 응답은 AI 애플리케이션이 언어 모델과 상호작용할 때 컨텍스트로 사용할 수 있는 실행 가능한 정보를 제공합니다.

이 실행 패턴을 통해 AI 애플리케이션은 서버 기능을 동적으로 호출하고 언어 모델과의 대화에 통합할 수 있는 구조화된 응답을 받을 수 있습니다.

AI 애플리케이션에서의 작동 방식

언어 모델이 대화 중 도구를 사용하기로 결정하면 AI 애플리케이션이 도구 호출을 가로채 적절한 MCP 서버로 전달하고 실행한 다음, 결과를 대화 흐름의 일부로 LLM에 반환합니다. 이를 통해 LLM은 실시간 데이터에 접근하고 외부 세계에서 작업을 수행할 수 있습니다.

# Pseudo-code for AI application tool execution
async def handle_tool_call(conversation, tool_name, arguments):
client = app.find_mcp_client_for_tool(tool_name)
result = await client.call_tool(tool_name, arguments)
conversation.add_tool_result(result.content)

실시간 업데이트(알림)

MCP는 서버가 클라이언트의 폴링 없이도 변경 사항을 알릴 수 있는 실시간 알림을 지원합니다. 이는 클라이언트를 동기화하고 신속하게 반응하도록 유지하는 핵심 기능인 알림 시스템을 보여줍니다.

변경 사항 구독

변경 알림은 옵트인 방식입니다. 알림을 받으려면 클라이언트가 원하는 이벤트 유형을 지정하는 notifications 필터와 함께 subscriptions/listen 요청을 보내 장기 실행 알림 스트림을 엽니다. 여기서는 클라이언트가 도구 목록 변경을 요청합니다.

{
"jsonrpc": "2.0",
"id": 4,
"method": "subscriptions/listen",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "example-client",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": {}
}
},
"notifications": {
"toolsListChanged": true
}
}
}

모든 클라이언트 요청은 _metaio.modelcontextprotocol/protocolVersionio.modelcontextprotocol/clientCapabilities 필드를 담으며, 일반적으로 io.modelcontextprotocol/clientInfo도 포함하므로 서버는 연결 상태에 의존하지 않고 클라이언트를 식별할 수 있습니다.

서버는 notifications/subscriptions/acknowledged로 구독을 확인합니다. 이 메시지는 _meta에 해당 구독 ID를 담는 첫 번째 메시지이며, 서버는 그 전에 해당 구독에 다른 알림을 보내지 않습니다. 메시지의 notifications 필드는 서버가 처리하기로 동의한 요청 필터의 하위 집합을 나타내며 지원되지 않는 알림 유형은 생략됩니다.

{
"jsonrpc": "2.0",
"method": "notifications/subscriptions/acknowledged",
"params": {
"_meta": {
"io.modelcontextprotocol/subscriptionId": 4
},
"notifications": {
"toolsListChanged": true
}
}
}

도구 목록 변경 알림 이해하기

구독이 확인된 후 서버에서 사용 가능한 도구가 변경되면(예: 새 기능을 사용할 수 있게 되거나 기존 도구가 수정되거나 도구를 일시적으로 사용할 수 없게 되는 경우) 서버는 해당 스트림으로 알림을 전달합니다.

{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed",
"params": {
"_meta": {
"io.modelcontextprotocol/subscriptionId": 4
}
}
}

MCP 알림의 주요 기능

  1. 응답 불필요: 알림에 id 필드가 없다는 점에 유의하세요. 응답을 기대하거나 보내지 않는 JSON-RPC 2.0 알림 의미 체계를 따릅니다.

  2. 옵트인 기반: 이 알림은 subscriptions/listen 필터에서 "toolsListChanged": true를 요청한 클라이언트에만 전송되며, 1단계에서 본 것처럼 도구 기능에 "listChanged": true를 선언한 서버에서만 사용할 수 있습니다.

  3. 구독 ID 태그 지정: 스트림의 모든 알림은 _metaio.modelcontextprotocol/subscriptionId를 포함합니다. 이 값은 스트림을 연 subscriptions/listen 요청의 JSON-RPC ID(이 예제에서는 4)이므로 클라이언트는 각 알림을 해당 알림을 생성한 구독과 연결할 수 있습니다.

  4. 이벤트 기반: 서버는 내부 상태 변경에 따라 알림을 보낼 시점을 결정하므로 MCP 연결을 동적이고 신속하게 유지할 수 있습니다.

  5. 최선 노력 방식: 특히 전송 연결이 다시 설정되는 동안에는 모든 알림의 전송이나 수신을 보장하지 않습니다. 클라이언트는 결과의 최신성을 유지하기 위해 폴링도 함께 사용해야 합니다.

알림에 대한 클라이언트 응답

이 알림을 받으면 클라이언트는 일반적으로 업데이트된 도구 목록을 요청합니다. 이로써 클라이언트가 사용 가능한 도구를 항상 최신 상태로 파악하도록 하는 새로 고침 주기가 만들어집니다.

{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/list",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "example-client",
"version": "1.0.0"
},
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": {}
}
}
}
}

알림이 중요한 이유

이 알림 시스템은 다음과 같은 이유로 중요합니다.

  1. 동적 환경: 서버 상태, 외부 종속성 또는 사용자 권한에 따라 도구가 추가되거나 제거될 수 있습니다.
  2. 효율성: 클라이언트가 변경 사항을 폴링할 필요 없이 업데이트가 발생하면 알림을 받습니다.
  3. 일관성: 클라이언트가 사용 가능한 서버 기능에 관한 정확한 정보를 항상 유지하도록 합니다.
  4. 실시간 협업: 변화하는 컨텍스트에 적응할 수 있는 반응성 높은 AI 애플리케이션을 지원합니다.

이 알림 패턴은 도구뿐 아니라 다른 MCP 프리미티브에도 적용되어 클라이언트와 서버 사이의 포괄적인 실시간 동기화를 지원합니다.

AI 애플리케이션에서의 작동 방식

AI 애플리케이션은 관심 있는 변경 사항에 대한 알림 스트림을 열린 상태로 유지합니다. 알림이 도착하면 즉시 도구 레지스트리를 새로 고치고 LLM에서 사용 가능한 기능을 업데이트합니다. 따라서 진행 중인 대화는 항상 최신 도구 집합에 접근할 수 있으며, LLM은 새 기능이 제공되는 즉시 동적으로 적응할 수 있습니다.

# Pseudo-code for AI application notification handling
async def follow_tool_changes(client):
async with client.listen(tools_list_changed=True) as sub:
async for _event in sub:
tools_response = await client.list_tools()
app.update_available_tools(client, tools_response.tools)
if app.conversation.is_active():
app.conversation.notify_llm_of_new_capabilities()