알아보자 MCP
앤트로픽이 2024년 11월에 MCP(Model Context Protocol)를 발표했을 당시에는 많은 사람들이 Function calling과의 특별한 차이점을 느끼지 못했습니다. 하지만 최근 Cursor IDE에서 MCP 기능을 활용할 수 있게 되면서 관심이 높아지고 있습니다. 이번 글에서는 MCP의 개념, 최근 등장하고 있는 MCP 기능, 그리고 앞으로 기대되는 점들을 이야기해 보겠습니다.
Function Calling과 MCP는 어떻게 다른가?
MCP를 이해하기 전에, 먼저 Function calling이 어떤 배경에서 등장했으며 무엇인지 알아보겠습니다. Function calling은 그 이름 그대로 “함수를 호출한다”는 의미로, LLM이 함수를 호출하여 활용하는 것을 말합니다.
LLM에게 Function Calling이 필요한 이유는 무엇일까요?
LLM은 학습 과정을 통해 다음 단어(토큰)를 예측하는 메커니즘을 사용합니다. LLM은 학습 데이터에 많이 노출된 단어를 예측할 가능성이 높습니다. 예를 들어, 1+1=?
이라는 데이터는 LLM에 많이 학습되었지만, 4512*1237=?
은 학습되었을 가능성이 희박합니다. 이러한 문제를 해결하기 위해 다양한 방법들(CoT
, Reasoning model
등)이 등장했지만, Function calling이 대표적인 예시 중 하나입니다. 앞서 설명한 것처럼, Function calling은 “함수를 호출한다”는 의미처럼, 곱하기 함수를 다음과 같이 langchain
으로 구현할 수 있습니다.
from langchain.tools import tool
@tool
def multiply(a: int, b: int) -> int:
"""
Multiply two integers
Args:
a: int
b: int
Returns:
int: The product of a and b
"""
return a * b
이렇게 구현된 함수 정보를 LLM에게 전달하면, LLM은 필요에 따라 이 함수를 호출하여 활용합니다. 이 과정은 다음과 같이 구현할 수 있습니다.
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
llm = llm.bind_tools([multiply])
response = llm.invoke("What is 4512 times 1237?")
response를 출력해 보면 다음과 같이 tool을 호출하는 값을 확인할 수 있습니다.
{
'tool_calls': [
{
'id': 'call_7jUwk87HCzqmtRjlTyI0Gu7Y',
'function': {
'arguments': '{"a":4512,"b":1237}',
'name': 'multiply'
},
'type': 'function'}
]
}
이 일련의 과정을 간단히 설명하자면, LLM에게 활용할 수 있는 함수를 알려주고, 필요하다면 LLM이 이 함수를 활용하는 것이라고 볼 수 있습니다. 코드에서는 단순하게 표현되어 있지만, 함수를 정의하면서 추가한 어노테이션 정보와 그에 대응될 수 있는 JSON 포맷을 프롬프트에 추가하여 JSON 형태의 값을 받아 이를 실행하는 구조입니다.
OpenAI에서 이를 설명하는 이미지는 다음과 같습니다.
OpenAI Function Calling 이미지
이제 Function calling에 대해서는 어느 정도 이해가 된 것 같습니다. 그렇다면 MCP는 어떻게 다를까요?
MCP는 REST API 호출과 유사합니다.
MCP는 앞서 설명한 Function calling과 유사하지만, 호출 대상이 되는 함수, 즉 Function이 다릅니다. 웹 백엔드 엔드포인트 함수들을 활용하는 것이 차이점입니다.
FastAPI Swagger 이미지
위 이미지는 FastAPI를 사용하면 확인할 수 있는 Swagger라는 화면입니다. 이미지에서 각 카드별로 하나의 엔드포인트가 표현되어 있는데, 이 엔드포인트들이 Function calling에서 사용했던 함수로 활용됩니다.
그렇다면 함수 형태의 tool과 엔드포인트 형태의 tool은 어떤 차이점이 있을까요? MCP 이전의 함수 형태 tool은 LLM을 이용하여 만든 워크플로우나 Agent 시스템과 같은 곳(컴퓨터)에서 함수가 실행(Execute)되었지만, MCP는 실행 환경이 분리되어 있는 것이 특징입니다 (모놀리식 시스템 아키텍처 vs 마이크로 서비스 아키텍처 관점과 유사합니다).
Function Calling vs MCP 이미지
MCP는 실행 환경이 분리되어 있기 때문에, 온라인에 공개된 MCP가 있다면 tool로서 URL 연결만으로 호출이 가능합니다.
예를 들어, SQL을 실행하는 엔진을 활용하는 tool을 사용한다고 생각해 봅시다. 이 경우, DB 접근을 위해 직접 엔진 인스턴스를 생성하여 DB에 SQL을 실행하지만, MCP의 경우, 직접적인 엔진 인스턴스 생성은 MCP 서버에서 수행합니다.
MCP 서버 구현 방법
langchain
에서 Function calling을 구현하는 것과 유사하게 구현할 수 있습니다.
from mcp.server.fastmcp import FastMCP
# Create an MCP server
mcp = FastMCP("Demo")
# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
다만 차이점은 LLM을 사용하여 바인딩하는 코드가 없으며, 이 역할은 MCP Host에서 수행합니다.
그렇다면 MCP Server 외 나머지는?
MCP 서버의 엔드포인트로 tool을 정의하는 것까지 다루었습니다. 이러한 엔드포인트들을 활용하는 서비스는 Claude Desktop
, Cursor
, Windsurf
등이 대표적입니다.
Claude Desktop
: 앤트로픽에서 제공하는 ChatBot 서비스로, MCP tool들을 활용하여 필요한 정보 또는 기능을 요청하고 답변을 생성합니다.Cursor
,Windsurf
: 두 서비스는 LLM을 활용하는 IDE 서비스로, Figma, Github, Jira 등 협업 시스템들을 MCP 서버로 활용하여 코딩 작업에 필요한 것들을 파악하고 수행합니다.
MCP를 만든 앤트로픽에서 서비스하고 있는 Claude Desktop
이 가장 먼저 기능을 제공했지만, ChatBot 서비스로서 큰 주목을 받지는 못했습니다. 그 이유로는 ChatBot 비즈니스가 정보를 취득하는 것이 주요 목적이기 때문에 큰 주목을 받지 못한 것으로 예상됩니다. 반면, Cursor는 개발자 도메인에 직접적인 영향을 주는 비즈니스이며, 최근 화제가 되고 있는 Vibe coding(명령만으로 개발)이 실제로 가능하다는 관측도 나오고 있습니다. 그리고 Cursor는 개발자 도메인이라는 구체적인 방향성이 있어, 우리 눈에는 보이지 않지만 내부적으로 정교한 Workflow가 설계되어 있으며, 이와 함께 MCP를 통해 활용할 수 있는 tool들이 많아져 더욱 효과를 본 것으로 해석됩니다.
앞으로의 미래는?
“올해는 Agent의 해”라는 말이 흔하게 들리는데, Agent의 핵심 중 하나인 Tool 구현은 앞으로 MCP 서버를 활용할 가능성이 높다고 생각합니다. 최근 OpenAI도 앤트로픽에서 제안한 MCP를 수용하여 개발하겠다는 소식이 전해지고 있습니다. 현재 서비스를 제공하고 있는 기업들도 MCP 서버를 제공하여 서비스 개발이 진행될 것으로 전망됩니다. 다만, 이보다 더 중요하고 가치 있는 것은 MCP Host가 더욱 중요한 역할을 하게 될 것이라는 점입니다. 그 이유로, MCP 서버에 필요한 것은 별다른 것이 없습니다. 기능과 그에 대한 설명만 있다면 충분합니다.(물론 너무 많은 기능을 LLM에 바인딩하면 성능이 좋지 않을 것입니다.) 하지만, MCP Host는 더욱 정교한 워크플로우 정의가 필요해질 것입니다.
MCP Architecture 이미지
Useful links
Click the image to watch the video!