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
25 25
26## Blog26## Blog
27 27
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.
29- [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.29- [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.
30 30
31## Source31## Source
apps/marketing/src/components/blog/context-flood-demo.tsx+3−4
@@ -12,10 +12,9 @@ import { fmt, useAnimatedNumber } from "./shared"; · 11 unmodified lines
12 * (on demand or everything up front). Flipping the interface barely moves the12 * (on demand or everything up front). Flipping the interface barely moves the
13 * number; flipping the loading strategy moves it ~20x.13 * number; flipping the loading strategy moves it ~20x.
14 *14 *
15 * Figures are illustrative but anchored: the arXiv paper everyone cited15 * Figures are illustrative: the official GitHub MCP server's 44-tool catalog
16 * measured the official GitHub MCP server at 44 tools, eager clients resending16 * at roughly 800 tokens per tool schema, resent every request by eager
17 * the whole catalog every request, and ~22k tokens for 27 built-in tool17 * clients.
18 * schemas (~800 tokens per schema).
19 */18 */
20 19
21type Interface_ = "cli" | "mcp";20type 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
6import { useState } from "react";
7import { 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
20type Row = { readonly name: string; readonly tokens: number };
21
22const 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];
31const MAX2 = 410797;
32
33type Paired = { readonly name: string; readonly ratio: number; readonly note?: string };
34
35// Table 3: cost with MCP attached ÷ cost without, per harness.
36const 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.
46const 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
52type Stage = "guess" | "revealed" | "paired";
53
54export 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 @@
1---1---
2title: "MCPs, CLIs, and APIs are the same thing"2title: "MCPs, CLIs, and APIs are the same thing"
3description: "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."3description: "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."
4date: 2026-08-234date: 2026-08-23
5author: "Rhys Sullivan"5author: "Rhys Sullivan"
6---6---
@@ -8,10 +8,9 @@ author: "Rhys Sullivan" · 1 unmodified line
8import { SameCallDemo } from "../../components/blog/same-call-demo";8import { SameCallDemo } from "../../components/blog/same-call-demo";
9import { McpToCliDemo } from "../../components/blog/mcp-to-cli-demo";9import { McpToCliDemo } from "../../components/blog/mcp-to-cli-demo";
10import { ContextFloodDemo } from "../../components/blog/context-flood-demo";10import { ContextFloodDemo } from "../../components/blog/context-flood-demo";
11import { HarnessSpreadDemo } from "../../components/blog/harness-spread-demo";
12import { InstallRaceDemo } from "../../components/blog/install-race-demo";11import { InstallRaceDemo } from "../../components/blog/install-race-demo";
13 12
14Last 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.13Every 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.
15 14
16The 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.15The 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.
17 16
@@ -45,19 +44,7 @@ There are two independent choices hiding in every setup: which interface you use · 27 unmodified lines
45 44
46The 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.45The 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.
47 46
48This 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."47The 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.
49
50## What the paper actually measured
51
52So 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
56The 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
58When 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
60To 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.
61 48
62## The restart is not in the spec49## The restart is not in the spec
63 50
@@ -91,4 +78,4 @@ Stop arguing about envelopes. Fix the client. · 27 unmodified lines
91 78
92---79---
93 80
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
2080 white-space: nowrap;2080 white-space: nowrap;
2081}2081}
2082 2082
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
2224/* ── Install race lanes ── */2083/* ── Install race lanes ── */
2225.bw-lanes {2084.bw-lanes {
2226 display: grid;2085 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