LangChain 챗봇5장 · LLM 외부 도구 연동9 / 21← 이전목차다음 →MetaContents

5장. LLM 외부 도구 연동

MCP 란 무엇인가

예전에는 휴대폰마다 충전기 단자가 달라서, 새 휴대폰을 사면 충전기도 새로 사야 했습니다. 단자를 USB-C 하나로 맞추자 어느 회사의 충전기든 꽂아 쓸 수 있게 됐습니다. AI 앱과 도구 사이에도 같은 일이 있었습니다. 앱마다 도구를 붙이는 방식이 달라서, 같은 "상품 찾기" 도구를 챗봇용, 코드 편집기용으로 따로 만들어야 했습니다. MCP 는 도구를 꽂는 단자를 맞춘 규격입니다.

MCP 없이 앱마다 도구를 따로 붙이는 경우와 MCP 서버가 한 규격으로 도구를 내놓아 어느 앱이든 꽂아 쓰는 경우를 나란히 놓은 비교 그림

왼쪽 파랑 상자는 규격이 없을 때입니다. 앱이 바뀔 때마다 같은 도구를 다시 짭니다. 오른쪽 보라 상자는 MCP 를 쓸 때입니다. 도구를 MCP 서버 하나로 만들어 두면, MCP 를 아는 앱(챗봇, 코드 편집기, 데스크톱 AI 앱)은 어디서든 꽂아 씁니다. 여기서 충전기가 MCP 서버, 휴대폰이 AI 앱, USB-C 단자가 MCP 규격입니다. 비유와 다른 점은, 충전기는 전기만 보내지만 MCP 서버는 도구 목록과 설명까지 함께 알려 주어서, 앱이 무슨 도구인지 미리 몰라도 받아 쓸 수 있다는 것입니다.

MCP 는 Anthropic 이 공개한 열린 규격(open protocol)입니다. 규격 문서와 여러 언어의 SDK(Software Development Kit, 개발 도구 모음)가 공개되어 있어 누구나 서버와 클라이언트를 만들 수 있습니다. 이 장에서는 파이썬 SDK 인 mcp 패키지(이 교안은 1.30 판)를 씁니다.

@tool 과 MCP 견주기

견줄 것@tool(LangChain 도구)MCP 서버의 도구
사는 곳우리 챗봇 프로그램 안따로 도는 서버 프로그램
쓸 수 있는 앱그 프로그램(LangChain)만MCP 를 아는 모든 앱
만드는 법@tool@mcp.tool()
부르는 법함수처럼 바로클라이언트가 요청을 보내 서버가 실행
어울리는 때이 챗봇에서만 쓰는 작은 도구여러 앱이 함께 쓸 도구, 남이 만든 도구

MCP 서버가 내놓는 세 가지

이름원래 말뜻이 장에서
도구tools모델이 골라 부르는 함수find_products, read_file 을 만든다
자료resources앱이 읽어 가는 파일, 표 같은 자료다루지 않는다
프롬프트prompts미리 만들어 둔 프롬프트 틀다루지 않는다

짧은 예시

같은 함수 하나를 LangChain 도구와 MCP 도구로 각각 포장해 봅니다. 서버는 띄우지 않고, MCP 서버 객체에 등록된 도구 목록만 꺼내 봅니다.

Python
import asyncio

from langchain_core.tools import tool
from mcp.server.fastmcp import FastMCP


def find_region(region: str) -> str:
    """지역 이름으로 구름다리여행 상품을 찾는다."""
    return f"{region} 상품 목록"


# 포장 하나: LangChain 도구
lc_tool = tool(find_region)

# 포장 둘: MCP 서버의 도구. mcp.tool() 이 돌려준 데코레이터에 함수를 넣는다
mcp = FastMCP("demo")
mcp.tool()(find_region)
# list_tools 는 비동기 함수라 asyncio.run 으로 실행한다. 서버를 띄우지는 않는다
mcp_tools = asyncio.run(mcp.list_tools())

print("LangChain:", lc_tool.name, "|", lc_tool.description, "|", list(lc_tool.args))
for t in mcp_tools:
    print("MCP      :", t.name, "|", t.description, "|", list(t.inputSchema["properties"]))
출력
LangChain: find_region | 지역 이름으로 구름다리여행 상품을 찾는다. | ['region']
MCP      : find_region | 지역 이름으로 구름다리여행 상품을 찾는다. | ['region']

두 포장 모두 함수 이름, docstring, 인자에서 같은 세 가지(이름, 설명, 인자)를 뽑아냈습니다. 차이는 사는 곳입니다. LangChain 도구는 이 프로그램 안에서 바로 불리고, MCP 도구는 서버를 띄운 뒤 다른 프로그램(클라이언트)이 요청을 보내야 불립니다. 그 대신 MCP 도구는 LangChain 을 쓰지 않는 앱에서도 씁니다.

코드가 의미하는 것

이 코드는 같은 충전기 하나를 두 가지 단자로 포장해 보는 것입니다. 함수 하나를 LangChain 도구로 한 번, MCP 서버의 도구로 한 번 포장하고, 둘이 내놓는 이름표를 견줍니다.

코드하는 일챗봇에서 뜻하는 것
tool(find_region)데코레이터를 함수처럼 불러 도구로 바꾼다함수 위에 @tool 을 얹는 것과 같습니다. 이 프로그램 안에서만 쓰는 포장입니다
FastMCP("demo")이름이 demo 인 MCP 서버 객체를 만든다다른 앱이 꽂아 쓸 충전기 몸통입니다. 아직 켜지지 않았습니다
mcp.tool()(find_region)서버에 함수를 도구로 등록한다함수 위에 @mcp.tool() 을 얹는 것과 같습니다. 같은 함수가 MCP 규격의 도구가 됩니다
asyncio.run(mcp.list_tools())등록된 도구 목록을 비동기로 꺼낸다클라이언트가 "도구 목록을 달라"고 할 때 서버가 내놓을 목록입니다
t.inputSchema["properties"]MCP 도구의 인자 스키마를 읽는다LangChain 도구의 args 에 해당하는 칸입니다. 이름만 다르고 담긴 것은 같습니다

결과에서 읽을 것은 두 가지입니다.

  • 두 줄이 똑같습니다. 이름 find_region, 설명, 인자 ['region'] 가 두 포장에서 같게 나왔습니다. 도구를 이루는 세 부분은 포장이 바뀌어도 그대로입니다.
  • 다른 점은 출력에 보이지 않는 곳에 있습니다. LangChain 도구는 이 프로그램이 바로 부르고, MCP 도구는 서버를 띄운 뒤 클라이언트의 요청으로 불립니다. 그 차이는 실습 4에서 서버를 실제로 켜 보면 드러납니다.

주의할 점

  • MCP 는 모델이 아니라 "도구를 꽂는 방식"입니다. MCP 서버를 붙여도 도구를 고르는 것은 여전히 모델이고, 이 장에서는 OpenAI 모델이 고릅니다.
  • 남이 만든 MCP 서버는 내 컴퓨터에서 프로그램으로 돕니다. 믿을 수 있는 곳의 서버만 쓰고, 어떤 파일과 서비스에 손대는지 먼저 읽어 봅니다. "도구를 맡길 때의 안전" 절에서 다시 봅니다.
← 이전 절5장 · 에이전트에게 고리 맡기기다음 절 →5장 · 호스트·클라이언트·서버의 짜임