All articles LLM & Agents

Agentic AI and the Model Context Protocol (MCP)

A senior engineer's tour of the path from plain RAG to autonomous, multi-agent systems, and how the Model Context Protocol standardizes the way LLM apps connect to tools and data.

Retrieval-augmented generation (RAG) was the first widely adopted pattern for grounding large language models (LLMs) in private data. But grounding is not the same as acting. Over the last two years the frontier has shifted from "fetch context, then answer" to systems that reason, call tools, observe results, and adapt — agents. This piece traces that progression with concrete engineering detail, then explains the Model Context Protocol (MCP): an open standard that decouples models from integrations the way USB-C decoupled devices from proprietary chargers. Throughout, I illustrate the ideas with three of my own projects rather than abstractions.

RAG gives a model knowledge; agents give it agency; MCP gives that agency a standard socket to plug into the world.

From plain RAG to something that acts

Classic RAG is a fixed, one-shot pipeline: embed the query, retrieve the top-k chunks from a vector store, stuff them into the prompt, and generate. It is powerful because it separates knowledge from parameters — you can update a knowledge base without retraining — but it is also rigid. The pipeline runs the same way regardless of whether the retrieved context is relevant, contradictory, or empty.

The limitations show up quickly in production:

  • No recovery. If retrieval returns junk, the model still answers from junk (or hallucinates).
  • Single hop. Questions that require decomposition — "compare A's Q3 numbers to B's and flag anomalies" — cannot be answered by one retrieval pass.
  • Read-only. Plain RAG reads context; it cannot take an action, call an API, or write to a system of record.

Advanced RAG variants close part of this gap by making the pipeline adaptive: hybrid search (dense vectors plus sparse lexical BM25) improves recall on rare terms; a reranker (a cross-encoder scoring query-document pairs) sharpens precision on the shortlist; and corrective and self-RAG add feedback — the system grades its own retrieved context, and if it is insufficient it re-queries, reformulates, or falls back to another source. Once you add those decision points, you have effectively introduced control flow, and you are one step away from an agent.

Tool use and function calling

The pivotal capability that turns a language model into an agent is tool use, exposed by most model providers as function calling. Instead of only emitting prose, the model can emit a structured request — a function name plus JSON arguments conforming to a schema you supply. Your runtime executes that function, captures the result, and feeds it back into the conversation.

{
  "tool": "search_invoices",
  "arguments": {
    "vendor": "Acme Corp",
    "status": "unpaid",
    "period": "2026-Q2"
  }
}

Three engineering points matter here:

  • The schema is the contract. The model chooses whether and how to call a tool based purely on the tool's name, description, and parameter schema. Good descriptions are prompt engineering.
  • The model does not run code. It only proposes a call; your host decides whether to execute it. That separation is where you attach authorization and validation.
  • Retrieval itself becomes a tool. In an agentic RAG system, "search the knowledge base" is just one more callable tool the agent can choose, alongside "query SQL" or "call the ERP API."

The ReAct reason-act-observe loop

Tool use becomes agency when you wrap it in a loop. The ReAct pattern (Yao et al., "ReAct: Synergizing Reasoning and Acting in Language Models") interleaves free-form reasoning ("Thought") with tool calls ("Action") and their returned results ("Observation"). The model reasons about what it knows, acts, observes the outcome, and reasons again — iterating until it can produce a final answer.

flowchart TD A[User goal] --> B[Thought: reason about next step] B --> C{Need a tool?} C -- Yes --> D[Action: emit tool call + args] D --> E[Observation: tool result] E --> F[Update working context] F --> B C -- No --> G[Self-critique: is the answer complete and grounded?] G -- No --> B G -- Yes --> H[Final answer]

The loop is deceptively simple but introduces the core operational concerns of agents: it can loop forever, rack up cost, or wander off task. Production loops therefore add a step budget, a timeout, and a termination condition beyond "the model said it is done." The "Observation" step is also the natural place to enforce output validation — if a tool returns an error or an out-of-range value, the agent should see that and correct, not silently proceed.

Planning, memory, and self-critique

A raw ReAct loop is reactive. Robust agents add three capabilities on top.

Planning

For multi-step goals, letting the model improvise every step is fragile. Plan-and-execute approaches first generate an explicit plan (an ordered list of subgoals), then execute each step, re-planning when reality diverges. This reduces wasted tool calls and makes behavior more auditable — you can log the plan and diff it against what actually happened.

Memory

Agents need state that outlives a single context window. It is useful to distinguish:

  • Short-term / working memory — the running scratchpad of thoughts, actions, and observations within one task.
  • Long-term memory — persisted facts, past interactions, or learned preferences, typically stored in a vector database and retrieved on demand. This is where RAG re-enters: retrieval becomes the agent's recall mechanism.

Self-critique

Reflection patterns (for example, Reflexion) have the agent evaluate its own output against the goal before finalizing: "Did I answer every part? Is each claim supported by an observation? Did any tool fail silently?" A distinct critic pass — sometimes a separate model call or a separate agent — catches errors the actor is blind to. Corrective and self-RAG are a specialized form of this: the critique target is specifically the quality and sufficiency of retrieved evidence.

Multi-agent orchestration with LangGraph

A single agent handling planning, retrieval, tool use, and critique in one prompt eventually hits a ceiling: the prompt becomes overloaded and the model's attention is split across too many responsibilities. The response is decomposition into multiple specialized agents — a planner, one or more workers, a critic, and often a supervisor that routes work between them.

Orchestrating this reliably requires more than chaining prompts. LangGraph models the system as a stateful graph: nodes are agents or tools, edges are transitions, and a shared typed state object flows through the graph. Because edges can be conditional and cyclic, you can express loops (retry, re-plan, escalate to a human) as first-class structure rather than hoping the model decides correctly inside a single prompt. Crucially, that explicit graph is also what makes the system observable: every node transition is a checkpoint you can log, replay, and audit.

Common multi-agent topologies:

  • Supervisor / router — a coordinator agent decides which specialist handles each subtask.
  • Pipeline — agents run in sequence, each refining the previous output (extract, then validate, then post).
  • Debate / critic — an actor proposes and a critic challenges, iterating until convergence or a step limit.

Guardrails, governance, and auditability

An agent that can call tools can, by definition, cause side effects — send an email, move money, modify a record. That makes safety engineering non-optional. Guardrails operate at several layers:

  • Input validation — schema and range checks on tool arguments before execution; reject or clamp bad values rather than trusting the model.
  • Authorization — the host, not the model, enforces which tools are callable and with what scope. The model proposes; policy disposes.
  • Human-in-the-loop — high-impact actions (payments above a threshold, irreversible deletes) pause for explicit approval. LangGraph's interrupt-and-resume support makes this a graph edge.
  • Output filtering — checks for PII leakage, prompt-injection artifacts, and policy violations before a result is committed or shown.
  • Audit trail — every thought, tool call, argument, observation, and approval is logged so a decision can be reconstructed after the fact. In regulated workflows this is the difference between a demo and a deployable system.

Prompt injection deserves special mention: any tool that ingests untrusted text (a web page, an email, a PDF) can carry instructions aimed at hijacking the agent. Treat all tool output as untrusted data, never as privileged instructions, and keep authorization outside the model's reach.

The Model Context Protocol

Every capability above depends on connecting a model to external tools and data. Historically, each connection was bespoke: a custom adapter per model, per framework, per data source. That is an M-by-N integration problem — every new tool must be re-wired for every host. The Model Context Protocol (MCP), an open standard introduced by Anthropic, collapses that to M-plus-N by defining a common interface between LLM applications and integrations. It is frequently described as "USB-C for AI tools": one standard port, many interchangeable peripherals.

MCP defines a client-server architecture with a small, well-defined vocabulary:

  • Host — the LLM application the user interacts with (an IDE assistant, a chat app, a custom agent runtime).
  • Client — a connector inside the host that maintains a one-to-one session with a server.
  • Server — a program that exposes capabilities for a specific system (a database, a filesystem, a SaaS API).

Servers expose three kinds of primitives over a defined transport:

  • Tools — callable functions with typed schemas, meant to be invoked by the model (model-controlled actions).
  • Resources — read-only data the host can load as context, such as files or records (application-controlled).
  • Prompts — reusable, parameterized prompt templates a server offers, typically surfaced to the user (user-controlled).

Communication uses JSON-RPC 2.0 messages over a transport — commonly stdio for local servers and an HTTP-based streaming transport for remote ones. The payoff is decoupling: because a tool is described by the protocol rather than baked into a particular framework, any MCP-compatible host can use any MCP server without custom glue. Swap the model, keep the servers; add a server, and every host gains the capability.

MCP host and server topology

The diagram shows a single host running multiple MCP clients, each bound to one server, with the model reasoning over the tools and resources those servers advertise.

flowchart TD U[User] --> H[Host: LLM application] H --> M[LLM / agent loop] subgraph HostProcess[Host process] H M C1[MCP client A] C2[MCP client B] C3[MCP client C] end M --> C1 M --> C2 M --> C3 C1 -- JSON-RPC over stdio --> S1[MCP server: filesystem] C2 -- JSON-RPC over stdio --> S2[MCP server: database] C3 -- JSON-RPC over HTTP stream --> S3[MCP server: SaaS API] S1 --> R1[(Local files)] S2 --> R2[(SQL store)] S3 --> R3[(External service)] S1 -. exposes .-> P[Tools / Resources / Prompts] S2 -. exposes .-> P S3 -. exposes .-> P

Grounding it in real projects

These patterns are not theoretical for me — they map directly onto systems I have built.

Advanced RAG

My Advanced RAG project implements the adaptive-retrieval ideas from the first section: hybrid search combines dense and sparse retrieval, a reranker reorders the candidate set for precision, and corrective / self-RAG logic grades retrieved evidence and re-queries when it is insufficient. The whole flow is orchestrated as a LangGraph graph, so the "grade context, then decide to answer or retry" decision is an explicit conditional edge rather than hidden prompt behavior. It is the clearest illustration of the RAG-to-agent boundary: still retrieval-centric, but with genuine control flow and self-critique.

Custodian

Custodian is a multi-agent accounts-payable automation system with explicit governance layers. It is the multi-agent and guardrails sections made concrete: specialized agents handle stages of the AP workflow, while governance layers enforce validation, authorization, and auditability around actions that touch financial records. Because AP is a domain where an incorrect or unapproved action has real consequences, the human-in-the-loop and audit-trail concerns discussed above are core requirements, not afterthoughts.

Job Application Agent

The Job Application Agent is an agentic RAG system built with LangChain and a FAISS vector store. It demonstrates the memory-as-retrieval idea: FAISS provides the recall layer the agent queries as a tool, and LangChain wires the reasoning loop around it. It shows how the same retrieval primitives from Advanced RAG can serve as an agent's long-term memory rather than a one-shot answer pipeline.

RAG vs single agent vs multi-agent

Dimension Plain RAG Single agent (ReAct) Multi-agent
Control flow Fixed, one-shot pipeline Dynamic loop; model chooses next step Graph of agents with routing and cycles
Can take actions No (read-only retrieval) Yes, via tool calls Yes, distributed across specialists
Handles multi-step tasks Weak (single hop) Moderate; can overload one prompt Strong; decomposed by responsibility
Error recovery None built in Self-critique and retry in loop Dedicated critic/supervisor agents
Latency and cost Lowest, predictable Higher, variable per loop Highest; parallel or chained calls
Observability / audit Simple to trace Trace of thought-action-observation Per-node checkpoints; richest audit trail
Best fit Grounded Q&A over a corpus Tasks needing a few tools and iteration Complex workflows with governance needs
My example Baseline retrieval Job Application Agent; Advanced RAG Custodian (AP automation)

Takeaways

  • The progression from RAG to agents is a progression in control flow: from a fixed pipeline, to an adaptive loop, to a graph of cooperating specialists.
  • Tool use is the hinge; the ReAct loop turns tool use into agency; planning, memory, and self-critique make that agency reliable.
  • Guardrails and auditability are what separate a demo from a deployable agent, especially where actions have real consequences.
  • MCP standardizes the connection between LLM apps and the outside world, turning an M-by-N integration mess into a swappable ecosystem of tools, resources, and prompts.
  • Choose the simplest architecture that meets the need: reach for a multi-agent system only when a single agent genuinely cannot carry the workload or the governance requirements.
← Back to all articles