langchain-mcp-adapters vs Native langchain.mcp (2026)

langchain-mcp-adapters vs Native langchain.mcp (2026)

langchain-mcp-adapters vs langchain.mcp: The 2026 Migration Guide

If you built a LangChain agent that talks to Model Context Protocol servers at any point in the last year, you almost certainly imported MultiServerMCPClient from the standalone langchain-mcp-adapters package. That package is now being wound down. As of langchain[mcp]>=1.4.0, MCP support lives inside LangChain itself, and the langchain-mcp-adapters vs langchain.mcp migration question has stopped being theoretical — it is the thing you need to sort out before your next dependency bump quietly breaks a production agent. The new langchain.mcp module ships a single MCPAdapter class that replaces the old client, adds elicitation as a first-class human-in-the-loop primitive, and targets the stateless MCP specification rewritten on 2026-07-28. It is currently BETA and Python-only, and it changes enough of the surface area that a mechanical find-and-replace will not get you all the way there.

What this covers: why LangChain absorbed MCP support instead of leaving it in a satellite package, the exact MultiServerMCPClient to MCPAdapter code diff, how elicitation resumes through a LangGraph interrupt, what OAuth 2.1 setup looks like conceptually under the new client, and the trade-offs you should weigh before moving a production agent onto a beta integration.

Context and Background

MCP shipped in late 2024 as a session-based protocol: a client opened a long-lived connection to a server, negotiated capabilities, and kept state for the life of that connection. That architecture worked well for local stdio servers and single-tenant setups, but it strained under the load patterns that show up once MCP servers sit behind a load balancer, get called from serverless functions, or need to scale horizontally without sticky sessions. On 2026-07-28 the Model Context Protocol specification went through what its maintainers describe as the largest rewrite since launch, eliminating the session-based architecture in favor of a stateless request/response model. We covered the mechanics of that spec change — what stateless actually means at the wire-protocol level and why it forces a migration across the whole MCP ecosystem — in a dedicated breakdown of the MCP 2026-07-28 stateless migration; this post does not repeat that ground. What matters here is narrower: LangChain had to update its own SDK to speak the new protocol, and it used that moment to fold MCP support into the core langchain package rather than continuing to maintain it as an external adapter layer.

That decision has a real precedent. Framework maintainers tend to externalize integrations early, when a protocol is unproven, and internalize them once the protocol becomes load-bearing. LangChain’s own blog post announcing the change — “MCP in LangChain: Stateless Protocol, Elicitation, and More!”, published September 3, 2026 — frames the shift explicitly around scale: MCP SDK downloads are approaching roughly half a billion a month across the ecosystem, and MCP tool-call volume from ChatGPT users alone is reported up 98x across 2026, more than doubling again in August. Those are ecosystem-wide MCP numbers, not LangChain-specific usage, and they should be read as context for why the protocol earned a first-class module rather than as a claim about LangChain’s own adoption curve. If you want to compare how different server frameworks are responding to the same pressure, our piece on FastMCP versus the official MCP SDK covers the server side of this same transition.

For teams deciding whether to adopt MCP for internal tooling at all, this timing matters. A framework absorbing a protocol into its core package is a stronger signal of long-term commitment than a community-maintained adapter ever was — it means the maintainers expect to keep paying the integration cost themselves, indefinitely, rather than leaving it to a smaller team that could abandon the package. That is a reasonable input into a build-versus-wait decision if you have been holding off on MCP because the tooling felt provisional.

The practical upshot for LangChain developers: the standalone langchain-mcp-adapters package is a dead end. Its GitHub repository is being wound down in favor of the built-in module, and LangChain has published an official migration guide at docs.langchain.com/oss/python/migrate/langchain-mcp-adapters. New feature work — elicitation, OAuth 2.1, stateless protocol negotiation — is landing in langchain.mcp only. If you stay on the old package, you get a frozen client talking an increasingly legacy dialect of MCP.

From MultiServerMCPClient to MCPAdapter: The Actual Migration

Direct answer: MCPAdapter is a single class that replaces MultiServerMCPClient and folds transport selection, authentication, and tool discovery into one constructor argument. It accepts URLs, file paths, transport objects, in-process FastMCP servers, multi-server config dicts, or prebuilt fastmcp.Client instances, and it exposes an async context manager instead of requiring you to manage server lifecycles by hand.

The old package asked you to instantiate a client with a dictionary describing every server, keyed by name, each with its own transport type and connection parameters. That pattern worked, but it meant your MCP configuration lived in Python-side dictionaries that had to be kept in sync with whatever the servers themselves expected, and multi-server fan-out was baked into the client’s identity — you could not easily treat “one server” as the unit of connection when that was all you needed.

What MultiServerMCPClient looked like

A typical langchain-mcp-adapters setup connecting to a single remote MCP server and handing its tools to an agent looked roughly like this:

from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient(
    {
        "example": {
            "url": "https://example.com/mcp",
            "transport": "streamable_http",
        }
    }
)
tools = await client.get_tools()
agent = create_agent("claude-sonnet-5", tools)
result = await agent.ainvoke({"messages": [{"role": "user", "content": "..."}]})

Every server needed an entry in that top-level dict even when there was exactly one server in play, and the transport string had to match one of a small fixed set of literal values. Connection lifecycle — when the underlying HTTP or stdio connection actually opened and closed — was handled implicitly by the client, which made it easy to leak connections in long-running processes if you were not careful about calling cleanup methods.

What MCPAdapter looks like

The native replacement collapses that into a single adapter that is also an async context manager, so connection lifetime is explicit and scoped:

from langchain.mcp import MCPAdapter

async with MCPAdapter("https://example.com/mcp") as adapter:
    tools = await adapter.list_tools()
    agent = create_agent("claude-sonnet-5", tools)
    result = await agent.ainvoke({"messages": [{"role": "user", "content": "..."}]})

Note the method rename alongside the class rename: get_tools() becomes list_tools(). That is a small thing, but it is exactly the kind of change that a naive search-and-replace on MultiServerMCPClient -> MCPAdapter will miss, and it will surface as an AttributeError at runtime rather than at import time, which makes it more annoying to catch in a quick manual test.

MCPAdapter is deliberately polymorphic on its constructor argument. According to LangChain’s documentation, the accepted inputs are:

  • an HTTP or HTTPS URL string, for a remote streamable server
  • a local file path, which the adapter spawns as a stdio subprocess
  • a StreamableTransport object, for cases where you need to configure transport behavior explicitly
  • an in-process FastMCP server instance, so you can wire a server and an agent into the same process without a network hop
  • an MCPConfig dict, for the multi-server case that used to be MultiServerMCPClient‘s only mode
  • a prebuilt fastmcp.Client object, for teams that already manage FastMCP clients directly and want LangChain to consume one rather than construct its own

That last point matters more than it looks. The reason a single class can accept a URL, a file path, a config dict, and a live server object is that langchain.mcp does not implement its own transport stack — it delegates to FastMCP underneath. MCPAdapter is effectively a LangChain-shaped wrapper around a FastMCP client, which is also why the multi-server case is still available: pass an MCPConfig dict and you get the old fan-out behavior back, just under the new class name.

Why so many constructor shapes

It is worth understanding why LangChain chose polymorphism here instead of separate constructors or factory functions, because it changes how you should think about MCPAdapter in your own code. Each accepted input type maps to a different deployment shape you are likely to hit in practice:

  • A URL string covers the common case of a remote server your team does not operate directly, reached over HTTP.
  • A local file path covers development and single-machine deployments, where spawning a subprocess over stdio is simpler than standing up a network service.
  • An in-process FastMCP server instance covers the case where the “server” and the “client” are the same process — useful for testing, for embedding a tool server inside a larger application, or for avoiding a network hop entirely when latency matters.
  • A StreamableTransport object covers cases where the default transport behavior needs explicit tuning that a bare URL string cannot express.
  • An MCPConfig dict covers fan-out across several servers of potentially different transport types in one adapter.
  • A prebuilt fastmcp.Client covers teams that already have FastMCP client management elsewhere in their stack and want LangChain to consume that object rather than construct a competing one.

The practical implication is that you rarely need to reach for the more exotic constructor shapes unless your deployment topology specifically calls for them. Most migrations from MultiServerMCPClient will land on either a bare URL string, for the single-server case, or an MCPConfig dict, for the multi-server case — both of which map almost directly onto what the old package already asked you to write.

Migrating a multi-server setup

For teams that were using the multi-server dictionary pattern specifically, the migration is closer to a rename than a redesign, because MCPAdapter still accepts that shape:

# Before
from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient({
    "search": {"url": "https://search.internal/mcp", "transport": "streamable_http"},
    "files": {"command": "python", "args": ["file_server.py"]},
})
tools = await client.get_tools()

# After
from langchain.mcp import MCPAdapter

config = {
    "search": {"url": "https://search.internal/mcp", "transport": "streamable_http"},
    "files": {"command": "python", "args": ["file_server.py"]},
}
async with MCPAdapter(config) as adapter:
    tools = await adapter.list_tools()

The shape of the config dict is unchanged in the examples LangChain publishes, which is the friendliest possible outcome for teams with several servers already wired up. The real work in most migrations will not be the constructor call — it will be everywhere in your codebase that imported from langchain_mcp_adapters directly, everywhere that called .get_tools(), and any code that relied on the old client’s implicit lifecycle management instead of an explicit async with block. Search your codebase for both the old import path and the old method name before considering the migration done; either one left behind will fail loudly enough in testing, but only if your test suite actually exercises the MCP-connected code paths.

Before and after architecture showing MultiServerMCPClient replaced by MCPAdapter, both connecting to the same MCP servers, with MCPAdapter additionally routed through a FastMCP transport layer
Figure 1: The old langchain-mcp-adapters client connected directly to each configured MCP server. The new MCPAdapter keeps the same server-facing shape but routes everything through a shared FastMCP transport layer underneath, which is where OAuth, protocol negotiation, and caching now live.

Long description: the diagram shows two parallel architectures. On the left, labeled Before, agent code calls into MultiServerMCPClient, which connects directly to MCP Server A and MCP Server B. On the right, labeled After, agent code calls into MCPAdapter, which connects to the same two servers but also routes through a FastMCP transport layer, shown as a dashed connection, representing the shared transport, auth, and negotiation logic that the new client delegates to rather than implementing itself.

Elicitation, OAuth 2.1, and the New Trust Boundary

Two capabilities in this release change what your agent code needs to handle, beyond the client rename: elicitation, which is a protocol-level way for a tool to pause and ask the caller something before it can finish, and OAuth 2.1, which is how the adapter authenticates against servers that require it. Both are new responsibilities for agent code that previously assumed every tool call either succeeded, failed, or returned data — elicitation adds a third outcome, “I need more information from a human before I can continue.”

Elicitation as a LangGraph interrupt

Elicitation exists in the MCP spec for tools that cannot safely complete without checking with the caller — confirming a destructive action like a file deletion, disambiguating between two matching records, or filling in a parameter the tool needs but was not given. Before this integration, handling that pattern inside a LangChain agent meant building your own out-of-band signaling, usually by having the tool raise a custom exception and catching it somewhere in your orchestration code, then figuring out how to resume the same tool call once you had an answer.

langchain.mcp maps elicitation onto a primitive LangGraph already has for exactly this kind of pause-and-resume flow: the interrupt. When a connected MCP server raises an elicitation during a tool call, the adapter surfaces it as a LangGraph interrupt, which halts graph execution at that node and returns control to whatever is driving the graph — your application code, a chat UI, or a CLI. The graph’s state is checkpointed at the point of the interrupt, so resuming it later with the human’s answer continues from exactly where it paused rather than replaying the whole run.

A representative pattern looks like this:

from langgraph.types import Command
from langchain.mcp import MCPAdapter

async with MCPAdapter("https://ops.internal/mcp") as adapter:
    tools = await adapter.list_tools()
    graph = build_agent_graph(tools)

    config = {"configurable": {"thread_id": "run-482"}}
    result = await graph.ainvoke({"messages": [user_message]}, config=config)

    # The tool call inside the graph raised an elicitation; LangGraph
    # surfaces it as an interrupt and pauses execution here.
    if "__interrupt__" in result:
        elicitation = result["__interrupt__"][0].value
        print(f"Tool needs input: {elicitation['prompt']}")

        # Somewhere downstream, a human answers. You resume the same
        # thread with their response, and the tool call completes.
        result = await graph.ainvoke(
            Command(resume={"answer": "yes, proceed with deletion"}),
            config=config,
        )

The important structural point is that the elicitation does not terminate the run — it suspends it. Your application is responsible for surfacing the elicitation prompt to whatever is standing in for the human (a chat message, a dashboard, an approval queue) and for eventually calling the graph again with a Command(resume=...) carrying that answer, keyed to the same thread so LangGraph can find the checkpoint it paused at. This is the same mechanism LangGraph already uses for other human-in-the-loop patterns, which is the actual design win here: elicitation is not a new orchestration concept bolted onto LangChain, it is an existing one wired up to a new protocol-level trigger.

That reuse has a practical requirement attached: interrupts only survive across separate ainvoke calls if your graph is compiled with a checkpointer. A graph running with no checkpointer configured, or with an in-memory saver that does not outlive the process, will lose the paused state the moment your application restarts between the interrupt and the resume — which matters a great deal if the human answering an elicitation might take minutes or hours, not milliseconds. If you are moving an existing agent onto this pattern for the first time, confirm your checkpointer is durable enough for your expected approval latency before you rely on elicitation for anything with real consequences, like the destructive-action confirmation example above. A short-lived in-process checkpointer is fine for a demo; it is not fine for a workflow where a human might not look at their approval queue until the next morning.

Sequence diagram showing an elicitation flow, where a tool call from the agent triggers an interrupt, LangGraph asks the user for confirmation, and the tool resumes once the user responds
Figure 2: An elicitation-triggered tool call does not fail — it pauses. The agent raises a LangGraph interrupt, something outside the graph collects a human answer, and the same run resumes and completes once that answer comes back through Command(resume=…).

Long description: the sequence diagram shows a user sending a request to the agent, the agent calling an MCP tool, the tool responding that elicitation is needed, the agent raising an interrupt to LangGraph, LangGraph asking the user for confirmation, the user providing a response, LangGraph resuming the tool with that answer, the tool returning its result, and the agent returning a final answer to the user.

OAuth 2.1 at the config level

The second major addition is native OAuth 2.1 support in the adapter’s authentication stack, alongside plain bearer tokens and custom httpx-style auth objects. Because MCPAdapter delegates its transport layer to FastMCP, the OAuth handling is FastMCP’s implementation rather than something LangChain built from scratch — which is a reasonable design choice, since transport-layer auth is exactly the kind of thing you want implemented once and shared across every framework that sits on top of the same client.

At a conceptual level, the flow an OAuth-protected connection goes through is what you would expect from OAuth 2.1: the adapter recognizes that a server requires authorization, obtains a token from the configured authorization server, attaches it as a bearer credential on outbound requests, and refreshes or re-authorizes when that token expires or is rejected. What LangChain’s current documentation does not spell out in full is the exact configuration surface — parameter names for registering client credentials, the specific refresh and retry behavior, and any caching semantics around tokens. Rather than guess at those specifics, treat OAuth 2.1 setup as something to wire up by consulting the current LangChain and FastMCP documentation directly at implementation time, since a beta feature’s configuration surface is exactly the part most likely to shift between point releases.

Conceptual flowchart of OAuth 2.1 authentication in MCPAdapter, showing the decision to authenticate, token request, validation, and connection to the MCP server
Figure 3: Conceptual shape of the OAuth 2.1 path inside MCPAdapter. The adapter checks whether a server needs authorization, requests and validates a token, and either attaches it as a bearer credential or refreshes and retries before connecting.

Long description: the flowchart shows MCPAdapter initializing, checking whether authorization is required, connecting directly if not, and if so loading OAuth 2.1 configuration, requesting a token from the authorization server, checking whether that token is valid, attaching it as a bearer token if valid, or refreshing and re-authorizing and looping back to the token request if not, before finally connecting to the MCP server.

One detail worth flagging for anyone building against multiple MCP servers with different auth requirements in the same agent: because MCPConfig supports per-server entries, there is no reason a single MCPAdapter instance cannot mix an OAuth-protected server with a plain bearer-token server and an unauthenticated local stdio server in the same config dict. The authentication decision is made per connection, not per adapter instance.

There is also a maintenance argument for delegating auth to FastMCP rather than having LangChain implement its own OAuth 2.1 stack. Token handling is exactly the kind of code where a subtle bug — a missed refresh, an incorrectly scoped token, a race between two concurrent requests both triggering a refresh — is expensive to get wrong and tedious to get right twice. By sitting on top of FastMCP’s client rather than duplicating it, LangChain avoids maintaining a second OAuth implementation that could drift out of sync with the first. The cost, as noted above, is that your agent’s auth behavior is now only as good as FastMCP’s, and any FastMCP-side auth bug reaches you without LangChain necessarily being the one to fix it. For teams running multi-tenant agents — where different end users need to authenticate against the same downstream MCP server under their own identity rather than a single shared service credential — treat scope and token-isolation design as a question to resolve against current FastMCP documentation, since per-user credential isolation is not something this integration guarantees automatically just because OAuth 2.1 is supported.

Trade-offs, Gotchas, and What Goes Wrong

The single most important caveat here is status: this is a BETA feature. Importing anything from langchain.mcp triggers a LangChainBetaWarning, raised once per process, which is LangChain’s own signal that the API surface can still change before it stabilizes. If you are building something you plan to run in production for the next year, pin your langchain version deliberately rather than tracking latest, and read release notes before bumping — a beta module is exactly where a minor version bump is most likely to rename a method or change a default.

Second, this is Python-only right now. LangChain’s announcement is explicit that TypeScript and langchain.js support is “coming soon,” with no committed date given. If your stack is JavaScript-based, or if you have agents split across Python and TypeScript services that both need MCP access, you are stuck maintaining the older pattern — or a different client entirely — on the TypeScript side until that lands. Do not architect around a same-quarter TypeScript release; treat it as unscheduled until LangChain says otherwise.

Third, protocol negotiation is where the “two eras of MCP” framing actually bites in practice. LangChain’s own announcement describes the ecosystem as having “two distinct eras” of the protocol, split by the 2026-07-28 stateless rewrite. MCPAdapter is built to negotiate the new stateless protocol first and fall back to the legacy session-based handshake when a server has not upgraded yet. That fallback is convenient, but it also means your adapter’s behavior — and its performance characteristics — silently depends on which era each server you connect to is running. A server still on the pre-rewrite spec will get a session-based connection with all of that architecture’s overhead, while a rewritten server gets the leaner stateless path. If you are debugging latency differences between two MCP servers that should behave identically, check which protocol era each one actually negotiated before assuming the difference is in your agent code.

Flowchart showing MCPAdapter checking whether a server supports the 2026-07-28 stateless spec, using the stateless protocol if so, and falling back to a legacy session-based handshake if not
Figure 4: Protocol negotiation inside MCPAdapter tries the stateless 2026-07-28 spec first and falls back to the legacy session-based handshake on servers that have not upgraded — a fork that changes both wire behavior and latency depending on which “era” of MCP the target server is running.

Long description: the flowchart shows MCPAdapter connecting to a server and checking whether that server supports the 2026-07-28 spec. If yes, it uses the stateless protocol, leading directly to a request-response tool execution path. If no, it falls back to a legacy session-based handshake, which requires session initialization and teardown before reaching the same tool execution step.

Fourth, the response-caching behavior that respects server-declared TTLs is mentioned in LangChain’s materials without full mechanics attached — how caching interacts with tool calls that have side effects, what the cache key is scoped to, and exact TTL handling are not detailed publicly at the level this migration guide would need to state them precisely. Do not assume caching behaves like a generic HTTP cache; consult current LangChain and FastMCP documentation before relying on it for anything where staleness would matter, particularly tools that read frequently-changing state.

Fifth, and easy to miss: because the underlying transport is now FastMCP rather than a LangChain-authored client, bugs and behavior changes in FastMCP itself now surface directly in your LangChain agents. That is mostly a good thing — one well-maintained transport implementation instead of two — but it does mean your dependency graph now has a real, load-bearing dependency on FastMCP’s release cadence, not just LangChain’s.

Sixth, think through what happens when an elicitation never gets answered. A run paused on a LangGraph interrupt does not automatically time out or clean itself up — it sits checkpointed until something resumes it or your own application logic decides to abandon it. For a low-stakes internal tool that is a minor annoyance. For anything customer-facing, or anything running at meaningful volume, an unanswered elicitation is a paused run consuming checkpoint storage indefinitely, and you should build your own timeout and cleanup logic around it rather than assuming the framework handles staleness for you — neither LangChain nor the MCP spec, as covered in the materials for this piece, defines a default expiry for a pending elicitation.

Practical Recommendations

If you are running langchain-mcp-adapters in production today, treat this as a planned migration, not an urgent one, unless you specifically need elicitation, OAuth 2.1, or stateless-spec compatibility with a server that has already moved on. A checklist for the migration itself:

  • Audit imports first. Grep your codebase for langchain_mcp_adapters and for .get_tools() calls — both need to change, and only one of them fails at import time.
  • Pin your beta dependency deliberately. Set langchain[mcp] to an exact version rather than a floor, and read the changelog before bumping, given the LangChainBetaWarning this module raises.
  • Test the multi-server config path explicitly if you use it. The MCPConfig dict shape carries over, but confirm your specific transport types and auth combinations behave the same way under the new adapter before cutting over production traffic.
  • Wrap tool calls to handle interrupts, not just exceptions, if any connected server might raise elicitation. A tool call that used to only return data or raise can now also pause — make sure your calling code checks for __interrupt__ rather than assuming a two-outcome contract.
  • Do not hand-roll OAuth 2.1 parameters from guesswork. Pull the exact configuration keys and refresh behavior from current LangChain and FastMCP docs at implementation time, since this is one of the areas most likely to still be in flux.
  • Check which protocol era each of your MCP servers is running before comparing their latency or debugging inconsistent behavior between them.
  • Keep TypeScript agents on their current MCP integration until LangChain ships langchain.js support — there is no committed timeline to plan around yet.
  • Re-run your MCP-touching test suite specifically, not just your broader CI — a rename this central can pass a shallow smoke test while still breaking a code path your tests never exercised.
  • Confirm your checkpointer is durable enough for real approval latency before shipping any elicitation-dependent workflow — an in-memory checkpointer that does not survive a process restart will silently drop a paused run if a human takes longer than a few minutes to answer.
  • Add explicit timeout and cleanup logic around elicitation-heavy flows rather than assuming a paused run expires on its own; neither LangGraph interrupts nor the MCP spec define a default expiry.
  • Roll the migration out server by server if you operate several MCP servers, rather than flipping your entire fleet to the new adapter in one deploy, so a protocol-negotiation surprise on one server does not take down every agent that depends on MCP tools.

Frequently Asked Questions

Is langchain-mcp-adapters actually deprecated?

Functionally, yes. LangChain has published an official migration guide moving developers off langchain-mcp-adapters and onto the built-in langchain.mcp module, and the standalone package’s GitHub repository is being wound down in favor of the native integration. New capabilities — elicitation, OAuth 2.1, stateless protocol support — are landing only in langchain.mcp, so the old package will fall further behind the current MCP spec over time even if it keeps running for existing use cases.

Do I need to change my MCP server code, or only my LangChain client code?

This migration is entirely client-side. Your MCP servers do not need code changes to work with MCPAdapter, since the adapter negotiates protocol version automatically and falls back to the legacy session-based handshake for servers that have not adopted the 2026-07-28 stateless spec. That said, if your servers are also due for their own upgrade to the new spec, that is a separate project worth planning alongside this client migration rather than instead of it.

What exactly is MCP elicitation, in plain terms?

Elicitation is a protocol-level mechanism for a tool to say “I cannot finish this call without asking you something” mid-execution — confirming a risky action, resolving an ambiguous match, or requesting a missing parameter. It is distinct from a tool simply failing or returning an error, because the call is not done; it is paused pending an answer. In LangChain, that pause is implemented as a LangGraph interrupt, and the run resumes from its checkpoint once your application supplies the human’s response via Command(resume=...).

Can I use MCPAdapter without OAuth if my servers don’t need it?

Yes. OAuth 2.1 is one of several supported authentication modes, alongside plain bearer tokens and custom httpx-based auth objects, and it is only engaged for servers whose configuration calls for it. An unauthenticated local stdio server, a bearer-token-protected remote server, and an OAuth-protected server can all coexist in the same MCPConfig dict, with the adapter handling each connection’s authentication independently.

Is it safe to run langchain.mcp in production given the BETA status?

That depends on your tolerance for API churn, not on stability in the reliability sense. LangChainBetaWarning signals that method names, defaults, or configuration shapes could still change before the module graduates out of beta — it is not a claim that the code is unreliable. Teams that need the new capabilities now (elicitation, OAuth 2.1, stateless-spec servers) can run it in production if they pin versions deliberately and budget time to review each release’s changes; teams that can wait for a stable release with no urgent need should consider doing so.

When is TypeScript or langchain.js support coming?

LangChain has stated that TypeScript support is “coming soon” without giving a committed date in the material available at the time of writing. If you have production agents in TypeScript, do not plan around a specific release window — check LangChain’s current documentation and release notes directly before committing a roadmap item to it, and in the meantime continue using whatever MCP client pattern your TypeScript stack currently relies on.

What happens if a human never responds to an elicitation?

The run stays paused. A LangGraph interrupt does not carry a built-in expiry, so a tool call waiting on an elicitation answer will sit checkpointed indefinitely unless your own application logic decides to time it out and clean it up. This is fine for low-volume internal tools where a stale approval request is a minor nuisance, but it becomes a real operational concern at scale, since every unanswered elicitation is a paused run holding onto checkpoint state. Build your own timeout and abandonment handling around elicitation-heavy workflows rather than assuming the framework or the MCP spec enforces one for you.

Further Reading

By Riju — about

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *