MCP vs LangChain: framework, protocol, or both?
LangChain is a framework: code you import to build an application, with abstractions for models, tools, memory and orchestration. MCP is a protocol: a wire format for exposing tools and data across a process or network boundary. They sit at different layers of the same system, so an application written with LangChain can reach its tools over MCP, and an MCP server can be written by someone who has never used LangChain.
Either works without the other, and the two are routinely used together. Official adapter packages exist for both languages LangChain supports, one package per language.
The two get compared because they answer different parts of the same question: how a model gets access to things.
What does each one actually give you?
| LangChain | MCP | |
|---|---|---|
| What it is | A library in your application | A protocol between processes |
| Language | Python and JavaScript | Language-agnostic |
| Gives you | Chains, agents, memory, orchestration, integrations | Tool discovery, invocation, resources, prompts |
| Tool reuse | Within the LangChain ecosystem | Any compliant client, any language |
| Runs where | In your process | Across a boundary |
The important row is the last but one. A LangChain tool is a Python or JavaScript object usable by LangChain applications. An MCP tool is reachable by any compatible MCP client in any language, including ones that have nothing to do with LangChain, so long as the two agree on a protocol revision and the client is authorised for what it asks for. That is the trade: LangChain gives you a richer programming model inside one ecosystem, MCP gives you a narrower contract that crosses ecosystems.
How do you use MCP tools in LangChain?
In Python, through langchain-mcp-adapters, which wraps the tools an MCP server exposes as ordinary LangChain Tool objects. Once wrapped, your agent treats them like any other tool, and the calls travel over MCP underneath. JavaScript and TypeScript have a separate package, @langchain/mcp-adapters, maintained alongside it rather than being the same code.
That is the whole integration story. The practical question it leaves is where you want the boundary: LangGraph handles the orchestration, MCP handles the tool calls inside it.
When should you use just one?
LangChain alone is fine when every tool is yours, lives in your process, and is only ever used by this application. You skip a protocol, a connection and a failure mode. For a single Python application with a handful of internal tools, adding MCP buys very little.
MCP alone is right when you are building the capability rather than the application. If you are exposing an internal API for other people’s agents, you write an MCP server and never touch LangChain, because you are not building an agent at all. Publishing a tool and orchestrating one are separate jobs, and only the second needs a framework.
Both when you are building an agent that needs third-party tools, or when your own tools need to serve more than one application.
Does using LangChain change your security position?
It changes who you are trusting, not how much.
LangChain integrations are Python or JavaScript dependencies: you install them, they run in your process, and the trust question is your dependency tree. Familiar territory, with mature tooling for auditing it.
MCP servers are either packages you execute or endpoints you call, and two things decide the rest: who owns them, and how you reach them.
Ownership is the larger factor. A server your team wrote and self-hosts carries roughly the supply-chain risk of a library you wrote. A packaged server from someone else is a dependency with execution rights, and a remote one someone else operates sees every argument your agent sends and can change what its tools do without you deploying anything.
Transport decides what you have to secure yourself. A stdio server reads and writes JSON-RPC over the standard input and output of a subprocess your client launched, so it opens no listening port. That is the entire security property. Stdio does not sandbox the process, does not limit which files it reads or writes, and does not stop it opening outbound connections of its own. The process runs with whatever rights your user has until you take some away. For a server you did not write, that means giving it its own credentials scoped to the one job it does, restricting the directories it can reach, and restricting where it is allowed to connect out to.
An HTTP server instead makes transport security, authentication, credential storage and operational monitoring explicit work. Self-hosting reduces the supply-chain question to one you can answer, but the boundary is still yours to configure.
Two differences worth noting rather than one:
- Tool descriptions are untrusted text either way, but with a server you do not control they can change between calls without you shipping anything. A pinned LangChain dependency cannot rewrite its own docstrings under you; a remote MCP server run by someone else can.
- MCP tools are more often written by strangers. Not because the protocol is less safe, but because reaching other people’s tools is what it is for. The official registry is a large, open, mostly unvetted population, which is the part we score.
Neither point is an argument against the combination. Both point at the same practice: review the MCP server list as carefully as you review requirements.txt.
Where to go next
- The layer below both: MCP vs function calling, on how a tool actually reaches the model.
- The category question this one rhymes with: MCP vs agents.
- Publishing a tool for reuse: build a secure MCP server, then check what it scores.
LangChain is how you build the thing. MCP is how the thing reaches what it needs. Deciding between them is really deciding where the boundary between the two should fall.