caveman-shrink MCP Middleware: How It Compresses Tool Descriptions for Token Efficiency
The caveman-shrink MCP middleware is a proxy that intercepts JSON-RPC responses from upstream MCP servers and compresses tool descriptions by removing articles, filler words, and hedging phrases while preserving code blocks, URLs, and identifiers through a sentinel-based protection system.
The caveman-shrink middleware is part of the JuliusBrussee/caveman repository and solves a critical bottleneck in Model-Context-Protocol (MCP) integrations: verbose tool descriptions consume excessive context window tokens. By acting as a transparent proxy between clients like Claude and upstream MCP servers, it reduces token usage by 15–30% without sacrificing semantic meaning.
What Is caveman-shrink?
caveman-shrink functions as an MCP middleware proxy that spawns an upstream MCP server and intercepts its responses. According to the implementation in src/mcp-servers/caveman-shrink/index.js, the middleware creates a child process using spawn options defined in src/mcp-servers/caveman-shrink/spawn-options.js, then pipes stdin/stdout while applying transformations to specific JSON-RPC response types.
MCP Proxy Architecture
The middleware operates using a pass-through architecture with selective interception:
- Spawning: Executes the upstream server command (e.g.,
npx @modelcontextprotocol/server-filesystem) via Node.jschild_process.spawn - Request pass-through: Client requests flow unmodified to the upstream server
- Response buffering: Line-buffered JSON-RPC responses are parsed and analyzed
- Selective transformation: Only responses containing
tools,prompts,resources, orresourceTemplatesarrays trigger compression
Interception Points
The transformResponse function in index.js specifically targets four array types in JSON-RPC results:
toolspromptsresourcesresourceTemplates
When these arrays are detected, the middleware invokes compression routines on configured fields within each object.
How Tool Description Compression Works
The compression logic resides in src/mcp-servers/caveman-shrink/compress.js and implements a multi-stage text processing pipeline designed for LLM-friendly prose reduction.
The Compression Algorithm
The core compress() function applies systematic text reduction:
- Article removal: Strips
a,an, andtheto reduce token count without semantic loss - Filler elimination: Removes conversational padding like
sure,just, andbasicallythat LLMs ignore - Hedging deletion: Cuts tentative prefixes such as
I willorbasicallyfrom command descriptions - Whitespace normalization: Collapses multiple spaces and normalizes punctuation spacing
Sentinel Protection Strategy
Critical technical content is protected through a placeholder system:
- Pattern matching: Identifies code fences (```), inline code (
...), URLs, file paths, constant-style identifiers (SCREAMING_SNAKE_CASE), and enum strings - Placeholder substitution: Replaces protected sections with numbered sentinels before text processing
- Post-processing restoration: Restores original content verbatim after compression completes
This ensures functional identifiers like get_weather or paths like /usr/local/bin remain unchanged even when embedded in descriptive text.
Handling Nested Payloads
When top-level arrays don't match but descriptions exist deeper in the object hierarchy, the compressDescriptionsInPlace helper traverses the entire payload recursively. This catches nested parameter descriptions or metadata objects that might otherwise escape compression.
Configuration and Environment Variables
Behavior is controlled through environment variables:
CAVEMAN_SHRINK_FIELDS: Comma-separated list of field names to compress (default:description)CAVEMAN_SHRINK_DEBUG=1: Enables stderr logging showing byte-size deltas for each compressed field
The middleware deliberately excludes two critical areas from modification:
- Request payloads sent to the upstream server (preserves upstream parsing compatibility)
tools/callRPC responses (high-risk for downstream consumers expecting exact formatting)
Practical Implementation Examples
Running the Proxy
Register caveman-shrink in your MCP client configuration:
{
"mcpServers": {
"fs-shrunk": {
"command": "npx",
"args": ["caveman-shrink", "npx", "@modelcontextprotocol/server-filesystem", "/some/path"]
}
}
}
The proxy spawns the filesystem server and automatically compresses all description fields in list responses.
Compression Before and After
Consider this transformation applied by the compress() function:
// Original description from upstream server
"The user is the owner of an account and can manage it freely."
// After caveman-shrink processing
"User is owner of account can manage freely."
The test suite in tests/test_mcp_shrink.js validates that articles and filler words disappear while code blocks survive:
// Protected content remains verbatim
"Use `get_weather()` to fetch data from https://api.example.com"
// Becomes
"Use `get_weather()` to fetch data from https://api.example.com"
Debugging Token Savings
Enable debug logging to verify compression efficiency:
CAVEMAN_SHRINK_DEBUG=1 npx caveman-shrink npx @modelcontextprotocol/server-filesystem /tmp
Example stderr output from index.js:
[caveman-shrink] tools.get_weather.description: 78→52 bytes
Safety Guarantees and Limitations
The compression system maintains functional integrity through explicit boundaries:
- Immutable technical tokens: File paths, URLs, and code identifiers referenced by the LLM remain unchanged
- Recursive depth:
compressDescriptionsInPlacehandles arbitrarily nested objects within tool definitions - Protocol compliance: Only MCP list responses are modified; call responses and requests pass through untouched
Summary
- caveman-shrink acts as a transparent MCP proxy in
src/mcp-servers/caveman-shrink/index.js, spawning upstream servers and intercepting their JSON-RPC responses - The compression engine in
src/mcp-servers/caveman-shrink/compress.jsremoves articles, filler words, and hedging phrases while protecting code blocks, URLs, and identifiers via sentinel placeholders - Configuration via
CAVEMAN_SHRINK_FIELDSallows customization of which fields to compress, withCAVEMAN_SHRINK_DEBUGproviding visibility into byte savings - The
compressDescriptionsInPlacehelper ensures nested description fields are processed regardless of object depth - Request payloads and tool call responses remain unmodified to preserve upstream compatibility and downstream safety
Frequently Asked Questions
What is the caveman-shrink MCP middleware?
caveman-shrink is an MCP middleware proxy from the JuliusBrussee/caveman repository that sits between AI clients and MCP servers. It spawns upstream MCP servers and intercepts their JSON-RPC responses to compress verbose text fields—primarily tool descriptions—reducing token usage by 15–30% before the data reaches the language model.
How does caveman-shrink protect code blocks and URLs during compression?
The middleware uses a sentinel-based protection system in src/mcp-servers/caveman-shrink/compress.js. Before processing text, it identifies code fences, inline code, URLs, file paths, and constant-style identifiers, replacing them with numbered placeholders. After removing articles and filler words, it restores the original protected content verbatim, ensuring technical references remain exact.
Can I configure which fields get compressed?
Yes. Set the CAVEMAN_SHRINK_FIELDS environment variable to a comma-separated list of field names. By default, only description fields are compressed, but you can extend this to include summary, documentation, or custom fields your MCP server uses.
Does caveman-shrink modify requests sent to the upstream server?
No. The middleware specifically avoids touching request payloads sent to the upstream server to prevent breaking upstream parsing. It only transforms responses containing tools, prompts, resources, or resourceTemplates arrays, and explicitly excludes tools/call responses from modification.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →