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 |
멀티 서버 MCPConfig나 ClientGroup에서는 자동 접두사({server}_{tool}). multiple servers 참고. |
handle_tool_errors |
플래그로 제거됨. 동작은 고정됨: isError=True는 ToolMessage(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.Client에 auth 설정. 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.mcp는 elicitation 요청을 인터럽트로 처리하지만, 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-adapters의 Callbacks 객체는 사라졌지만, 실제 핸들러는 사라지지 않았어요—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로 옮겨졌어요. 연결 설정의 auth와 headers 대신, 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 prompts나 resources는 아직 래핑하지 않아요. 다음 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 resources와 Getting 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) | 해당 사항 없음; 요청은 개별 전송. |