Show HN: Sub-Agent MCP: LLM delegation and sub-agent orchestration via MCP A developer released Sub-Agent MCP, a production-ready Python MCP server that enables parent LLMs to delegate tasks to specialized sub-agents defined in YAML configuration files. The server registers each sub-agent as an MCP tool with its own LLM, system prompt, and optional downstream tool servers, allowing parent models to call agents like "researcher" directly without context bloat. The tool aims to streamline multi-agent orchestration for AI coding assistants like Cursor by keeping parent models lightweight while giving each sub-agent role-specific tools and configurations. Production-ready Python MCP server for LLM delegation and sub-agent orchestration . A parent LLM for example, Cursor’s agent connects to this server and delegates work by calling a tool named after each agent defined in YAML for example, researcher . Each sub-agent is defined in YAML with its own LLM, system prompt, and optional downstream MCP tool servers. What is this? what-is-this Why use it? why-use-it Features features Prerequisites prerequisites Quick start quick-start Verify installation verify-installation Connect Cursor connect-cursor How it works how-it-works Agent configuration agent-configuration MCP tools reference mcp-tools-reference Environment variables environment-variables Project layout project-layout Development development Docker image and releases docker-image-and-releases Troubleshooting troubleshooting License license Sub-Agent MCP sits between a parent LLM and one or more specialized sub-agents : - The parent connects to this server over Streamable HTTP at /mcp . - At startup, each agent in agents.yaml is registered as an MCP tool named by its id . - The parent calls that tool with a prompt ; the server runs the sub-agent and returns the final response. Each sub-agent is a LangChain https://github.com/langchain-ai/langchain agent with its own OpenAI-compatible LLM, system prompt, and optional connections to other MCP servers filesystem, search, your own tools, and so on . Tool access can be restricted per agent with an allowlist. sequenceDiagram participant Parent as Parent LLM participant SAMCP as Sub Agent MCP participant Agent as LangChain sub agent participant LLM as OpenAI compatible LLM participant Tools as Downstream MCP servers Parent- SAMCP: researcher prompt SAMCP- Agent: build agent + downstream tools Agent- LLM: reasoning loop Agent- Tools: MCP tool calls Tools-- Agent: tool results LLM-- Agent: final answer Agent-- SAMCP: response text SAMCP-- Parent: {"response": "..."} This is different from giving one agent every tool in the workspace: the parent stays lightweight, roles stay explicit, and each sub-agent only sees the MCP servers and tools you configure for it. Delegation without context bloat — The parent calls agent tools directly; it does not need every downstream tool schema in its own context. Per-role configuration — Different id s can use different models, prompts, MCP servers, and tool allowlists. Production-oriented — Pydantic-validated YAML, structured logging, Docker health checks, CI, and GHCR images on release tags. OpenAI-compatible providers — Point llm.base uri at OpenAI, Azure, Ollama, LM Studio, or any compatible API. Transport - Streamable HTTP only streamable-http ; no stdio or legacy SSE. Configuration - YAML agent definitions with strict Pydantic validation. - Environment substitution: ${VAR} and ${VAR:-default} . Runtime - LangChain 1.x create agent with OpenAI-compatible chat models. - Per-agent MCP connections via langchain-mcp-adapters , with optional server.tool allowlists. Security - Agent tool descriptions never expose API keys. Operations - Structured logging structlog https://www.structlog.org/ . - Docker image with health check; GitHub Actions CI. - Container images published to GHCR on version tags v0.x.y . MCP tools exposed by this server Each agent in agents.yaml is registered as a tool named by its id for example, researcher . Each tool accepts a single prompt argument and runs that sub-agent. | Requirement | Notes | |---|---| | Python 3.10+ | CI uses 3.12; requires-python = 3.10 in pyproject.toml | | API key for your LLM provider | Default example uses OPENAI API KEY | pip | Choose one path. Docker Compose is the fastest way to run the full demo stack server + mock tool servers . export OPENAI API KEY=sk-... docker compose up --build | Service | Port | Endpoint | |---|---|---| | Sub-Agent MCP | 8000 | http://localhost:8000/mcp | | Mock filesystem MCP | 8001 | http://localhost:8001/mcp | | Mock search MCP | 8002 | http://localhost:8002/mcp | The bundled config/agents.yaml /stormaref/Sub-Agent-MCP/blob/main/config/agents.yaml uses Docker network hostnames filesystem-mcp , search-mcp , which resolve correctly inside Compose. uv sync --dev or: pip install -e ". dev " cp config/agents.example.yaml config/agents.yaml if you don't have config/agents.yaml yet export OPENAI API KEY=sk-... python -m sub agent mcp.main or: uv run sub-agent-mcp Server listens at http://0.0.0.0:8000/mcp reachable as http://localhost:8000/mcp from your machine . Important: The example config points MCP servers at Docker service names. For local Python you must either run the mock servers and use localhost URLs see table below , or run only the mocks via Compose: Terminal 1: mock tool servers only docker compose up filesystem-mcp search-mcp Terminal 2: sub-agent server after editing agents.yaml URLs to localhost export OPENAI API KEY=sk-... python -m sub agent mcp.main | Environment | filesystem MCP URL | search MCP URL | |---|---|---| | Docker Compose network | http://filesystem-mcp:8001/mcp | http://search-mcp:8002/mcp | | Host machine / local Python | http://localhost:8001/mcp | http://localhost:8002/mcp | Images are published on git tags matching v for example v0.1.2 , not on every push to main . docker run -p 8000:8000 \ -e OPENAI API KEY=sk-... \ -v "$ pwd /config/agents.yaml:/app/config/agents.yaml:ro" \ ghcr.io/stormaref/sub-agent-mcp:latest Mount your own agents.yaml and ensure MCP url values are reachable from inside the container use host networking, service names, or host.docker.internal as appropriate . OpenAPI document generated from registered MCP tools : curl -s http://localhost:8000/mcp/openapi.json | head Open WebUI OpenAPI tool server — Register as OpenAPI not MCP : | Field | Value | |---|---| URL | http://localhost:8000/mcp or http://mcp.example.com/sub-agent/mcp behind a proxy | OpenAPI path | openapi.json default | Open WebUI appends tool paths from the spec for example /tools/researcher to that URL: curl -s -X POST http://localhost:8000/mcp/tools/researcher \ -H 'Content-Type: application/json' \ -d '{"prompt":"Summarize what tools you have access to."}' Docker health — The image health check probes http://127.0.0.1:8000/mcp . Functional check — After connecting Cursor below , ask the parent agent to call the researcher tool with a short prompt. A successful run returns { "response": "..." } . - Open Cursor Settings → MCP or edit your MCP config JSON . - Add the server: { "mcpServers": { "sub-agent-mcp": { "url": "http://localhost:8000/mcp" } } } - Ensure the Sub-Agent MCP process is running and Cursor can reach localhost:8000 . On WSL or Docker Desktop, confirm port forwarding if the server runs in a VM or container. - Reload MCP tools. You should see one tool per agent for example, . researcher Example delegation prompt for the parent agent: Call the researcher tool with prompt: "Summarize what tools you have access to." Other MCP clients — Any client that supports Streamable HTTP can connect to http://