caveman-shrink MCP Middleware: A Complete Guide to Compressing MCP Server Responses
caveman-shrink is a stdio proxy middleware that intercepts Model Context Protocol (MCP) server responses and compresses prose fields like description to reduce token usage while preserving code fragments, URLs, and identifiers.
The caveman-shrink middleware is a lightweight Node.js utility from the JuliusBrussee/caveman repository that acts as a transparent proxy between MCP clients and upstream servers. It processes JSON-RPC traffic in real-time, applying intelligent text compression to reduce the token footprint of tool catalogs and resource listings without stripping syntactically meaningful content.
What caveman-shrink MCP Middleware Does
caveman-shrink functions as a stdio proxy that transparently sits between an MCP client (such as Claude Code) and an upstream MCP server. Its primary purpose is to compress prose fields—by default the description field—in JSON-RPC responses returned by the upstream server.
The compression algorithm follows the same token-saving rules as the caveman-compress skill: it preserves code fragments, URLs, file paths, identifiers, and other structured tokens while removing filler words, articles, and hedging language. This ensures that language models receive the essential semantic content without wasting tokens on verbose formatting.
How caveman-shrink Works: Architecture and Implementation
Understanding the internal architecture of caveman-shrink helps explain its efficiency and reliability.
Process Spawning and Management
The middleware entry point is src/mcp-servers/caveman-shrink/index.js, which executes as a Node.js script (#!/usr/bin/env node). It parses command-line arguments and spawns the upstream MCP server using child_process.spawn with platform-specific options imported from spawn-options.js (lines 45-52). Errors and exit codes from the upstream process propagate directly back to the caller, ensuring reliable error handling.
Line-Buffered JSON-RPC Processing
MCP transports JSON objects one per line. The makeLineBuffer function (lines 60-70 in index.js) accumulates incoming data chunks until it encounters a newline, then parses each complete line as JSON. This approach ensures that partial TCP packets or stdio buffers never corrupt the JSON-RPC message stream.
Response Transformation Logic
The transformResponse function (lines 73-100) inspects the result object of upstream responses and searches for arrays named tools, prompts, resources, or resourceTemplates. For each object within these arrays, it compresses fields specified in the CAVEMAN_SHRINK_FIELDS environment variable (default: description).
The actual compression logic resides in src/mcp-servers/caveman-shrink/compress.js, specifically the compress and compressDescriptionsInPlace functions. If any top-level fields are compressed, the helper skips compressDescriptionsInPlace to avoid double-processing nested schemas (lines 104-106).
Traffic Direction Handling
Client-to-upstream traffic passes through unchanged—version 1 does not modify request bodies. Only upstream-to-client responses undergo transformation, and only for the specific response types listed above.
Installing caveman-shrink
You can install the middleware globally or run it on-demand without installation.
Install globally using npm:
npm install -g caveman-shrink
Or use npx to run without installing:
npx caveman-shrink <upstream-cmd> [...args]
Configuring caveman-shrink in Claude Code
To use caveman-shrink with Claude Code or any MCP-compatible client, add a new entry under mcpServers in your configuration. The middleware wraps the real upstream command as arguments:
{
"mcpServers": {
"fs-shrunk": {
"command": "npx",
"args": [
"caveman-shrink",
"npx", "@modelcontextprotocol/server-filesystem", "/path/to/dir"
]
}
}
}
When Claude Code loads this configuration, it starts caveman-shrink, which in turn spawns the @modelcontextprotocol/server-filesystem server. Every tools/list, prompts/list, resources/list, or resourceTemplates/list response has its description fields compressed before reaching the model.
Customizing Compression Behavior
Configure which fields get compressed and enable debugging output using environment variables.
Targeting Specific Fields
Set CAVEMAN_SHRINK_FIELDS to a comma-separated list of field names:
CAVEMAN_SHRINK_FIELDS=description,summary \
npx caveman-shrink npx @modelcontextprotocol/server-filesystem /my/project
This compresses both description and summary fields in the MCP responses.
Debugging Compression Metrics
Enable debug mode to see per-field size deltas:
CAVEMAN_SHRINK_DEBUG=1 \
npx caveman-shrink npx @modelcontextprotocol/server-filesystem /my/project
When CAVEMAN_SHRINK_DEBUG=1 is set, the middleware writes compression statistics to stderr, showing exactly how many bytes or tokens were saved per field.
Summary
- caveman-shrink is a stdio proxy middleware from the JuliusBrussee/caveman repository that compresses MCP server responses to reduce token usage.
- It processes JSON-RPC line-by-line using
makeLineBufferand transforms responses viatransformResponseinsrc/mcp-servers/caveman-shrink/index.js. - By default, it compresses the
descriptionfield intools,prompts,resources, andresourceTemplatesarrays while preserving code tokens and identifiers. - Configure custom fields using the
CAVEMAN_SHRINK_FIELDSenvironment variable and enable debugging withCAVEMAN_SHRINK_DEBUG=1. - Install via
npm install -g caveman-shrinkor run directly withnpx caveman-shrink <command>.
Frequently Asked Questions
What is the difference between caveman-shrink and caveman-compress?
While both tools reduce token usage, caveman-compress is a skill that operates on text directly within prompts, whereas caveman-shrink is a middleware that intercepts and modifies MCP server responses transparently. The shrink middleware applies the same compression rules as the compress skill but works at the protocol level between the client and server.
Does caveman-shrink modify MCP request bodies or only responses?
caveman-shrink only modifies upstream-to-client responses, specifically those containing tools, prompts, resources, or resourceTemplates lists. Client-to-upstream traffic passes through unchanged according to the source code in src/mcp-servers/caveman-shrink/index.js (lines 23-26).
Can I compress fields other than description?
Yes. Set the CAVEMAN_SHRINK_FIELDS environment variable to a comma-separated list of field names. For example, CAVEMAN_SHRINK_FIELDS=description,summary compresses both description and summary fields in the JSON-RPC responses.
How do I troubleshoot if caveman-shrink is not compressing responses?
Enable debug mode by setting CAVEMAN_SHRINK_DEBUG=1 before running the command. This outputs per-field size deltas to stderr, allowing you to verify that compression is occurring and measure the token savings. Check that your upstream server actually returns the fields specified in CAVEMAN_SHRINK_FIELDS.
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 →