Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Integrating the Model Context Protocol (MCP) with LangChain has four steps: configure an MCP client for each server, discover the server’s tools, pass those tools to a LangChain agent, and keep the client alive until calls finish. Python and JavaScript follow that same pattern, but their current adapters, error behavior, and cleanup APIs differ.

This guide shows both implementations, local stdio and remote HTTP transports, authentication, multi-server naming, lifecycle management, failure handling, and approval for destructive tools. Pin the package versions you deploy: Python’s current langchain.mcp namespace is beta, while JavaScript documentation also contains older MultiServerMCPClient examples.

The MCP-to-LangChain integration model

An MCP server advertises tools. An adapter reads those definitions and converts them into LangChain tools. Your agent then receives the adapted tools exactly as it would receive a native LangChain tool.

  1. Install and pin LangChain, the language adapter, and your model integration.
  2. Describe each MCP server using stdio or HTTP transport, plus credentials where required.
  3. Discover tools with list_tools() in Python or listTools() in the current JavaScript adapter.
  4. Pass the resulting collection to create_agent.
  5. Keep sessions open while the agent runs, then close them in cleanup code.

Tool discovery and agent construction are separate operations. Discovering a tool does not execute it; execution occurs only when the model selects it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose an adapter and pin versions

Python options

The current LangChain documentation describes langchain.mcp, installed with langchain[mcp]>=1.4.0. The documentation explicitly labels this namespace beta, so its API may change. LangChain support material also discusses the separate langchain-mcp-adapters package, whose primary client is MultiServerMCPClient. Do not mix imports, configuration objects, or lifecycle methods from those two generations.

JavaScript options

The current @langchain/mcp-adapters README uses MCPAdapter. Broader JavaScript documentation still shows MultiServerMCPClient. Both describe the same adapter pattern, but their constructors and cleanup methods are not interchangeable. The examples below use the current MCPAdapter interface; if your pinned package exposes only MultiServerMCPClient, follow that package’s matching documentation instead.

Model compatibility

Adapters expose standard LangChain tools, so they can be used with supported OSS chat-model integrations such as ChatOpenAI and ChatAnthropic. This does not configure provider credentials for you, nor does it guarantee that every model handles every tool schema identically.

Python: connect MCP tools to an agent

Install and configure credentials

python -m venv .venv
source .venv/bin/activate
pip install "langchain[mcp]>=1.4.0" langchain-openai
export OPENAI_API_KEY="your-key"

Use a lock file or constraints file in production. Keep bearer tokens, API keys, and private URLs in environment variables or a secret manager.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Current langchain.mcp pattern

The following illustrates the documented sequence. Adapter constructor details can change while the namespace is beta, so verify the exact configuration keys against the version you pin.

import asyncio
import os
from langchain.agents import create_agent
from langchain.mcp import MCPAdapter
from langchain_openai import ChatOpenAI

async def main():
    adapter = MCPAdapter(
        servers={
            "local_tools": {
                "transport": "stdio",
                "command": "npx",
                "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
            },
            "remote_tools": {
                "transport": "http",
                "url": os.environ["MCP_SERVER_URL"],
                "headers": {
                    "Authorization": f"Bearer {os.environ['MCP_BEARER_TOKEN']}"
                },
            },
        }
    )
    try:
        tools = await adapter.list_tools()
        model = ChatOpenAI(model="gpt-4.1-mini", temperature=0)
        agent = create_agent(
            model=model,
            tools=tools,
            system_prompt="Use MCP tools when they are appropriate. Explain failures clearly.",
        )
        result = await agent.ainvoke({
            "messages": [{"role": "user", "content": "List the files in /tmp."}]
        })
        print(result["messages"][-1].content)
    finally:
        close = getattr(adapter, "close", None)
        if close is not None:
            await close()

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

The local entry launches a server process and communicates over standard input and output. The remote entry uses an HTTP endpoint and an authorization header. A private server still needs network reachability from the process running your agent.

Using the separate langchain-mcp-adapters package

Support material commonly shows this alternative:

pip install langchain-mcp-adapters langchain-openai
from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient({
    "local": {
        "transport": "stdio",
        "command": "npx",
        "args": ["-y", "your-mcp-server"],
    },
    "hosted": {
        "transport": "sse",
        "url": "https://example.invalid/mcp/sse",
        "headers": {"Authorization": "Bearer ${MCP_TOKEN}"},
    },
})
tools = await client.get_tools()
agent = create_agent(model, tools=tools)

Treat this as a different API generation: its discovery method is typically get_tools() (or load_mcp_tools in lower-level usage), not the beta namespace’s list_tools(). Confirm the package’s current transport and authentication names before deployment.

JavaScript and TypeScript: use the current MCPAdapter

Install

npm install @langchain/mcp-adapters @langchain/core @langchain/langgraph @langchain/openai

Remote HTTP and local stdio in one agent

import { MCPAdapter } from "@langchain/mcp-adapters";
import { createAgent } from "@langchain/langgraph/prebuilt";
import { ChatOpenAI } from "@langchain/openai";

const adapter = new MCPAdapter({
  servers: {
    local_tools: {
      transport: "stdio",
      command: "npx",
      args: ["-y", "your-mcp-server"]
    },
    remote_tools: {
      transport: "http",
      url: process.env.MCP_SERVER_URL,
      headers: { Authorization: `Bearer ${process.env.MCP_BEARER_TOKEN}` }
    }
  }
});

try {
  const tools = await adapter.listTools();
  const agent = createAgent({
    model: new ChatOpenAI({ model: "gpt-4.1-mini", temperature: 0 }),
    tools
  });
  const result = await agent.invoke({
    messages: [{ role: "user", content: "Use the available tool to summarize the current status." }]
  });
  console.log(result.messages.at(-1)?.content);
} catch (error) {
  console.error("MCP or agent call failed:", error);
} finally {
  await adapter.close();
}

Keep the adapter open for every invocation that may call an MCP tool. Closing it immediately after discovery leaves later tool calls without a live session. In a long-running service, create one managed adapter per process or worker and close it during shutdown.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Name collisions with multiple servers

Two servers can publish the same tool name. Prefix names with the server name when your adapter or application exposes that option, such as jira_search and slack_search. This makes prompts, logs, and approval rules unambiguous.

Older MultiServerMCPClient examples

Older JavaScript documentation uses a client configured with a map of servers, then calls getTools() and passes those tools to createAgent. It is still useful when your installed package exposes that class, but do not combine its imports with the newer MCPAdapter code. The README also describes negotiation between modern and legacy modes; explicit modern mode requires MCP revision 2026-07-28. Avoid hard-coding a revision unless both server and client require it.

Transport, authentication and deployment choices

Transport Use it when Operational considerations
stdio The server runs locally and can be launched by your process. Set the executable and arguments; capture stderr separately so protocol messages on stdout are not corrupted.
HTTP/streamable HTTP The server is hosted remotely or shared by several agents. Configure URL, headers, timeouts and TLS; ensure the agent host can reach the endpoint.
SSE or other legacy mode An older server or adapter requires it. Check both package and server generations before copying an SSE example.

Never place real tokens in source files, screenshots, prompts, or public repositories. For self-hosted Jira, Slack, or Confluence servers, authentication and network access belong to the MCP server boundary as well as the LangChain process.

Error handling and lifecycle

Python tool errors versus connection failures

When an MCP server returns a tool result marked isError=True, the Python integration represents it as a LangChain ToolMessage with status="error". The model can often explain or recover from that result. A dropped transport, failed handshake, or closed session raises instead, because no tool result reached the model. Catch those exceptions around the agent call, log the server name and operation, and decide whether a retry is safe.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

JavaScript exceptions

The JavaScript adapter documentation describes an isError: true tool result as a thrown ToolException. Wrap direct tool calls and, where appropriate, the entire agent invocation in try/catch. Distinguish a server-declared failure from a timeout, authentication error, or disconnected adapter before retrying.

Structured results and multimodal content

Python exposes structured MCP content as an artifact, while text and multimodal parts appear through standardized content blocks. Preserve artifacts when downstream code needs machine-readable fields instead of parsing the model-facing text.

Human approval for risky tools

MCP metadata can include server identity, annotations, and destructive-operation hints. Use those hints to route deletion, sending, purchasing, or permission-changing tools through LangGraph human-in-the-loop approval. Elicitation is a separate MCP capability: the server can pause a tool call and request input from a person. Neither feature is an automatic security boundary; define which tools require approval, validate arguments, and audit the decision.

Testing and production checklist

  • Pin the adapter, LangChain, model integration, and server versions.
  • Run a discovery-only check and record tool names and schemas before enabling execution.
  • Test both a successful call and a server-declared error.
  • Test expired credentials, unreachable HTTP endpoints, and a terminated local process.
  • Keep secrets in environment variables or a secret manager.
  • Set timeouts and bounded retries for idempotent operations only.
  • Keep adapters alive through all calls and close them on worker shutdown.
  • Use server prefixes when names collide.
  • Require human approval for destructive actions.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your MCP agent needs website images or PDFs, ScreenshotNeo provides an HTTP screenshot API and an MCP server. It accepts cookie and consent banners before capture, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and bills only clean shots: bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Every response reports the page verdict and billing status in X-Page-Verdict and X-Billed headers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

One request is enough:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for the 63 capture options, including full-page lazy-image loading, CSS-selector elements, dark mode, device presets, retina scale, PDF paper and page settings, custom CSS or JavaScript, clicks, waits, blocking rules, headers, cookies, user agents, authorization, timezone, geolocation, transparency, resizing, TTL caching, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs, usage data, and the OpenAPI specification.

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo also exposes an MCP server, so Claude, Cursor, and other MCP clients can take screenshots through tools such as take_screenshot, get_page_info, and capture_pdf. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.

Common problems and fixes

Import or constructor errors

Cause: code from langchain.mcp, langchain-mcp-adapters, and older JavaScript clients was mixed. Fix: inspect installed versions, choose one API generation, and align imports, discovery method, and close method.

No tools are discovered

Cause: the server process failed to start, the URL is wrong, or authentication was rejected. Fix: run the server independently, inspect stderr and HTTP status, verify environment variables, and test network access from the agent host.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Agent answers without calling a tool

Cause: tools were never passed to create_agent, the prompt did not require a tool, or the model declined because the schema did not fit. Fix: print the discovered tool names, pass the exact collection to the agent, and test with a request that clearly requires one tool.

Calls fail after the first request

Cause: the adapter was closed too early or a persistent session expired. Fix: keep it open for the agent lifetime, close only during cleanup, and recreate the session after a transport failure.

Destructive action runs unexpectedly

Cause: discovery metadata was treated as enforcement. Fix: implement an explicit approval gate, validate arguments, and deny high-risk tools by default.

FAQ

Can I connect Jira, Slack and Confluence MCP servers at once?

Yes. Configure each server in the same adapter, discover the combined tool set, and prefix names with the server identity to avoid collisions. Each server still needs its own reachable endpoint and credentials.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can I use Anthropic models with MCP servers in LangChain?

Yes, where the corresponding LangChain model integration is configured. The adapter supplies standard LangChain tools; provider authentication and model-specific tool behavior remain separate concerns.

Is a remote MCP host required?

No. Local stdio servers are supported and are often simplest for development. Use HTTP when the server is hosted, shared, or isolated from the agent process.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.