<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Warmplane — The Hot Local Control Plane for MCP Sessions</title>
<meta name="description" content="Warmplane keeps MCP sessions warm. A Rust-native local control plane that cuts token overhead by up to 96%, with persistent sessions, hybrid vector search, fine-grained RBAC policy governance, and deterministic execution envelopes.">
<meta name="keywords" content="MCP, Model Context Protocol, control plane, AI agents, tool calling, Rust, token efficiency, enterprise, vector search, SSE">
<meta name="author" content="Warmplane">
<meta property="og:title" content="Warmplane — The Hot Local Control Plane for MCP Sessions">
<meta property="og:description" content="Cut AI agent token costs by up to 96%. Persistent MCP sessions, hybrid BM25/vector search, policy governance, and deterministic execution envelopes.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://warmplane.github.io/warmplane/">
<link rel="canonical" href="https://warmplane.github.io/warmplane/">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,400&family=Instrument+Serif:ital@0;1&family=Plus+Jakarta+Sans:ital,wght@0,300..800;1,300..800&family=JetBrains+Mono:ital,wght@0,400..700;1,400..700&display=swap" rel="stylesheet">
<style>
:root {
--amber-50: oklch(98% 0.02 75);
--amber-100: oklch(93% 0.04 75);
--amber-200: oklch(85% 0.08 72);
--amber-300: oklch(76% 0.13 65);
--amber-400: oklch(70% 0.18 55);
--amber-500: oklch(62% 0.19 48);
--amber-glow: oklch(70% 0.18 55 / 0.25);
--cyan-glow: oklch(78% 0.16 195);
--green-glow: oklch(78% 0.18 145);
--n-0: oklch(6% 0.006 260);
--n-50: oklch(10% 0.01 260);
--n-100: oklch(14% 0.012 260);
--n-150: oklch(18% 0.014 260);
--n-200: oklch(24% 0.016 260);
--n-300: oklch(34% 0.015 260);
--n-400: oklch(48% 0.012 260);
--n-500: oklch(62% 0.008 260);
--n-700: oklch(82% 0.004 260);
--n-800: oklch(92% 0.002 260);
--n-900: oklch(98% 0.001 260);
--bg: var(--n-0);
--surface: var(--n-50);
--surface-alt: var(--n-100);
--surface-hover: var(--n-150);
--border: var(--n-200);
--border-subtle: var(--n-150);
--border-glow: var(--amber-glow);
--text: var(--n-800);
--text-muted: var(--n-500);
--text-dim: var(--n-400);
--accent: var(--amber-400);
--accent-muted: var(--amber-500);
--ff-display: 'Instrument Serif', Georgia, serif;
--ff-sans: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
--ff-mono: 'JetBrains Mono', 'DM Mono', monospace;
--fs-xs: clamp(0.72rem, 0.65rem + 0.3vw, 0.82rem);
--fs-sm: clamp(0.82rem, 0.74rem + 0.35vw, 0.92rem);
--fs-base: clamp(0.92rem, 0.85rem + 0.4vw, 1.02rem);
--fs-md: clamp(1.05rem, 0.92rem + 0.6vw, 1.25rem);
--fs-lg: clamp(1.35rem, 1.1rem + 1.1vw, 1.85rem);
--fs-xl: clamp(1.85rem, 1.3rem + 2.2vw, 3.1rem);
--fs-2xl: clamp(2.45rem, 1.5rem + 3.8vw, 4.6rem);
--fs-3xl: clamp(3.1rem, 1.8rem + 5.5vw, 6.6rem);
--sp-1: 0.25rem;
--sp-2: 0.5rem;
--sp-3: 0.75rem;
--sp-4: 1rem;
--sp-6: 1.5rem;
--sp-8: 2rem;
--sp-12: 3rem;
--sp-16: 4rem;
--sp-24: 6rem;
--sp-32: 8rem;
--max-width: 1240px;
--radius-sm: 8px;
--radius-md: 14px;
--radius-lg: 22px;
--transition-fast: 0.18s cubic-bezier(0.16, 1, 0.3, 1);
--transition-smooth: 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
color-scheme: dark;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
background-color: var(--bg);
color: var(--text);
font-family: var(--ff-sans);
font-size: var(--fs-base);
line-height: 1.6;
overflow-x: hidden;
min-height: 100vh;
}
::selection {
background: oklch(70% 0.18 55 / 0.35);
color: #fff;
}
a {
color: inherit;
text-decoration: none;
}
button {
font: inherit;
cursor: pointer;
border: none;
background: none;
}
.bg-canvas {
position: fixed;
inset: 0;
pointer-events: none;
z-index: -2;
overflow: hidden;
}
.bg-canvas::before {
content: '';
position: absolute;
top: -15%;
left: 50%;
transform: translateX(-50%);
width: 1100px;
height: 700px;
background: radial-gradient(ellipse at center, oklch(70% 0.18 55 / 0.12) 0%, oklch(62% 0.19 48 / 0.03) 45%, transparent 75%);
filter: blur(90px);
}
.bg-canvas::after {
content: '';
position: absolute;
bottom: -10%;
right: -10%;
width: 800px;
height: 600px;
background: radial-gradient(circle at center, oklch(78% 0.16 195 / 0.05) 0%, transparent 70%);
filter: blur(110px);
}
.grid-overlay {
position: fixed;
inset: 0;
background-image:
linear-gradient(to right, oklch(24% 0.016 260 / 0.22) 1px, transparent 1px),
linear-gradient(to bottom, oklch(24% 0.016 260 / 0.22) 1px, transparent 1px);
background-size: 64px 64px;
mask-image: radial-gradient(ellipse at center, black 35%, transparent 80%);
pointer-events: none;
z-index: -1;
}
body::after {
content: '';
position: fixed;
inset: 0;
pointer-events: none;
z-index: 9999;
opacity: 0.032;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
background-repeat: repeat;
background-size: 256px 256px;
}
.container {
max-width: var(--max-width);
margin: 0 auto;
padding: 0 var(--sp-6);
}
header.nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
padding: var(--sp-4) var(--sp-6);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
background: oklch(6% 0.006 260 / 0.75);
border-bottom: 1px solid var(--border-subtle);
transition: all var(--transition-fast);
}
header.nav.scrolled {
background: oklch(6% 0.006 260 / 0.92);
border-bottom-color: var(--border);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
}
.nav-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
max-width: var(--max-width);
margin: 0 auto;
}
.logo {
display: flex;
align-items: center;
gap: 0.75rem;
font-family: var(--ff-mono);
font-size: var(--fs-md);
font-weight: 600;
letter-spacing: -0.02em;
}
.logo-mark {
width: 28px;
height: 28px;
border-radius: 8px;
background: linear-gradient(135deg, var(--accent), var(--amber-500));
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 14px var(--amber-glow);
}
.logo-mark svg {
width: 16px;
height: 16px;
color: var(--n-0);
}
.nav-heat-dot {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--accent);
box-shadow: 0 0 8px var(--accent), 0 0 20px var(--amber-glow);
animation: pulse-heat 2.2s ease-in-out infinite;
}
.nav-links {
display: flex;
gap: var(--sp-6);
align-items: center;
list-style: none;
}
.nav-links a {
font-family: var(--ff-mono);
font-size: var(--fs-xs);
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-muted);
transition: color var(--transition-fast);
}
.nav-links a:hover {
color: var(--accent);
}
.nav-actions {
display: flex;
align-items: center;
gap: 0.75rem;
}
.version-badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 10px;
border-radius: 100px;
background: oklch(70% 0.18 55 / 0.12);
border: 1px solid oklch(70% 0.18 55 / 0.3);
font-family: var(--ff-mono);
font-size: var(--fs-xs);
color: var(--accent);
font-weight: 500;
}
.btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.65rem 1.3rem;
border-radius: var(--radius-sm);
font-family: var(--ff-mono);
font-size: var(--fs-xs);
text-transform: uppercase;
letter-spacing: 0.06em;
font-weight: 600;
cursor: pointer;
transition: all var(--transition-fast);
border: 1px solid transparent;
white-space: nowrap;
}
.btn-primary {
background: var(--accent);
color: var(--n-0);
border-color: var(--accent);
box-shadow: 0 4px 20px var(--amber-glow);
}
.btn-primary:hover {
background: color-mix(in oklch, var(--accent), white 12%);
border-color: color-mix(in oklch, var(--accent), white 12%);
transform: translateY(-1px);
box-shadow: 0 6px 24px oklch(70% 0.18 55 / 0.4);
}
.btn-ghost {
background: transparent;
color: var(--text-muted);
border-color: var(--border);
}
.btn-ghost:hover {
background: var(--surface-hover);
border-color: var(--text-muted);
color: var(--text);
transform: translateY(-1px);
}
.btn-code {
font-family: var(--ff-mono);
font-size: var(--fs-xs);
background: var(--n-100);
border: 1px solid var(--border);
color: var(--cyan-glow);
padding: 0.65rem 1.1rem;
}
.btn-code:hover {
border-color: var(--cyan-glow);
background: var(--n-150);
}
.hero {
min-height: 100vh;
min-height: 100dvh;
padding: var(--sp-32) var(--sp-6) var(--sp-12);
display: flex;
flex-direction: column;
justify-content: space-between;
position: relative;
}
.hero-content {
max-width: 960px;
margin-bottom: var(--sp-12);
}
.hero-eyebrow {
font-family: var(--ff-mono);
font-size: var(--fs-xs);
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--accent);
margin-bottom: var(--sp-6);
display: flex;
align-items: center;
gap: var(--sp-3);
}
.hero-title {
font-family: var(--ff-display);
font-size: var(--fs-3xl);
line-height: 1.0;
font-weight: 400;
color: var(--n-900);
margin-bottom: var(--sp-8);
text-wrap: balance;
letter-spacing: -0.02em;
}
.hero-title em {
font-style: italic;
color: var(--accent);
background: linear-gradient(135deg, #ffffff 30%, var(--accent) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.hero-subtitle {
font-size: var(--fs-lg);
line-height: 1.55;
color: var(--text-muted);
max-width: 680px;
margin-bottom: var(--sp-12);
text-wrap: pretty;
font-weight: 400;
}
.hero-subtitle strong {
color: var(--text);
font-weight: 600;
}
.hero-cta {
display: flex;
flex-wrap: wrap;
gap: var(--sp-4);
align-items: center;
}
.hero-stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: var(--sp-4);
padding-top: var(--sp-8);
border-top: 1px solid var(--border-subtle);
}
.hero-stat-card {
border: 1px solid var(--border-subtle);
background: var(--surface);
border-radius: var(--radius-sm);
padding: var(--sp-5) var(--sp-6);
display: flex;
flex-direction: column;
justify-content: center;
transition: border-color var(--transition-fast);
}
.hero-stat-card:hover {
border-color: var(--border);
}
.hero-stat-val {
font-family: var(--ff-display);
font-size: var(--fs-2xl);
line-height: 1;
color: var(--accent);
}
.hero-stat-lbl {
font-family: var(--ff-mono);
font-size: 0.72rem;
color: var(--text-dim);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-top: var(--sp-2);
line-height: 1.3;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.hero-demo-wrapper {
margin-top: var(--sp-16);
margin-bottom: var(--sp-16);
}
.demo-deck {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
overflow: hidden;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6);
}
.demo-header {
background: oklch(10% 0.01 260);
padding: 0.85rem 1.25rem;
border-bottom: 1px solid var(--border-subtle);
display: flex;
align-items: center;
justify-content: space-between;
}
.window-dots {
display: flex;
gap: 0.45rem;
}
.dot {
width: 11px;
height: 11px;
border-radius: 50%;
}
.dot-red { background: #ff5f56; }
.dot-yellow { background: #ffbd2e; }
.dot-green { background: #27c93f; }
.demo-tabs {
display: flex;
gap: 0.5rem;
}
.demo-tab {
padding: 0.35rem 0.85rem;
border-radius: 6px;
font-size: var(--fs-xs);
font-family: var(--ff-mono);
color: var(--text-muted);
cursor: pointer;
transition: all var(--transition-fast);
background: transparent;
border: none;
}
.demo-tab.active {
background: var(--surface-hover);
color: var(--text);
}
.demo-body {
display: grid;
grid-template-columns: 1fr 1.2fr;
min-height: 400px;
}
.demo-pane-left {
padding: 1.75rem;
border-right: 1px solid var(--border-subtle);
background: oklch(8% 0.01 260);
display: flex;
flex-direction: column;
justify-content: center;
}
.demo-pane-right {
padding: 1.75rem;
background: oklch(6% 0.008 260);
font-family: var(--ff-mono);
font-size: var(--fs-xs);
line-height: 1.65;
overflow-x: auto;
}
.arch-flow {
display: flex;
flex-direction: column;
gap: 1rem;
}
.flow-node {
background: var(--surface);
border: 1px solid var(--border-subtle);
padding: 0.9rem 1.1rem;
border-radius: var(--radius-sm);
transition: all var(--transition-fast);
}
.flow-node.highlight {
border-color: var(--accent);
box-shadow: 0 0 16px var(--amber-glow);
}
.node-title {
font-size: var(--fs-xs);
font-weight: 700;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 0.2rem;
}
.node-desc {
font-size: var(--fs-sm);
font-weight: 600;
color: var(--text);
}
.flow-arrow {
text-align: center;
color: var(--accent);
font-weight: 700;
font-size: 1.1rem;
margin: -0.4rem 0;
}
.code-output {
color: var(--text-muted);
white-space: pre-wrap;
}
.code-key { color: var(--accent); }
.code-str { color: var(--green-glow); }
.code-num { color: var(--cyan-glow); }
.code-comment { color: var(--text-dim); font-style: italic; }
.section {
padding: var(--sp-24) var(--sp-6);
position: relative;
}
.section-inner {
max-width: var(--max-width);
margin: 0 auto;
}
.section-label {
font-family: var(--ff-mono);
font-size: var(--fs-xs);
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--accent-muted);
margin-bottom: var(--sp-4);
}
.section-heading {
font-family: var(--ff-display);
font-size: var(--fs-xl);
font-weight: 400;
line-height: 1.12;
color: var(--n-900);
margin-bottom: var(--sp-4);
text-wrap: balance;
}
.section-desc {
font-size: var(--fs-md);
color: var(--text-muted);
max-width: 680px;
margin-bottom: var(--sp-12);
text-wrap: pretty;
}
.divider {
max-width: var(--max-width);
margin: 0 auto;
border: none;
border-top: 1px solid var(--border-subtle);
}
.problem-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--sp-6);
}
.problem-card {
padding: var(--sp-8);
border: 1px solid var(--border-subtle);
background: var(--surface);
border-radius: var(--radius-md);
position: relative;
overflow: hidden;
}
.problem-card-bad::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 3px;
background: oklch(60% 0.2 25);
}
.problem-card-good::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 3px;
background: var(--accent);
}
.problem-card-tag {
font-family: var(--ff-mono);
font-size: var(--fs-xs);
text-transform: uppercase;
letter-spacing: 0.1em;
margin-bottom: var(--sp-6);
}
.problem-card-bad .problem-card-tag { color: oklch(60% 0.2 25); }
.problem-card-good .problem-card-tag { color: var(--accent); }
.problem-card-title {
font-family: var(--ff-display);
font-size: var(--fs-lg);
margin-bottom: var(--sp-4);
color: var(--text);
}
.problem-card-body {
color: var(--text-muted);
font-size: var(--fs-sm);
line-height: 1.7;
}
.problem-card-items {
margin-top: var(--sp-6);
display: flex;
flex-direction: column;
gap: var(--sp-3);
}
.problem-card-item {
font-family: var(--ff-mono);
font-size: var(--fs-xs);
padding: var(--sp-3) var(--sp-4);
border: 1px solid var(--border-subtle);
background: var(--n-100);
border-radius: var(--radius-sm);
color: var(--text-muted);
display: flex;
align-items: center;
gap: var(--sp-3);
}
.problem-card-bad .item-icon { color: oklch(60% 0.2 25); }
.problem-card-good .item-icon { color: var(--green-glow); }
.savings-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--sp-6);
}
.savings-card {
border: 1px solid var(--border);
background: var(--surface);
border-radius: var(--radius-md);
padding: var(--sp-8);
}
.savings-card-suite {
font-family: var(--ff-mono);
font-size: var(--fs-xs);
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--accent);
margin-bottom: var(--sp-4);
}
.savings-card-big {
font-family: var(--ff-display);
font-size: var(--fs-2xl);
color: var(--text);
line-height: 1;
margin-bottom: var(--sp-2);
}
.savings-card-context {
font-family: var(--ff-mono);
font-size: var(--fs-xs);
color: var(--text-dim);
margin-bottom: var(--sp-8);
}
.savings-bar {
margin-bottom: var(--sp-4);
}
.savings-bar-header {
display: flex;
justify-content: space-between;
font-family: var(--ff-mono);
font-size: 0.72rem;
color: var(--text-dim);
margin-bottom: var(--sp-1);
}
.savings-bar-track {
height: 6px;
background: var(--n-200);
border-radius: 3px;
position: relative;
overflow: hidden;
}
.savings-bar-fill {
position: absolute;
top: 0; left: 0;
height: 100%;
background: var(--accent);
border-radius: 3px;
transition: width 1.5s cubic-bezier(0.16, 1, 0.3, 1);
width: 0;
}
.savings-bar-fill-alt {
background: oklch(60% 0.2 25 / 0.4);
}
.terminal-box {
border-radius: var(--radius-md);
border: 1px solid var(--border);
overflow: hidden;
background: oklch(7% 0.01 260);
color: #eee6d7;
box-shadow: 0 16px 28px rgba(0, 0, 0, 0.4);
font-family: var(--ff-mono);
margin-top: var(--sp-12);
}
.terminal-head {
border-bottom: 1px solid var(--border-subtle);
padding: 14px 24px;
background: oklch(11% 0.01 260);
color: var(--text-muted);
font-size: var(--fs-xs);
display: flex;
justify-content: space-between;
}
.terminal-box pre {
margin: 0;
padding: 24px 28px !important;
white-space: pre-wrap;
line-height: 1.7;
font-size: 0.88rem;
}
.terminal-box pre code {
display: block;
padding: 0;
}
.bento-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--sp-4);
}
.bento-cell {
background: var(--surface);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-md);
padding: var(--sp-6);
transition: all var(--transition-smooth);
position: relative;
overflow: hidden;
&:hover {
border-color: var(--border);
background: var(--surface-hover);
transform: translateY(-2px);
}
}
.bento-cell-wide {
grid-column: span 2;
background: linear-gradient(135deg, var(--surface) 50%, oklch(14% 0.03 55 / 0.3) 100%);
}
.bento-icon {
font-family: var(--ff-mono);
font-size: var(--fs-lg);
color: var(--accent);
margin-bottom: var(--sp-4);
}
.bento-tag {
display: inline-block;
font-family: var(--ff-mono);
font-size: 0.68rem;
text-transform: uppercase;
letter-spacing: 0.08em;
padding: 2px 8px;
border-radius: 100px;
border: 1px solid var(--border);
color: var(--accent);
background: oklch(70% 0.18 55 / 0.08);
margin-bottom: var(--sp-3);
}
.bento-title {
font-family: var(--ff-display);
font-size: var(--fs-md);
color: var(--text);
margin-bottom: var(--sp-2);
}
.bento-body {
font-size: var(--fs-sm);
color: var(--text-muted);
line-height: 1.6;
}
.pill-list {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-top: var(--sp-4);
}
.pill {
font-family: var(--ff-mono);
font-size: 0.72rem;
padding: 4px 10px;
border-radius: 100px;
border: 1px solid var(--border-subtle);
background: var(--n-100);
color: var(--text-muted);
}
.modes-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--sp-6);
}
.mode-card {
border: 1px solid var(--border-subtle);
padding: var(--sp-8) var(--sp-6);
background: var(--surface);
border-radius: var(--radius-md);
transition: border-color 0.3s;
&:hover { border-color: var(--accent-muted); }
}
.mode-card-icon {
font-family: var(--ff-mono);
font-size: var(--fs-xl);
color: var(--accent);
margin-bottom: var(--sp-4);
}
.mode-card-title {
font-family: var(--ff-display);
font-size: var(--fs-lg);
color: var(--text);
margin-bottom: var(--sp-3);
}
.mode-card-body {
font-size: var(--fs-sm);
color: var(--text-muted);
line-height: 1.6;
margin-bottom: var(--sp-4);
}
.mode-card-code {
font-family: var(--ff-mono);
font-size: var(--fs-xs);
color: var(--text-dim);
padding: var(--sp-3) var(--sp-4);
background: var(--n-100);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-sm);
white-space: nowrap;
overflow-x: auto;
}
.playground-box {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
display: grid;
grid-template-columns: 320px 1fr;
overflow: hidden;
}
.playground-sidebar {
background: oklch(8% 0.01 260);
border-right: 1px solid var(--border-subtle);
padding: 1.5rem;
}
.pg-item {
padding: 0.85rem 1rem;
border-radius: var(--radius-sm);
cursor: pointer;
font-size: var(--fs-xs);
font-family: var(--ff-mono);
font-weight: 500;
color: var(--text-muted);
margin-bottom: 0.5rem;
transition: all var(--transition-fast);
display: flex;
align-items: center;
justify-content: space-between;
}
.pg-item:hover, .pg-item.active {
background: var(--surface);
color: var(--text);
}
.pg-item.active {
border-left: 3px solid var(--accent);
}
.pg-tag {
font-size: 0.7rem;
padding: 0.15rem 0.4rem;
border-radius: 4px;
background: var(--n-150);
color: var(--cyan-glow);
}
.playground-content {
padding: 1.75rem;
background: oklch(5% 0.008 260);
font-family: var(--ff-mono);
font-size: var(--fs-xs);
line-height: 1.65;
white-space: pre-wrap;
overflow-x: auto;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
}
.playground-content .code-output {
margin: 0;
align-self: flex-start;
width: 100%;
}
.code-showcase {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--sp-6);
}
.code-block {
border: 1px solid var(--border-subtle);
background: var(--surface);
border-radius: var(--radius-md);
overflow: hidden;
}
.code-block-header {
padding: var(--sp-3) var(--sp-4);
border-bottom: 1px solid var(--border-subtle);
background: var(--n-100);
display: flex;
align-items: center;
justify-content: space-between;
}
.code-block-filename {
font-family: var(--ff-mono);
font-size: var(--fs-xs);
color: var(--text-muted);
}
.code-block-lang {
font-family: var(--ff-mono);
font-size: 0.65rem;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--text-dim);
padding: 2px 6px;
border: 1px solid var(--border-subtle);
border-radius: 4px;
}
.code-block pre {
padding: var(--sp-4) var(--sp-6);
overflow-x: auto;
font-family: var(--ff-mono);
font-size: var(--fs-xs);
line-height: 1.7;
color: var(--n-700);
}
.code-block pre .kw { color: var(--amber-300); }
.code-block pre .str { color: var(--green-glow); }
.code-block pre .cmt { color: var(--n-400); font-style: italic; }
.code-block pre .num { color: var(--cyan-glow); }
.cta-section {
text-align: center;
padding: var(--sp-32) var(--sp-6);
position: relative;
}
.cta-glow {
position: absolute;
bottom: -20%;
left: 50%;
transform: translateX(-50%);
width: 60vw;
height: 60vw;
max-width: 600px;
max-height: 600px;
border-radius: 50%;
background: radial-gradient(ellipse at center, oklch(70% 0.18 55 / 0.08) 0%, transparent 65%);
filter: blur(80px);
pointer-events: none;
}
.cta-title {
font-family: var(--ff-display);
font-size: var(--fs-2xl);
font-weight: 400;
color: var(--n-900);
margin-bottom: var(--sp-4);
text-wrap: balance;
}
.cta-title em {
font-style: italic;
color: var(--accent);
}
.cta-sub {
font-size: var(--fs-md);
color: var(--text-muted);
margin-bottom: var(--sp-8);
}
footer.footer {
padding: var(--sp-8) var(--sp-6);
border-top: 1px solid var(--border-subtle);
background: oklch(5% 0.006 260);
font-size: var(--fs-xs);
color: var(--text-dim);
}
.footer-wrapper {
max-width: var(--max-width);
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: var(--sp-4);
}
.footer-links {
display: flex;
gap: var(--sp-6);
list-style: none;
}
.footer-links a:hover {
color: var(--accent);
}
.copied-toast {
position: fixed;
bottom: 2rem; right: 2rem;
background: var(--accent);
color: var(--n-0);
padding: 0.75rem 1.25rem;
border-radius: var(--radius-sm);
font-family: var(--ff-mono);
font-weight: 700;
font-size: var(--fs-xs);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
transform: translateY(100px);
opacity: 0;
transition: all var(--transition-smooth);
z-index: 10000;
}
.copied-toast.show {
transform: translateY(0);
opacity: 1;
}
.reveal {
animation: reveal-up linear both;
animation-timeline: view();
animation-range: entry 0% cover 18%;
}
@keyframes reveal-up {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulse-heat {
0%, 100% { opacity: 1; box-shadow: 0 0 8px var(--accent), 0 0 20px var(--amber-glow); }
50% { opacity: 0.5; box-shadow: 0 0 4px var(--accent), 0 0 10px oklch(70% 0.18 55 / 0.15); }
}
@media (prefers-reduced-motion: reduce) {
.reveal { animation: none; }
.nav-heat-dot { animation: none; }
}
@media (max-width: 960px) {
.hero-stats { grid-template-columns: repeat(2, 1fr); }
.problem-grid, .savings-grid, .code-showcase { grid-template-columns: 1fr; }
.bento-grid, .modes-grid { grid-template-columns: 1fr; }
.bento-cell-wide { grid-column: span 1; }
.demo-body { grid-template-columns: 1fr; }
.playground-box { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
.nav-links { display: none; }
.hero-stats { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="bg-canvas"></div>
<div class="grid-overlay"></div>
<header class="nav" id="nav">
<div class="nav-wrapper">
<a href="#" class="logo">
<div class="logo-mark">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon>
</svg>
</div>
<span>warmplane</span>
<span class="nav-heat-dot"></span>
</a>
<ul class="nav-links">
<li><a href="#why">Why</a></li>
<li><a href="#architecture">Architecture</a></li>
<li><a href="#capabilities">Capabilities</a></li>
<li><a href="#savings">Savings</a></li>
<li><a href="#playground">Spec</a></li>
<li><a href="integrators.html">Integrators</a></li>
<li><a href="PERFORMANCE.html">Performance</a></li>
</ul>
<div class="nav-actions">
<span class="version-badge">v0.14.0</span>
<a href="https://github.com/Warmplane/warmplane" target="_blank" rel="noopener" class="btn btn-ghost">GitHub ↗</a>
</div>
</div>
</header>
<section class="hero container">
<div class="hero-content">
<div class="hero-eyebrow">
<span>Open Source · Rust-Native Runtime</span>
<span class="version-badge">v0.14.0 · Agent Enrichment & Facade Search</span>
</div>
<h1 class="hero-title">
Keep your MCP<br>sessions <em>warm & hot</em>
</h1>
<p class="hero-subtitle">
Warmplane is the <strong>local control plane</strong> that multiplexes upstream Model Context Protocol (MCP) servers behind one hot, policyable runtime. Cut token overhead by up to <strong>96%</strong> with lazy capability indexes, Multi Round-Trip Requests (MRTR), hybrid vector search, fine-grained RBAC governance, and deterministic execution envelopes.
</p>
<div class="hero-cta">
<button class="btn btn-code" onclick="copyInstall()">
<span>$ cargo install warmplane</span>
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
</button>
<a href="https://github.com/Warmplane/warmplane" class="btn btn-primary" target="_blank" rel="noopener">View on GitHub</a>
<a href="https://github.com/Warmplane/warmplane/blob/main/docs/USER-GUIDE.md" class="btn btn-ghost" target="_blank" rel="noopener">Read User Guide →</a>
</div>
</div>
<div class="hero-stats">
<div class="hero-stat-card">
<div class="hero-stat-val">95.8%</div>
<div class="hero-stat-lbl">Copilot MCP Token Savings</div>
</div>
<div class="hero-stat-card">
<div class="hero-stat-val">< 1 ms</div>
<div class="hero-stat-lbl">Warm Session Reuse Latency</div>
</div>
<div class="hero-stat-card">
<div class="hero-stat-val">4</div>
<div class="hero-stat-lbl">Client Modes (HTTP / CLI / MCP / UI)</div>
</div>
<div class="hero-stat-card">
<div class="hero-stat-val">0</div>
<div class="hero-stat-lbl">Tokens on ETag 304 Cache Hit</div>
</div>
</div>
</section>
<section class="container hero-demo-wrapper" id="architecture">
<div class="demo-deck">
<div class="demo-header">
<div class="window-dots">
<div class="dot dot-red"></div>
<div class="dot dot-yellow"></div>
<div class="dot dot-green"></div>
</div>
<div class="demo-tabs">
<button class="demo-tab active" onclick="switchDemoTab('flow', this)">Architecture Flow</button>
<button class="demo-tab" onclick="switchDemoTab('config', this)">mcp_servers.json</button>
<button class="demo-tab" onclick="switchDemoTab('envelope', this)">Response Envelope</button>
</div>
</div>
<div class="demo-body">
<div class="demo-pane-left">
<div class="arch-flow">
<div class="flow-node highlight">
<div class="node-title">AI Client (Claude / Cursor / CLI)</div>
<div class="node-desc">Single Gateway Endpoint</div>
</div>
<div class="flow-arrow">↓</div>
<div class="flow-node" style="border-color: var(--accent);">
<div class="node-title">Warmplane Runtime</div>
<div class="node-desc">Policy • Hybrid Search • Idempotency • ETag</div>
</div>
<div class="flow-arrow">↓</div>
<div class="flow-node">
<div class="node-title">Upstream MCP Sessions (Hot)</div>
<div class="node-desc">SQLite • Filesystem • GitHub • Postgres</div>
</div>
</div>
</div>
<div class="demo-pane-right">
<div id="tab-flow" class="code-output">
<span class="code-comment">// High-Performance Local Control Plane</span>
Warmplane manages the lifecycle of upstream MCP servers.
- Maintains warm sub-process stdio & HTTP/SSE sessions
- Eliminates startup penalties on tool invocations
- Enforces fine-grained allow/deny rules & key redaction
- Exposes BM25 + ONNX vector embedding search
- Provides standardized execution envelopes & OTLP tracing
</div>
<div id="tab-config" class="code-output" style="display:none;">
{
<span class="code-key">"port"</span>: <span class="code-num">9090</span>,
<span class="code-key">"capabilityAliases"</span>: {
<span class="code-key">"sqlite.read_query"</span>: <span class="code-str">"db.query"</span>
},
<span class="code-key">"policy"</span>: {
<span class="code-key">"allow"</span>: [<span class="code-str">"db.*"</span>, <span class="code-str">"fs.*"</span>],
<span class="code-key">"deny"</span>: [<span class="code-str">"fs.secret"</span>],
<span class="code-key">"redactKeys"</span>: [<span class="code-str">"token"</span>, <span class="code-str">"api_key"</span>]
},
<span class="code-key">"mcpServers"</span>: {
<span class="code-key">"sqlite"</span>: {
<span class="code-key">"command"</span>: <span class="code-str">"npx"</span>,
<span class="code-key">"args"</span>: [<span class="code-str">"-y"</span>, <span class="code-str">"@modelcontextprotocol/server-sqlite"</span>, <span class="code-str">"./db"</span>]
}
}
}
</div>
<div id="tab-envelope" class="code-output" style="display:none;">
{
<span class="code-key">"request_id"</span>: <span class="code-str">"req_984372a"</span>,
<span class="code-key">"status"</span>: <span class="code-str">"success"</span>,
<span class="code-key">"retry_metadata"</span>: {
<span class="code-key">"classification"</span>: <span class="code-str">"idempotent"</span>,
<span class="code-key">"attempt"</span>: <span class="code-num">1</span>
},
<span class="code-key">"result"</span>: {
<span class="code-key">"rows"</span>: [<span class="code-str">"{\"id\": 1, \"status\": \"active\"}"</span>]
}
}
</div>
</div>
</div>
</div>
</section>
<hr class="divider">
<section class="section" id="why">
<div class="section-inner">
<div class="section-label reveal">01 — The Problem</div>
<h2 class="section-heading reveal">The description tax is real</h2>
<p class="section-desc reveal">
Before an LLM agent executes a single tool call, it ingests the full schema catalog of every connected MCP server on every turn. As server count grows, prompt tokens balloon rapidly—adding cost, latency, and context distraction.
</p>
<div class="problem-grid reveal">
<div class="problem-card problem-card-bad">
<div class="problem-card-tag">Direct MCP Pattern</div>
<div class="problem-card-title">Uncontrolled Overhead</div>
<div class="problem-card-body">
Every turn re-transmits full JSON schemas, detailed descriptions, resource trees, and prompt definitions from every upstream server.
</div>
<div class="problem-card-items">
<div class="problem-card-item">
<span class="item-icon">✕</span>
54,715 tokens per discovery pull (GitHub Copilot MCP)
</div>
<div class="problem-card-item">
<span class="item-icon">✕</span>
547,150 tokens over a 10-turn mixed agent loop
</div>
<div class="problem-card-item">
<span class="item-icon">✕</span>
No cross-server caching, no search, no policy profile
</div>
</div>
</div>
<div class="problem-card problem-card-good">
<div class="problem-card-tag">With Warmplane</div>
<div class="problem-card-title">Compact Control Plane</div>
<div class="problem-card-body">
Index-first discovery with lazy schema expansion. Agents pull compact alias indices and query expanded schemas on demand.
</div>
<div class="problem-card-items">
<div class="problem-card-item">
<span class="item-icon">✓</span>
2,386 tokens per discovery pull (95.6% reduction)
</div>
<div class="problem-card-item">
<span class="item-icon">✓</span>
22,895 tokens over same 10-turn mixed loop
</div>
<div class="problem-card-item">
<span class="item-icon">✓</span>
SHA-256 ETag caching → 0 tokens on 304 Not Modified
</div>
</div>
</div>
</div>
</div>
</section>
<hr class="divider">
<section class="section" id="savings">
<div class="section-inner">
<div class="section-label reveal">02 — Empirical Measurement</div>
<h2 class="section-heading reveal">Proven Token Savings</h2>
<p class="section-desc reveal">
Reproducible evaluation measured with the <code style="font-family:var(--ff-mono);color:var(--text)">cl100k_base</code> tokenizer. Run the evaluation suite in <code style="font-family:var(--ff-mono);color:var(--text)">eval/token-efficiency/</code> to verify on your own workloads.
</p>
<div class="savings-grid reveal" id="savings-cards">
<div class="savings-card">
<div class="savings-card-suite">GitHub Copilot MCP Suite</div>
<div class="savings-card-big">95.8%</div>
<div class="savings-card-context">Token Savings · 10-turn mixed loop</div>
<div class="savings-bar">
<div class="savings-bar-header">
<span>Discovery pull</span>
<span>54,715 → 2,386 tokens</span>
</div>
<div class="savings-bar-track">
<div class="savings-bar-fill savings-bar-fill-alt" data-width="100"></div>
<div class="savings-bar-fill" data-width="4.4"></div>
</div>
</div>
<div class="savings-bar">
<div class="savings-bar-header">
<span>5-turn tool loop</span>
<span>260,005 → 11,173 tokens</span>
</div>
<div class="savings-bar-track">
<div class="savings-bar-fill savings-bar-fill-alt" data-width="100"></div>
<div class="savings-bar-fill" data-width="4.3"></div>
</div>
</div>
<div class="savings-bar">
<div class="savings-bar-header">
<span>10-turn mixed loop</span>
<span>547,150 → 22,895 tokens</span>
</div>
<div class="savings-bar-track">
<div class="savings-bar-fill savings-bar-fill-alt" data-width="100"></div>
<div class="savings-bar-fill" data-width="4.2"></div>
</div>
</div>
</div>
<div class="savings-card">
<div class="savings-card-suite">Filesystem Control Suite</div>
<div class="savings-card-big">58.2%</div>
<div class="savings-card-context">Token Savings · 10-turn mixed loop</div>
<div class="savings-bar">
<div class="savings-bar-header">
<span>Discovery pull</span>
<span>2,552 → 1,066 tokens</span>
</div>
<div class="savings-bar-track">
<div class="savings-bar-fill savings-bar-fill-alt" data-width="100"></div>
<div class="savings-bar-fill" data-width="41.8"></div>
</div>
</div>
<div class="savings-bar">
<div class="savings-bar-header">
<span>5-turn tool loop</span>
<span>12,760 → 5,349 tokens</span>
</div>
<div class="savings-bar-track">
<div class="savings-bar-fill savings-bar-fill-alt" data-width="100"></div>
<div class="savings-bar-fill" data-width="41.9"></div>
</div>
</div>
<div class="savings-bar">
<div class="savings-bar-header">
<span>10-turn mixed loop</span>
<span>25,520 → 10,669 tokens</span>
</div>
<div class="savings-bar-track">
<div class="savings-bar-fill savings-bar-fill-alt" data-width="100"></div>
<div class="savings-bar-fill" data-width="41.8"></div>
</div>
</div>
</div>
</div>
<div class="terminal-box reveal">
<div class="terminal-head">
<span>Token Efficiency Benchmark | Measured Eval Harness Output</span>
<span>Tokenizer: cl100k_base</span>
</div>
<pre><code><span style="color:#7a7264">Suite: github_copilot_only</span>
Discovery <span style="color:#e6b85c">54,715</span> -> <span style="color:#7ac98a">2,386</span> <span style="color:#7ac98a">(95.6% savings)</span>
5-turn loop <span style="color:#e6b85c">260,005</span> -> <span style="color:#7ac98a">11,173</span> <span style="color:#7ac98a">(95.7% savings)</span>
10-turn mixed <span style="color:#e6b85c">547,150</span> -> <span style="color:#7ac98a">22,895</span> <span style="color:#7ac98a">(95.8% savings)</span>
<span style="color:#7a7264">Control: public_filesystem_only</span>
Discovery <span style="color:#e6b85c">2,552</span> -> <span style="color:#7ac98a">1,066</span> <span style="color:#7ac98a">(58.2% savings)</span>
5-turn loop <span style="color:#e6b85c">12,760</span> -> <span style="color:#7ac98a">5,349</span> <span style="color:#7ac98a">(58.1% savings)</span>
10-turn mixed <span style="color:#e6b85c">25,520</span> -> <span style="color:#7ac98a">10,669</span> <span style="color:#7ac98a">(58.2% savings)</span></code></pre>
</div>
</div>
</section>
<hr class="divider">
<section class="section" id="capabilities">
<div class="section-inner">
<div class="section-label reveal">03 — Capability Matrix</div>
<h2 class="section-heading reveal">Built for Hot Production Stacks</h2>
<p class="section-desc reveal">
Everything ships in a single zero-dependency Rust binary compliant with Microsoft Pragmatic Rust guidelines.
</p>
<div class="bento-grid reveal">
<div class="bento-cell bento-cell-wide">
<span class="bento-tag">Unified Control Plane</span>
<div class="bento-icon">⊞</div>
<div class="bento-title">Unified Facade for Tools, Resources & Prompts</div>
<div class="bento-body">
Build a clean, stable contract across heterogeneous upstream MCP servers. Enumerate compact aliases, fetch full schemas lazily, and route standard invocations with complete correlation.
</div>
<div class="pill-list">
<span class="pill">Alias Registry</span>
<span class="pill">Compact Schemas</span>
<span class="pill">On-demand Expansion</span>
<span class="pill">MCP Native Exposure</span>
<span class="pill">Hybrid Search</span>
</div>
</div>
<div class="bento-cell">
<span class="bento-tag">v0.12.0 Spec Parity</span>
<div class="bento-icon">⚡</div>
<div class="bento-title">MCP 2026-07-28, MRTR & Subscriptions</div>
<div class="bento-body">
Full compliance with MCP 2026-07-28 spec: Multi Round-Trip Requests (MRTR) with <code>input_responses</code> propagation, <code>subscriptions_listen</code> change feed, real-time <code>GET /v1/resources/updates</code> SSE streams, and LLM delegation sampling.
</div>
</div>
<div class="bento-cell">
<span class="bento-tag">Vector & Lexical</span>
<div class="bento-icon">◎</div>
<div class="bento-title">Hybrid BM25 + Vector Search</div>
<div class="bento-body">
Find the right tool by name or natural language intention using BM25 keyword matching plus optional ONNX vector embeddings.
</div>
</div>
<div class="bento-cell">
<span class="bento-tag">v0.6.0 Resiliency</span>
<div class="bento-icon">⇌</div>
<div class="bento-title">Idempotency & Operation Cancel</div>
<div class="bento-body">
Pass <code>Idempotency-Key</code> to share in-flight calls and avoid duplicate side-effects. Abort stuck calls instantly via <code>POST /v1/operations/cancel</code>.
</div>
</div>
<div class="bento-cell">
<span class="bento-tag">Governance</span>
<div class="bento-icon">⊘</div>
<div class="bento-title">Fine-Grained RBAC & Policy Profiles</div>
<div class="bento-body">
Centralized policy rules for read-only, constrained write, and privileged paths with automated argument key redaction.
</div>
</div>
<div class="bento-cell">
<span class="bento-tag">Observability</span>
<div class="bento-icon">⊙</div>
<div class="bento-title">OTLP Traces & Request Context</div>
<div class="bento-body">
Propagate <code>operation_id</code>, <code>actor_id</code>, and <code>grant_id</code> across execution envelopes, structured JSON logs, and OpenTelemetry spans.
</div>
</div>
<div class="bento-cell">
<span class="bento-tag">v0.12.0 Benchmarks</span>
<div class="bento-icon">🦀</div>
<div class="bento-title">Criterion Micro-Benchmarks & Hot-Path Optimization</div>
<div class="bento-body">
56% faster tag search, 83% faster idempotency under concurrency, and 66% faster zero-copy ETag validation — all verified with a full Criterion benchmark suite.
</div>
</div>
<div class="bento-cell">
<span class="bento-tag">Enterprise Auth</span>
<div class="bento-icon">⊕</div>
<div class="bento-title">OAuth 2.1 & OIDC Client Infrastructure</div>
<div class="bento-body">
Complete OAuth 2.1 authorization code flow with PKCE, dynamic discovery, scope accumulation, and silent background token refresh with rotation for HTTP upstreams.
</div>
</div>
<div class="bento-cell">
<span class="bento-tag">Catalog Engine</span>
<div class="bento-icon">⌗</div>
<div class="bento-title">Catalog Versioning & ETag Validation</div>
<div class="bento-body">
SHA-256 state hashing with conditional 304 Not Modified responses and cursor-based event feeds for zero-token client revalidation.
</div>
</div>
</div>
</div>
</section>
<hr class="divider">
<section class="section" id="playground">
<div class="section-inner">
<div class="section-label reveal">04 — API & Protocol Spec</div>
<h2 class="section-heading reveal">Interactive Control Plane Endpoints</h2>
<p class="section-desc reveal">
Explore the primary RESTful HTTP/v1 endpoints exposed by Warmplane daemon.
</p>
<div class="playground-box reveal">
<div class="playground-sidebar">
<div class="pg-item active" onclick="switchPg('caps', this)">
<span>GET /v1/capabilities</span>
<span class="pg-tag">INDEX</span>
</div>
<div class="pg-item" onclick="switchPg('search', this)">
<span>POST /v1/capabilities/search</span>
<span class="pg-tag">SEARCH</span>
</div>
<div class="pg-item" onclick="switchPg('call', this)">
<span>POST /v1/tools/call</span>
<span class="pg-tag">EXEC</span>
</div>
<div class="pg-item" onclick="switchPg('sse', this)">
<span>GET /v1/resources/updates</span>
<span class="pg-tag">SSE</span>
</div>
<div class="pg-item" onclick="switchPg('complete', this)">
<span>POST /v1/completion/complete</span>
<span class="pg-tag">AUTO</span>
</div>
</div>
<div class="playground-content">
<div id="pg-caps" class="code-output">
<span class="code-comment">// HTTP GET /v1/capabilities</span>
<span class="code-comment">// ETag header matching yields HTTP 304 Not Modified (0 tokens)</span>
{
<span class="code-key">"etag"</span>: <span class="code-str">"\"3a8f9c1b-cl100k\""</span>,
<span class="code-key">"capabilities"</span>: [
{
<span class="code-key">"alias"</span>: <span class="code-str">"db.query"</span>,
<span class="code-key">"upstream_id"</span>: <span class="code-str">"sqlite.read_query"</span>,
<span class="code-key">"summary"</span>: <span class="code-str">"Execute a read-only SQL query against SQLite"</span>,
<span class="code-key">"policy_group"</span>: <span class="code-str">"read_only"</span>
},
{
<span class="code-key">"alias"</span>: <span class="code-str">"fs.read"</span>,
<span class="code-key">"upstream_id"</span>: <span class="code-str">"filesystem.read_file"</span>,
<span class="code-key">"summary"</span>: <span class="code-str">"Read text contents of a file"</span>,
<span class="code-key">"policy_group"</span>: <span class="code-str">"read_only"</span>
}
]
}
</div>
<div id="pg-search" class="code-output" style="display:none;">
<span class="code-comment">// HTTP POST /v1/capabilities/search</span>
<span class="code-comment">// Body: {"query": "database sql query", "limit": 2}</span>
{
<span class="code-key">"matches"</span>: [
{
<span class="code-key">"alias"</span>: <span class="code-str">"db.query"</span>,
<span class="code-key">"score"</span>: <span class="code-num">0.942</span>,
<span class="code-key">"match_type"</span>: <span class="code-str">"hybrid_bm25_vector"</span>,
<span class="code-key">"description"</span>: <span class="code-str">"Run parameterized SELECT query on configured SQLite database"</span>
}
]
}
</div>
<div id="pg-call" class="code-output" style="display:none;">
<span class="code-comment">// HTTP POST /v1/tools/call</span>
<span class="code-comment">// Header: Idempotency-Key: op-9481-run1</span>
{
<span class="code-key">"request_id"</span>: <span class="code-str">"req_01HJ8Z"</span>,
<span class="code-key">"status"</span>: <span class="code-str">"success"</span>,
<span class="code-key">"execution_time_ms"</span>: <span class="code-num">12</span>,
<span class="code-key">"retry_metadata"</span>: {
<span class="code-key">"classification"</span>: <span class="code-str">"idempotent"</span>,
<span class="code-key">"attempt"</span>: <span class="code-num">1</span>
},
<span class="code-key">"content"</span>: [
{ <span class="code-key">"type"</span>: <span class="code-str">"text"</span>, <span class="code-key">"text"</span>: <span class="code-str">"[{\"id\":101, \"name\":\"warmplane\"}]"</span> }
]
}
</div>
<div id="pg-sse" class="code-output" style="display:none;">
<span class="code-comment">// HTTP GET /v1/resources/updates (Server-Sent Events)</span>
<span class="code-comment">// Streams real-time catalog changes and resource update notifications</span>
event: catalog_change
data: {"event_id": 42, "type": "capability_registered", "alias": "github.search_issues"}
event: resource_update
data: {"uri": "file:///workspace/logs/app.log", "timestamp": 1770982800}
</div>
<div id="pg-complete" class="code-output" style="display:none;">
<span class="code-comment">// HTTP POST /v1/completion/complete (MCP Autocompletion API)</span>
<span class="code-comment">// Body: {"ref": {"type": "ref/prompt", "name": "sql_query"}, "argument": {"name": "table", "value": "us"}}</span>
{
<span class="code-key">"completion"</span>: {
<span class="code-key">"values"</span>: [<span class="code-str">"users"</span>, <span class="code-str">"user_permissions"</span>, <span class="code-str">"user_sessions"</span>],
<span class="code-key">"total"</span>: <span class="code-num">3</span>,
<span class="code-key">"has_more"</span>: <span class="code-num">false</span>
}
}
</div>
</div>
</div>
</div>
</section>
<hr class="divider">
<section class="section" id="modes">
<div class="section-inner">
<div class="section-label reveal">05 — Access Modes</div>
<h2 class="section-heading reveal">Three Client Modes, One Engine</h2>
<p class="section-desc reveal">
All interfaces share identical policy rules, session warmers, idempotency layers, and execution envelopes.
</p>
<div class="modes-grid reveal">
<div class="mode-card">
<div class="mode-card-icon">⌁</div>
<div class="mode-card-title">HTTP Daemon</div>
<div class="mode-card-body">
RESTful <code>/v1/</code> API exposing capability indices, hybrid search, resource updates via SSE streams, and operation cancellation.
</div>
<div class="mode-card-code">warmplane daemon --config mcp_servers.json</div>
</div>
<div class="mode-card">
<div class="mode-card-icon">⊞</div>
<div class="mode-card-title">MCP Server</div>
<div class="mode-card-body">
Standard stdio MCP interface. Point Claude Desktop, Cursor, or any agent framework directly at Warmplane as a unified MCP server.
</div>
<div class="mode-card-code">warmplane mcp-server --config mcp_servers.json</div>
</div>
<div class="mode-card">
<div class="mode-card-icon">⊳</div>
<div class="mode-card-title">CLI Interface</div>
<div class="mode-card-body">
Direct terminal commands for scripting, manual tool execution, catalog inspection, and config validation.
</div>
<div class="mode-card-code">warmplane search-capabilities "query db"</div>
</div>
</div>
</div>
</section>
<hr class="divider">
<section class="section" id="quickstart">
<div class="section-inner">
<div class="section-label reveal">06 — Quick Start</div>
<h2 class="section-heading reveal">Running in Three Minutes</h2>
<p class="section-desc reveal">
Configure your upstreams, validate your profile, and start serving warm sessions.
</p>
<div class="code-showcase reveal">
<div class="code-block">
<div class="code-block-header">
<span class="code-block-filename">mcp_servers.json</span>
<span class="code-block-lang">json</span>
</div>
<pre>{
<span class="kw">"port"</span>: <span class="num">9090</span>,
<span class="kw">"toolTimeoutMs"</span>: <span class="num">15000</span>,
<span class="kw">"capabilityAliases"</span>: {
<span class="kw">"sqlite.read_query"</span>: <span class="str">"db.query"</span>
},
<span class="kw">"policy"</span>: {
<span class="kw">"allow"</span>: [<span class="str">"db.*"</span>, <span class="str">"fs.*"</span>],
<span class="kw">"deny"</span>: [<span class="str">"fs.secret"</span>],
<span class="kw">"redactKeys"</span>: [<span class="str">"token"</span>, <span class="str">"api_key"</span>]
},
<span class="kw">"mcpServers"</span>: {
<span class="kw">"sqlite"</span>: {
<span class="kw">"command"</span>: <span class="str">"npx"</span>,
<span class="kw">"args"</span>: [<span class="str">"-y"</span>, <span class="str">"@modelcontextprotocol/server-sqlite"</span>, <span class="str">"./db"</span>]
}
}
}</pre>
</div>
<div class="code-block">
<div class="code-block-header">
<span class="code-block-filename">Terminal Commands</span>
<span class="code-block-lang">shell</span>
</div>
<pre><span class="cmt"># Install binary from source or crates.io</span>
<span class="kw">$</span> cargo install warmplane
<span class="cmt"># Interactively add servers, or import from Claude Desktop / Cursor</span>
<span class="kw">$</span> warmplane server add
<span class="kw">$</span> warmplane config import
<span class="cmt"># Start the local control plane daemon</span>
<span class="kw">$</span> warmplane daemon --config mcp_servers.json
<span class="cmt"># Perform vector/keyword hybrid tool search</span>
<span class="kw">$</span> warmplane search-capabilities <span class="str">"query database"</span> --limit 5
<span class="cmt"># Execute tool through control plane</span>
<span class="kw">$</span> warmplane call-capability db.query \
--params <span class="str">'{"query":"SELECT 1"}'</span> \
--idempotency-key op-42-run-1</pre>
</div>
</div>
</div>
</section>
<section class="cta-section container" id="get-started">
<div class="cta-glow"></div>
<div class="section-label reveal">Open Source · MIT License</div>
<h2 class="cta-title reveal">
The cheapest token is<br>the one <em>never sent</em>
</h2>
<p class="cta-sub reveal">
Start cutting AI agent token overhead while adding enterprise policy control.
</p>
<div class="hero-cta" style="justify-content: center;">
<a href="https://github.com/Warmplane/warmplane" class="btn btn-primary" target="_blank" rel="noopener">GitHub Repository ↗</a>
<a href="https://github.com/Warmplane/warmplane/blob/main/docs/USER-GUIDE.md" class="btn btn-ghost" target="_blank" rel="noopener">User Guide</a>
<a href="PERFORMANCE.html" class="btn btn-ghost">Performance Guide</a>
</div>
</section>
<footer class="footer">
<div class="footer-wrapper">
<div>
© 2026 Warmplane · MIT License · Local Control Plane for MCP Sessions
</div>
<ul class="footer-links">
<li><a href="https://github.com/Warmplane/warmplane" target="_blank" rel="noopener">GitHub</a></li>
<li><a href="USER-GUIDE.html" target="_blank" rel="noopener">User Guide</a></li>
<li><a href="integrators.html">Integrators Guide</a></li>
<li><a href="PERFORMANCE.html">Performance</a></li>
<li><a href="NEXT_LEVEL_TOOL_CALLING.html">Next-Level Tooling</a></li>
<li><a href="WHITEPAPER.html">Whitepaper</a></li>
</ul>
</div>
</footer>
<div id="toast" class="copied-toast">Copied to clipboard!</div>
<script>
const nav = document.getElementById('nav');
let ticking = false;
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(() => {
nav.classList.toggle('scrolled', window.scrollY > 40);
ticking = false;
});
ticking = true;
}
});
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const fills = entry.target.querySelectorAll('.savings-bar-fill');
fills.forEach(fill => {
const width = fill.dataset.width;
if (width) {
setTimeout(() => { fill.style.width = width + '%'; }, 200);
}
});
observer.unobserve(entry.target);
}
});
}, { threshold: 0.25 });
const savingsSection = document.getElementById('savings-cards');
if (savingsSection) observer.observe(savingsSection);
function switchDemoTab(tabName, btn) {
document.querySelectorAll('.demo-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
document.getElementById('tab-flow').style.display = tabName === 'flow' ? 'block' : 'none';
document.getElementById('tab-config').style.display = tabName === 'config' ? 'block' : 'none';
document.getElementById('tab-envelope').style.display = tabName === 'envelope' ? 'block' : 'none';
}
function switchPg(pgId, btn) {
document.querySelectorAll('.pg-item').forEach(item => item.classList.remove('active'));
btn.classList.add('active');
['caps', 'search', 'call', 'sse', 'complete'].forEach(id => {
const el = document.getElementById('pg-' + id);
if (el) el.style.display = (id === pgId) ? 'block' : 'none';
});
}
function copyInstall() {
navigator.clipboard.writeText('cargo install warmplane');
const toast = document.getElementById('toast');
toast.classList.add('show');
setTimeout(() => toast.classList.remove('show'), 2600);
}
</script>
</body>
</html>