History

marketing: drop the paper section from the MCP/CLI post

Rhys Sullivan committed 2 months ago

Commit 9dc6cb71 parent 90f79655 files · +8 −321Browse files

Unified · Split

5 files
  1. apps/marketing/public/llms.txt +1 −1
  2. apps/marketing/src/components/blog/context-flood-demo.tsx +3 −4
  3. apps/marketing/src/components/blog/harness-spread-demo.tsx +0 −158
  4. apps/marketing/src/content/blog/mcp-cli-same-thing.mdx +4 −17
  5. apps/marketing/src/styles/global.css +0 −141
apps/marketing/public/llms.txt+1−1
@@ -25,7 +25,7 @@ Run it your way: local CLI, a desktop app, hosted Executor Cloud, or self-hosted · 24 unmodified lines
2525
2626 ## Blog
2727
28−- [MCPs, CLIs, and APIs are the same thing](https://executor.sh/blog/mcp-cli-same-thing): interactive tour of tool-calling envelopes, why context bloat is a client problem, and what the MCP-vs-CLI paper actually measured.
28+- [MCPs, CLIs, and APIs are the same thing](https://executor.sh/blog/mcp-cli-same-thing): interactive tour of tool-calling envelopes, why context bloat is a client problem, and why the MCP-vs-CLI debate is a category error.
2929 - [Why MCP had so many growing pains](https://executor.sh/blog/why-mcp-had-growing-pains): what went wrong in MCP's first year and where it goes from here.
3030
3131 ## Source
apps/marketing/src/components/blog/context-flood-demo.tsx+3−4
@@ -12,10 +12,9 @@ import { fmt, useAnimatedNumber } from "./shared"; · 11 unmodified lines
1212 * (on demand or everything up front). Flipping the interface barely moves the
1313 * number; flipping the loading strategy moves it ~20x.
1414 *
15− * Figures are illustrative but anchored: the arXiv paper everyone cited
16− * measured the official GitHub MCP server at 44 tools, eager clients resending
17− * the whole catalog every request, and ~22k tokens for 27 built-in tool
18− * schemas (~800 tokens per schema).
15+ * Figures are illustrative: the official GitHub MCP server's 44-tool catalog
16+ * at roughly 800 tokens per tool schema, resent every request by eager
17+ * clients.
1918 */
2019
2120 type Interface_ = "cli" | "mcp";
apps/marketing/src/components/blog/harness-spread-demo.tsx+0−158
@@ -1,158 +0,0 @@
1−"use client";
2−
3−/* eslint-disable react/forbid-elements -- blog widgets use bespoke styled
4− controls; the product design-system <Button> does not model them. */
5−
6−import { useState } from "react";
7−import { fmt } from "./shared";
8−
9−/**
10− * What the paper actually measured. Stage one shows Table 2 — median input
11− * tokens per completed run for seven harnesses on the same GitHub task — and
12− * asks the reader which runs had an MCP server attached. The reveal: none of
13− * them; the 28x spread is pure harness overhead. Stage two shows Table 3 —
14− * what happened when the MCP server *was* attached — where four of five
15− * harnesses got cheaper.
16− *
17− * Data: arXiv 2608.08654, Tables 2 and 3 (median input tokens, completed runs).
18− */
19−
20−type Row = { readonly name: string; readonly tokens: number };
21−
22−const TABLE2: ReadonlyArray<Row> = [
23− { name: "pi", tokens: 14660 },
24− { name: "Tau", tokens: 16459 },
25− { name: "Codex", tokens: 82378 },
26− { name: "Hermes", tokens: 83954 },
27− { name: "opencode", tokens: 137800 },
28− { name: "qwen-code", tokens: 297649 },
29− { name: "Claude Code", tokens: 410797 },
30−];
31−const MAX2 = 410797;
32−
33−type Paired = { readonly name: string; readonly ratio: number; readonly note?: string };
34−
35−// Table 3: cost with MCP attached ÷ cost without, per harness.
36−const TABLE3: ReadonlyArray<Paired> = [
37− { name: "Claude Code", ratio: 0.57 },
38− { name: "qwen-code", ratio: 0.74 },
39− { name: "Hermes", ratio: 0.84 },
40− { name: "opencode", ratio: 0.95 },
41− { name: "Codex", ratio: 16.09, note: "n=2" },
42−];
43−
44−// Position on a log scale from 0.4x to 20x, so 1.0x sits at a fixed line and
45−// the Codex outlier stays on the chart without flattening everything else.
46−const logPos = (r: number) => {
47− const min = Math.log(0.4);
48− const max = Math.log(20);
49− return ((Math.log(r) - min) / (max - min)) * 100;
50−};
51−
52−type Stage = "guess" | "revealed" | "paired";
53−
54−export function HarnessSpreadDemo() {
55− const [stage, setStage] = useState<Stage>("guess");
56−
57− return (
58− <div className="bw">
59− <p className="sr-only" aria-live="polite">
60− {stage === "guess"
61− ? "Seven harnesses ran the same GitHub task. Median input tokens range from 14,660 to 410,797."
62− : stage === "revealed"
63− ? "Reveal: none of these runs had an MCP server attached. The 28x spread is harness overhead."
64− : "With the MCP server attached, four of five harnesses got cheaper. Median paired ratio 0.93."}
65− </p>
66−
67− {stage !== "paired" ? (
68− <>
69− <div className="bw-head">
70− <span className="bw-eyebrow">Seven harnesses, one task, median input tokens</span>
71− </div>
72− <div className="bw-bars">
73− {TABLE2.map((r) => (
74− <div key={r.name} className="bw-bars__row">
75− <span className="bw-bars__name">{r.name}</span>
76− <div className="bw-bars__track">
77− <div
78− className="bw-bars__fill"
79− style={{ width: `${Math.max(2, (r.tokens / MAX2) * 100)}%` }}
80− />
81− </div>
82− <span className="bw-bars__val">{fmt(r.tokens)}</span>
83− </div>
84− ))}
85− </div>
86− {stage === "guess" ? (
87− <div className="bw-quiz">
88− <span>Which of these runs had an MCP server attached?</span>
89− <button type="button" className="bw-btn" onClick={() => setStage("revealed")}>
90− Reveal
91− </button>
92− </div>
93− ) : (
94− <div className="bw-quiz bw-quiz--answer">
95− <span>
96− <strong>None of them.</strong> No MCP server was attached to any run in this chart —
97− the 28x spread between the cheapest and most expensive harness is pure harness
98− overhead.
99− </span>
100− <button type="button" className="bw-btn" onClick={() => setStage("paired")}>
101− So what happened when they attached it?
102− </button>
103− </div>
104− )}
105− </>
106− ) : (
107− <>
108− <div className="bw-head">
109− <span className="bw-eyebrow">Cost with MCP attached ÷ cost without, per harness</span>
110− </div>
111− <div className="bw-ratio" style={{ "--one-x": `${logPos(1)}%` } as React.CSSProperties}>
112− <div className="bw-ratio__row bw-ratio__row--axis" aria-hidden="true">
113− <span className="bw-ratio__name" />
114− <div className="bw-ratio__axis">
115− <span style={{ left: `${logPos(0.5)}%` }}>0.5×</span>
116− <span style={{ left: `${logPos(1)}%` }}>1×</span>
117− <span style={{ left: `${logPos(2)}%` }}>2×</span>
118− <span style={{ left: `${logPos(5)}%` }}>5×</span>
119− <span style={{ left: `${logPos(16)}%` }}>16×</span>
120− </div>
121− </div>
122− {TABLE3.map((p) => (
123− <div key={p.name} className="bw-ratio__row">
124− <span className="bw-ratio__name">
125− {p.name}{" "}
126− <span className="bw-ratio__val">
127− {p.ratio}×{p.note ? ` (${p.note})` : ""}
128− </span>
129− </span>
130− <div className="bw-ratio__track">
131− <span
132− className="bw-ratio__marker"
133− data-cheaper={p.ratio < 1 ? "true" : undefined}
134− style={{ left: `${logPos(p.ratio)}%` }}
135− />
136− </div>
137− </div>
138− ))}
139− <div className="bw-ratio__legend">
140− <span>← cheaper with MCP</span>
141− <span>more expensive with MCP →</span>
142− </div>
143− </div>
144− <div className="bw-quiz bw-quiz--answer">
145− <span>
146− Four of five harnesses got <strong>cheaper</strong> with the MCP server attached.
147− Across the thirteen strictly paired runs the median ratio is <strong>0.93</strong> —
148− the authors call the comparison inconclusive.
149− </span>
150− <button type="button" className="bw-btn" onClick={() => setStage("guess")}>
151− Back to the spread
152− </button>
153− </div>
154− </>
155− )}
156− </div>
157− );
158−}
apps/marketing/src/content/blog/mcp-cli-same-thing.mdx+4−17
@@ -1,6 +1,6 @@
11 ---
22 title: "MCPs, CLIs, and APIs are the same thing"
3−description: "You can compile an MCP server into a CLI without changing a single tool. An interactive look at what tool calling actually is, why context bloat is a client problem, and what that viral paper really measured."
3+description: "You can compile an MCP server into a CLI without changing a single tool. An interactive look at what tool calling actually is, why context bloat is a client problem, and why the MCP-vs-CLI debate is a category error."
44 date: 2026-08-23
55 author: "Rhys Sullivan"
66 ---
@@ -8,10 +8,9 @@ author: "Rhys Sullivan" · 1 unmodified line
88 import { SameCallDemo } from "../../components/blog/same-call-demo";
99 import { McpToCliDemo } from "../../components/blog/mcp-to-cli-demo";
1010 import { ContextFloodDemo } from "../../components/blog/context-flood-demo";
11−import { HarnessSpreadDemo } from "../../components/blog/harness-spread-demo";
1211 import { InstallRaceDemo } from "../../components/blog/install-race-demo";
1312
14−Last week a [paper](https://arxiv.org/abs/2608.08654) made the rounds claiming that agents finish software tasks just as reliably without MCP, and 5 to 28 times cheaper. The replies sorted themselves into the usual camps: MCP is dead, CLIs won, protocols were a mistake.
13+Every few weeks the debate comes back around: CLIs beat MCP, MCP is dead, agents just need bash. Benchmarks get run, threads get written, and everyone sorts into camps.
1514
1615 The whole argument is built on a category error. MCP servers, CLIs, and APIs are not three competing technologies. They are three envelopes around the same thing: an agent invoking a tool.
1716
@@ -45,19 +44,7 @@ There are two independent choices hiding in every setup: which interface you use · 27 unmodified lines
4544
4645 The number follows the loading axis. A CLI feels cheap because no one would ever dream of inlining the help text for every `gh` subcommand up front — the model runs `--help` for the two commands it needs, when it needs them. Then we built MCP clients that do exactly the thing nobody would do to a CLI, and blamed the protocol for the result.
4746
48−This is not a hypothetical; it is in the paper's own data. Against the same 44-tool GitHub server, the harnesses that resent the full catalog with every request spent a median of 216,986 tokens per completed run. The one harness that exposed a two-tool gateway — list tools, invoke tool — and fetched descriptions on demand spent 70,836. A 3.1x difference the authors themselves call "a property of the agent scaffolding rather than of the protocol." They also cite [Anthropic's write-up on code execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp) as establishing that eager transmission "is a design choice rather than a requirement of the protocol."
49−
50−## What the paper actually measured
51−
52−So where did 5 to 28x come from? Here is the chart behind the headline: seven harnesses, the same GitHub task, median input tokens per completed run. Before reading on, answer the question under the chart.
53−
54−<HarnessSpreadDemo client:visible />
55−
56−The 28x is a comparison between harnesses with **no MCP server attached to any run**. That is not my gotcha — it is the abstract's own phrasing: the two lean harnesses were "5.0× to 28× cheaper than the five scaffoldings that do support MCP, comparing CLI runs alone with no MCP server attached anywhere." Claude Code starts around 22,000 tokens before the task says anything, because it ships 27 built-in tool schemas with every request. pi finishes the _entire task_ in 14,660. That spread — the headline number — is pure harness overhead, measured in a room MCP never entered.
57−
58−When the authors did attach the server, four of five harnesses got _cheaper_, the median paired ratio was 0.93, and both arms failed the same number of times. Their own stated noise floor is a factor of two: anything smaller "cannot be distinguished from run-to-run variation."
59−
60−To be fair to the authors, they know this — the paper is literally titled _The Scaffolding Matters More Than the Interface_. My complaints are that it tests one task against one server, nearly every cell is a single run, and it still got passed around as "MCP costs 28x more." The measured content of the paper is one of the better arguments for the thesis of this post.
47+The good clients already work this way. Lazy loading, tool search, and code mode all defer tool descriptions until the model actually needs them — [Anthropic's write-up on code execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp) describes cutting token use dramatically by having the model write code that calls tools instead of front-loading every definition. Eager transmission is a client design choice, not a requirement of the protocol. Any benchmark that measures an eager client and reports the result as a property of MCP is measuring the client.
6148
6249 ## The restart is not in the spec
6350
@@ -91,4 +78,4 @@ Stop arguing about envelopes. Fix the client. · 27 unmodified lines
9178
9279 ---
9380
94−_Numbers in this post are from [arXiv:2608.08654](https://arxiv.org/abs/2608.08654), Tables 2, 3, and 5: median input tokens per completed run. Token figures in the loading-strategy widget are illustrative, anchored to the paper's measurements (~800 tokens per tool schema, 44 tools on the official GitHub MCP server)._
81+_Token figures in the loading-strategy widget are illustrative: roughly 800 tokens per tool schema, against the official GitHub MCP server's catalog of 44 tools._
apps/marketing/src/styles/global.css+0−141
@@ -2080,147 +2080,6 @@ body { · 2079 unmodified lines
20802080 white-space: nowrap;
20812081 }
20822082
2083−/* ── Harness spread bars + paired ratios ── */
2084−.bw-bars {
2085− display: flex;
2086− flex-direction: column;
2087− gap: 0.45rem;
2088−}
2089−.bw-bars__row {
2090− display: grid;
2091− grid-template-columns: 92px 1fr 64px;
2092− align-items: center;
2093− gap: 0.6rem;
2094−}
2095−.bw-bars__name {
2096− font-family: var(--font-mono);
2097− font-size: 11.5px;
2098− color: var(--color-ink);
2099− overflow: hidden;
2100− text-overflow: ellipsis;
2101− white-space: nowrap;
2102−}
2103−.bw-bars__track {
2104− height: 13px;
2105− background: var(--color-surface-2);
2106− border-radius: 3px;
2107− overflow: hidden;
2108−}
2109−.bw-bars__fill {
2110− height: 100%;
2111− background: rgba(13, 13, 16, 0.55);
2112− border-radius: 3px;
2113−}
2114−.bw-bars__val {
2115− font-family: var(--font-mono);
2116− font-size: 11px;
2117− font-variant-numeric: tabular-nums;
2118− color: var(--color-ink-3);
2119− text-align: right;
2120− white-space: nowrap;
2121−}
2122−.bw-quiz {
2123− display: flex;
2124− align-items: center;
2125− justify-content: space-between;
2126− gap: 0.9rem;
2127− flex-wrap: wrap;
2128− margin-top: 1rem;
2129− padding-top: 0.85rem;
2130− border-top: 1px solid var(--color-rule);
2131− font-size: 13.5px;
2132− color: var(--color-ink-2);
2133−}
2134−.bw-quiz--answer {
2135− color: var(--color-ink-2);
2136−}
2137−.bw-quiz strong {
2138− color: var(--color-ink);
2139− font-weight: 600;
2140−}
2141−.bw-quiz > span {
2142− flex: 1;
2143− min-width: 240px;
2144−}
2145−.bw-ratio {
2146− display: flex;
2147− flex-direction: column;
2148− gap: 0.55rem;
2149−}
2150−.bw-ratio__row {
2151− display: grid;
2152− grid-template-columns: 150px 1fr;
2153− align-items: center;
2154− gap: 0.6rem;
2155−}
2156−.bw-ratio__row--axis {
2157− margin-bottom: 0.1rem;
2158−}
2159−.bw-ratio__name {
2160− font-family: var(--font-mono);
2161− font-size: 11.5px;
2162− color: var(--color-ink);
2163− white-space: nowrap;
2164− overflow: hidden;
2165− text-overflow: ellipsis;
2166−}
2167−.bw-ratio__val {
2168− color: var(--color-ink-3);
2169−}
2170−.bw-ratio__axis {
2171− position: relative;
2172− height: 14px;
2173−}
2174−.bw-ratio__axis span {
2175− position: absolute;
2176− transform: translateX(-50%);
2177− font-family: var(--font-mono);
2178− font-size: 10px;
2179− color: var(--color-ink-3);
2180− white-space: nowrap;
2181−}
2182−.bw-ratio__track {
2183− position: relative;
2184− height: 18px;
2185− background: var(--color-surface-2);
2186− border-radius: 3px;
2187−}
2188−/* The 1× line every track shares, positioned by --one-x on .bw-ratio. */
2189−.bw-ratio__track::after {
2190− content: "";
2191− position: absolute;
2192− top: -2px;
2193− bottom: -2px;
2194− left: var(--one-x);
2195− width: 1px;
2196− background: var(--color-rule-strong);
2197−}
2198−.bw-ratio__marker {
2199− position: absolute;
2200− top: 50%;
2201− transform: translate(-50%, -50%);
2202− width: 9px;
2203− height: 9px;
2204− border-radius: 999px;
2205− background: white;
2206− border: 2px solid var(--color-ink-3);
2207− z-index: 1;
2208−}
2209−.bw-ratio__marker[data-cheaper="true"] {
2210− background: var(--color-ink);
2211− border-color: var(--color-ink);
2212−}
2213−.bw-ratio__legend {
2214− display: flex;
2215− justify-content: space-between;
2216− font-family: var(--font-mono);
2217− font-size: 10px;
2218− text-transform: uppercase;
2219− letter-spacing: 0.06em;
2220− color: var(--color-ink-3);
2221− margin-top: 0.2rem;
2222−}
2223−
22242083 /* ── Install race lanes ── */
22252084 .bw-lanes {
22262085 display: grid;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t