MCP vs LangChain Tools: Which to Build

A LangChain tool is a function inside your agent’s process; an MCP server is a separate program any MCP host can use. How they differ, how LangChain now loads MCP tools itself, and when to write which.

6 min read

Write a LangChain tool when the capability belongs to one agent you are building in LangChain and needs that agent’s state: it is a Python function in the same process, described by its docstring and type hints, and nothing outside your application can call it. Build an MCP server when the capability should be usable by more than one host, such as Claude Code, Cursor, ChatGPT and your own LangChain agent, or when it should run with its own credentials in its own process. The two are not rivals. LangChain can load any MCP server’s tools and hand them to an agent as ordinary LangChain tools, so a common shape is a LangChain agent that uses a few tools of its own and several MCP servers that other people, or other teams, maintain.

If MCP itself is new, start with what MCP is. The neighbouring comparison with a model API’s own tool feature is MCP vs function calling.

A LangChain tool, in one function

LangChain’s tools documentation (opens in a new tab) defines tools as callable functions with well-defined inputs and outputs that are passed to a chat model, which decides when to call them. You make one with the @tool decorator. The docstring becomes the description the model reads, and type hints are required because they define the input schema.

Python: a LangChain tool
from langchain.tools import tool

@tool
def search_orders(customer_id: str, limit: int = 10) -> str:
    """Find a customer's most recent orders.

    Args:
        customer_id: The customer's id
        limit: How many orders to return
    """
    return db.recent_orders(customer_id, limit)

The strengths come from living in your process. The function can use the database connection your application already holds, read the agent’s state and context through LangChain’s runtime injection, and return in microseconds with no network hop. It is tested like any other function. The cost is reach: the tool exists only inside LangChain, only in Python (or only in JavaScript, for LangChain.js), and only in the application that imports it.

An MCP server, as a separate program

MCP moves the tool out of your application. In the MCP architecture (opens in a new tab), a host such as Claude Code runs one client per server, and each server is its own program, local over stdio or remote over HTTP. The host asks the server what it offers and calls tools by name over the same protocol whichever server it is.

A tool on an MCP server has the same parts as a LangChain tool. The MCP specification for tools (opens in a new tab) gives each one a name, a description and an input schema, listed with tools/list and run with tools/call. What differs is everything around it: the server can also offer resources and prompts (the three building blocks), remote servers sign users in with OAuth, and the same server works in every host that speaks MCP. Writing one is covered in how to build an MCP server.

The bridge: LangChain loads MCP tools

For a while the bridge was a separate package, langchain-mcp-adapters, with a MultiServerMCPClient that converted MCP tools into LangChain tools for LangChain and LangGraph agents. Its repository (opens in a new tab) now says it is no longer actively maintained: MCP support has moved into LangChain itself, as the langchain.mcp namespace, and existing code should migrate.

LangChain’s MCP documentation (opens in a new tab) describes the replacement. You install langchain[mcp], open an MCPAdapter, call list_tools() and pass the result to create_agent. The adapter is built on FastMCP and infers the transport from what you give it: an https URL is reached over streamable HTTP, a script path is launched as a subprocess over stdio, and an in-process FastMCP server is connected in memory, which is handy for tests. The namespace needs version 1.4.0 or later and is marked beta, so the API may change.

Python: MCP tools in a LangChain agent
from fastmcp.client import Client
from langchain.agents import create_agent
from langchain.mcp import MCPAdapter

async def build_agent(model, token):
    client = Client("https://fenbs.ai/api/mcp", auth=token)
    async with MCPAdapter(client) as adapter:
        mcp_tools = await adapter.list_tools()
    return create_agent(model, [search_orders, *mcp_tools])

Three details from LangChain’s migration guide are worth knowing before you build on it. The new adapter wraps tools only: MCP prompts and resources have no wrapper yet, and you read them through the FastMCP client directly. Each tool the adapter returns opens its own session per call by default, which suits stateless servers and is worth checking for one that keeps state between calls. And authentication is FastMCP’s: a bearer token, the full OAuth 2.1 flow with dynamic client registration, or per-server credentials when one agent reaches several servers.

One more, because it is a security detail rather than a convenience. A plain string given to the adapter must be an http or https address. The documentation explains why: underneath, a string naming an existing script would be launched as a local process, and targets often arrive from configuration files or from a model. So never build the target from text a user or an agent supplied without checking it, and pass a script as a path on purpose when you mean to run one.

The differences that matter in practice

  • Reuse. A LangChain tool serves one application. An MCP server serves every MCP host, including the coding assistants your team already uses.
  • Access to the agent. A LangChain tool can read the run’s state and context. An MCP server sees only the arguments it is sent.
  • Speed. In-process is a function call. MCP adds a process boundary, and for remote servers a network round trip and a session.
  • Credentials. A LangChain tool runs with whatever your application holds. An MCP server holds its own, and a remote one signs each user in, so the agent never needs the underlying key.
  • Language. LangChain tools are Python or JavaScript, matching the framework. MCP servers can be written in any language with an SDK and used from any host.
  • Ownership. A tool in your codebase changes when you change it. A third-party MCP server changes when its maintainer ships, so tool names and fields can move under you.

When to use which

  • The capability needs the agent’s state, or is glue between steps in one graph: a LangChain tool.
  • Someone already publishes an MCP server for the product, such as GitHub, Linear or Notion: load theirs through MCPAdapter rather than wrapping their API again.
  • Your own product or service should be reachable from Claude Code and Cursor as well as your agent: build an MCP server once and load it into LangChain too.
  • The tool touches something sensitive and should hold its own narrow credential, or run on another machine: an MCP server, so the key never enters the agent’s process.
  • A quick prototype of one agent: LangChain tools. Move a tool to an MCP server when a second host needs it, not before.

Whichever you pick, the tool’s description is what the model reads when it decides what to call, so short, specific descriptions and clear refusals matter more than the transport.

Where a task board fits

An agent built in LangChain still has to report somewhere. fenbs exposes its board as an MCP server, so a LangChain agent loads the same tools Claude Code and Cursor use: fenbs_list_items, fenbs_create_item, fenbs_update_item and fenbs_comment. A script cannot open a browser, so it uses a token issued by hand under Settings, with a name, the scopes you tick and an optional expiry, sent as a bearer token as in the example above. The token acts as the person who issued it, narrowed by their role, and every change is recorded under the assistant’s name. Revoking it stops the agent at once.

Related

How MCP compares with the layers around it: MCP vs REST API, MCP vs function calling and MCP vs A2A. Connecting to fenbs: the MCP docs.

Questions people ask.

Is MCP a replacement for LangChain?

No. LangChain is a framework for building agents; MCP is a protocol for serving tools to any agent host. A LangChain agent can use MCP servers as a source of tools alongside tools written in LangChain.

Should I still use langchain-mcp-adapters?

Its README says it is no longer actively maintained and that MCP support has moved into LangChain as the langchain.mcp namespace, installed with the mcp extra from version 1.4.0. The namespace is in beta, so pin your version and follow LangChain’s migration guide.

Can a LangChain agent use MCP resources and prompts?

Not through the new adapter yet. LangChain says langchain.mcp wraps tools only for now, and that resources and prompts can be read through the FastMCP client directly.

Are MCP tools slower than LangChain tools?

Usually a little, because each call crosses a process boundary and, for a remote server, the network. For most agent work the model’s own response time dominates. For a tool called many times in a tight loop, keep it in process.

Start with one thing.

There is nothing to set up first. Write one line and you’ve started.