Apidog

올인원 협업 API 개발 플랫폼

API 설계

API 문서

API 디버깅

API 모킹

API 자동화 테스트

LangChain을 langchain-mcp-adapters를 사용하여 MCP 서버와 통합하는 방법

Young-jae

Young-jae

Updated on April 14, 2025

모델 컨텍스트 프로토콜(Model Context Protocol, MCP)은 AI 모델이 외부 도구 및 서비스와 상호작용하는 방식을 표준화하는 것을 목표로 합니다. 이는 서로 다른 모델과 도구 공급자가 효과적으로 통신할 수 있도록 공통 인터페이스를 정의합니다. 그러나 MCP 준수 도구를 LangChain과 같은 기존 AI 프레임워크에 직접 통합하려면 적응이 필요합니다.

여기서 langchain-mcp-adapters 라이브러리가 필요합니다. 이 라이브러리는 MCP 도구를 LangChain과 강력한 에이전트 프레임워크인 LangGraph가 이해하고 활용할 수 있는 형식으로 매끄럽게 변환하는 중요한 다리 역할을 합니다. 이 라이브러리는 경량 래퍼를 제공하여 개발자가 LangChain 애플리케이션 내에서 MCP 도구의 성장하는 생태계를 활용할 수 있게 합니다.

주요 기능은 다음과 같습니다:

  • MCP 도구 변환: MCP 도구를 LangChain 호환 BaseTool 객체로 자동 변환합니다.
  • 다중 서버 클라이언트: 여러 MCP 서버에 동시에 연결할 수 있는 강력한 클라이언트(MultiServerMCPClient)를 제공합니다. 다양한 출처에서 도구를 집계합니다.
  • 전송 유연성: 표준 입력/출력(stdio) 및 서버 전송 이벤트(sse)와 같은 일반적인 MCP 통신 전송 수단을 지원합니다.

이 튜토리얼에서는 MCP 서버 설정, 어댑터 라이브러리를 사용한 연결 및 로드된 도구를 LangGraph 에이전트에 통합하는 과정을 안내합니다.

💡
아름다운 API 문서를 생성하는 훌륭한 API 테스트 도구가 필요하신가요?

개발 팀이 최고의 생산성으로 함께 작업할 수 있는 통합된 올인원 플랫폼이 필요하신가요?

Apidog는 모든 요구를 충족하며 훨씬 더 저렴한 가격에 Postman을 대체합니다!
button

MCP 서버란 무엇인가? 어떻게 작동하는가?

예제에 들어가기 전에 몇 가지 핵심 개념을 이해하는 것이 중요합니다:

MCP 서버:

  • MCP 서버는 AI 모델이 호출할 수 있는 도구(함수)를 노출합니다.
  • mcp 라이브러리(langchain-mcp-adapters의 종속성)는 Python에서 이러한 서버를 쉽게 생성할 수 있는 FastMCP와 같은 도구를 제공합니다.
  • 도구는 유형 힌트와 문서 문자열에서 입력 스키마를 자동으로 유추하는 @mcp.tool() 데코레이터를 사용하여 정의됩니다.
  • 서버는 @mcp.prompt()를 사용하여 정형화된 대화 시작자 또는 지침을 제공하는 프롬프트를 정의할 수도 있습니다.
  • 서버는 전송 메커니즘(예: mcp.run(transport="stdio") 또는 mcp.run(transport="sse"))을 지정하여 실행됩니다. stdio는 표준 입력/출력을 통해 통신하는 하위 프로세스에서 서버를 실행하는 반면 sse는 일반적으로 통신을 위한 간단한 웹 서버를 실행합니다.

MCP 클라이언트 (langchain-mcp-adapters):

  • 클라이언트의 역할은 하나 이상의 MCP 서버에 연결하는 것입니다.
  • 클라이언트는 통신 프로토콜 세부 사항(stdio, sse)을 처리합니다.
  • 서버에서 사용 가능한 도구와 그 정의(이름, 설명, 입력 스키마) 목록을 가져옵니다.
  • MultiServerMCPClient 클래스는 특히 여러 도구 서버를 다룰 때 연결을 관리하는 주요 방법입니다.

도구 변환:

  • MCP 도구는 고유한 정의 형식을 가지고 있습니다. LangChain은 BaseTool 클래스 구조를 사용합니다.
  • langchain-mcp-adapters 라이브러리는 서버에 대한 활성 ClientSession을 통해 연결하고 MCP 도구를 나열하고 각 도구를 LangChain StructuredTool로 래핑하는 load_mcp_tools와 같은 기능을 제공합니다.
  • 이 래퍼는 LangChain 에이전트가 도구를 사용하기로 결정할 때 실제 MCP 도구 호출(session.call_tool)을 처리하고 응답을 올바르게 형식화합니다.

프롬프트 변환:

  • 도구와 유사하게, MCP 프롬프트는 load_mcp_prompt(langchain_mcp_adapters.prompts에서) 사용하여 가져올 수 있습니다.
  • 이 함수는 MCP 서버에서 프롬프트 구조를 검색하고 이를 LangChain HumanMessage 또는 AIMessage 객체 목록으로 변환하여 대화를 초기화하거나 안내하는 데 적합합니다.

Langchain-mcp-adapter 설치

우선 필요한 패키지를 설치합니다:

pip install langchain-mcp-adapters langgraph langchain-openai # 또는 선호하는 LangChain LLM 통합

선택한 언어 모델 공급자에 대한 API 키도 구성해야 하며, 일반적으로 환경 변수를 설정하여 수행합니다:

export OPENAI_API_KEY=<your_openai_api_key>
# 또는 export ANTHROPIC_API_KEY=<...> 등.

langchain-mcp-adapters로 빠른 단일 MCP 서버 구축

간단한 예제를 만들어 보겠습니다: 수학 함수를 제공하는 MCP 서버와 그 함수를 사용하는 LangGraph 에이전트.

1단계: MCP 서버 만들기 (math_server.py)

# math_server.py
from mcp.server.fastmcp import FastMCP

# 이름으로 MCP 서버 초기화
mcp = FastMCP("Math")

@mcp.tool()
def add(a: int, b: int) -> int:
    """두 숫자를 더합니다"""
    print(f"Executing add({a}, {b})") # 서버 측 로그
    return a + b

@mcp.tool()
def multiply(a: int, b: int) -> int:
    """두 숫자를 곱합니다"""
    print(f"Executing multiply({a}, {b})") # 서버 측 로그
    return a * b

# 예제 프롬프트 정의
@mcp.prompt()
def configure_assistant(skills: str) -> list[dict]:
    """지정된 기술로 어시스턴트를 구성합니다."""
    return [
        {
            "role": "assistant", # AIMessage에 해당합니다
            "content": f"당신은 유용한 어시스턴트입니다. 다음 기술을 보유하고 있습니다: {skills}. 항상 한 번에 하나의 도구만 사용하세요.",
        }
    ]

if __name__ == "__main__":
    # stdio 전송을 사용하여 서버 실행
    print("Starting Math MCP server via stdio...")
    mcp.run(transport="stdio")

이 코드를 math_server.py로 저장하세요.

2단계: 클라이언트 및 에이전트 만들기 (client_app.py)

import asyncio
import os
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI

# --- 중요: 이 경로를 업데이트하세요 ---
# math_server.py 파일에 대한 절대 경로 가져오기
current_dir = os.path.dirname(os.path.abspath(__file__))
math_server_script_path = os.path.join(current_dir, "math_server.py")
# ---

async def main():
    model = ChatOpenAI(model="gpt-4o") # 선호하는 모델로 변경 가능

    # math_server.py 스크립트를 실행하기 위한 매개변수 구성
    server_params = StdioServerParameters(
        command="python", # 실행할 명령
        args=[math_server_script_path], # 인자(스크립트 경로)
        # cwd=..., env=... # 선택적 작업 디렉터리 및 환경 변수
    )

    print("MCP 서버에 연결 중...")
    # stdio_client 컨텍스트 관리자를 사용하여 연결 설정
    async with stdio_client(server_params) as (read, write):
        # 읽기/쓰기 스트림을 사용하여 ClientSession 생성
        async with ClientSession(read, write) as session:
            print("세션 초기화 중...")
            # 서버와 핸드 셰이크 수행
            await session.initialize()
            print("세션이 초기화되었습니다.")

            print("MCP 도구 로드 중...")
            # MCP 도구를 가져오고 LangChain 도구로 변환
            tools = await load_mcp_tools(session)
            print(f"로드된 도구: {[tool.name for tool in tools]}")

            # 모델과 로드된 도구를 사용하여 LangGraph ReAct 에이전트 생성
            agent = create_react_agent(model, tools)

            print("에이전트 호출 중...")
            # 에이전트 실행
            inputs = {"messages": [("human", "what's (3 + 5) * 12?")]}
            async for event in agent.astream_events(inputs, version="v1"):
                 print(event) # 관찰 가능성을 위한 이벤트 스트림

            # 또는 최종 응답을 직접 얻을 수 있습니다
            # final_response = await agent.ainvoke(inputs)
            # print("에이전트 응답:", final_response['messages'][-1].content)

if __name__ == "__main__":
    asyncio.run(main())

이 코드를 client_app.pymath_server.py와 같은 디렉토리에 저장하세요.

실행하려면:

클라이언트 스크립트를 실행하세요:

python client_app.py

클라이언트 스크립트는 자동으로 math_server.py를 하위 프로세스로 시작하고, 이를 연결하여 addmultiply 도구를 로드한 후 LangGraph 에이전트를 사용하여 MCP 서버를 통해 해당 도구를 호출하여 수학 문제를 해결합니다. 클라이언트와 서버 모두의 로그를 확인할 수 있습니다.

여러 MCP 서버에 연결하기

종종 여러 전문 서버의 도구를 결합하고 싶을 것입니다. MultiServerMCPClient를 사용하면 이것이 간단해집니다.

1단계: 또 다른 서버 만들기 (weather_server.py)

SSE 전송을 사용하는 날씨 서버를 만들어 보겠습니다.

# weather_server.py
from mcp.server.fastmcp import FastMCP
import uvicorn # 필요: pip install uvicorn

mcp = FastMCP("Weather")

@mcp.tool()
async def get_weather(location: str) -> str:
    """위치에 대한 날씨 정보를 가져옵니다."""
    print(f"Executing get_weather({location})")
    # 실제 시나리오에서는 날씨 API를 호출합니다
    return f"{location}에서는 항상 맑습니다."

if __name__ == "__main__":
    # SSE 전송을 사용하여 서버 실행(uvicorn과 같은 ASGI 서버가 필요)
    # mcp 라이브러리는 SSE를 위해 암묵적으로 FastAPI 앱을 생성합니다.
    # 기본적으로 포트 8000의 /sse 엔드포인트에서 실행됩니다.
    print("포트 8000에서 SSE를 통해 Weather MCP 서버 시작 중...")
    # uvicorn.run(mcp.app, host="0.0.0.0", port=8000) # 수동으로 실행할 수 있습니다
    mcp.run(transport="sse", host="0.0.0.0", port=8000) # 또는 mcp.run 편의 기능 사용

이 코드를 weather_server.py로 저장하세요.

2단계: MultiServerMCPClient 사용을 위해 클라이언트 업데이트 (multi_client_app.py)

import asyncio
import os
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI

# --- 중요: 경로 업데이트 ---
current_dir = os.path.dirname(os.path.abspath(__file__))
math_server_script_path = os.path.join(current_dir, "math_server.py")
# 날씨 서버는 별도로 실행되므로 URL을 통해 연결합니다
# ---

async def main():
    model = ChatOpenAI(model="gpt-4o")

    # 여러 서버에 대한 연결 정의
    server_connections = {
        "math_service": { # 이 연결의 고유 이름
            "transport": "stdio",
            "command": "python",
            "args": [math_server_script_path],
            # 필요한 경우 다른 StdioConnection 매개변수를 추가합니다 (env, cwd 등)
        },
        "weather_service": { # 이 연결의 고유 이름
            "transport": "sse",
            "url": "http://localhost:8000/sse", # 날씨 서버가 실행 중인 URL
            # 필요한 경우 다른 SSEConnection 매개변수를 추가합니다 (headers, timeout 등)
        }
    }

    print("여러 MCP 서버에 연결 중...")
    # MultiServerMCPClient 컨텍스트 관리자를 사용합니다
    async with MultiServerMCPClient(server_connections) as client:
        print("연결이 설정되었습니다.")

        # 모든 연결된 서버에서 *모든* 도구를 가져옵니다
        all_tools = client.get_tools()
        print(f"로드된 도구: {[tool.name for tool in all_tools]}")

        # 결합된 도구 목록으로 에이전트를 생성합니다
        agent = create_react_agent(model, all_tools)

        # --- 에이전트와 상호작용 ---
        print("\n수학 쿼리에 대한 에이전트 호출 중...")
        math_inputs = {"messages": [("human", "what's (3 + 5) * 12?")]}
        math_response = await agent.ainvoke(math_inputs)
        print("수학 응답:", math_response['messages'][-1].content)

        print("\n날씨 쿼리에 대한 에이전트 호출 중...")
        weather_inputs = {"messages": [("human", "뉴욕의 날씨는 어떤가요?")]}
        weather_response = await agent.ainvoke(weather_inputs)
        print("날씨 응답:", weather_response['messages'][-1].content)

        # --- 예제: 프롬프트 가져오기 ---
        # print("\n수학 서버 프롬프트 가져오기...")
        # prompt_messages = await client.get_prompt(
        #     server_name="math_service", # connections에 정의된 이름 사용
        #     prompt_name="configure_assistant",
        #     arguments={"skills": "기본 산수"}
        # )
        # print("프롬프트:", prompt_messages)


if __name__ == "__main__":
    # 먼저 별도의 터미널에서 날씨 서버를 시작합니다:
    # python weather_server.py
    # 그런 다음 이 클라이언트 스크립트를 실행합니다:
    asyncio.run(main())

이 코드를 multi_client_app.py로 저장하세요.

실행하려면:

  1. 하나의 터미널에서 날씨 서버를 시작합니다: python weather_server.py
  2. 다른 터미널에서 다중 클라이언트 앱을 실행합니다: python multi_client_app.py

MultiServerMCPClientmath_server.py 하위 프로세스(stdio)를 시작하고 실행 중인 weather_server.py(sse)에 연결합니다. 이는 LanGraph 에이전트에 제공되는 도구(add, multiply, get_weather)를 집계합니다.

LangGraph API 서버와의 통합

MCP 도구를 사용하는 LangGraph 에이전트를 지속적인 API 서비스로 배포할 수 있으며, 이를 위해 langgraph deploy를 사용합니다. 핵심은 LangGraph 애플리케이션 컨텍스트 내에서 MultiServerMCPClient 생명주기를 올바르게 관리하는 것입니다.

graph.py 파일을 만듭니다:

# graph.py
from contextlib import asynccontextmanager
import os
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI # 또는 Anthropic 등

# --- 중요: 경로 업데이트 ---
# 서버가 LangGraph 서버가 실행되는 곳에 상대적이라고 가정합니다
math_server_script_path = os.path.abspath("math_server.py")
# ---

# 연결 정의(서버 환경에 대해 경로/URL이 올바른지 확인)
server_connections = {
    "math_service": {
        "transport": "stdio",
        "command": "python",
        "args": [math_server_script_path],
    },
    "weather_service": {
        "transport": "sse",
        "url": "http://localhost:8000/sse", # 날씨 서버는 독립적으로 실행 중이어야 합니다
    }
}

model = ChatOpenAI(model="gpt-4o")

# 클라이언트 설정/해제를 처리하기 위해 비동기 컨텍스트 관리자를 사용합니다
@asynccontextmanager
async def lifespan(_app): # LangGraph는 생명주기 관리를 위한 이 구조를 기대합니다
    async with MultiServerMCPClient(server_connections) as client:
        print("생명주기 내에서 MCP 클라이언트가 초기화되었습니다.")
        # 클라이언트가 활성화된 컨텍스트 내에서 에이전트를 생성합니다
        agent = create_react_agent(model, client.get_tools())
        yield {"agent": agent} # 에이전트를 사용 가능하게 만듭니다

# 별도의 메인 그래프 정의가 필요하지 않습니다

귀하의 langgraph.json (또는 pyproject.toml[tool.langgraph])를 이 그래프 정의와 생명주기 관리자를 사용하도록 구성합니다:

// langgraph.json (예)
{
  "dependencies": ["."], // 또는 필요한 패키지 지정
  "graphs": {
    "my_mcp_agent": {
      "entrypoint": "graph:agent", // 생명주기로 인해 제공되는 키를 가리킵니다
      "lifespan": "graph:lifespan"
    }
  }
}

이제 langgraph up를 실행하면 lifespan 함수가 실행되어 MultiServerMCPClient (및 stdio 수학 서버)를 시작합니다. 이 컨텍스트 내에서 생성된 에이전트는 LangGraph에 의해 제공됩니다. SSE 날씨 서버는 여전히 별도로 실행되어야 함을 기억하세요.

서버 전송 방식 (stdio 대 SSE)

stdio:

  • 통신: 서버 프로세스의 표준 입력 및 출력 스트림을 통해 이루어집니다.
  • 장점: 로컬 개발을 위한 간단한 설정; 클라이언트가 서버 생명주기를 관리합니다. 네트워킹이 필요하지 않습니다.
  • 단점: 밀접하게 결합되어 있으며 분산 시스템이나 비-Python 서버에 적합하지 않습니다. commandargs 설정이 필요합니다.

sse (서버 전송 이벤트):

  • 통신: HTTP를 통해 SSE 프로토콜을 사용합니다. 서버는 웹 서비스(종종 FastAPI/Uvicorn을 통해 암묵적으로)로 실행됩니다.
  • 장점: 표준 웹 프로토콜; 네트워크 서버나 원격 서버에 적합하며, 다양한 언어로 구현될 수 있습니다. 서버는 독립적으로 실행됩니다.
  • 단점: 서버를 별도로 실행해야 하며 url 설정이 필요합니다.

배포 요구에 따라 전송 방식을 선택하십시오.

langchain-mcp-adapters 설정을 위한 고급 클라이언트 구성

MultiServerMCPClient 내의 StdioConnectionSSEConnection 사전은 더 세밀한 제어를 위한 추가 선택적 매개변수를 수용합니다:

  • Stdio: env (하위 프로세스를 위한 사용자 정의 환경 변수), cwd (작업 디렉터리), encoding, encoding_error_handler, session_kwargs (클라이언트 세션에 전달됨).
  • SSE: headers (사용자 정의 HTTP 헤더), timeout (HTTP 연결 시간 초과), sse_read_timeout, session_kwargs.

자세한 내용은 langchain_mcp_adapters/client.pyMultiServerMCPClient 정의를 참조하십시오.

결론 (100단어)

langchain-mcp-adapters 라이브러리는 표준화된 모델 컨텍스트 프로토콜과 유연한 LangChain 생태계 간의 간극을 효과적으로 메웁니다. MultiServerMCPClient와 자동 도구 변환을 제공함으로써 개발자가 다양한 MCP 준수 도구를 LangChain 에이전트 및 LangGraph 애플리케이션에 쉽게 통합할 수 있게 합니다.

핵심 워크플로우는 다음과 같습니다:

  1. @mcp.tool()을 사용하여 MCP 서버에서 도구(및 선택적으로 프롬프트)를 정의합니다.
  2. 각 서버에 대한 연결 세부 정보를 포함하여 MultiServerMCPClient를 구성합니다 (stdio 또는 sse).
  3. 클라이언트 컨텍스트 관리자(async with ...)를 사용하여 연결하고 client.get_tools()를 통해 도구를 가져옵니다.
  4. 가져온 LangChain 호환 도구를 에이전트(create_react_agent 또는 사용자 정의 에이전트)에 전달합니다.

이를 통해 표준화된 프로토콜을 통해 특화된 외부 도구를 활용한 강력하고 모듈식 AI 응용 프로그램을 구축할 수 있습니다. 레포지토리 내의 예제 및 테스트를 탐색하여 추가 통찰을 얻으십시오.