TechByteByByte

MCP with LlamaIndex — Practical Integration

LlamaIndex's own, idiomatic pattern for loading MCP tools directly into a real FunctionAgent — plus a genuine, honest look at combining MCP tools with your LlamaIndex course's own retrieval capabilities.

#MCP#LlamaIndex

Recall Module 11’s own generic create_llamaindex_tool_from_mcp function — genuinely useful for understanding the mechanism, but LlamaIndex has its own, real, official, idiomatic pattern, worth using directly.

The real, official LlamaIndex MCP integration

Let’s load a real, running MCP server’s tools directly into LlamaIndex’s own native format.

We’ll connect to Module 9’s own server and pull its real tools using LlamaIndex’s dedicated MCP module.

from llama_index.tools.mcp import BasicMCPClient, McpToolSpec
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai import OpenAI

async def build_llamaindex_mcp_agent():
    mcp_client = BasicMCPClient("support_server.py")  # a real, live MCP connection
    tool_spec = McpToolSpec(client=mcp_client)  # LlamaIndex's own, real MCP-to-tool bridge
    tools = await tool_spec.to_tool_list_async()  # real, discovered tools, in LlamaIndex's native format

    agent = FunctionAgent(tools=tools, llm=OpenAI(model="gpt-4o-mini"))
    return agent

Notice McpToolSpec — recall Module 11’s own real translation function; this is genuinely the same job, done by real, official, maintained LlamaIndex code, following the exact same real pattern your LlamaIndex course’s own ToolSpec classes already taught.

Combining real MCP tools with your own, real retrieval

Recall your LlamaIndex course’s own real QueryEngineTool — a genuinely realistic agent needs both real, external MCP capabilities and its own, internal retrieval.

flowchart TD
    A[FunctionAgent] --> B["policy_tool\n(internal RAG,\nfrom your LlamaIndex course)"]
    A --> C["MCP tools\n(external, from this course)"]
    B --> D[One combined, real tool list]
    C --> D

Let’s build one agent with real tools from both genuinely separate sources at once.

from llama_index.core import VectorStoreIndex, Document
from llama_index.core.tools import QueryEngineTool
from llama_index.tools.mcp import BasicMCPClient, McpToolSpec
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai import OpenAI

async def build_combined_agent():
    # a real, internal retrieval tool, exactly from your LlamaIndex course
    docs = [Document(text="Our return policy allows returns within 30 days.")]
    policy_index = VectorStoreIndex.from_documents(docs)
    policy_tool = QueryEngineTool.from_defaults(query_engine=policy_index.as_query_engine(), name="policy_search")

    # a real, external MCP tool, from this course
    mcp_client = BasicMCPClient("support_server.py")
    mcp_tools = await McpToolSpec(client=mcp_client).to_tool_list_async()

    agent = FunctionAgent(tools=[policy_tool] + mcp_tools, llm=OpenAI(model="gpt-4o-mini"))
    return agent

Notice this genuinely combines two, real, distinct worlds — recall your LlamaIndex course’s own, internal RAG pipeline, and this course’s own, external MCP servers — into one agent, reasoning over both real capability sets identically.

Selectively loading only certain, real tools

Recall Module 5’s own real, security-relevant distinction — read-only versus write-capable tools. LlamaIndex’s own real integration supports filtering directly.

We’ll load only the real tools whose names match an explicit, deliberate allowlist.

tool_spec = McpToolSpec(client=mcp_client, allowed_tools=["get_order_status", "search_documentation"])  # a real, deliberate filter
tools = await tool_spec.to_tool_list_async()

Notice allowed_tools — a genuinely deliberate, real safeguard, worth remembering directly once this course reaches Module 14’s own real security discipline: exposing every single real tool a server offers isn’t always the right, deliberate choice for a given, specific agent.

Common mistakes worth avoiding

Hand-writing the MCP-to-LlamaIndex translation in real, ongoing production code. Recall this module’s own real comparison — McpToolSpec genuinely handles this correctly and stays current; Module 11’s version was for understanding the mechanism.

Loading every real tool a server exposes, without considering whether a given agent genuinely needs all of them. Recall this module’s own real allowed_tools filter — a deliberate, real allowlist is worth considering any time a server exposes both read and write capabilities.

Forgetting that MCP tools and your own, native LlamaIndex tools genuinely combine into one, single list. Recall this module’s own combined example — an agent doesn’t distinguish between the two once they’re loaded; they’re both just real, callable tools from that point forward.

What you should take away from this module

  • llama_index.tools.mcp’s BasicMCPClient and McpToolSpec are the real, official, idiomatic replacement for Module 11’s hand-written function.
  • Real, external MCP tools and your own, internal LlamaIndex retrieval tools genuinely combine into one agent, with no real, structural distinction once loaded.
  • allowed_tools provides a real, deliberate way to expose only a genuine subset of what a server offers — worth using whenever a server mixes read and write capabilities.

Where this goes next

The next module covers the topic this entire course has been building toward carefully: Security, Permissions, and Trust — real, documented incidents, real CVEs, and the genuine, structural safeguards a real MCP deployment actually needs.

Author
TechByteByByte Editorial Team
Reviewed by
TechByteByByte Admin
Published
Last reviewed