<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://hypercall-public.github.io/mcpzip/blog</id>
    <title>mcpzip Blog</title>
    <updated>2026-04-01T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://hypercall-public.github.io/mcpzip/blog"/>
    <subtitle>mcpzip Blog</subtitle>
    <icon>https://hypercall-public.github.io/mcpzip/img/logo.svg</icon>
    <entry>
        <title type="html"><![CDATA[mcpzip Performance Deep Dive]]></title>
        <id>https://hypercall-public.github.io/mcpzip/blog/benchmarks</id>
        <link href="https://hypercall-public.github.io/mcpzip/blog/benchmarks"/>
        <updated>2026-04-01T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[We built mcpzip to be fast, lightweight, and invisible. Here is a detailed breakdown of its performance characteristics -- startup time, search latency, memory footprint, and binary size.]]></summary>
        <content type="html"><![CDATA[<p>We built mcpzip to be fast, lightweight, and invisible. Here is a detailed breakdown of its performance characteristics -- startup time, search latency, memory footprint, and binary size.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="startup-time-instant">Startup Time: Instant<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#startup-time-instant" class="hash-link" aria-label="Direct link to Startup Time: Instant" title="Direct link to Startup Time: Instant">​</a></h2>
<p>The most important performance metric for a CLI tool is startup time. mcpzip starts serving in <strong>under 5 milliseconds</strong>.</p>
<p>How? Disk caching. On startup, mcpzip:</p>
<ol>
<li>Reads <code>~/.config/compressed-mcp-proxy/cache/tools.json</code> (typically 100KB-2MB)</li>
<li>Deserializes the tool catalog into memory</li>
<li>Starts the MCP server on stdio</li>
</ol>
<p>No network connections. No process spawning. Just read a file and serve.</p>
<p>The background refresh runs concurrently -- it connects to all upstream servers in parallel, calls <code>tools/list</code> on each, and merges the results into the catalog. This takes 2-10 seconds depending on your servers, but it never blocks a request.</p>
<table><thead><tr><th>Phase</th><th>Duration</th><th>Blocks Requests?</th></tr></thead><tbody><tr><td>Load disk cache</td><td>under 5ms</td><td>No (this IS serving)</td></tr><tr><td>Start MCP server</td><td>under 1ms</td><td>No</td></tr><tr><td>Background: connect to servers</td><td>1-5s per server</td><td>No</td></tr><tr><td>Background: list tools</td><td>0.5-2s per server</td><td>No</td></tr><tr><td>Background: merge + persist</td><td>under 100ms</td><td>No</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="search-latency">Search Latency<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#search-latency" class="hash-link" aria-label="Direct link to Search Latency" title="Direct link to Search Latency">​</a></h2>
<p>mcpzip's search engine is the heart of the proxy. It needs to be fast because Claude calls it on nearly every tool interaction.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="keyword-search-under-1ms">Keyword Search: under 1ms<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#keyword-search-under-1ms" class="hash-link" aria-label="Direct link to Keyword Search: under 1ms" title="Direct link to Keyword Search: under 1ms">​</a></h3>
<p>The keyword search engine tokenizes the query and scores it against tool metadata. It runs entirely in memory with no I/O.</p>
<table><thead><tr><th>Operation</th><th>Time</th></tr></thead><tbody><tr><td>Query tokenization</td><td>under 0.01ms</td></tr><tr><td>Score all tools (500)</td><td>under 0.5ms</td></tr><tr><td>Sort and take top N</td><td>under 0.1ms</td></tr><tr><td><strong>Total</strong></td><td><strong>under 1ms</strong></td></tr></tbody></table>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="llm-search-200-500ms">LLM Search: 200-500ms<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#llm-search-200-500ms" class="hash-link" aria-label="Direct link to LLM Search: 200-500ms" title="Direct link to LLM Search: 200-500ms">​</a></h3>
<p>When Gemini is configured, mcpzip sends the query and a compact tool catalog to the Gemini API. Latency depends on:</p>
<ul>
<li>Network round-trip to Gemini (~50-100ms)</li>
<li>Gemini inference time (~100-300ms)</li>
<li>Response parsing (~1ms)</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="query-cache-under-01ms">Query Cache: under 0.1ms<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#query-cache-under-01ms" class="hash-link" aria-label="Direct link to Query Cache: under 0.1ms" title="Direct link to Query Cache: under 0.1ms">​</a></h3>
<p>Repeated or similar queries hit the cache. Cache keys are normalized (lowercased, tokenized, sorted) so "slack send message" and "send message slack" are the same cache entry.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="combined-flow">Combined Flow<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#combined-flow" class="hash-link" aria-label="Direct link to Combined Flow" title="Direct link to Combined Flow">​</a></h3>
<p>On a cache miss with Gemini enabled:</p>
<ol>
<li>Keyword search runs immediately: under 1ms</li>
<li>LLM search runs in parallel: 200-500ms</li>
<li>Results are merged and cached: under 1ms</li>
</ol>
<p><strong>Total: 200-500ms</strong> (dominated by LLM network latency)</p>
<p>On a cache hit: <strong>under 0.1ms</strong></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="memory-footprint">Memory Footprint<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#memory-footprint" class="hash-link" aria-label="Direct link to Memory Footprint" title="Direct link to Memory Footprint">​</a></h2>
<p>mcpzip is designed to be lightweight. It runs as a child process of Claude Code, so every megabyte matters.</p>
<table><thead><tr><th>State</th><th>RSS</th></tr></thead><tbody><tr><td>Startup (no cache)</td><td>~10 MB</td></tr><tr><td>Idle (500 tools cached)</td><td>~15 MB</td></tr><tr><td>Active (5 stdio connections)</td><td>~20 MB*</td></tr><tr><td>Active (5 HTTP connections)</td><td>~18 MB</td></tr><tr><td>Peak (catalog refresh, 10 servers)</td><td>~25 MB</td></tr></tbody></table>
<p>*stdio connections spawn child processes (e.g., <code>npx @anthropic/slack-mcp</code>). Those processes have their own memory, typically 30-100MB each. The ~20MB figure is mcpzip itself, not including the child processes.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-so-small">Why So Small?<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#why-so-small" class="hash-link" aria-label="Direct link to Why So Small?" title="Direct link to Why So Small?">​</a></h3>
<ol>
<li><strong>No garbage collector</strong> -- Rust uses compile-time memory management. No GC pauses, no overhead.</li>
<li><strong>No runtime</strong> -- Rust compiles to native code. No JVM, no V8, no interpreter.</li>
<li><strong>Compact data structures</strong> -- Tool entries use <code>String</code> and <code>serde_json::Value</code>, not heavyweight ORM objects.</li>
<li><strong>Lazy connections</strong> -- Upstream connections are created on first use, not at startup.</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="binary-size-58mb">Binary Size: 5.8MB<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#binary-size-58mb" class="hash-link" aria-label="Direct link to Binary Size: 5.8MB" title="Direct link to Binary Size: 5.8MB">​</a></h2>
<table><thead><tr><th>Version</th><th>Size</th></tr></thead><tbody><tr><td>mcpzip (Rust, release, stripped)</td><td><strong>5.8 MB</strong></td></tr><tr><td>mcpzip (Go, release, stripped)</td><td>11 MB</td></tr><tr><td>Typical Node.js MCP server</td><td>50-200 MB</td></tr><tr><td>mcp-remote (Node.js)</td><td>~80 MB</td></tr></tbody></table>
<p>The Rust binary is statically linked with musl libc on Linux, meaning it runs on any Linux distribution without installing runtime dependencies. On macOS, it links against system libraries.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-in-the-binary">What is in the binary?<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#what-is-in-the-binary" class="hash-link" aria-label="Direct link to What is in the binary?" title="Direct link to What is in the binary?">​</a></h3>
<ul>
<li>Tokio async runtime (~1.5MB)</li>
<li>HTTP client (reqwest) (~1MB)</li>
<li>JSON parser (serde_json) (~0.3MB)</li>
<li>MCP protocol implementation (~0.5MB)</li>
<li>CLI framework (clap) (~0.3MB)</li>
<li>Business logic (~0.5MB)</li>
<li>Other dependencies (~1.7MB)</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="connection-pooling">Connection Pooling<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#connection-pooling" class="hash-link" aria-label="Direct link to Connection Pooling" title="Direct link to Connection Pooling">​</a></h2>
<p>mcpzip maintains a connection pool with lazy initialization and idle reaping.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="lazy-connects">Lazy Connects<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#lazy-connects" class="hash-link" aria-label="Direct link to Lazy Connects" title="Direct link to Lazy Connects">​</a></h3>
<p>Connections are created on first use. If you have 10 servers configured but only use 3, only 3 connections are created.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="idle-timeout">Idle Timeout<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#idle-timeout" class="hash-link" aria-label="Direct link to Idle Timeout" title="Direct link to Idle Timeout">​</a></h3>
<p>Idle connections are closed after 5 minutes (configurable). This is important for stdio connections, which are full OS processes consuming resources.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="concurrent-startup">Concurrent Startup<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#concurrent-startup" class="hash-link" aria-label="Direct link to Concurrent Startup" title="Direct link to Concurrent Startup">​</a></h3>
<p>During catalog refresh, all servers are connected in parallel with a 30-second per-server timeout. A slow server does not block the others.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="reconnection">Reconnection<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#reconnection" class="hash-link" aria-label="Direct link to Reconnection" title="Direct link to Reconnection">​</a></h3>
<p>If a connection drops (process crashes, network error), it is automatically re-established on the next <code>execute_tool</code> call. No manual intervention needed.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="tool-call-latency">Tool Call Latency<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#tool-call-latency" class="hash-link" aria-label="Direct link to Tool Call Latency" title="Direct link to Tool Call Latency">​</a></h2>
<p>The overhead mcpzip adds to a tool call is minimal:</p>
<table><thead><tr><th>Phase</th><th>Time</th></tr></thead><tbody><tr><td>Parse prefixed name</td><td>under 0.01ms</td></tr><tr><td>Connection pool lookup</td><td>under 0.01ms</td></tr><tr><td>Argument serialization</td><td>under 0.1ms</td></tr><tr><td><strong>mcpzip overhead</strong></td><td><strong>under 0.15ms</strong></td></tr><tr><td>Upstream tool execution</td><td>varies (1ms - 30s)</td></tr><tr><td>Result deserialization</td><td>under 0.1ms</td></tr></tbody></table>
<p>The total overhead is under 0.3ms. Tool call latency is entirely dominated by the upstream server's execution time, not mcpzip.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a href="https://hypercall-public.github.io/mcpzip/blog/benchmarks#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary">​</a></h2>
<table><thead><tr><th>Metric</th><th>Value</th></tr></thead><tbody><tr><td>Time to first request</td><td>under 5ms</td></tr><tr><td>Keyword search latency</td><td>under 1ms</td></tr><tr><td>LLM search latency</td><td>200-500ms</td></tr><tr><td>Cache hit latency</td><td>under 0.1ms</td></tr><tr><td>Tool call overhead</td><td>under 0.3ms</td></tr><tr><td>Memory (idle)</td><td>~15MB</td></tr><tr><td>Memory (active)</td><td>~20MB</td></tr><tr><td>Binary size</td><td>5.8MB</td></tr><tr><td>Test count</td><td>240+</td></tr></tbody></table>
<p>mcpzip is designed to be invisible. It starts instantly, searches in milliseconds, and adds negligible overhead to tool calls. The only thing you notice is that your context window is 99% larger.</p>
<hr>
<p>mcpzip is open source at <a href="https://github.com/hypercall-public/mcpzip" target="_blank" rel="noopener noreferrer">github.com/hypercall-public/mcpzip</a>. Built by <a href="https://hypercall.xyz/" target="_blank" rel="noopener noreferrer">Hypercall</a>.</p>]]></content>
        <author>
            <name>Hypercall Team</name>
            <uri>https://hypercall.xyz</uri>
        </author>
        <category label="performance" term="performance"/>
        <category label="benchmarks" term="benchmarks"/>
        <category label="engineering" term="engineering"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[How mcpzip Saves 99% of Your Context Window]]></title>
        <id>https://hypercall-public.github.io/mcpzip/blog/context-compression</id>
        <link href="https://hypercall-public.github.io/mcpzip/blog/context-compression"/>
        <updated>2026-03-28T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[If you use MCP tools with Claude Code, you are probably burning tens of thousands of tokens on tool schemas -- before your conversation even starts. Here is the math, and how mcpzip fixes it.]]></summary>
        <content type="html"><![CDATA[<p>If you use MCP tools with Claude Code, you are probably burning tens of thousands of tokens on tool schemas -- before your conversation even starts. Here is the math, and how mcpzip fixes it.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-problem">The Problem<a href="https://hypercall-public.github.io/mcpzip/blog/context-compression#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem">​</a></h2>
<p>Every MCP tool has a JSON Schema that describes its parameters. When Claude Code connects to an MCP server, it calls <code>tools/list</code> and loads every tool schema into the context window. This happens on <strong>every message</strong>.</p>
<p>A typical tool schema looks like this:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token property" style="color:hsl(355, 65%, 65%)">"name"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"send_message"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token property" style="color:hsl(355, 65%, 65%)">"description"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"Send a message to a Slack channel or direct message"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token property" style="color:hsl(355, 65%, 65%)">"inputSchema"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token property" style="color:hsl(355, 65%, 65%)">"type"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"object"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token property" style="color:hsl(355, 65%, 65%)">"properties"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token property" style="color:hsl(355, 65%, 65%)">"channel"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token property" style="color:hsl(355, 65%, 65%)">"type"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"string"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token property" style="color:hsl(355, 65%, 65%)">"description"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"Channel ID or name (e.g., #general or C01234567)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token property" style="color:hsl(355, 65%, 65%)">"text"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token property" style="color:hsl(355, 65%, 65%)">"type"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"string"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token property" style="color:hsl(355, 65%, 65%)">"description"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"The message text, supports Slack markdown"</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token property" style="color:hsl(355, 65%, 65%)">"thread_ts"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token property" style="color:hsl(355, 65%, 65%)">"type"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"string"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token property" style="color:hsl(355, 65%, 65%)">"description"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"Thread timestamp to reply in a thread"</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token property" style="color:hsl(355, 65%, 65%)">"unfurl_links"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token property" style="color:hsl(355, 65%, 65%)">"type"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"boolean"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token property" style="color:hsl(355, 65%, 65%)">"description"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"Whether to unfurl URLs"</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">      </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token property" style="color:hsl(355, 65%, 65%)">"required"</span><span class="token operator" style="color:hsl(207, 82%, 66%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token string" style="color:hsl(95, 38%, 62%)">"channel"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(95, 38%, 62%)">"text"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">  </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This single tool consumes <strong>~350 tokens</strong>. Now multiply.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-math">The Math<a href="https://hypercall-public.github.io/mcpzip/blog/context-compression#the-math" class="hash-link" aria-label="Direct link to The Math" title="Direct link to The Math">​</a></h2>
<table><thead><tr><th>Setup</th><th>Servers</th><th>Tools/Server</th><th>Total Tools</th><th>Tokens</th></tr></thead><tbody><tr><td>Light</td><td>3</td><td>15</td><td>45</td><td>15,750</td></tr><tr><td>Medium</td><td>5</td><td>30</td><td>150</td><td>52,500</td></tr><tr><td>Heavy</td><td>10</td><td>50</td><td>500</td><td>175,000</td></tr><tr><td>Power</td><td>15</td><td>60</td><td>900</td><td>315,000</td></tr></tbody></table>
<p>With Claude's 200K context window, a heavy setup uses <strong>87.5%</strong> of the context just for tool schemas. A power setup <strong>exceeds</strong> the context window entirely.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="with-mcpzip">With mcpzip<a href="https://hypercall-public.github.io/mcpzip/blog/context-compression#with-mcpzip" class="hash-link" aria-label="Direct link to With mcpzip" title="Direct link to With mcpzip">​</a></h2>
<p>mcpzip replaces all tool schemas with exactly 3 meta-tools:</p>
<table><thead><tr><th>Meta-Tool</th><th>Purpose</th><th>Size</th></tr></thead><tbody><tr><td><code>search_tools</code></td><td>Find tools by query</td><td>~400 tokens</td></tr><tr><td><code>describe_tool</code></td><td>Get full schema on demand</td><td>~400 tokens</td></tr><tr><td><code>execute_tool</code></td><td>Run a tool</td><td>~400 tokens</td></tr><tr><td><strong>Total</strong></td><td></td><td><strong>~1,200 tokens</strong></td></tr></tbody></table>
<p>The savings:</p>
<table><thead><tr><th>Setup</th><th>Without mcpzip</th><th>With mcpzip</th><th>Savings</th></tr></thead><tbody><tr><td>Light (45 tools)</td><td>15,750</td><td>1,200</td><td><strong>92.4%</strong></td></tr><tr><td>Medium (150 tools)</td><td>52,500</td><td>1,200</td><td><strong>97.7%</strong></td></tr><tr><td>Heavy (500 tools)</td><td>175,000</td><td>1,200</td><td><strong>99.3%</strong></td></tr><tr><td>Power (900 tools)</td><td>315,000</td><td>1,200</td><td><strong>99.6%</strong></td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="try-it-yourself">Try It Yourself<a href="https://hypercall-public.github.io/mcpzip/blog/context-compression#try-it-yourself" class="hash-link" aria-label="Direct link to Try It Yourself" title="Direct link to Try It Yourself">​</a></h2>
<div style="background:rgba(255,255,255,0.02);border:1px solid rgba(255,255,255,0.08);border-radius:16px;padding:28px;margin:24px 0"><div style="font-size:16px;font-weight:700;color:#fff;margin-bottom:20px">Token Savings Calculator</div><div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:24px"><div><label style="display:block;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:rgba(255,255,255,0.4);margin-bottom:8px">MCP Servers</label><input type="range" min="1" max="20" style="width:100%;accent-color:#5CF53D" value="5"><div style="font-size:28px;font-weight:700;color:#5CF53D;margin-top:4px">5</div></div><div><label style="display:block;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.08em;color:rgba(255,255,255,0.4);margin-bottom:8px">Tools per Server</label><input type="range" min="1" max="150" style="width:100%;accent-color:#5CF53D" value="25"><div style="font-size:28px;font-weight:700;color:#5CF53D;margin-top:4px">25</div></div></div><div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-bottom:24px"><div style="background:rgba(248, 113, 113, 0.06);border:1px solid rgba(248, 113, 113, 0.15);border-radius:10px;padding:14px;text-align:center"><div style="font-size:11px;color:rgba(255,255,255,0.4);margin-bottom:4px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em">Without mcpzip</div><div style="font-size:22px;font-weight:700;color:#F87171">43,750</div><div style="font-size:11px;color:rgba(255,255,255,0.35)">tokens</div></div><div style="background:rgba(92, 245, 61, 0.06);border:1px solid rgba(92, 245, 61, 0.15);border-radius:10px;padding:14px;text-align:center"><div style="font-size:11px;color:rgba(255,255,255,0.4);margin-bottom:4px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em">With mcpzip</div><div style="font-size:22px;font-weight:700;color:#5CF53D">1,200</div><div style="font-size:11px;color:rgba(255,255,255,0.35)">tokens</div></div><div style="background:rgba(167, 139, 250, 0.06);border:1px solid rgba(167, 139, 250, 0.15);border-radius:10px;padding:14px;text-align:center"><div style="font-size:11px;color:rgba(255,255,255,0.4);margin-bottom:4px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em">Savings</div><div style="font-size:22px;font-weight:700;color:#A78BFA">97<!-- -->%</div><div style="font-size:11px;color:rgba(255,255,255,0.35)">42,550<!-- --> tokens saved</div></div></div><div style="margin-top:8px"><div style="display:flex;align-items:center;gap:10px;margin-bottom:8px"><div style="width:80px;font-size:11px;color:rgba(255,255,255,0.4);font-weight:500">Without</div><div style="flex:1;background:rgba(255,255,255,0.04);border-radius:6px;height:24px;overflow:hidden"><div style="width:100%;height:100%;background:linear-gradient(90deg, rgba(248,113,113,0.4), rgba(248,113,113,0.2));border-radius:6px;transition:width 0.4s ease"></div></div><div style="width:70px;font-size:12px;color:#F87171;font-weight:600;text-align:right">125<!-- --> tools</div></div><div style="display:flex;align-items:center;gap:10px"><div style="width:80px;font-size:11px;color:rgba(255,255,255,0.4);font-weight:500">With</div><div style="flex:1;background:rgba(255,255,255,0.04);border-radius:6px;height:24px;overflow:hidden"><div style="width:2.742857142857143%;height:100%;background:linear-gradient(90deg, rgba(92,245,61,0.5), rgba(92,245,61,0.25));border-radius:6px;transition:width 0.4s ease"></div></div><div style="width:70px;font-size:12px;color:#5CF53D;font-weight:600;text-align:right">3 tools</div></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-this-matters">Why This Matters<a href="https://hypercall-public.github.io/mcpzip/blog/context-compression#why-this-matters" class="hash-link" aria-label="Direct link to Why This Matters" title="Direct link to Why This Matters">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-more-room-for-conversation">1. More Room for Conversation<a href="https://hypercall-public.github.io/mcpzip/blog/context-compression#1-more-room-for-conversation" class="hash-link" aria-label="Direct link to 1. More Room for Conversation" title="Direct link to 1. More Room for Conversation">​</a></h3>
<p>Every token spent on tool schemas is a token you cannot use for your actual conversation. With 500 tools consuming 175K tokens, you have only 25K tokens left for your prompt, conversation history, and model output. That is barely enough for a meaningful interaction.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="2-faster-responses">2. Faster Responses<a href="https://hypercall-public.github.io/mcpzip/blog/context-compression#2-faster-responses" class="hash-link" aria-label="Direct link to 2. Faster Responses" title="Direct link to 2. Faster Responses">​</a></h3>
<p>More context tokens means more processing time. The model has to read and attend to all those tool schemas on every message, even if it is not going to use any of them. Fewer tokens means faster inference.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-better-tool-selection">3. Better Tool Selection<a href="https://hypercall-public.github.io/mcpzip/blog/context-compression#3-better-tool-selection" class="hash-link" aria-label="Direct link to 3. Better Tool Selection" title="Direct link to 3. Better Tool Selection">​</a></h3>
<p>Research and practical experience show that LLMs make worse tool choices when presented with too many options. With 500 tools, the model might:</p>
<ul>
<li>Pick a similar but wrong tool</li>
<li>Hallucinate parameters from a different tool</li>
<li>Fail to find the right tool entirely</li>
</ul>
<p>With 3 meta-tools and on-demand search, Claude gets exactly the tools it needs, when it needs them.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="4-no-hard-limits">4. No Hard Limits<a href="https://hypercall-public.github.io/mcpzip/blog/context-compression#4-no-hard-limits" class="hash-link" aria-label="Direct link to 4. No Hard Limits" title="Direct link to 4. No Hard Limits">​</a></h3>
<p>Some models cap the number of tools they can handle. GPT-4 starts degrading noticeably past ~60 tools. By compressing everything behind 3 meta-tools, mcpzip removes this limit entirely.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-compact-representation">The Compact Representation<a href="https://hypercall-public.github.io/mcpzip/blog/context-compression#the-compact-representation" class="hash-link" aria-label="Direct link to The Compact Representation" title="Direct link to The Compact Representation">​</a></h2>
<p>When mcpzip returns search results, it uses a compact format that is ~7x smaller than full JSON schemas:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">slack__send_message: Send a Slack message [channel:string*, text:string*]</span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">todoist__create_task: Create a new task [content:string*, project_id:string]</span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">github__create_issue: Create a GitHub issue [title:string*, body:string]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Each line is ~50 tokens instead of ~350 tokens. The <code>*</code> marks required parameters. Claude gets enough information to decide which tool to use and can optionally call <code>describe_tool</code> for the full schema if it needs more detail.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="getting-started">Getting Started<a href="https://hypercall-public.github.io/mcpzip/blog/context-compression#getting-started" class="hash-link" aria-label="Direct link to Getting Started" title="Direct link to Getting Started">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token comment" style="color:hsl(220, 10%, 40%)"># Install</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token function" style="color:hsl(207, 82%, 66%)">cargo</span><span class="token plain"> </span><span class="token function" style="color:hsl(207, 82%, 66%)">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(207, 82%, 66%)">--git</span><span class="token plain"> https://github.com/hypercall-public/mcpzip</span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)"># Migrate from existing Claude Code config</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">mcpzip migrate --dry-run  </span><span class="token comment" style="color:hsl(220, 10%, 40%)"># preview</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">mcpzip migrate             </span><span class="token comment" style="color:hsl(220, 10%, 40%)"># do it</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token comment" style="color:hsl(220, 10%, 40%)"># Restart Claude Code</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>That is it. Your existing MCP servers keep working, but now they are behind mcpzip's 3 meta-tools instead of flooding the context window.</p>
<hr>
<p>mcpzip is open source at <a href="https://github.com/hypercall-public/mcpzip" target="_blank" rel="noopener noreferrer">github.com/hypercall-public/mcpzip</a>. Built by <a href="https://hypercall.xyz/" target="_blank" rel="noopener noreferrer">Hypercall</a>.</p>]]></content>
        <author>
            <name>Hypercall Team</name>
            <uri>https://hypercall.xyz</uri>
        </author>
        <category label="mcp" term="mcp"/>
        <category label="context-window" term="context-window"/>
        <category label="performance" term="performance"/>
        <category label="ai" term="ai"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Why We Rewrote mcpzip from Go to Rust]]></title>
        <id>https://hypercall-public.github.io/mcpzip/blog/rust-rewrite</id>
        <link href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite"/>
        <updated>2026-03-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[mcpzip started as a Go project. It worked well -- the Go SDK for MCP was solid, the binary was reasonable, and the codebase was clean. But as we pushed the proxy harder with more servers, more tools, and tighter performance requirements, we hit Go's limits.]]></summary>
        <content type="html"><![CDATA[<p>mcpzip started as a Go project. It worked well -- the Go SDK for MCP was solid, the binary was reasonable, and the codebase was clean. But as we pushed the proxy harder with more servers, more tools, and tighter performance requirements, we hit Go's limits.</p>
<p>So we rewrote the entire thing in Rust. Here is why, and how it went.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-numbers">The Numbers<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#the-numbers" class="hash-link" aria-label="Direct link to The Numbers" title="Direct link to The Numbers">​</a></h2>
<table><thead><tr><th>Metric</th><th>Go Version</th><th>Rust Version</th><th>Change</th></tr></thead><tbody><tr><td>Files</td><td>45</td><td>35</td><td>-22%</td></tr><tr><td>Lines of code</td><td>5,703</td><td>8,147</td><td>+43% (more tests)</td></tr><tr><td>Binary size</td><td>11 MB</td><td>5.8 MB</td><td><strong>-47%</strong></td></tr><tr><td>Tests</td><td>~60</td><td>240+</td><td><strong>4x more</strong></td></tr><tr><td>Dependencies</td><td>~30</td><td>~25</td><td>-17%</td></tr></tbody></table>
<p>The Rust version is 47% smaller as a binary, has 4x more tests, and uses fewer files despite being more code (because test code is colocated with source in Rust).</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-rewrite">Why Rewrite?<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#why-rewrite" class="hash-link" aria-label="Direct link to Why Rewrite?" title="Direct link to Why Rewrite?">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-binary-size">1. Binary Size<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#1-binary-size" class="hash-link" aria-label="Direct link to 1. Binary Size" title="Direct link to 1. Binary Size">​</a></h3>
<p>Go's runtime and garbage collector add a fixed overhead. Our Go binary was 11MB -- not huge, but unnecessary for what is essentially a proxy. The Rust binary is 5.8MB with zero runtime overhead.</p>
<p>For a tool that gets installed on developer machines and runs as a child process of Claude Code, every megabyte matters.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="2-memory-usage">2. Memory Usage<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#2-memory-usage" class="hash-link" aria-label="Direct link to 2. Memory Usage" title="Direct link to 2. Memory Usage">​</a></h3>
<p>Go's garbage collector means unpredictable memory spikes during catalog refresh. With 500+ tools and 10+ upstream connections, these spikes were noticeable. Rust's ownership model gives us predictable, low memory usage.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-concurrency-model">3. Concurrency Model<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#3-concurrency-model" class="hash-link" aria-label="Direct link to 3. Concurrency Model" title="Direct link to 3. Concurrency Model">​</a></h3>
<p>mcpzip needs careful concurrency: multiple upstream connections, parallel search strategies, background catalog refresh, and real-time tool calls -- all at once.</p>
<p>Go's goroutines are lightweight, but sharing mutable state requires careful channel choreography or mutex discipline. Rust's type system enforces correct concurrency at compile time:</p>
<p><strong>Go version</strong> -- runtime race detection:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:hsl(286, 60%, 67%)">type</span><span class="token plain"> Catalog </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">struct</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    mu    sync</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">RWMutex</span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    tools </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">map</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token builtin" style="color:hsl(95, 38%, 62%)">string</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token operator" style="color:hsl(207, 82%, 66%)">*</span><span class="token plain">ToolEntry</span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    path  </span><span class="token builtin" style="color:hsl(95, 38%, 62%)">string</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:hsl(286, 60%, 67%)">func</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">c </span><span class="token operator" style="color:hsl(207, 82%, 66%)">*</span><span class="token plain">Catalog</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token function" style="color:hsl(207, 82%, 66%)">GetTool</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">name </span><span class="token builtin" style="color:hsl(95, 38%, 62%)">string</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token operator" style="color:hsl(207, 82%, 66%)">*</span><span class="token plain">ToolEntry</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token builtin" style="color:hsl(95, 38%, 62%)">bool</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    c</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">mu</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">RLock</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">defer</span><span class="token plain"> c</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">mu</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">RUnlock</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    t</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> ok </span><span class="token operator" style="color:hsl(207, 82%, 66%)">:=</span><span class="token plain"> c</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">tools</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token plain">name</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">return</span><span class="token plain"> t</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> ok</span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Rust version</strong> -- compile-time safety:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:hsl(286, 60%, 67%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(29, 54%, 61%)">Catalog</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    tools</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">RwLock</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&lt;</span><span class="token class-name" style="color:hsl(29, 54%, 61%)">HashMap</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&lt;</span><span class="token class-name" style="color:hsl(29, 54%, 61%)">String</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">ToolEntry</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&gt;&gt;</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    cache_path</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">PathBuf</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token keyword" style="color:hsl(286, 60%, 67%)">impl</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">Catalog</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(207, 82%, 66%)">get_tool</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&amp;</span><span class="token keyword" style="color:hsl(286, 60%, 67%)">self</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> name</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(207, 82%, 66%)">&amp;</span><span class="token keyword" style="color:hsl(286, 60%, 67%)">str</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">-&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">Option</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&lt;</span><span class="token class-name" style="color:hsl(29, 54%, 61%)">ToolEntry</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">let</span><span class="token plain"> tools </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">self</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">tools</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">read</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">unwrap</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        tools</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">get</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">name</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">cloned</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Both use a <code>RwLock</code>, but Rust's borrow checker ensures you <strong>cannot</strong> forget to acquire the lock or accidentally access the data without it. In Go, nothing stops you from accessing <code>c.tools</code> directly -- you rely on discipline and race detectors to catch mistakes.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="4-error-handling">4. Error Handling<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#4-error-handling" class="hash-link" aria-label="Direct link to 4. Error Handling" title="Direct link to 4. Error Handling">​</a></h3>
<p>Go's <code>if err != nil</code> pattern is verbose but workable. Rust's <code>Result</code> and <code>?</code> operator give us the same explicit error handling with less boilerplate:</p>
<p><strong>Go</strong>:</p>
<div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:hsl(286, 60%, 67%)">func</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">c </span><span class="token operator" style="color:hsl(207, 82%, 66%)">*</span><span class="token plain">Catalog</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token function" style="color:hsl(207, 82%, 66%)">Load</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token builtin" style="color:hsl(95, 38%, 62%)">error</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    data</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> err </span><span class="token operator" style="color:hsl(207, 82%, 66%)">:=</span><span class="token plain"> os</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">ReadFile</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">c</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">path</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">if</span><span class="token plain"> err </span><span class="token operator" style="color:hsl(207, 82%, 66%)">!=</span><span class="token plain"> </span><span class="token boolean" style="color:hsl(29, 54%, 61%)">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">return</span><span class="token plain"> fmt</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">Errorf</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:hsl(95, 38%, 62%)">"load catalog: %w"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> err</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">var</span><span class="token plain"> tools </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">map</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">[</span><span class="token builtin" style="color:hsl(95, 38%, 62%)">string</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">]</span><span class="token operator" style="color:hsl(207, 82%, 66%)">*</span><span class="token plain">ToolEntry</span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">if</span><span class="token plain"> err </span><span class="token operator" style="color:hsl(207, 82%, 66%)">:=</span><span class="token plain"> json</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">Unmarshal</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token plain">data</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token operator" style="color:hsl(207, 82%, 66%)">&amp;</span><span class="token plain">tools</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"> err </span><span class="token operator" style="color:hsl(207, 82%, 66%)">!=</span><span class="token plain"> </span><span class="token boolean" style="color:hsl(29, 54%, 61%)">nil</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">        </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">return</span><span class="token plain"> fmt</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">Errorf</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token string" style="color:hsl(95, 38%, 62%)">"parse catalog: %w"</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> err</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    c</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">mu</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">Lock</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    c</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">tools </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> tools</span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    c</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">mu</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">Unlock</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">return</span><span class="token plain"> </span><span class="token boolean" style="color:hsl(29, 54%, 61%)">nil</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Rust</strong>:</p>
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token keyword" style="color:hsl(286, 60%, 67%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(207, 82%, 66%)">load</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&amp;</span><span class="token keyword" style="color:hsl(286, 60%, 67%)">self</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">-&gt;</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">Result</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&lt;</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">McpzipError</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">let</span><span class="token plain"> data </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(220, 14%, 71%)">::</span><span class="token namespace">fs</span><span class="token namespace punctuation" style="color:hsl(220, 14%, 71%)">::</span><span class="token function" style="color:hsl(207, 82%, 66%)">read_to_string</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&amp;</span><span class="token keyword" style="color:hsl(286, 60%, 67%)">self</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">cache_path</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token operator" style="color:hsl(207, 82%, 66%)">?</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token keyword" style="color:hsl(286, 60%, 67%)">let</span><span class="token plain"> tools</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">HashMap</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&lt;</span><span class="token class-name" style="color:hsl(29, 54%, 61%)">String</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">ToolEntry</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> </span><span class="token namespace">serde_json</span><span class="token namespace punctuation" style="color:hsl(220, 14%, 71%)">::</span><span class="token function" style="color:hsl(207, 82%, 66%)">from_str</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token operator" style="color:hsl(207, 82%, 66%)">&amp;</span><span class="token plain">data</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token operator" style="color:hsl(207, 82%, 66%)">?</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token operator" style="color:hsl(207, 82%, 66%)">*</span><span class="token keyword" style="color:hsl(286, 60%, 67%)">self</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token plain">tools</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">write</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">.</span><span class="token function" style="color:hsl(207, 82%, 66%)">unwrap</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(207, 82%, 66%)">=</span><span class="token plain"> tools</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain">    </span><span class="token class-name" style="color:hsl(29, 54%, 61%)">Ok</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">(</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(220, 14%, 71%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Same logic, half the code. The <code>?</code> operator propagates errors automatically, and the <code>From</code> trait handles error type conversion.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-was-preserved">What Was Preserved<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#what-was-preserved" class="hash-link" aria-label="Direct link to What Was Preserved" title="Direct link to What Was Preserved">​</a></h2>
<p>The Rust rewrite is a faithful port. Everything that worked in Go works the same way in Rust:</p>
<ul>
<li><strong>Same config format</strong> -- your <code>config.json</code> works without changes</li>
<li><strong>Same 3 meta-tools</strong> -- <code>search_tools</code>, <code>describe_tool</code>, <code>execute_tool</code></li>
<li><strong>Same architecture</strong> -- ProxyServer, Catalog, Manager, Searcher</li>
<li><strong>Same search algorithm</strong> -- keyword + Gemini orchestrated search</li>
<li><strong>Same OAuth flow</strong> -- PKCE, browser callback, token persistence</li>
<li><strong>Same CLI</strong> -- <code>serve</code>, <code>init</code>, <code>migrate</code> with the same flags</li>
<li><strong>Same file locations</strong> -- <code>~/.config/compressed-mcp-proxy/</code></li>
</ul>
<p>If you were using the Go version, the Rust version is a drop-in replacement.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-improved">What Improved<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#what-improved" class="hash-link" aria-label="Direct link to What Improved" title="Direct link to What Improved">​</a></h2>
<p>Beyond the raw performance numbers, several things got better:</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="background-catalog-refresh">Background Catalog Refresh<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#background-catalog-refresh" class="hash-link" aria-label="Direct link to Background Catalog Refresh" title="Direct link to Background Catalog Refresh">​</a></h3>
<p>The Go version refreshed the catalog synchronously on startup. The Rust version loads from disk cache immediately and refreshes in the background. First request is served in under 5ms instead of waiting for all servers to connect.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="sse-parsing">SSE Parsing<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#sse-parsing" class="hash-link" aria-label="Direct link to SSE Parsing" title="Direct link to SSE Parsing">​</a></h3>
<p>The Rust version uses a more robust SSE parser that handles edge cases in multi-line <code>data:</code> fields and reconnection.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="oauth-token-reuse">OAuth Token Reuse<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#oauth-token-reuse" class="hash-link" aria-label="Direct link to OAuth Token Reuse" title="Direct link to OAuth Token Reuse">​</a></h3>
<p>The Rust version checks for mcp-remote tokens in addition to its own, so you do not have to re-authenticate if you have already used mcp-remote with the same server.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="test-coverage">Test Coverage<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#test-coverage" class="hash-link" aria-label="Direct link to Test Coverage" title="Direct link to Test Coverage">​</a></h3>
<p>We went from ~60 tests to 240+. Every module has comprehensive unit tests, including edge cases like:</p>
<ul>
<li>Nullable JSON types (<code>"type": ["string", "null"]</code>)</li>
<li><code>anyOf</code> schemas</li>
<li>Double-underscore tool name parsing</li>
<li>Config validation (missing commands, invalid types)</li>
<li>Token refresh and expiration</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-claude-code-experience">The Claude Code Experience<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#the-claude-code-experience" class="hash-link" aria-label="Direct link to The Claude Code Experience" title="Direct link to The Claude Code Experience">​</a></h2>
<p>Both the Go and Rust versions were written with <a href="https://claude.ai/claude-code" target="_blank" rel="noopener noreferrer">Claude Code</a>. The rewrite was a fascinating exercise in using an AI coding assistant for a major port:</p>
<ol>
<li>We fed Claude the Go codebase and the MCP specification</li>
<li>Claude generated Rust modules matching the Go architecture</li>
<li>We iteratively refined the code with Claude, adding tests and fixing edge cases</li>
<li>The entire rewrite took about a day of wall-clock time</li>
</ol>
<p>The tight feedback loop -- write code, run tests, fix issues -- works exceptionally well with Claude Code. Having 240+ tests pass gives high confidence that the port is correct.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="should-you-rewrite-your-project">Should You Rewrite Your Project?<a href="https://hypercall-public.github.io/mcpzip/blog/rust-rewrite#should-you-rewrite-your-project" class="hash-link" aria-label="Direct link to Should You Rewrite Your Project?" title="Direct link to Should You Rewrite Your Project?">​</a></h2>
<p>Probably not. Rewrites are risky and usually not worth it. We did it because:</p>
<ol>
<li>mcpzip is relatively small (~6K LOC)</li>
<li>The architecture was clean and well-understood</li>
<li>We had specific, measurable goals (binary size, memory, test coverage)</li>
<li>We had 60+ tests as a safety net for the port</li>
</ol>
<p>If your project is larger, consider incremental improvements instead. But if you are starting fresh and care about binary size, memory usage, and compile-time safety, Rust is an excellent choice for CLI tools and proxies.</p>
<hr>
<p>mcpzip is open source at <a href="https://github.com/hypercall-public/mcpzip" target="_blank" rel="noopener noreferrer">github.com/hypercall-public/mcpzip</a>. Built by <a href="https://hypercall.xyz/" target="_blank" rel="noopener noreferrer">Hypercall</a>.</p>]]></content>
        <author>
            <name>Hypercall Team</name>
            <uri>https://hypercall.xyz</uri>
        </author>
        <category label="engineering" term="engineering"/>
        <category label="rust" term="rust"/>
        <category label="go" term="go"/>
        <category label="rewrite" term="rewrite"/>
    </entry>
</feed>