Back to all posts

Reliable Tool-Calling Agents with LangGraph and MCP

Savinay Kumar

The first version of any agent is a while-loop: ask the model what to do, run the tool it picked, feed the result back, repeat until it says it is done. It works in a demo and falls apart in production. It loops forever, calls tools with malformed arguments, and gives you no way to see why it went wrong. Making agents reliable is mostly about replacing that loop with structure.

We build agents with two pieces: LangGraph for control and state, and MCP for the tools.

Why a graph beats a loop

LangGraph models the agent as a state machine: nodes do work, edges decide what happens next, and a shared state object carries everything between them. That structure buys things a loop cannot:

def should_continue(state: AgentState) -> str:
    if state["steps"] >= MAX_STEPS:
        return "end"
    if state["messages"][-1].tool_calls:
        return "tools"
    return "end"

graph.add_conditional_edges("agent", should_continue,
                            {"tools": "tools", "end": END})

That MAX_STEPS check is not a detail. An unbounded agent is an unbounded bill and an unbounded outage.

Why MCP for the tools

The other half is the tools, and the trap is wiring them straight into the agent. Do that and every tool is welded to one agent's code. The Model Context Protocol (MCP) puts a standard interface between the agent and its tools instead: tools live behind an MCP server, the agent is a client, and the two evolve independently.

The payoff is reuse and isolation. The same MCP server that exposes our database queries and internal APIs can back a LangGraph agent, the Claude Agent SDK, or an IDE assistant, with no changes. Tools get versioned, permissioned, and tested on their own, like any other service.

Where reliability actually comes from

The model picking tools is the easy part. The engineering is everything around it:

The pattern

An agent is not a magic loop around a model. It is a small, observable state machine that calls well-defined, well-guarded tools. LangGraph gives you the state machine; MCP gives you the tool boundary. The model is just one node in the graph, and treating it that way is what turns an impressive demo into something you can put in front of users.