Skip to content

Why Can't AI Sub-Agents Use MCP? The Workaround Explained

I spent hours debugging why my sub-agents couldn’t access MCP tools. The main orchestrator worked fine, but spawned agents kept failing. Turns out, this is by design.

The Problem

MCP (Model Context Protocol) connections live at the process level. When you initialize an MCP client, that connection belongs to your main process. Period.

When your main agent spawns sub-agents, they don’t inherit MCP connections. Each sub-agent runs in its own execution context. No MCP access.

This hit me when building a multi-agent system:

Main Agent (has MCP)
└── Spawns Sub-Agent A (NO MCP)
└── Spawns Sub-Agent B (NO MCP)

I tried passing MCP clients to sub-agents. Didn’t work. The connection state doesn’t transfer.

Why This Happens

Three reasons:

  1. Connection isolation - Each MCP connection has its own state, auth, and session data
  2. Security boundaries - MCP servers often have file system and network permissions
  3. Framework design - Agent frameworks spawn sub-agents as independent contexts

The Workaround: Dual-Interface Pattern

I redesigned my tools to have two interfaces. Both hit the same backend:

┌─────────────────────────────────────────────────────────────┐
│ Your Backend Service │
│ (filesystem, web scraper, database, etc.) │
└─────────────────┬───────────────────────┬───────────────────┘
│ │
┌─────────▼─────────┐ ┌────────▼────────┐
│ MCP Interface │ │ CLI/API Interface │
│ (for orchestrator) │ │ (for sub-agents) │
└─────────┬─────────┘ └────────┬────────┘
│ │
┌─────────▼─────────┐ ┌────────▼────────┐
│ Main Agent │ │ Sub-Agents │
│ (MCP Client) │ │ (CLI/API calls)│
└───────────────────┘ └──────────────────┘

Implementation

First, build a shared backend. This contains all your actual logic:

backend_service.py
class WebScraperBackend:
"""Core scraping logic used by both MCP and CLI interfaces."""
def scrape_url(self, url: str, selectors: list[str]) -> dict:
return {
"url": url,
"content": self._fetch_and_parse(url, selectors)
}

Then create an MCP interface for your main orchestrator:

mcp_server.py
from mcp.server import Server
from backend_service import WebScraperBackend
backend = WebScraperBackend()
server = Server("web-scraper")
@server.tool("scrape")
async def scrape_tool(url: str, selectors: list[str]) -> dict:
return backend.scrape_url(url, selectors)

Now add a CLI interface for sub-agents:

cli_interface.py
import click
import json
from backend_service import WebScraperBackend
backend = WebScraperBackend()
@click.command()
@click.option('--url', required=True)
@click.option('--selectors', multiple=True)
def scrape(url, selectors):
result = backend.scrape_url(url, list(selectors))
click.echo(json.dumps(result))
if __name__ == '__main__':
scrape()

Unified Wrapper

I wrapped both interfaces so my code doesn’t care which context it runs in:

tool_wrapper.py
import subprocess
import json
from mcp import Client
class ToolAccess:
"""Unified tool access for both main agent and sub-agents."""
def __init__(self, use_mcp: bool = True):
self.use_mcp = use_mcp
if use_mcp:
self.mcp_client = Client("tool-server")
def scrape(self, url: str, selectors: list[str]) -> dict:
if self.use_mcp:
# Main orchestrator: use MCP directly
return self.mcp_client.call_tool("scrape", {
"url": url,
"selectors": selectors
})
else:
# Sub-agent: call CLI
result = subprocess.run(
["python", "cli_interface.py", "scrape",
"--url", url, "--selectors", *selectors],
capture_output=True, text=True
)
return json.loads(result.stdout)

Usage is simple:

# Main agent
tool = ToolAccess(use_mcp=True)
result = tool.scrape("https://example.com", ["h1", "p"])
# Sub-agent
tool = ToolAccess(use_mcp=False)
result = tool.scrape("https://example.com", ["h1", "p"])

Key Lessons

  1. Design dual interfaces from day one. Retrofitting is painful
  2. Keep feature parity between MCP and CLI interfaces
  3. Test both paths - they can drift apart
  4. Document which context uses which interface

This pattern added some complexity upfront. But it saved me from a complete rewrite later.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments