들어가며
최근 Anthropic에서 Claude LLM을 통해 모델 컨텍스트 프로토콜(Model Context Protocol, 이하 MCP)을 발표했습니다. MCP는 대형 언어 모델(large language model, 이하 LLM)이 외부 데이터 소스나 기능을 사용할 수 있도록 돕는 프로토콜로, Anthropic 에서 누구나 사용할 수 있는 오픈 프로토콜로 공개했습니다(참고). 이에 따라 많은 서비스에서 MCP를 지원하기 시작했고, 많은 사용자가 MCP를 사용해 LLM과 외부 서비스를 연결하는 방법에 관심을 갖기 시작했습니다.
이번 글에서는 많은 관심을 받고 있는 MCP의 개념과 아키텍처를 설명하고, LINE Messaging API를 활용해 MCP 서버를 구현하는 방법을 소개하겠습니다.
MCP 소개
MCP는 LLM이 외부 기능을 사용할 수 있도록 지원하는 프로토콜입니다. 아래는 LLM만 단독으로 사용하는 경우와 MCP를 활용한 경우를 비교한 그림입니다.
예를 들어 LINE의 오픈소스 라이브러리인 Armeria에서 특정 코드를 검색하고 싶을 때 LLM 애플리케이션에 프롬프트를 작성해 요청하면, LLM 애플리케이션은 실제 GitHub에 접속해서 Armeria 라이브러리를 조사하는 것이 아니라 기존에 학습한 모델을 바탕으로 응답할 것입니다. AI 할루시네이션이 발생할 수 있는 상황이죠.
반면 GitHub MCP를 사용하면 LLM 애플리케이션이 GitHub에 접속해 실제 Armeria 리포지터리에서 해당 코드를 검색한 뒤 검색 결과를 기준으로 응답합니다. 다만 이를 위해서는 외부 서비스인 GitHub에서 MCP 서버를 제공해야 하며, 사용하는 LLM 애플리케이션에서도 이 MCP를 사용해 호출해야 하는데요. 이와 같이 LLM 애플리케이션에서 외부 기능을 사용할 수 있도록 정의한 프로토콜을 MCP라고 합니다(참고로 GitHub은 실제로 GitHub MCP를 제공하고 있습니다).
아키텍처
MCP는 기본적으로 호스트의 클라이언트가 서버와 연결되는 클라이언트-서버 아키텍처를 따릅니다.
이 아키텍처는 호스트, 클라이언트, 서버, 이 세 가지 주체로 구성되며, 각 주체의 역할은 다음과 같습니다.
- 호스트: MCP를 사용하는 주체인 LLM 애플리케이션을 가리키며, 사용자의 요청을 받아 응답하는 애플리케이션입니다. 이후 예제에서 'Claude 데스크톱 애플리케이션'이 호스트에 해당합니다.
- 클라이언트: 호스트의 내부 모듈로 MCP 서버에 요청을 전송한 뒤 응답을 받아 호스트에게 전달합니다.
- 서버: 호스트 외부에 존재하며 MCP 클라이언트로부터 받은 요청을 처리하고 응답하는 애플리케이션입니다.
구성 요소
MCP 호스트가 사용할 수 있는 요소는 다양합니다. 그중 가장 핵심적인 요소인 툴과 리소스를 소개하겠습니다.
툴
툴(tools)은 MCP의 핵심 요소로 외부 기능을 실행할 수 있도록 MCP 서버가 제공하는 요소입니다. MCP 서버는 실행할 수 있는 툴 목록을 확인할 수 있는 엔드포인트인 tools/list와, 원하는 툴을 호출할 수 있는 엔드포인트인 tools/call를 제공합니다. MCP 호스트는 사용자 프롬프트에 대한 응답을 처리하는 과정에서 외부 기능 호출이 필요한 경우 MCP 클라이언트를 통해 MCP 서버가 제공하는 툴을 사용합니다.
예를 들어 GitHub MCP 서버에서는 create_pull_request라는 툴을 제공하며, 사용자는 프롬프트를 통해 이 툴을 이용해 새로운 PR을 만들 수 있습니다.
리소스
리소스(resources) 역시 MCP의 핵심 요소로, MCP 서버가 제공할 수 있는 다양한 형태의 데이터나 콘텐츠를 의미합니다. 리소스는 파일 내용이나 데이터베이스 레코드, API 응답 등 다양한 형태로 존재할 수 있습니다. MCP 클라이언트는 MCP 서버에 사용할 수 있는 리소스 목록을 요청해 받은 뒤, 다시 필요한 리소스를 요청해서 데이터를 가져올 수 있습니다. MCP 클라이언트가 가져온 데이터는 MCP 호스트로 전달되며, MCP 호스트는 이 데이터를 사용자의 프롬프트 응답에 활용할 수 있습니다.
예를 들어 GitHub MCP 서버에서는 repo://{owner}/{repo}/contents{/path*} API 리소스를 통해 특정 리포지터리의 소스 코드를 제공합니다.
작동 방식
MCP는 어떻게 구현하느냐에 따라서 다양한 방식으로 작동할 수 있는데요. 이 글에서는 아래 그림과 함께 가장 기초적인 방식을 알아보겠습니다.
- MCP 호스트가 실행될 때 MCP 클라이언트를 통해 MCP 서버의 tools/list 엔드포인트를 호출해 사용 가능한 툴 목록을 받아옵니다.
- 사용자가 MCP 호스트에게 프롬프트를 보냅니다.
- MCP 호스트는 사용자의 프롬프트와 사전에 받아온 툴 목록을 LLM 모델로 전달합니다. LLM 모델은 툴 목록 중 사용이 필요하다고 판단된 툴들을 사용하겠다고 응답합니다.
- MCP 호스트는 MCP 클라이언트를 통해 MCP 서버의 tools/call 엔드포인트로 해당 툴 사용을 요청합니다.
- MCP 호스트는 MCP 서버의 툴 응답과 기존 사용자의 프롬프트를 다시 LLM 모델로 전달하고, LLM 모델은 이를 기반으로 최종 응답을 생성합니다.
- MCP 호스트는 LLM 모델로부터 받은 최종 응답을 가공해 사용자에게 전달합니다.
LINE Messaging API와 함께 하는 MCP 활용 사례
이제 LINE의 Messaging API를 활용해 MCP를 직접 사용해 보겠습니다. LINE은 LINE 공식 계정(Official Account, OA)을 위한 Messaging API를 제공하고 있으며, 이를 통해 공식 계정을 친구로 등록한 사용자에게 메시지를 보내는 등의 행동을 할 수 있는데요. 이를 활용해 MCP 서버를 구축해 보겠습니다. MCP 공식 사용자 가이드의 For Server Developers 문서와 LINE Developers 사이트의 Messaging API 문서를 함께 참고하시면 좋을 것 같습니다.
사전 준비
LINE Messaging API를 활용해 MCP 서버를 구축하기 위해서는 다음 준비가 필요합니다.
- Claude 데스크톱 애플리케이션 설치(참고)
- LINE Messaging API 사용 준비
- LINE Developers의 Get started with the Messaging API 문서를 참고해 공식 계정 생성 후 Messaging API 활성화해 채널 생성
- LINE Developer Console에 접속해 앞서 생성한 채널의 Messaging API 탭 하단에서 채널 액세스 토큰(channel access token) 발급
- LINE 계정에서 생성한 채널(LINE 공식 계정)을 친구로 추가
LINE Messaging API 사용 준비까지 완료됐다면 발급받은 채널 액세스 토큰을 사용해 API가 정상적으로 작동하는지 확인합니다. 이 글에서는 셸(shell)에서 확인하겠습니다. 다음과 같이 앞서 발급받은 채널 액세스 토큰을 Authorization 헤더에 넣고 broadcast API를 호출합니다(broadcast API의 사양은 LINE Messaging API 공식 가이드의 Send broadcast message 문서를 참고하세요).
curl -v -X POST https://api.line.me/v2/bot/message/broadcast \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer {Channel Access Token}" \ -H "X-Line-Retry-Key: ${uuidgen}" \ -d '{ "messages": [ { "type": "text", "text": "Hello, world" } ] }'위 명령어를 실행했을 때 미리 친구로 추가해 둔 공식 계정으로부터 메시지가 오면 성공입니다!
MCP 서버 개발
이제 본격적으로 MCP 서버를 개발해 보겠습니다. 먼저 MCP 공식 사용자 가이