Dynamic MCP tool list updates without rebuilding the compiled graph? #6116
Replies: 2 comments
|
Yes — the graph topology does not need to be rebuilt just because the MCP tool registry changes. What must change together is (1) the tools exposed to the model and (2) the tool implementation used when the resulting call is executed. For current LangChain agents, runtime tool registration is the supported route: use model-call middleware to load the current MCP snapshot and return For a manually assembled
That last point prevents a race where the model sees schema v1 but the executor runs a same-named v2 tool (or the tool disappears). If a call references a removed/stale version, fail explicitly and send the refreshed tool list through another model turn.
Also, with So: rebind per invocation (or per cached registry version), keep compilation, and make model exposure + execution resolution use one atomic snapshot. |
|
You do not need to recompile the
Stay on StateGraph (closest to what you have) Keep a process-wide registry. Refresh it on a timer or on MCP registry: dict[str, Any] = {}
async def refresh():
tools = await client.get_tools()
registry.clear()
registry.update({t.name: t for t in tools})
# per request / per turn
bound_llm = llm.bind_tools(list(registry.values()))
Current LangChain agents path If you can move the agent to
I have not run this exact refresh loop against |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
We're running a LangGraph agent that loads MCP tools once at startup via
MultiServerMCPClient.get_tools(), classifies them, and compiles them into aStateGraphwithbind_tools()on the LLM. The graph is long-lived across many requests.When the MCP server adds or removes tools, we currently need to rebuild and recompile the entire graph — which means re-binding the LLM, recreating all middleware nodes, and swapping the graph reference. This feels heavy.
Is there a pattern in LangGraph / the new
langchain[mcp]MCPAdapterto handle tool list changes without a full graph recompile? Specifically we're wondering:ToolNode(or a custom node) resolve tools dynamically at call-time from a mutable registry, while the LLM's tool binding is handled separately per-turn?RunnableConfig/configurable)?We saw issue #33808 which seems to be the right ask, but wanted to check if there's a recommended workaround in the meantime.
Transport:
streamable_http. Usinglangchain-mcp-adapters==0.3.1.All reactions