learn-mcp-agent-crew
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@learn-mcp-agent-crewDelegate inspecting all 240 jars to a crew and empty any tampered ones."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
π₯ One Agent That Hires Help
Project #3 built an agent that stops and asks before it does something it can't undo. It's a very good cook, working alone. Give it a job with sixty pieces and it's perfect. Give it four times that and it runs out of room somewhere in the middle, having achieved nothing at all β and having spent 440,000 tokens getting nowhere.
This is the same agent, plus one tool: spawn_agent, whose implementation is the agent loop calling itself.
π΄ Live app: https://learn-mcp-agent-crew.vercel.app
π Live MCP endpoints: /api/pantry (60 jars) and /api/jar β both open, deliberately, and here's why
πͺ #1 the server Β· #2 the loop Β· #3 the gate
The whole delegation model is one file: lib/crew.ts.
π¨ Want to build it yourself, from an empty folder? BUILD_FROM_SCRATCH.md is the developer walkthrough β 12 stages, every command, a checkpoint proving each one, and an appendix of the ten things that actually broke while this was being built. This README teaches you what delegation is and when it's worth it; that one teaches you how to build it.
The headline, before anything else
We measured before we celebrated, and it took two goes to get the measurement right:
one agent | a crew | verdict | |
60 jars | 100% Β· ~99k tokens | 100% Β· ~83k tokens | a wash. Same answer, comparable cost |
240 jars | 0 of 36 found Β· 439k tokens | 36 of 36 Β· 248k tokens | the crew wins β correct and roughly half the price |
Two things worth saying immediately.
The single agent does not fail expensively at 240 jars because it does more work. It fails expensively because it re-sends everything it has read on every iteration. All 240 inspection reports ride along in the conversation, growing each trip around the loop, until it hits the iteration cap with nothing to show. Three workers each carry 80 reports and finish; the orchestrator only ever sees three paragraphs.
And the first version of this table was wrong. It said the crew cost 1.7Γ more at 60 jars and concluded "delegation is pure overhead at this size." That number came from dividing one mode's total token spend by the other's β while the two modes had run different numbers of runs. Corrected, the crew is marginally cheaper even at 60. The mistake, and how to avoid it, is gotcha 9.
So the honest summary is not the tidy "delegation is a trade" line this README originally carried. It's this: for this job shape, delegating never cost more, and past a certain size it was the difference between an answer and 440,000 tokens of nothing. Whether that holds for your job is a question with a script attached β see part 3.
Related MCP server: cn-llm-mcp
Table of contents
Part | What it covers |
The ceiling you can't prompt your way out of | |
A sub-agent is a tool that happens to think | |
The honest question | |
Five agents, one human | |
Five seatbelts, and why five | |
Rewinding a tree | |
Your own past projects are third-party services | |
Run it yourself | |
Where to go next |
Part 1 β The ceiling you can't prompt your way out of
Project #3's agent handles one cookie jar beautifully. So this project gave it a pantry: sixty jars, each one needing its own inspection, one jar per tool call, each report about 250 tokens of seal state, weights, notes and movement log. Nine of them have been tampered with, and the rule for spotting one has two clauses and an exception.
At sixty jars, it just... did it. Perfectly. Four iterations, every jar inspected, all nine found, nothing innocent touched.
So we turned the pantry up to 240. Here is what happened, and it is not a crash:
flowchart TB
START(["π§ 'find every tampered jar<br/>in these 240, empty only those'"]) --> I1
subgraph ONE["π§βπ³ one agent, one context window"]
direction TB
I1["iteration 1<br/><i>list all 240 jars</i>"]
I2["iterations 2-9<br/><i>inspect ~20 jars per turn</i>"]
I3["iteration 10<br/><i>still inspectingβ¦</i>"]
WALL["π MAX_ITERATIONS<br/>180 of 240 inspected<br/><b>0 of 36 found</b><br/><b>440,000 tokens spent</b>"]
I1 --> I2 --> I3 --> WALL
end
WALL --> NOTHING["πΈ nothing emptied.<br/>nothing learned.<br/>full price paid."]
style ONE fill:#450a0a,stroke:#ef4444,color:#fecaca
style WALL fill:#7f1d1d,stroke:#ef4444,stroke-width:3px,color:#fecaca
style NOTHING fill:#450a0a,stroke:#ef4444,color:#fecaca
style START fill:#1e293b,stroke:#38bdf8,color:#f8fafcNotice what kind of failure that is. It isn't wrong, it isn't crashed, and it isn't stuck. It ran out of room β and it charged full price on the way. A failing agent is expensive precisely because it fails slowly.
You cannot fix that with a better prompt, because it isn't a prompt problem. It's a shape problem. One pair of hands, one head, everything in sequence.
The kitchen
A head chef doesn't cook faster. They do something different: they split the work, hand pieces to other cooks, and keep only the plan in their own head instead of every detail. The details live with whoever's doing that piece.
flowchart TB
subgraph MANY["π¨βπ³ the same job, with a crew"]
direction TB
BOSS["π§ orchestrator<br/><i>holds the PLAN,<br/>not the details</i>"]
BOSS --> W1["π©βπ³ jars 1-80"]
BOSS --> W2["π¨βπ³ jars 81-160"]
BOSS --> W3["π§βπ³ jars 161-240"]
W1 --> R["π three short reports<br/><i>conclusions, not transcripts</i>"]
W2 --> R
W3 --> R
R --> BOSS
BOSS --> ASK["βΈ ONE approval,<br/>36 jars listed"]
end
ASK --> WIN["β
36 of 36 found<br/>246,000 tokens<br/><i>cheaper than failing</i>"]
style MANY fill:#052e16,stroke:#4ade80,color:#dcfce7
style BOSS fill:#78350f,stroke:#fbbf24,stroke-width:2px,color:#fef3c7
style ASK fill:#7f1d1d,stroke:#ef4444,stroke-width:2px,color:#fecaca
style WIN fill:#052e16,stroke:#4ade80,stroke-width:2px,color:#dcfce7The real name for this is sub-agents, or multi-agent orchestration. "Head chef and cooks" is the whole idea; everything below is detail.
Why the crew gets further, and it's not the reason people usually give. It isn't that three agents are somehow smarter. It's that each worker gets its own fresh context and its own fresh ten-iteration budget. The advantage is structural, not motivational. Three workers with ten iterations each is thirty iterations of capacity where one agent had ten β and none of them is carrying the other two's jar reports around.
Part 2 β A sub-agent is a tool that happens to think
"Multi-agent orchestration" sounds like a framework: a message bus, a scheduler, a supervisor tree, a state machine. Here is the entire mechanism.
The model gets one extra tool. Its implementation is runAgentLoop β the function that is calling it.
// lib/crew.ts, with the bookkeeping removed
async run(args, context) {
for await (const event of runAgentLoop({
messages: [{ role: "user", content: briefing(args.task) }],
toolbox: context.toolbox, // same kitchen
gate: true, // same handbrake
delegate: false, // β cooks don't hire cooks
budget: context.budget, // same wallet
})) {
context.emit(event); // forward its trace upward
if (event.type === "done") return event.finalText; // its report
}
}That's it. Look at the signature of the loop: it takes messages in, and yields events out. A sub-agent is a thing you give a task to, which then gets on with it and reports back. Those are the same sentence. There was never anything to build here β only something to notice.
And then look at what the orchestrator receives. A worker's entire forty-second investigation of eighty cookie jars arrives in the orchestrator's conversation as one paragraph of text, in an ordinary tool_result block. The orchestrator reads it exactly like it reads a dice roll. It has no idea an agent produced it.
A sub-agent is a tool that happens to think.
The one genuinely new concept: a local tool
Every tool in projects #1β#3 lived on an MCP server at the end of an HTTP connection. spawn_agent cannot β it has to call back into this loop, holding this run's budget and identity, none of which survives a trip over the wire.
So the loop learns about local tools: tools the host implements itself. There is exactly one in this repo, and the distinction is worth keeping sharp, because it's also a security boundary:
an MCP tool | a local tool | |
runs | on a machine you don't control | inside your host |
privileges | whatever that server has | whatever your host has |
how many here | 11 | 1 |
Part 3 β The honest question
Sub-agents are impressive to watch. Three lanes light up, tool calls scroll past, reports come back, and the whole thing feels like an upgrade.
Feeling like an upgrade is not being one. Every worker re-reads the system prompt and the tool definitions, and then there's a summarising trip home on top. The cost of delegation is real, immediate, and paid on every single run. The benefit is conditional on the job being big enough.
So scripts/08-compare.ts runs the same eval cases twice β once with spawn_agent withheld, once with it offered β and prints both numbers. Same model, same prompt, same toolbox, same gate, same seatbelts. One flag differs.
flowchart LR
subgraph SMALL["60 jars β the demo size"]
direction TB
S1["one agent<br/><b>100%</b> Β· ~99k tokens"]
S2["a crew<br/><b>100%</b> Β· ~83k tokens"]
S1 -.->|"same answer,<br/>comparable cost<br/><b>a wash</b>"| S2
end
subgraph BIG["240 jars β past the ceiling"]
direction TB
B1["one agent<br/><b>0 of 36</b> Β· 439k tokens"]
B2["a crew<br/><b>36 of 36</b> Β· 248k tokens"]
B1 -.->|"correct AND<br/><b>0.56x the price</b>"| B2
end
SMALL --> GROW{{"as the job grows,<br/>the lone agent's<br/>context grows with it"}} --> BIG
style SMALL fill:#1e293b,stroke:#64748b,color:#f8fafc
style BIG fill:#052e16,stroke:#4ade80,color:#dcfce7
style GROW fill:#78350f,stroke:#fbbf24,stroke-width:2px,color:#fef3c7
style S1 fill:#1e293b,stroke:#94a3b8,color:#f8fafc
style S2 fill:#052e16,stroke:#4ade80,color:#dcfce7
style B2 fill:#052e16,stroke:#4ade80,color:#dcfce7
style B1 fill:#7f1d1d,stroke:#ef4444,color:#fecacaThree things in that picture are worth saying out loud:
1. At the demo size it's a wash, and that itself is the finding. Both modes score 100%, and the cost difference (0.84Γ, measured on runs both modes actually did) is inside run-to-run variance β one agent came in at 85k, 85k and 99k tokens across runs; the crew at ~74k, ~79k and 83k. The useful conclusion is not "delegate everything." It's that at this size the decision doesn't matter much, which is worth knowing before you spend a week building an orchestrator.
2. Past the ceiling, the crew is cheaper as well as better β and the mechanism is the interesting part. The intuition is that correctness costs more. Here the single agent's 439k tokens bought nothing, because a lone agent re-sends its entire conversation on every iteration, and that conversation contains all 240 inspection reports. Its cost grows with the square of the job while its capacity stays fixed. Three workers each carry 80 reports, finish in three iterations, and hand back a paragraph.
That is the real argument for delegation, and it isn't "more agents are smarter." It's that a single context window makes you pay for everything you have already read, over and over. Splitting the work is how you stop re-reading.
3. The crossover is a property of the job, not of agents. It depends on how big each tool result is, how many calls the job needs, and how tight your iteration cap is. The useful skill isn't "know that delegation is good." It's knowing how to find your own crossover β which is a script you can run, not an opinion you can hold.
How solid are these numbers?
The 60-jar accuracy row is solid. Three attempts per case, both modes, and every case scored 100% in both β 6/6 for one agent, 12/12 for the crew:
case ONE AGENT A CREW
pantry-sweep 100% 3/3 100% 3/3
pantry-no-overkill 100% 3/3 100% 3/3
crew-delegates n/a 100% 3/3
crew-one-approval n/a 100% 3/3Both are perfectly reliable at this size, so the pass rate isn't the interesting number β the cost is. Note also that crew-delegates and crew-one-approval at 3/3 are phase 2 and phase 3 measured rather than asserted: the crew reliably splits the work into disjoint ranges covering everything, and it reliably brings every destructive call to one approval.
The 60-jar cost row is the softest number here, and it's stated as a wash for that reason. It comes from two attempts of the one case both modes run identically, and the spread between individual runs (85kβ99k for one agent, 74kβ83k for the crew) is a meaningful fraction of the gap between them. "Comparable" is as strong a claim as this data supports; "the crew is 16% cheaper" is not.
The 240-jar row is a single attempt per mode, plus a standalone probe that independently agreed with it (single agent 439k tokens finding 0 of 36; crew 248k finding 36 of 36). The direction is not in doubt β one mode finished the job and the other emptied nothing β but treat the magnitudes as one-significant-figure. PANTRY_JARS=240 npm run compare -- --attempts 3 would tighten it, at about a million tokens a go.
β οΈ And one correction worth reading, because the mistake is very easy to make and very hard to see. Earlier versions of this README said the crew cost 1.7Γ at 60 jars, and concluded "delegation is pure overhead at this size." Both the number and the conclusion were wrong.
The number came from dividing one mode's total token spend by the other's β while the two modes had run different numbers of runs.
crew-one-approvalis delegation-only, so a 3-attempt comparison is 3 runs in single mode and 6 in crew mode. Part of what "1.7Γ" measured was "the crew did twice as many runs."Every individual figure in that report was accurate. The division was the lie. The script now tracks tokens per observation group and compares only the groups both modes actually executed, which turns 1.87Γ into 0.84Γ.
Any comparison between two configurations has to check that they did the same work, not just that they both ran. This is an A/B test with unequal traffic, and it is exactly the kind of error that survives review because every number on the page is right.
And the regression net still passes
A regression in project #3's suite would matter more than any of this working:
look-only chain-dice-to-cookies no-tools gate-fires picks-right-cipher reads-history
SCORE: 100% (18/18)Six cases, three attempts each, unchanged from project #3 β despite a third MCP server, four new tools, a recursive loop and a rewritten persistence path.
Part 4 β Five agents, one human
This is the part that stops it being a toy, and it's where the real engineering is.
Project #3's approval model has an assumption buried in it so obviously true that it's invisible: the agent that hit the gate is the agent you're talking to. The loop stops, the request ends, the browser shows a card, you click, a new request restarts that same loop.
Delegation breaks that assumption completely. The agent that hits the gate is:
two levels down,
running inside a
Promise.all,alongside two siblings that are still working,
with nobody talking to it and no browser tab of its own.
And if each worker asked separately, you'd get three cards at three different moments, out of order, each with no context. Five agents each interrupting you is worse than no delegation at all.
So the pause travels up
sequenceDiagram
autonumber
participant H as π§ human
participant O as π§ orchestrator
participant W1 as π· worker 1
participant W2 as π· worker 2
participant DB as π Postgres
H->>O: "find every tampered jar, empty only those"
O->>W1: spawn_agent("jars 1-20")
O->>W2: spawn_agent("jars 21-40")
rect rgba(56, 189, 248, 0.12)
note over W1,W2: both working, in parallel
W1->>W1: inspect 20 jars
W2->>W2: inspect 20 jars
W1-->>O: β
report: "3 tampered"
end
rect rgba(239, 68, 68, 0.14)
note over W2: worker 2 wants something irreversible
W2->>W2: empty_jar { id: 38 }
W2--xO: βΈ STOPPED β needs a human
end
rect rgba(251, 191, 36, 0.14)
note over O,DB: freeze the WHOLE tree
O->>DB: worker 1's finished report β partial_results
O->>DB: worker 2's entire mind β paused_children
O->>DB: own state β messages
end
O-->>H: βΈ ONE card: "worker 2 (jars 21-40) wants to<br/>empty jar 38 β 78g heavy, no AUTHORIZED note"
note over H,O: the HTTP request has ENDED.<br/>nothing is running. close the laptop.
H->>DB: approve (a brand-new request, minutes later)
DB-->>W2: rebuilt from jsonb, told "yes"
W2->>W2: empties jar 38, carries on
W2-->>O: β
report: "3 tampered"
note over O: worker 1 is NOT re-run β<br/>its report came back from partial_results
O-->>H: final answerThree details in there are the whole of phase 3, and each one is a bug if you skip it:
The detail | What breaks without it |
| The card says "approve |
| Clicking Approve re-runs the two workers that had already finished. You pay for them twice, they may answer differently the second time, and any side effect happens again. |
| The stopped worker's entire conversation vanishes when the HTTP request ends, and there is nothing left to say yes to. |
And the thing that makes all of it work is the same thing that made project #3's pause work: the agent's whole state is its messages array. Persisting three agents is persisting three arrays. There is no continuation, no serialized generator, no coroutine library β the freeze is a return and the thaw is a function call with a bigger array.
The screen
That single approval standing in front of three agents' worth of work is the picture this project is aiming at:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βΈ ONE APPROVAL, 9 DESTRUCTIVE CALL(S)
9 of them came from 3 sub-agent(s) that are frozen mid-task.
Frozen sub-agents: "jars 1-20", "jars 21-40", "jars 41-60"
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βΈ pantry__empty_jar {"id":46,"reason":"Seal broken (lid gasket β¦"}
asked by : sub-agent "jars 41-60"
because : Seal broken (lid gasket displaced) - not merely scuffed,
no AUTHORIZED note present.
host rule: empty_jar permanently destroys every cookie in that jar.Nine calls. Three frozen agents. One decision. And when we approved eight and denied the ninth, the worker that got the "no" read it as an ordinary tool result, adapted, and reported honestly β and the orchestrator surfaced it to the human rather than quietly dropping it:
One jar flagged but NOT emptied: Jar 59 β it does meet the tampering criteria, but the sub-agent's attempt to empty it was declined. This one still needs your attention.
Verified against the database, not against the model's summary: 8 jars emptied, jar 59 untouched, zero false positives.
Part 5 β Five seatbelts, and why five
Project #3 had seatbelts and they were all correct. Every one of them was scoped to one loop.
Recursion multiplies per-loop limits instead of adding them. An orchestrator allowed ten iterations that hires three workers allowed ten each has quietly authorised forty API calls against conversations that keep growing.
Seatbelt | Kind of limit | From | What it catches that the others don't |
| per agent | #2 | One agent spinning. Kept at ten on purpose β raising it would have hidden the effect being measured. |
| rate | new | Three-wide is a bill times three, not times sixty. The model may ask for more; they queue. |
| quantity | new | An orchestrator that wants one agent per jar, hiring sixty of them three at a time, politely, within the concurrency cap. |
| money | new | The only check that sees the whole bill. Shared by reference; workers spend from the boss's wallet. |
no | structural | new | Infinite recursion. |
That last row is the one worth stealing. There is no depth counter here. A sub-agent is started with delegate: false, so spawn_agent is not in its tool list at all. It cannot recurse for the same reason you cannot dial a phone number that was never printed.
Prefer a design where the bad thing is unreachable over a check that catches it. A counter can be off by one. An absence cannot.
Part 6 β Rewinding a tree
Nested replay was the stretch goal. It cost one extra select and one expandable row.
Not because it was over-estimated β because of a decision in lib/run-driver.ts: a sub-agent gets a real row in runs, with a parent_run_id, and its own stream of trace_events under its own sequence numbers.
It isn't a special kind of thing needing special handling. It's a run with a parent. So it already had a status, a stop reason, an iteration count and a token bill, for the same reason every other run does β and replaying one is GET /api/runs?id=<childRunId>, the same handler, recursing exactly the way the loop does.
flowchart TB
subgraph DB["π one runs table"]
direction TB
P["run Β· parent_run_id = null Β· depth 0<br/><i>'find every tampered jar'</i><br/>13,303 tokens"]
C1["run Β· parent_run_id = P Β· depth 1<br/><i>'jars 1-20'</i> Β· 51 trace rows"]
C2["run Β· parent_run_id = P Β· depth 1<br/><i>'jars 21-40'</i> Β· 51 trace rows"]
C3["run Β· parent_run_id = P Β· depth 1<br/><i>'jars 41-60'</i> Β· 51 trace rows"]
P --> C1
P --> C2
P --> C3
end
DB --> Q["<b>one nullable self-reference</b><br/>turns a flat list of runs<br/>into a tree"]
style DB fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe
style P fill:#78350f,stroke:#fbbf24,stroke-width:2px,color:#fef3c7
style Q fill:#052e16,stroke:#4ade80,color:#dcfce7The general shape is worth stealing too: when the new feature turns out to be an instance of the old one, you get the tooling for free.
One deliberate choice in the UI: each worker's trace is collapsed by default, and lazy-loaded. Delegation exists so the details of twenty jar inspections don't have to be in anybody's head β not the orchestrator's, and not yours. The summary is what you normally need. The full trace is there for the ten percent of the time when "trust me" isn't good enough.
Part 7 β Your own past projects are third-party services
Before designing the toolbox, we curled all three previous projects. Five minutes:
https://learn-mcp-5-year-old.vercel.app/api/mcp -> 200 open
https://learn-mcp-agent-loop.vercel.app/api/toolbox -> 401 locked
https://learn-mcp-agent-guard.vercel.app/api/jar -> 401 lockedTwo of three locked. Project #2's stage 9 added withMcpAuth and set a shared token; project #3 did the same. Both work exactly as designed. This project just isn't holding the token.
This has now bitten three projects in a row, and project #3 discovered it mid-build after having architected around a server it couldn't reach.
Your own past projects are third-party services. Their auth, uptime and rate limits constrain you exactly as a stranger's would. The
Promise.allSettledinbuildToolboxis what keeps that a design decision instead of an outage β one server being asleep degrades the toolbox instead of killing the host.
So project #4's servers ship unlocked, on purpose, and that's a deliberate reversal rather than an oversight. A fresh clone works with zero setup, and project #5 won't have to write this section again. MCP_SHARED_TOKEN still locks them if you set it β the mechanism is intact, the default is flipped.
Part 8 β Run it yourself
git clone https://github.com/ketankshukla/learn-mcp-agent-crew.git
cd learn-mcp-agent-crew
npm install
cp .env.example .env.local # add ANTHROPIC_API_KEY, then a Neon DATABASE_URL
npm run db:init # creates the schema and stocks the pantry
npm run devThen, in a second terminal, the checkpoints in order:
npm run mcp:list # transport β 3 servers, 11 tools, no AI
npm run mcp:translate # schemas + the gate's rules, no AI
npm run agent # the loop, one agent
npm run approval # THE GATE β approve and deny
npm run evals # project #3's six cases, as a regression net
npm run crew # THE CREW β workers hit the gate, the pause bubbles up
npm run compare # delegate off vs on: pass rate AND token cost
npm run replay # rewind, including into each sub-agentThe interesting ones:
npm run crew -- --deny-all # say no to everything, watch them adapt
npm run crew -- --single # same job, one agent, no delegation
npm run compare -- --attempts 5 # tighten the numbers in part 3And to see the ceiling for yourself β all three need the same value, because the MCP server builds its input schema at startup:
PANTRY_JARS=240 npm run db:init
PANTRY_JARS=240 npm run dev
PANTRY_JARS=240 npm run compareThe map
flowchart TB
subgraph LIB["π lib/ β the brain"]
direction TB
L0["<b>crew.ts</b><br/><i>spawn_agent + approval bubbling</i>"]
L1["agent-loop.ts<br/><i>the loop, now recursive</i>"]
L2["run-driver.ts<br/><i>the ONE drive-and-persist path</i>"]
L3["approval.ts<br/><i>what counts as dangerous</i>"]
L4["evals.ts<br/><i>the report card</i>"]
L5["pantry.ts<br/><i>60 jars + the answer key</i>"]
L6["db.ts / runs.ts<br/><i>the notebook, now a tree</i>"]
L7["toolbox.ts / mcp-client.ts<br/><i>N servers, one curated shelf</i>"]
end
subgraph APP["π app/ β the face"]
direction TB
A1["api/chat Β· api/resume<br/><i>start, and un-freeze</i>"]
A2["api/pantry<br/><i>60 jars, 1 per call</i>"]
A3["Chat.tsx<br/><i>lanes + the one card</i>"]
A4["Replay.tsx<br/><i>rewind, nested</i>"]
end
L7 --> L1
L3 --> L1
L1 --> L0
L0 --> L2
L2 --> A1
L2 --> L6
L6 --> A4
A1 --> A3
L5 --> A2
L7 -.->|"tools/call"| A2
L1 --> L4
style L0 fill:#7f1d1d,stroke:#ef4444,stroke-width:3px,color:#fecaca
style L1 fill:#78350f,stroke:#fbbf24,stroke-width:2px,color:#fef3c7
style L2 fill:#78350f,stroke:#fbbf24,color:#fef3c7
style A1 fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe
style A2 fill:#0c4a6e,stroke:#38bdf8,color:#e0f2fe
style LIB fill:#1e293b,stroke:#475569,color:#f8fafc
style APP fill:#1e293b,stroke:#475569,color:#f8fafcPart 9 β Where to go next
Upgrade | Why it matters |
Find your own crossover |
|
Let workers report structurally | They return prose today, which the orchestrator has to re-read. A schema would compress further β and would be measurable with the suite you already have. |
Approve from somewhere else | The pause is rows keyed by id. Nothing says the approver has to be in the same browser. |
Deeper trees | Two levels is a deliberate structural choice. Three needs a real depth counter, and everything in part 5 gets harder. |
A cheaper model for workers | One string, per agent. The orchestrator is doing judgement; the workers are doing reading. Score it before believing it. |
NEXT_STEP.md argues for what project #5 should be β short version: four projects into a series named after the protocol, we have used one of MCP's five capabilities. The unused one lets a server ask your host to run a model call, on your key. That needs a gate, and project #3 already taught you how to build one.
β It got built: project #5 β the ledger. All five capabilities are now used. Two findings from it point back at this repo: the serverβclient push that every sampling tutorial shows cannot work on a serverless host (there is no connection to push down), and this project's own gotcha 9 was still live in
scripts/08-compare.tsβusageByGroupwas built and never wired to the headline ratio, so it still divided one mode's runs by another's. Fixed there; 2.01Γ became 1.08Γ, which agrees with the corrected table at the top of this README.
This is part of a series
flowchart LR
P1["πͺ #1<br/>learn-mcp-5-year-old<br/><i>an MCP SERVER</i><br/>offers tools, waits"]
P2["π #2<br/>learn-mcp-agent-loop<br/><i>an MCP HOST</i><br/>picks tools, runs the loop"]
P3["β #3<br/>learn-mcp-agent-guard<br/><i>the agent that ASKS FIRST</i><br/>gates, memory, evals"]
P4["π₯ <b>#4 β you are here</b><br/>learn-mcp-agent-crew<br/><i>one agent that HIRES HELP</i><br/>sub-agents, one queue"]
P5["πΈ #5<br/>learn-mcp-agent-ledger<br/><i>the host that OWNS THE WALLET</i><br/>sampling, a spend gate, a ledger"]
P1 --> P2 --> P3 --> P4 --> P5
style P1 fill:#1e293b,stroke:#38bdf8,color:#f8fafc
style P2 fill:#1e293b,stroke:#38bdf8,color:#f8fafc
style P3 fill:#1e293b,stroke:#38bdf8,color:#f8fafc
style P4 fill:#78350f,stroke:#fbbf24,stroke-width:3px,color:#fef3c7
style P5 fill:#052e16,stroke:#4ade80,color:#dcfce7What it builds | Start here if⦠| |
An MCP server | MCP itself is new to you | |
An MCP host that owns the loop | You want to know what Claude Desktop was actually doing | |
Approval gates, Postgres, evals, replay | You want to give an agent a dangerous tool and sleep at night | |
#4 (you are here) | Sub-agents, one approval queue, cost measurement | Your agent keeps running out of room on big jobs |
Sampling, a spend gate, a ledger | Something you connected can spend your money |
Each one is a sequel that reuses the last one's code. This project copies project #3's lib/ wholesale β the loop, the gate, the notebook, the report card β and makes the loop recursive.
The three documents
For | Answers | |
README.md (you are here) | Understanding | What is a sub-agent? When is delegating worth it? How does one human approve five agents? |
Doing | Which commands, in what order, and what breaks along the way? | |
Deciding | What's still missing, and what should project #5 be? β (answered, and built: MCP's other four capabilities, as |
Stack
Next.js 16 (App Router, Turbopack) + React 19 + Tailwind v4
@anthropic-ai/sdkβclaude-sonnet-5, adaptive thinking, twocache_controlblocks so both modes share one cached prefix@neondatabase/serverlessβ Postgres over HTTP, because serverless has no connection poolmcp-handler+@modelcontextprotocol/serverβ the pantry and the jarThe MCP client is hand-written in
lib/mcp-client.tsβ inherited from project #2, because the protocol is just JSON
β project #3: the gate Β· How this was built β Β· The crew itself β
A sub-agent is a tool that happens to think.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseAqualityCmaintenanceLocal MCP server that enables delegating low-risk tasks like summarization or code patches to a low-cost model, with the main agent reviewing results.2
- Alicense-qualityAmaintenanceMCP server that enables AI agents to run a deterministic orchestration loop with decomposition, subagent execution, and review feedback across multiple LLM backends.53MIT
- AlicenseAqualityBmaintenanceMCP server that enables a coordinator AI agent to spawn, control, and supervise local coding agents with interactive gating for high-risk operations.10381MIT
Related MCP Connectors
Agent Delegation MCP Server by MEOK AI Labs
Agent-native collaboration network: orchestrate a team of long-running agents from any MCP client.
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ketankshukla/learn-mcp-agent-crew'
If you have feedback or need assistance with the MCP directory API, please join our Discord server