Cook AI

Model Context Protocol(MCP) 과 구글 Gemini 2.5 Pro — 심층 분석

앤써니킴 2025. 5. 21. 10:28
이 글은 Arjun Prabhulal님의 동의 하에 그분의 깊이 있는 분석과 자료를 사용하여 작성했습니다. 원문은 [Model Context Protocol(MCP) with Google Gemini 2.5 Pro — A Deep Dive]에서 확인하실 수 있습니다. 독자 여러분께 더욱 유익한 정보를 전달할 수 있도록 귀한 내용을 공유해 주신 Arjun Prabhulal님께 다시 한번 감사드립니다.

 

GPT-4, Claude, Gemini, Llama3와 같은 대규모 언어 모델(LLM)이 발전하면서, 이러한 모델들을 외부 도구, API, 그리고 다양한 시스템과 표준화된 방식으로 연결해야 할 필요성이 점점 커지고 있습니다. 하지만 이 모델들은 사전 훈련된 데이터를 기반으로 독립적으로 작동하며, 실시간 데이터, 데이터베이스, 외부 API, 또는 로컬 파일에 직접 접근할 수 있는 기능이 내장되어 있지 않습니다.

Ollama와 Gemma3을 활용한 함수 호출에서는 함수 호출(Function Calling) 기능을 통해 자연어 명령을 실제 동작이나 데이터 접근으로 어떻게 변환할 수 있는지 설명해 드린 바 있습니다. 함수 호출이 핵심 기능을 제공한다면, Model Context Protocol(MCP)은 이 전체 과정을 한 단계 더 발전시켜 다양한 도구와 시스템 간의 구조화되고 유연하며 상호 운용 가능한 연결을 가능하게 합니다.

이번 글에서는 MCP의 개념을 좀 더 자세히 살펴보고, 실제 구현 방법에 대해서도 깊이 있게 다뤄보겠습니다. 함께 알아볼 내용은 다음과 같습니다.

  1. Model Context Protocol(MCP)이란 무엇일까요?
  2. MCP는 어떻게 작동하나요?
  3. MCP의 이점은 무엇일까요?
  4. MCP 서버의 예시
  5. 언제 MCP를 사용해야 할까요?
  6. 아키텍처 살펴보기
  7. 구현 단계 (코드와 함께)
  8. Gemini LLM과 MCP 사용을 위한 모범 사례
  9. 알려진 한계점

자, 그럼 시작해 볼까요?


Model Context Protocol(MCP)이란 무엇일까요?

Model Context Protocol(MCP)은 Anthropic에 의해 개발된 표준화된 개방형 프로토콜입니다. AI 모델이 외부 데이터 소스 및 도구와 원활하게 상호 작용할 수 있도록 지원하며, AI 통합을 위한 보편적인 연결고리 역할을 합니다.

MCP를 "AI 통합을 위한 USB-C"라고 생각하시면 이해가 쉬울 겁니다. 다양한 장치와 데이터 소스에 AI 모델을 연결하는 보편적인 방법을 제공하는 것이죠. 정말 편리하지 않나요?

MCP는 어떻게 작동하나요?

MCP는 클라이언트-서버 아키텍처를 따릅니다.

  • 클라이언트(AI 애플리케이션 또는 LLM 등)가
  • 서버(MCP 도구 제공자)에 연결하여 도구, API 또는 데이터 소스를 클라이언트에 노출합니다.

이를 통해 LLM 모델과 외부 API 간의 동적이고 구조화된 상호 작용이 가능해집니다.


MCP의 이점은 무엇일까요? 💯

MCP를 사용하면 다음과 같은 다양한 이점을 얻을 수 있습니다.

  • 표준화된 통합: 최소한의 사용자 정의 작업으로 LLM을 모든 외부 시스템에 연결할 수 있습니다.
  • 유연성: LLM이 필요에 따라 여러 도구와 서비스를 사용할 수 있습니다.
  • 보안: 자격 증명을 하드코딩하지 않고도 안전한 API 상호 작용을 지원합니다.
  • 간소화된 개발: 사용자 정의 MCP 서버를 쉽게 구축하고 노출할 수 있습니다.
  • 용이한 유지보수: 반복적인 통합 로직이 더 이상 필요 없습니다.
MCP는 API를 자동 검색, 예측 가능한 스키마, 구조화된 상호 작용을 갖춘 모델 친화적인 도구로 변환시켜 줍니다.

MCP 서버의 예시

MCP 서버는 다양한 형태로 구현될 수 있습니다. 몇 가지 예를 들어보겠습니다.

  • 파일 시스템: 로컬 파일 및 디렉터리에 접근합니다.
  • 웹 검색: 실시간 웹 검색을 실행합니다.
  • 데이터베이스: SQL 또는 NoSQL 데이터베이스를 쿼리 합니다.
  • CRM: Salesforce와 같은 CRM 시스템에 연결합니다.
  • 버전 관리: Git과 같은 버전 관리 시스템에 접근합니다.

언제 MCP를 사용해야 할까요? 🤔

다음과 같은 경우에 MCP 사용을 고려해 보세요.

  • 에이전트 시스템(agentic systems)을 구축할 때
  • 도구가 모듈식이고 재사용 가능하며 검색 가능하기를 원할 때
  • 여러 외부 소스를 사용하고자 할 때
  • 여러 도구 또는 도구 체인으로 확장하고자 할 때

아키텍처 살펴보기 🏗️

아래 프로젝트는 Gemini와 MCP를 사용하여 자연어 항공편 검색을 가능하게 하는 여러 구성 요소를 통합합니다.

구성 요소 간 상호 작용

  1. 사용자 → 클라이언트
    • 사용자가 자연어 질의를 제공합니다 (예: "애틀랜타에서 라스베이거스로 가는 내일 항공편 찾아줘").
    • 클라이언트 스크립트(client.py)가 입력을 처리합니다.
  2. 클라이언트 → MCP 서버
    • 클라이언트가 MCP 서버 프로세스(mcp-flight-search)를 시작합니다.
    • 표준 입출력(stdio) 통신 채널을 설정합니다.
    • 사용 가능한 도구와 해당 설명을 가져옵니다.
  3. 클라이언트 → Gemini API
    • 사용자의 질의를 전송합니다.
    • 함수 호출을 위해 도구 설명을 제공합니다.
    • 추출된 매개변수와 함께 구조화된 함수 호출을 수신합니다.
  4. 클라이언트 → MCP 도구
    • Gemini로부터 함수 호출 매개변수를 가져옵니다.
    • 매개변수를 사용하여 적절한 MCP 도구를 호출합니다.
    • 응답 처리를 담당합니다.
  5. MCP 서버 → SerpAPI
    • MCP 서버가 SerpAPI에 요청합니다.
    • Google Flights 데이터를 조회합니다.
    • 항공편 정보를 처리하고 형식을 지정합니다.

구현 단계 (코드와 함께) 💻

이제 Gemini AI를 사용하여 이 파이프라인을 구축하는 과정을 주요 구현 단계로 나누어 살펴보겠습니다.

사전 준비물

  1. Python 3.8 이상 설치
  2. API 키를 통한 Google Gemini Generative AI 접근 권한
  3. 유효한 SerpAPI 키 (실시간 항공편 데이터 가져오기에 사용)


1단계: 가상 환경 설정

먼저, 프로젝트를 위한 가상 환경을 설정하고 필요한 라이브러리를 설치합니다.

# 가상 환경 설정
python -m venv venv

# 가상 환경 활성화
source venv/bin/activate

# 의존성 설치
pip install google-genai mcp
  • google-genai: Google의 생성형 AI 모델(예: Gemini)과 상호 작용하기 위한 공식 Python 라이브러리입니다.
  • mcp: MCP(Model Context Protocol) 서버와 상호 작용하기 위한 Python SDK입니다. 이 SDK는 외부 도구 또는 서비스와 통신하는 기능을 제공할 가능성이 높습니다.


환경 변수 설정

API 키를 환경 변수로 설정합니다. 이는 보안상 중요한 단계입니다.

export GEMINI_API_KEY="여러분의-구글-API-키"
export SERP_API_KEY="여러분의-SerpAPI-키"


2단계: MCP 서버 설치 – mcp-flight-search

Gemini가 실제 API와 상호 작용할 수 있도록 MCP 호환 서버를 사용합니다.

이 글에서는 SerpAPI를 사용하여 실시간 항공편 데이터를 검색하는 도구를 노출하는 경량 MCP 서버인 mcp-flight-search를 사용할 것입니다. 이 서버는 FastMCP를 사용하여 구축되었습니다.

PyPI에 게시된 MCP 서버 패키지를 설치합니다.
https://pypi.org/project/mcp-flight-search/

# PyPI에서 설치
pip install mcp-flight-search


MCP 서버 패키지가 성공적으로 설치되었는지 확인해 보세요.


3단계: MCP 도구 패키지 이해하기

Gemini 및 MCP SDK를 초기화하고 비동기 실행을 준비하는 라이브러리를 가져옵니다.

from google import genai


위 코드는 google-generativeai 라이브러리에서 genai 모듈을 가져옵니다. 이를 통해 Gemini 1.5, 2.0, 2.5 모델과 같은 Google의 강력한 LLM에 접근하고 자연어를 사용하여 모델과 상호 작용하는 클라이언트 메서드를 포함합니다.

from google.genai import types

 

위 모듈은 Gemini API에서 사용하는 유형 정의 및 구성 구조에 대한 접근을 제공합니다. 예를 들면 다음과 같습니다.

  • Tool: 모델이 호출할 수 있는 도구(함수)를 정의합니다.
  • GenerateContentConfig: 모델이 응답하는 방식을 구성할 수 있습니다 (예: 온도, 도구 지원 등).
from mcp import ClientSession, StdioServerParameters


위 클래스들은 mcp-sdk-python 라이브러리에서 제공되며 MCP 서버와 상호 작용하는 데 필수적입니다.

  • ClientSession: 클라이언트/앱과 MCP 서버 간의 통신 세션을 관리합니다.
  • StdioServerParameters: stdio를 사용하면 서버가 언어 중립적이고 다양한 환경에 쉽게 내장될 수 있습니다.
from mcp.client.stdio import stdio_client


이 코드는 표준 입출력(standard I/O)을 통해 MCP 서버와의 연결을 설정하는 데 사용되는 비동기 콘텍스트 관리자stdio_client를 가져옵니다. 서버가 올바르게 시작되고 클라이언트가 구조화된 요청을 보내고 받을 준비가 되었는지 확인합니다.

from google import genai
from google.genai import types
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client


위 4가지 주요 가져오기(import)는 Gemini의 LLM 상호 작용MCP 도구를 통해 노출되는 실제 API를 연결하는 방법의 핵심을 형성합니다.


4단계: Gemini 클라이언트 초기화

client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))


genai.Client()는 Google의 생성 모델(예: Gemini 2.5 Pro, Gemini 2 Flash)과 상호 작용하는 데 사용되는 기본 인터페이스입니다.
GenAI 클라이언트가 초기화되면 이 클라이언트 객체는 다음을 수행할 수 있습니다.

  • Gemini 모델에 프롬프트 전송
  • 도구 정의 전달 (함수 호출)
  • 구조화된 응답 및 함수 호출 객체 수신


5단계: MCP 도구 서버 구성

아래 블록은 도구(여기서는 항공편 검색 기능)를 노출하는 MCP 서버를 시작하고 통신하는 데 필요한 매개변수를 설정합니다.

server_params = StdioServerParameters(
    command="mcp-flight-search",
    args=["--connection_type", "stdio"],
    env={"SERP_API_KEY": os.getenv("SERP_API_KEY")},
)
  • mcp-flight-search: 로컬 MCP 서버를 실행하기 위한 CLI 진입점이며, 이 경우에는 MCP 프로토콜을 구현하는 Python 모듈일 수 있습니다.
  • stdio: 서버가 통신 채널로 표준 입력/출력(stdio)을 사용하도록 지시합니다. Stdio는 간단하고 언어에 구애받지 않으며 도구 서버를 로컬 또는 하위 프로세스에서 실행하는 데 적합합니다.
  • SERP_API_KEY: 도구를 실행하는 하위 프로세스에 환경 변수(SERP_API_KEY)를 전달합니다. 이 경우 도구는 실시간 항공편 데이터를 가져오는 SerpAPI로 인증하는 데 필요합니다.

server_params가 정의되면 stdio_client 비동기 콘텍스트 관리자를 사용하여 서버를 가동할 수 있습니다.

>>> import os
>>> from google import genai
>>> from google.genai import types
>>> from mcp import ClientSession, StdioServerParameters
>>> from mcp.client.stdio import stdio_client
>>>
>>> client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
>>>
>>> server_params = StdioServerParameters(
...     command="mcp-flight-search",
...     args=["--connection_type", "stdio"],
...     env={"SERP_API_KEY": os.getenv("SERP_API_KEY")},
... )
>>> server_params
StdioServerParameters(command='mcp-flight-search', args=['--connection_type', 'stdio'], env={'SERP_API_KEY':'XXXXXXXXX'}, cwd=None, encoding='utf-8', encoding_error_handler='strict')
>>>
  • Gemini 클라이언트는 언어 이해, 프롬프트 생성 및 함수 호출을 처리합니다.
  • MCP 도구 서버(항공편 검색)는 도구 호출을 수신하고 SerpAPI를 통해 실시간으로 실행합니다.


6단계: MCP 서버에 연결하고 도구 나열하기

아래 코드 블록은 세 가지 중요한 단계를 수행합니다.

  1. MCP 서버와의 연결을 시작합니다.
  2. 구조화된 도구 통신을 위한 세션을 초기화합니다.
  3. Gemini에서 사용할 수 있는 도구를 동적으로 검색하고 형식을 지정합니다.
async def run():
    # 디버그 프린트 제거
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            prompt = f"2025년 5월 5일 애틀랜타에서 라스베이거스로 가는 항공편 찾아줘"
            await session.initialize()
            # 디버그 프린트 제거

            mcp_tools = await session.list_tools()
            # 디버그 프린트 제거
            tools = [
                types.Tool(
                    function_declarations=[
                        {
                            "name": tool.name,
                            "description": tool.description,
                            "parameters": {
                                k: v
                                for k, v in tool.inputSchema.items()
                                if k not in ["additionalProperties", "$schema"]
                            },
                        }
                    ]
                )
                for tool in mcp_tools.tools
            ]
            # 디버그 프린트 제거

            response = client.models.generate_content(
                model="gemini-2.5-pro-exp-03-25", # 모델명은 사용 가능 버전에 따라 확인 필요
                contents=prompt,
                config=types.GenerateContentConfig(
                    temperature=0,
                    tools=tools,
                ),
            )


MCP 클라이언트-서버 통신이 Gemini LLM과 함께 내부적으로 어떻게 발생하는지 한 줄씩 자세히 살펴보겠습니다.

  • stdio_client는 다음을 처리하는 비동기 콘텍스트 관리자입니다.
    • MCP 서버를 하위 프로세스로 시작
    • 메시지 교환을 위한 입력/출력 스트림 관리
  • readwrite 객체는 비동기 스트림입니다.
    • read: 서버로부터 응답 또는 도구 등록을 읽습니다.
    • write: 서버에 요청 또는 도구 호출을 보냅니다.
prompt = f"2025년 5월 5일 애틀랜타에서 라스베이거스로 가는 항공편 찾아줘"


위 프롬프트는 Gemini 모델에 보낼 자연어 질의입니다. Gemini는 나중에 이를 구조화된 도구 호출로 변환합니다.

await session.initialize()

 

session.initialize()는 클라이언트와 서버 간의 초기 MCP 핸드셰이크를 트리거합니다.
  • 서버는 사용 가능한 도구(여기서는 항공편 검색 도구)를 등록합니다.
  • 이제 세션은 도구를 나열, 호출 및 실행할 준비가 되었습니다.
mcp_tools = await session.list_tools()


위 코드는 서버에서 노출하는 모든 도구(함수) 목록을 요청합니다.
mcp_tools.tools의 각 도구에는 다음이 포함됩니다.

  • 이름
  • 설명
  • 입력 스키마 (즉, JSON 스키마 형식으로 허용하는 매개변수)
mcp_tools.tools는 MCP 서버를 자가 설명적(self-describing)으로 만들어 LLM이 각 도구를 호출하는 방법을 자동으로 이해할 수 있도록 합니다.
tools = [
    types.Tool(
        function_declarations=[
            {
                "name": tool.name,
                "description": tool.description,
                "parameters": {
                    k: v
                    for k, v in tool.inputSchema.items()
                    if k not in ["additionalProperties", "$schema"]
                },
            }
        ]
    )
    for tool in mcp_tools.tools
]


위 단계는 MCP 도구 정의를 Gemini의 function_declarations 형식으로 변환합니다.
이제 MCP 서버가 실행 중이고 세션이 초기화되어 Gemini가 사용할 MCP 서버의 도구를 검색할 준비가 되었습니다.


7단계: Gemini – 프롬프트 해석 및 함수 호출 제안

response = client.models.generate_content(
    model="gemini-2.5-pro-exp-03-25", # 실제 사용 가능한 모델명 확인 필요
    contents=prompt,
    config=types.GenerateContentConfig(
        temperature=0,
        tools=tools,
    ),
)


마지막으로 사용자의 프롬프트가 MCP 서버에서 검색된 사용 가능한 도구 목록과 함께 Gemini 모델로 전송됩니다.

Gemini가 프롬프트를 함수의 스키마와 일치하는 것으로 인식하면 도구 이름과 자동으로 채워진 매개변수를 포함하는 function_call 객체를 반환합니다.

 

8단계: Gemini LLM 최종 응답

Gemini가 프롬프트가 함수(이름, 설명 또는 매개변수 기준)와 일치한다고 판단하면 다음과 같은 구조화된 function_call 객체를 반환합니다.

{
  "function_call": {
    "name": "search_flights",
    "args": {
      "source": "ATL",
      "destination": "LAS",
      "date": "2025-05-05"
    }
  }
}


Gemini LLM은 수동적인 텍스트 모델에서 다음과 같은 능동적인 의사결정자로 전환됩니다:

  • 자연어 입력을 해석합니다.
  • 적절한 도구를 선택합니다.
  • 함수의 인수를 자동으로 채웁니다.
  • 우리는 별도의 파싱 로직을 작성하지 않았습니다.
  • Gemini LLM 모델이 사용자의 자연어를 해석하여 모든 필드를 채워주었기 때문입니다.
  • 이렇게 생성된 함수 호출은 구조화되어 바로 실행 가능한 상태가 됩니다.

최종 데모: MCP와 함께하는 Gemini 2.5 Pro  🚀

아래 디버그 로그(원문 참조)는 GeminiModel Context Protocol(MCP)이 함께 작동하여 사용자 의도를 해석하고, 도구를 일치시키며, 실시간 데이터를 반환하는 정확한 과정을 보여줍니다.


Gemini LLM과 MCP 사용을 위한 모범 사례 🌟

MCP와 Gemini LLM을 효과적으로 사용하기 위한 몇 가지 모범 사례를 공유합니다.

1. 도구 설계

  • 명확한 도구 이름: 짧고 의미 있는 이름을 사용하세요 (예: search_flights, get_weather).
  • 각 도구에 대한 상세한 설명: 간단하고 명확한 설명을 제공하세요. 모델은 이를 사용하여 도구를 언제 어떻게 호출할지 결정합니다.
  • 강력한 타입 사용: 입력 매개변수를 명시적으로 정의하여 (예: string, enum, number) 모델이 정확하게 채울 수 있도록 지원하세요.

2. 모델 상호 작용

  • 적은 수의 도구가 정확도 향상: 모델에 너무 많은 도구를 제공하지 마세요. 관련된 도구만 사용하는 것이 좋습니다.
  • 동적 도구 로딩: 사용자의 질의 또는 대화 콘텍스트에 따라 도구를 로드하세요.
  • 모델에 명확하게 프롬프트: 모델의 역할을 설정하고 도구를 언제 어떻게 사용해야 하는지 설명하세요.

3. 서버 설정

  • 단순성을 위한 stdio 사용: 로컬 개발을 쉽게 하려면 --connection_type stdio를 사용하여 MCP 서버를 시작하세요.
  • 환경 변수 안전하게 전달: env를 사용하여 SERP_API_KEY와 같은 키를 도구 서버에 안전하게 전달하세요.

4. 요청 처리

  • 세션 먼저 초기화: 도구를 나열하거나 호출하기 전에 항상 session.initialize()를 실행하세요.
  • 동적으로 도구 나열: session.list_tools()를 사용하여 클라이언트를 유연하고 도구에 구애받지 않도록 유지하세요.

5. 오류 처리 및 보안

  • 유용한 오류 반환: 도구 서버가 실패 시 의미 있는 메시지로 응답하도록 하세요.
  • API 보안: API 키와 같은 비밀 정보를 로그나 오류 메시지에 노출하지 마세요.

GitHub 저장소 💾

이 튜토리얼에서 사용된 모든 코드는 GitHub 저장소에서 확인하실 수 있습니다.

GitHub - arjunprabhulal/mcp-gemini-search

 

 

GitHub - arjunprabhulal/mcp-gemini-search: Model Context Protocol (MCP) with Gemini 2.5 Pro. Convert conversational queries into

Model Context Protocol (MCP) with Gemini 2.5 Pro. Convert conversational queries into flight searches using Gemini's function calling capabilities and MCP's flight search tools - arjunprabh...

github.com

 

 

결론 및 제언 💡

지금까지 Gemini LLM과 모델 콘텍스트 프로토콜(MCP)을 활용하여 실시간으로 도구를 사용하는 AI 어시스턴트를 구축하는 방법을 단계별로 살펴보았습니다. 이 과정을 통해 다음을 확인할 수 있었습니다.

  • Gemini는 자연어 프롬프트를 처리할 수 있습니다.
  • MCP는 구조화되고 자가 설명적인 도구를 노출합니다.
  • MCP와 함수 호출을 결합하면 실시간 데이터로 구동되는 원활한 함수 실행이 가능해집니다.

AI 애플리케이션을 외부 도구(이 데모에서는 mcp-flight-search와 같은)와 LLM(Gemini 2.0 Flash 또는 Gemini 2.5 Pro 실험 버전 등)과 MCP를 사용하여 통합함으로써, 우리 시스템은 하드코딩된 로직 없이 동적 의사 결정, 함수 호출 및 구조화된 결과 제공이 가능한 지능형 행동 기반 에이전트(action-driven-agent)로 발전합니다.