The Draw Tree Protocol
A wire protocol for AI-native equity research. Defines how a hypothesis tree is structured, how it is co-designed step by step with the user, how it is researched in a single batched job, and how it is monitored week after week. Any MCP-compatible AI client — ChatGPT, Claude.ai, Perplexity, Claude Code, Codex, Claude Desktop — can drive it.
0 · Protocol vs MCP — two different layers
A common point of confusion: MCP (Model Context Protocol) is a generic transport spec that lets any AI client talk to any tool server. It defines how to tools/list, how to call a tool, how OAuth works on the wire — it knows nothing about what the server actually does. The Draw Tree Protocol is a domain contract: what a valid investment hypothesis tree looks like, what verdict vocabulary it uses, how branch weights aggregate, what valuation methods are accepted.
| Layer | What it defines | Analogy |
|---|---|---|
| MCP | Transport, discovery, auth. | HTTP |
| Draw Tree Protocol | Tree schema, verdict vocab, aggregation rules, validation invariants. | OpenAPI schema |
You could in principle implement the Draw Tree Protocol over plain REST or gRPC and skip MCP entirely. You could equally host a completely different research methodology over MCP. Today we ship the protocol on MCP because that's the transport AI clients understand natively.
Why this protocol is open
A tool that claims to bring scientific method to investment research cannot itself be a black box. The whole point of scientific method, since Boyle and Hooke, has been that the procedure is public — the conclusions can be argued with, but only because the procedure can be inspected, repeated, and challenged by anyone.
So the Draw Tree Protocol — the tree schema, the verdict vocabulary, the aggregation rules, the validation invariants, the SKILL.md contract that governs how AI clients behave — belongs to whoever wants to use it. Anyone can read this page, implement a server, and produce trees that interoperate with the ones on drawtree.capital.
The full normative specification lives at github.com/Draw-Tree/drawtree-protocol. A reference Python validator (pip install drawtree-validator) is at github.com/Draw-Tree/drawtree-validator. The AI-client contract (SKILL.md / AGENTS.md / system prompt) is at github.com/Draw-Tree/drawtree-skill. All three are MIT-licensed.
If drawtree.capital ever disappears, the trees you have committed remain readable against this spec. Another team can re-implement the server without our cooperation. That is not a contingency plan — it is the property a protocol has to have for it to deserve being called a protocol.
1 · The five-layer tree
Every Draw Tree decomposes a single investment thesis into five strictly-ordered layers. Each layer answers one question and produces artefacts the next layer depends on.
Narrative → What does the market believe? What do you disagree with? H-0 → One falsifiable sentence, with a time window. Branches → 3-4 MECE branches, each bound to one of 164 frameworks. Leaves → 2-4 sub-hypotheses per branch. Each has a kill condition. Scenarios → Bull / Base / Bear. Peer group + multiple → implied price.
- Narrative requires a written statement of the current market consensus plus the specific claim you are contesting. A tree whose thesis agrees with consensus has no edge and is flagged before commit.
- H-0 must be a single sentence of the form “within X months, Y will (or will not) happen”. Generic sentiment statements are rejected at validation.
- Branches are MECE-checked and each binds to one of 164 indexed strategy frameworks (Porter Five Forces, Wide Moat, Unit Economics, Demand-Side Economics, …). The chosen framework drives what the Phase 2 research job actually searches for.
- Leaves are the unit of falsifiability. Every leaf must declare its kill condition — typed as observable, directional, or mechanism. Leaves without a kill condition fail validation and the tree cannot be committed.
- Scenarios use Peer Group Valuation: each scenario binds a peer set + a multiple method (EV/Sales, EV/EBITDA, P/E, P/FCF, SOTP). The server computes implied per-share value and its distance from the current price. DCF, reverse DCF, and DDM are not supported by design — they encode too much noise as precision.
2 · The six-state verdict vocabulary
Every leaf, every branch, and the root H-0 carries a verdict on a six-state monotone scale. Aggregation rolls leaves up to branches (Fibonacci-default weights, overridable) and branches up to H-0 conviction in [0, 1].
| Verdict | Score | Meaning |
|---|---|---|
| validated | 1.00 | Evidence strongly confirms the hypothesis. |
| trending_positive | 0.75 | Directional support; threshold not yet hit. |
| inconclusive | 0.50 | Data insufficient or ambiguous. Default for un-researched leaves. |
| trending_negative | 0.25 | Directional pressure against the hypothesis. |
| approaching_falsification | 0.10 | One more disconfirming data point flips it. |
| falsified | 0.00 | Hypothesis disproven. |
The expected return on a tree is conviction-weighted: Σ (scenario_prob × scenario_value_distance). The Phase 2 research job and the weekly cron both update verdicts using the same vocabulary, so a tree's history is always read on one consistent scale.
3 · Phase 1 — framework design (free)
Phase 1 is the protocol's most-enforced rule: the AI client must never chain stages. After each tool call it presents the result back to the user in plain language and asks whether to refine or proceed. save_* is only called after explicit user confirmation.
start_draft(ticker)
→ confirm company name
frame_narrative(draft_id)
→ present market-narrative archaeology
→ user confirms
→ save_narrative
frame_h0(draft_id)
→ present H-0 sentence + framework_from / framework_to + window
→ user confirms
→ save_h0
design_branches(draft_id, target_branch_count=4)
→ read 164-framework one-liner index + top-15 scored shortlist
→ fetch_framework_details(names=[...6-12 candidates...]) (free, batched)
→ walk user through 3-4 MECE branches
→ user confirms
→ save_branches
design_leaves(branch_id='A') ┐
→ render diagnostic axes │ repeat per branch
→ user confirms │ until is_last_branch
→ propose 2-4 leaves + kill cond. │
→ save_leaves({A: [...]}) ┘
design_scenarios → save_scenarios
preview_tree → confirm_frameworkThe protocol exposes a separate fetch_framework_details tool because the framework-shortlisting step requires the AI to read multiple candidates' full pitfalls + diagnostic axes before recommending one. Loading those is free and does not advance the draft stage.
4 · Phase 2 — deep research (one button, one bundle)
Once confirm_framework is called, the server holds a single flat 50-credit Phase 2 bundle and kicks off a deep-research job covering every narrative pillar and every leaf's falsification metric in one shot.
confirm_framework(draft_id) → 50 cr held as a single bundle (auto-confirms in 24h) research_phase2(draft_id, model='pro') → server starts a long-running research job → returns immediately with poll_after_seconds research_phase2_status(draft_id) (poll every 30-60s) → status: queued | running | ingested | failed → typical wall time: 60-180s compute_scenarios(draft_id) → server fetches live peer prices → computes Bull / Base / Bear implied per-share values commit_draft_tree(draft_id, visibility='private') → publishes the tree, locks a version_hash summarize_tree(tree_id) → renders the final 10-section report → asks once: "Set up weekly monitoring?"
Splitting the work this way is deliberate. The design of a research framework wants to be slow, interactive, and reversible. The execution of that framework — the fact-gathering — wants to be fast, parallel, and batched. Mixing the two produces the worst of both worlds.
5 · Weekly monitoring
After a tree is committed the user is asked once whether to enable weekly monitoring. The server then provisions a per-ticker GitHub Actions cron that runs every Saturday morning HKT and:
- Pulls the past week's news from public sources, deduplicated and quality-filtered by source.
- Attributes each article to specific branches and leaves it affects.
- Runs a two-pass hybrid verdict engine (evidence ingestion, then verdict re-evaluation), updating every leaf on the six-state vocabulary above.
- Writes the new evidence and verdict changes back as a new version of the same tree — history is append-only.
- Posts a structured update to the user's configured Slack channel (or email).
Monitoring is prepaid at 5 credits per week per tree. pause_monitoring, resume_monitoring, and cancel_monitoring are free; cancelling refunds unused weeks pro-rata.
6 · The MCP tool surface
The MCP server exposes 38 tools, grouped by phase. Free tools cover validation, reading, listing, and balance. Charged tools are explicitly labelled and use a hold-then-confirm credit model that auto-confirms in 24 hours (refundable at /account).
- start_draft
- frame_narrative / save_narrative
- frame_h0 / save_h0
- design_branches / save_branches
- fetch_framework_details
- design_leaves / save_leaves
- design_scenarios / save_scenarios
- preview_tree
- validate_tree / aggregate_tree
- commit_tree / commit_draft_tree
- read_tree / read_tree_by_ticker
- read_branch / read_history
- summarize_tree / read_committed_report
- my_workspace / list_my_drafts / list_my_trees
- suggest_framework
- set_report_language / set_phase2_notification
- propose_edit / apply_edit / abandon_draft
- pause_monitoring / resume_monitoring / cancel_monitoring
- balance / credit_balance
- refund_charge
- search / fetch (ChatGPT-compat)
- confirm_framework (50 cr bundle)
- research_phase2 (bundled)
- research_phase2_status (free polling)
- compute_scenarios (bundled)
- enrich_narrative_data (bundled)
- enrich_leaf_data (bundled)
- phase2_run_all (bundled)
- enrich_branches (per branch)
- register_narrative
- suggest_falsification
- derive_scenario_values
- auto_evidence (2 cr)
- append_evidence
- external_search (1 cr)
- subscribe_alerts (per alert)
- setup_monitoring (5 cr/week)
- confirm_charge (early confirm)
Polling tools like research_phase2_status never charge. Read-only tools never charge. The AI client is instructed by the skill never to mention credit costs to the user — they can check their own balance at /account.
7 · Architecture
Draw Tree runs as four independent services. The MCP server owns the protocol surface; the API owns all state; the dashboard renders the same data the AI sees; the cron runs background research without going through MCP transport.
┌──────────────┐ MCP (Streamable HTTP) ┌──────────────────┐
│ AI client │ ──────────────────────────▶ │ drawtree-mcp │
│ ChatGPT │ ◀────────────────────────── │ (FastMCP, OAuth │
│ Claude.ai │ │ 2.1 + PKCE, │
│ Perplexity │ │ dt_ Bearer) │
│ Claude Code │ └────────┬─────────┘
│ Codex CLI │ │ REST
│ Claude Desk. │ ▼
└──────────────┘ ┌──────────────────┐
│ drawtree-api │
│ (FastAPI + Neon │
│ Postgres) │
└────────┬─────────┘
┌──────────────────────┼──────────────────────┐
▼ ▼ ▼
┌────────────────┐ ┌──────────────────┐ ┌──────────────┐
│ drawtree- │ │ GitHub Actions │ │ deep-research│
│ dashboard │ │ weekly cron │ │ + verdict │
│ (Next.js, │ │ (one per tree) │ │ judge │
│ drawtree. │ └──────────────────┘ └──────────────┘
│ capital) │
└────────────────┘Why split MCP from API
drawtree-mcponly handles protocol: validation, aggregation, tool routing, OAuth discovery. It is stateless and trivially redeployable.drawtree-apiowns all state: trees, drafts, charges, subscriptions, monitoring jobs. Replacing the MCP transport does not touch user data.- The dashboard hits the same API. What you see at
drawtree.capitaland what the AI sees through MCP are always one source of truth. - The weekly cron talks to the API directly, not through MCP — background jobs should not be constrained by the transport limits of a synchronous tool call.
Why MCP and not function calling
- Discovery is standard. Clients call
tools/listand render schemas on their own. Adding a new tool requires no client change. - Streamable HTTP transport. Long-running jobs (Phase 2 research, 60–180 s) can stream intermediate progress over SSE.
- Two auth paths, one server. CLI clients send
Authorization: Bearer dt_…; web clients use OAuth 2.1 with PKCE and Dynamic Client Registration. Both hit the same tools.
8 · The skill — protocol contract on the client side
The server defines what tools exist. The shipped SKILL.md defines how AI clients must use them: the entry gate, the Phase 1 stage ordering, batched-vs-sequential rules, error fallback order, and wording rules (never mention credits, preserve the user's terminology, add an open question when sources conflict).
The same skill ships in three wrappers — Anthropic Skills format (Claude Code, Claude Desktop, Claude.ai), AGENTS.md (Codex CLI), and a system-prompt body (ChatGPT, Perplexity). Behaviour is identical across clients because the protocol enforces it.
9 · Versioning and what is not in the protocol
Every commit produces a content-addressed version_hash. Editing any leaf forks a new version; nothing is ever overwritten. A six-month-old tree and today's tree on the same ticker are directly comparable.
Some things are intentionally out of scope:
- DCF, reverse DCF, DDM, inverted scenarios. These methods encode noise as precision and conflict with the falsifiability requirement.
- Public directory of trees. All committed trees are private by default. There is no search across users or tickers.
- Model lock-in. The protocol does not prescribe which LLM the client uses. Any model that can read
SKILL.mdand follow its hard rules produces compliant trees.