Intro

이번 포스팅에서는 LangChain Agent에서 MCP와 Sub Agent를 사용하는 방법에 대해서 소개합니다.
특히, langchain 에코시스템이 아닌, fastmcp를 사용한 MCP 서버를 LangChain Agent에서 사용하는 방법을 위주로 설명합니다.

LangChain의 create_agent에서는 Multi-Agent를 구성하는 방식이 일반적인 표준과 조금 다릅니다.
host agent가 sub agent의 소개를 참고하여 호출하는 방식의 일반적인 사용법은 추후 Deep Agent에 관한 포스팅에서 자세히 다뤄보도록 하겠습니다.


0. 기본 MCP 코드 예시

from langchain.tools import tool
from langchain_openai import ChatOpenAI
from langchain.agents import create_tool_calling_agent, AgentExecutor

# Tool 정의 (Agent 내부)
@tool
def add(a: int, b: int) -> int:
    """두 정수를 더합니다"""
    return a + b


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

tools = [add]

agent = create_tool_calling_agent(
    llm=llm,
    tools=tools
)

executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True
)

executor.invoke({
    "input": "2랑 3 더해줘"
})

1. MCP Server (tools)

1.1. langchain.tools

langchain.tools는 MCP 개념이 나오기 이전에 langchain 에코시스템에서 LLM에 도구를 사용하기 위해 만든 모듈입니다.
따라서 MCP 서버 개념이 없으며, Client에 연결하는 함수입니다. @tool 데코레이터만 붙여주면 됩니다.
('0. 기본 MCP 코드 예시' 참고)

1.2. fastmcp

MCP 서버를 구현하는 가장 대표적인 라이브러리입니다. @mcp.tool 데코레이터를 통해 쉽게 json-rpc 통신하는 MCP 서버를 쉽게 구현할 수 있습니다.
mcp.run()에서는 MCP 서버가 어떤 방식으로 외부와 통신할지를 transport 옵션으로 지정할 수 있으며, 대표적으로 stdiosse 두 가지가 있습니다.

from fastmcp import FastMCP

mcp = FastMCP("math-tools")

@mcp.tool()
def add(a: int, b: int) -> int:
    """두 정수를 더합니다"""
    return a + b

if __name__ == "__main__":
    # SSE 서버 실행
    mcp.run(transport="sse", host="localhost", port=3333)

2. MCP Client

2.1. without adapter

Adapter를 사용하지 않는 경우, MCP 서버와 연결하기 위해 개발자가 직접 다음 내용을 모두 구현해야 합니다.

  • MCP 서버 실행
  • JSON-RPC 요청 포맷 구성
  • Tool 호출 시점 결정
  • 응답 파싱 및 후처리

이런 방식이 아니면, MCP 서버의 함수를 langchain.tools의 데코레이터로 갈아끼워서 agent에 직접 연결하는 방식으로 구현할 수 있습니다.
('0. 기본 MCP 코드 예시' 참고)

다만, 사실상 MCP 서버를 구현했는데 Client를 adapter없이 직접 구현하는 분은 없을 것이라 생각합니다.
개념적으로만 이해하고 adapter를 사용하도록 합시다..

2.2. langchain_mcp_adapter

langchain_mcp_adapter는 MCP 서버를 LangChain Agent가 이해할 수 있는 Tool 형태로 변환해주는 어댑터입니다.

이 어댑터를 사용하면, MCP 서버의 Tool → langchain.tools.Tool 로 자동 변환되어,
LangChain Agent가 다른 Tool과 완전히 동일한 방식으로 MCP Tool을 사용할 수 있습니다.

2.2.1. MCPToolkit (Single Server)

가장 기본적인 방식은 MCPToolkit을 사용하는 것입니다.
이는 단일 MCP 서버를 LangChain Tool 세트로 변환합니다.

from langchain_mcp_adapters import MCPToolkit

# MCP 서버 연결 (SSE)
toolkit = MCPToolkit.from_mcp_server(
    url="http://localhost:3333/sse"
)

tools = toolkit.get_tools()

2.2.2. MultiServer Client (Multiple MCP Servers)

실제 서비스 환경에서는 여러 MCP 서버를 동시에 사용하는 경우가 많습니다.
이를 위해 langchain_mcp_adapter는 Multi-Server Client 방식도 제공합니다.

이 방식에서는

  • 여러 MCP 서버를 동시에 연결
  • 각 서버의 Tool을 하나의 Tool 리스트로 병합
    할 수 있습니다.
from langchain_mcp_adapters import MultiServerMCPClient

client = MultiServerMCPClient(
    servers={
        "math": {
            "command": "python math_server.py"
        },
        "search": {
            "url": "http://localhost:3333/sse"
        }
    }
)

tools = client.get_tools()

3. Sub Agent

3.1. sub-agent

LangChain에서 multi-agent를 구현할 때, tools를 사용하는 것과 완벽히 동일한 방법으로 sub agent를 연결할 수 있습니다.

다만, create_agent를 사용하는 경우, sub agent를 따로 구현해놓은 뒤에 sub agent에 invoke를 보내는 tool을 연결하는 방식으로 구현이 가능합니다.
하지만 이러한 방식은 sub agent 객체/서버를 생성한 뒤, skills/description으로 host가 sub agent를 호출하는 일반적인 multi agent 표준과 다르기 때문에 개인적으로는 권장하지 않습니다.
따라서 이 부분은 이후 작성할 LangChain Deep Agent 포스팅에서 자세히 다뤄보도록 하겠습니다.

from langchain.messages import HumanMessage

@tool
def call_subagent_1(x: float) -> float:
    """Call subagent 1 in order to calculate the square root of a number"""
    response = subagent_1.invoke({"messages": [HumanMessage(content=f"Calculate the square root of {x}")]})
    return response["messages"][-1].content

@tool
def call_subagent_2(x: float) -> float:
    """Call subagent 2 in order to calculate the square of a number"""
    response = subagent_2.invoke({"messages": [HumanMessage(content=f"Calculate the square of {x}")]})
    return response["messages"][-1].content

## Creating the main agent

main_agent = create_agent(
    model='gpt-5-nano',
    tools=[call_subagent_1, call_subagent_2],
    system_prompt="You are a helpful assistant who can call subagents to calculate the square root or square of a number.")

Outro

다른 프레임워크의 Agent와 구별되는 LangChain의 Agent의 차별점 중 하나는 'State'입니다.
Agent가 LangGraph로 구성되기 때문에, 사용자 질의 ~ Agent 답변 사이의 모든 노드에서 State가 공유됩니다.
이를 활용해 정교한 컨텍스트 엔지니어링을 수행할 수 있습니다.

다음 포스팅(3. Context Engineering편)에서는 Context와 State, Memory 등의 Checkpoint 관리 방법에 대해서 자세히 다뤄보도록 하겠습니다.

0개의 댓글