Skip to main content
The Model Context Protocol (MCP) integration allows Junkie agents to access external tools and services through a standardized protocol. This enables agents to use tools like web scrapers, code analysis, and more.

Overview

MCP Tools provide:
  • Multi-server support: Connect to multiple MCP servers simultaneously
  • Streamable HTTP transport: Efficient communication with MCP servers
  • Lazy initialization: Tools are only loaded when needed
  • Automatic reconnection: Handles connection management
  • Integration with agents: Seamlessly add MCP tools to any agent

Installation

MCP tools are part of the Agno framework:
from agno.tools.mcp import MCPTools, MultiMCPTools

Configuration

Configure MCP servers via environment variable:
# Single MCP server
export MCP_URLS="https://mcp.example.com/"

# Multiple MCP servers (comma-separated)
export MCP_URLS="https://mcp.example.com/,https://another-mcp.com/"

Setup Functions

get_mcp_tools()

Lazy initialization of MCP tools - creates MultiMCPTools instance only when needed.
from tools.tools_factory import get_mcp_tools

mcp_tools = get_mcp_tools()
Returns: MultiMCPTools instance or empty list if no MCP URLs configured. Implementation (from tools_factory.py:9-30):
_mcp_tools = None
_mcp_connected = False

def get_mcp_tools():
    """Lazy initialization of MCP tools - only create when needed."""
    global _mcp_tools
    if _mcp_tools is None:
        if MCP_URLS:
            # Support comma-separated URLs from env
            urls = [url.strip() for url in MCP_URLS.split(",") if url.strip()]
        else:
            # Default fallback
            urls = [
                "https://litellm1-production-4090.up.railway.app/mcp/",
            ]
        
        if urls:
            _mcp_tools = MultiMCPTools(
                urls=urls,
                urls_transports=["streamable-http"],
            )
        else:
            _mcp_tools = []
    return _mcp_tools

setup_mcp()

Async function to connect to MCP tools.
from tools.tools_factory import setup_mcp

await setup_mcp()
Implementation (from tools_factory.py:32-46):
async def setup_mcp():
    """Lazy connect to MCP tools only if they exist."""
    global _mcp_connected
    mcp = get_mcp_tools()
    if mcp and not _mcp_connected:
        try:
            if isinstance(mcp, MultiMCPTools):
                await mcp.connect()
                _mcp_connected = True
                logger.info("MCP tools connected")
        except Exception as e:
            logger.warning(f"Failed to connect MCP tools: {e}")

MCPTools Class

Single MCP server connection.
from agno.tools.mcp import MCPTools

# Connect to a single MCP server
mcp_tools = MCPTools(
    transport="streamable-http",
    url="https://mcp.context7.com/mcp"
)
transport
str
required
Transport protocol. Use "streamable-http" for HTTP-based MCP servers.
url
str
required
URL of the MCP server endpoint.

MultiMCPTools Class

Connect to multiple MCP servers simultaneously.
from agno.tools.mcp import MultiMCPTools

mcp_tools = MultiMCPTools(
    urls=[
        "https://mcp.context7.com/mcp",
        "https://another-mcp.example.com/mcp",
    ],
    urls_transports=["streamable-http"],
)

# Connect to all servers
await mcp_tools.connect()
urls
list[str]
required
List of MCP server URLs to connect to.
urls_transports
list[str]
required
List of transport protocols. Usually ["streamable-http"].

Agent Integration

Code Agent with MCP

From agent_factory.py:182-232:
from agno.agent import Agent
from agno.models.openai import OpenAILike
from agno.tools.mcp import MCPTools
from tools.e2b_tools import E2BToolkit
from agno.tools.exa import ExaTools

# Build code agent tools with MCP
code_agent_tools = [
    MCPTools(transport="streamable-http", url="https://mcp.context7.com/mcp"),
    e2b_toolkit,
    ExaTools(),
]

# Add Firecrawl MCP server if API key is available
if FIRECRAWL_API_KEY:
    firecrawl_url = f"https://mcp.firecrawl.dev/{FIRECRAWL_API_KEY}/v2/mcp"
    code_agent_tools.append(
        MCPTools(transport="streamable-http", url=firecrawl_url)
    )

code_agent = Agent(
    id="code-agent",
    name="Code Agent",
    role="Designing and executing complex code",
    model=OpenAILike(
        id="gpt-5",
        base_url=PROVIDER,
        api_key=CUSTOM_PROVIDER_API_KEY,
    ),
    tools=code_agent_tools,
    instructions="You can use MCP tools for web scraping and code analysis."
)

Optional MCP Agent

From agent_factory.py:293-305:
# Create optional MCP agent if tools are configured
mcp_tools = get_mcp_tools()
if mcp_tools:
    mcp_agent = Agent(
        name="MCP Tools Agent",
        model=model,
        tools=[mcp_tools],
        add_datetime_to_context=True,
        timezone_identifier="Asia/Kolkata",
        instructions="You specialize in handling MCP-based tool interactions."
    )
    agents = [perplexity_agent, compound_agent, code_agent, context_qna_agent, mcp_agent]
else:
    agents = [perplexity_agent, compound_agent, code_agent, context_qna_agent]

Available MCP Servers

Context7 MCP

MCPTools(transport="streamable-http", url="https://mcp.context7.com/mcp")
Capabilities: Code analysis, context understanding

Firecrawl MCP

firecrawl_url = f"https://mcp.firecrawl.dev/{FIRECRAWL_API_KEY}/v2/mcp"
MCPTools(transport="streamable-http", url=firecrawl_url)
Capabilities: Web scraping, content extraction Requirements: FIRECRAWL_API_KEY environment variable

Custom MCP Server

MCPTools(transport="streamable-http", url="https://your-mcp-server.com/mcp")

Usage Examples

Basic MCP Setup

from tools.tools_factory import get_mcp_tools, setup_mcp

# Get MCP tools instance
mcp_tools = get_mcp_tools()

# Connect to MCP servers
await setup_mcp()

# MCP tools are now ready to use

Agent with MCP Tools

from agno.agent import Agent
from agno.tools.mcp import MCPTools

mcp_agent = Agent(
    name="MCP Agent",
    model=my_model,
    tools=[
        MCPTools(transport="streamable-http", url="https://mcp.context7.com/mcp")
    ],
    instructions="Use MCP tools to analyze code and extract information."
)

# Agent can now use MCP tools
response = await mcp_agent.run("Analyze this repository...")

Multiple MCP Servers

from agno.tools.mcp import MultiMCPTools

mcp_tools = MultiMCPTools(
    urls=[
        "https://mcp.context7.com/mcp",
        f"https://mcp.firecrawl.dev/{FIRECRAWL_API_KEY}/v2/mcp",
        "https://custom-mcp.example.com/mcp",
    ],
    urls_transports=["streamable-http"],
)

await mcp_tools.connect()

# Use with agent
agent = Agent(
    name="Multi-MCP Agent",
    model=my_model,
    tools=[mcp_tools]
)

Conditional MCP Loading

from tools.tools_factory import get_mcp_tools

# Only load MCP if configured
mcp_tools = get_mcp_tools()
if mcp_tools:
    agent_tools.append(mcp_tools)
    print("MCP tools enabled")
else:
    print("MCP tools not configured")

Environment Configuration

Single MCP Server

# .env file
MCP_URLS="https://mcp.context7.com/mcp"

Multiple MCP Servers

# .env file
MCP_URLS="https://mcp.context7.com/mcp,https://mcp.firecrawl.dev/YOUR_KEY/v2/mcp"

With Firecrawl

# .env file
MCP_URLS="https://mcp.context7.com/mcp"
FIRECRAWL_API_KEY="fc-your-api-key"

Best Practices

  • Use get_mcp_tools() for lazy loading
  • Only connect when MCP tools are actually needed
  • Reduces startup overhead
  • Handles missing configuration gracefully
  • Call setup_mcp() once at startup
  • Handle connection failures gracefully
  • Log connection status for debugging
  • Retry logic is built into MultiMCPTools
  • Check if get_mcp_tools() returns valid instance
  • Wrap setup_mcp() in try-except
  • Provide fallback behavior if MCP unavailable
  • Log warnings, not errors, for missing MCP
  • Store API keys in environment variables
  • Use conditional loading for paid services
  • Construct URLs dynamically with API keys
  • Never hardcode API keys in source code

Common Patterns

Startup Initialization

import asyncio
from tools.tools_factory import setup_mcp

async def initialize_app():
    # Setup MCP connections at startup
    await setup_mcp()
    print("MCP tools ready")

asyncio.run(initialize_app())

Conditional Agent Creation

from tools.tools_factory import get_mcp_tools

agents = [base_agent, code_agent, search_agent]

# Add MCP agent only if configured
mcp_tools = get_mcp_tools()
if mcp_tools:
    mcp_agent = Agent(
        name="MCP Agent",
        model=model,
        tools=[mcp_tools]
    )
    agents.append(mcp_agent)

Dynamic URL Construction

import os
from agno.tools.mcp import MCPTools

# Firecrawl with API key
if FIRECRAWL_API_KEY := os.getenv("FIRECRAWL_API_KEY"):
    firecrawl_url = f"https://mcp.firecrawl.dev/{FIRECRAWL_API_KEY}/v2/mcp"
    firecrawl_mcp = MCPTools(transport="streamable-http", url=firecrawl_url)

Troubleshooting

Connection Failures

import logging
from tools.tools_factory import setup_mcp

logger = logging.getLogger(__name__)

try:
    await setup_mcp()
    logger.info("MCP connected successfully")
except Exception as e:
    logger.warning(f"MCP connection failed: {e}")
    # Continue without MCP tools

Missing Configuration

from tools.tools_factory import get_mcp_tools

mcp_tools = get_mcp_tools()
if not mcp_tools or mcp_tools == []:
    print("Warning: No MCP URLs configured")
    print("Set MCP_URLS environment variable")

Testing MCP Connection

from tools.tools_factory import get_mcp_tools, setup_mcp

mcp_tools = get_mcp_tools()
if mcp_tools:
    print(f"MCP URLs: {mcp_tools.urls}")
    await setup_mcp()
    print("MCP connection successful")
else:
    print("No MCP tools configured")

See Also

E2B Sandbox

Execute code in isolated sandboxes

Web Search

Search the web with Perplexity and Exa

Build docs developers (and LLMs) love