langchain-mcp-adapters에서 langchain.mcp로 마이그레이션

langchain-mcp-adapters에서 langchain.mcp로 마이그레이션

독립 패키지였던 langchain-mcp-adapters를 쓰고 있다면, 이제 LangChain에 내장된 langchain.mcp 네임스페이스로 옮기면 돼요. 내장 MCP 지원은 FastMCP 기반으로 만들어졌는데, 기존 MultiServerMCPClient는 단일 MCPAdapter 클래스로 통합됐어요. import 경로, 클라이언트 API, 연결 설정이 어떻게 바뀌는지 하나씩 짚어볼게요.

출처: 공식문서

langchain.mcp 네임스페이스는 langchain[mcp]>=1.4.0이 필요하고 아직 베타예요. import하면 LangChainBetaWarning이 발생하고, API가 바뀔 수 있어요.

설치

독립 패키지를 제거하고 mcp 엑스트라로 교체하면 FastMCP가 함께 설치돼요.

pip uninstall langchain-mcp-adapters
pip install "langchain[mcp]"
uv remove langchain-mcp-adapters
uv add "langchain[mcp]"

Import 경로

langchain-mcp-adapters langchain.mcp
from langchain_mcp_adapters.client import MultiServerMCPClient from langchain.mcp import MCPAdapter
from langchain_mcp_adapters.tools import load_mcp_tools from langchain.mcp import MCPAdapter (MCPAdapter(...).list_tools() 사용)
from langchain_mcp_adapters.tools import convert_mcp_tool_to_langchain_tool from langchain.mcp import as_langchain_tool (이름 변경)
from langchain_mcp_adapters.tools import MCPToolArtifact from langchain.mcp import MCPToolArtifact

클라이언트

MultiServerMCPClient는 서버 설정 dict를 받고 여러 메서드를 노출했어요. MCPAdapter는 async 컨텍스트 매니저로서 대상에서 transport를 자동으로 추론하고 list_tools()를 노출해요.

Before:

from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient(
    {
        "math": {"transport": "stdio", "command": "python", "args": ["/path/to/math_server.py"]},
        "weather": {"transport": "http", "url": "http://localhost:8000/mcp"},
    }
)
tools = await client.get_tools()

After:

from langchain.mcp import MCPAdapter

config = {
    "mcpServers": {
        "math": {"command": "python", "args": ["/path/to/math_server.py"]},
        "weather": {"url": "http://localhost:8000/mcp"},
    }
}
async with MCPAdapter(config) as adapter:
    tools = await adapter.list_tools()

설정은 표준 MCPConfig 구조(mcpServers)를 쓰고, transport는 각 항목에서 추론되며 transport 키로 명시하지 않아요. 단일 서버라면 URL, 스크립트 경로, 또는 인프로세스 서버를 직접 넘기면 돼요. Connections를 참고하세요.

클라이언트 메서드

MultiServerMCPClient 메서드 langchain.mcp
get_tools(server_name=...) MCPAdapter(...).list_tools(). 어댑터를 해당 서버로 지정하면 한 서버로 스코프됨.
get_prompt(server_name, prompt_name, arguments=...) 지원 안 함. Prompts and resources 참고.
get_resources(server_name, uris=...) 지원 안 함. Prompts and resources 참고.
session(server_name, auto_initialize=...) 노출되지 않음. list_tools()가 세션을 관리하고, 반환된 각 도구는 호출마다 자체 세션을 염. connection lifecycle 참고.

생성자 인자

MultiServerMCPClient(...) 인자 langchain.mcp
connections (연결 설정 dict) 어댑터의 target: URL, Path, 인프로세스 서버, MCPConfig dict, 미리 만든 fastmcp.Client, 또는 ClientGroup.
tool_name_prefix 멀티 서버 MCPConfigClientGroup에서는 자동 접두사({server}_{tool}). multiple servers 참고.
handle_tool_errors 플래그로 제거됨. 동작은 고정됨: isError=TrueToolMessage(status="error")가 되고, transport 실패는 raise함. Tools 참고.
callbacks (Callbacks) 대응하는 핸들러를 fastmcp.Client에 설정. Callbacks 참고.
tool_interceptors (ToolCallInterceptor) LangChain @wrap_tool_call 미들웨어 사용.

연결 설정

langchain-mcp-adapters는 타입 있는 연결 클래스를 사용했어요. MCPAdapter는 transport를 추론하거나, 완전한 제어를 위해 fastmcp transport를 넘길 수 있어요.

langchain-mcp-adapters langchain.mcp
StdioConnection Path target, 또는 command/args가 있는 MCPConfig 항목.
StreamableHttpConnection http/https URL target, 또는 url이 있는 MCPConfig 항목.
SSEConnection Client(SSETransport(url))MCPAdapter에 전달. 지원되지만 transport는 deprecated. Deprecated transports 참고.
WebsocketConnection FastMCP transport 없음. 서버를 Streamable HTTP로 마이그레이션. Deprecated transports 참고.
httpx_client_factory fastmcp transport에 설정. shared connection pool 참고.
auth (연결별) fastmcp.Clientauth 설정. Authentication 참고.
headers (연결별) fastmcp transport(StreamableHttpTransport(url, headers=...))에 설정.

Deprecated transports

MCP 스펙은 HTTP+SSE transport를 deprecated(프로토콜 버전 2024-11-05) 처리하고 Streamable HTTP를 권장해요. FastMCP는 호환성을 위해 여전히 SSETransport를 제공하므로 MCPAdapter(Client(SSETransport(url)))로 SSE 서버가 계속 동작하지만, 서버를 Streamable HTTP로 마이그레이션하는 걸 권장해요. WebSocket은 FastMCP transport가 없어요.

Elicitation

Elicitation이 클라이언트에 등록된 콜백에서 LangGraph interrupt로 옮겨졌고, 이제 기본적으로 켜져 있어요. MCPAdapter는 만들어진 모든 클라이언트에 capability를 알리고 인터럽트 루프를 구동하며, 실행이 멈추면 서버 요청에 답하고 Command(resume={"responses": {key: answer}})로 재개해요.

langchain-mcp-adapters langchain.mcp
Callbacks(on_elicitation=...) 자동. MCPAdapter(target)이 옵트인 없이 elicitation을 활성화. 미리 만든 클라이언트의 자체 elicitation 핸들러는 우선됨.

Elicitation 참고.

Sampling과 roots

langchain.mcpelicitation 요청을 인터럽트로 처리하지만, sampling(서버가 클라이언트에 LLM completion 실행 요청)이나 roots(서버가 클라이언트가 접근 가능한 로컬 경로 질의)는 처리하지 않아요. 이 둘 중 하나를 반환하는 툴 콜은 NotImplementedError를 raise해요.

이는 프로토콜을 따른 결과예요. 현대 MCP 시대는 sessionless라 서버가 요청 중간에 콜백할 live back-channel이 없어서, push 형태의 sampling·roots는 레거시 handshake 시대에만 존재해요. 그래서 FastMCP 4도 모든 시대에서 ctx.sample()ctx.list_roots()를 제거했어요. 서버의 sampling·roots 요청을 LangChain으로 처리해야 한다면 이슈를 열어 주세요.

Callbacks

langchain-mcp-adaptersCallbacks 객체는 사라졌지만, 실제 핸들러는 사라지지 않았어요—FastMCP가 이것을 자체 Client에서 직접 받아요. 필요한 핸들러로 fastmcp.Client를 만들고 MCPAdapter에 넘기면 돼요.

Callbacks 필드 langchain.mcp
on_elicitation 인터럽트로 자동 처리 — 핸들러 불필요. 미리 만든 클라이언트의 자체 elicitation_handler는 우선됨. Elicitation 참고.
on_progress Client(transport, progress_handler=...).
on_logging_message Client(transport, log_handler=...).
from fastmcp.client import Client

from langchain.mcp import MCPAdapter

client = Client("https://example.com/mcp", progress_handler=on_progress, log_handler=on_log)
async with MCPAdapter(client) as adapter:
    tools = await adapter.list_tools()

Callback handlers 문서 참고.

Tool interceptors

langchain-mcp-adapters의 인터셉터 타입(tool_interceptors, ToolCallInterceptor, MCPToolCallRequest, MCPToolCallResult)은 사라졌어요. 툴 콜을 에이전트 측에서 가로채려면 LangChain @wrap_tool_call 미들웨어를 쓰면 돼요. 이것은 create_agent가 실행하는 모든 툴을 감싸며, MCP 툴에만 국한되지 않아요. MCP 출처는 툴 메타데이터의 metadata["mcp"]에서 확인할 수 있어서, 인터셉터가 이를 기준으로 분기할 수 있어요.

from collections.abc import Callable

from langchain.agents import create_agent
from langchain.agents.middleware import wrap_tool_call
from langchain.mcp import MCPAdapter
from langchain.messages import ToolMessage
from langchain.tools.tool_node import ToolCallRequest


@wrap_tool_call
def log_mcp_calls(
    request: ToolCallRequest,
    handler: Callable[[ToolCallRequest], ToolMessage],
) -> ToolMessage:
    """Intercept every tool call, MCP or otherwise, before and after it runs."""
    # Inspect or rewrite the request here; MCP provenance is on the tool's
    # metadata under `request.tool.metadata["mcp"]`.
    print(f"calling {request.tool_call['name']}")
    result = handler(request)
    print(f"-> {request.tool_call['name']} done")
    return result


async def agent_with_interception(target):
    async with MCPAdapter(target) as adapter:
        tools = await adapter.list_tools()
        return create_agent("claude-sonnet-5", tools, middleware=[log_mcp_calls])

에러 처리

handle_tool_errors 플래그는 사라졌어요. 동작은 이제 고정되어 있어요—isError=True로 보고하는 MCP 툴은 서버 메시지를 담은 ToolMessage status="error"로 모델에 도달하고, transport 실패는 raise해요. Tools 참고.

인증

Auth가 fastmcp.Client로 옮겨졌어요. 연결 설정의 authheaders 대신, auth를 bearer 토큰, 리터럴 "oauth", 또는 임의의 httpx.Auth로 설정한 클라이언트를 만들고 그 클라이언트를 MCPAdapter에 넘겨요. 서버별·사용자별 인증이 모두 지원돼요. Authentication 참고.

툴 결과

툴 결과 처리는 보존되고 확장됐어요.

langchain-mcp-adapters langchain.mcp
MCPToolArtifact (구조화 콘텐츠) 유지. langchain.mcp에서 export. structured content 참고.
Multimodal 콘텐츠 블록 유지. multimodal content 참고.
툴 메타데이터 확장. 툴 메타데이터의 mcp 네임스페이스로 그룹화, 어노테이션과 서버 식별 포함. tool metadata 참고.
convert_mcp_tool_to_langchain_tool as_langchain_tool로 이름 변경, 이제 코루틴: await as_langchain_tool(tool, client).
to_fastmcp (LangChain 툴 → FastMCP 툴) langchain.mcp에 상응하는 것 아직 없음. 필요하면 이슈를 열어 주세요.

Prompts와 resources

langchain.mcp는 툴에 집중하며 MCP promptsresources는 아직 래핑하지 않아요. 다음 langchain-mcp-adapters 헬퍼는 현재 langchain.mcp에 상응하는 것이 없어요.

langchain-mcp-adapters langchain.mcp
load_mcp_prompt, get_prompt, convert_mcp_prompt_message_to_langchain_message 아직 래퍼 없음
load_mcp_resources, get_resources, get_mcp_resource, convert_mcp_resource_to_langchain_blob 아직 래퍼 없음

아직 일급 래퍼를 우선순위로 둘 만큼 수요가 충분하지 않다고 판단했어요. 사용 사례가 있다면 이슈를 열어 주시면 우선순위를 정하는 데 도움이 돼요. 그동안은 FastMCP 클라이언트로 직접 읽으면 돼요—client.get_prompt(...)client.read_resource(...). Reading resourcesGetting prompts 참고.

MCP 프로토콜에서 deprecated된 것들

일부 langchain-mcp-adapters 기능은 langchain.mcp가 버리기로 해서가 아니라, 그것이 의존하던 메커니즘 자체를 MCP 프로토콜이 deprecated·제거했기 때문에 대체재가 없어요. langchain.mcp는 FastMCP 4를 통해 현대적이고 sessionless한 프로토콜 시대를 대상으로 해요.

메커니즘 프로토콜 상태 마이그레이션에 미치는 영향
HTTP+SSE transport Streamable HTTP를 위해 deprecated (프로토콜 2024-11-05) SSE는 FastMCP의 SSETransport로 계속 동작하지만, 서버를 Streamable HTTP로 옮기는 걸 권장. WebSocket은 FastMCP transport가 없음.
Server-pushed sampling·roots 현대 시대에서 제거 — sessionless 프로토콜엔 live back-channel이 없음. FastMCP 4가 모든 시대에서 ctx.sample()·ctx.list_roots() 제거 langchain.mcp가 처리하지 않음. Sampling and roots 참고.
Server-pushed elicitation 현대 시대가 push 요청을 input-required 라운드로 대체 콜백 대신 인터럽트로 처리. Elicitation 참고.
JSON-RPC batching 제거됨 (프로토콜 2025-06-18) 해당 사항 없음; 요청은 개별 전송.

더 알아보기 (Learn more)