# How MCP Shrink Middleware Works with Caveman: A Complete Technical Guide

> Discover how MCP shrink middleware seamlessly compresses prose fields with Caveman, preserving essential data like URLs and code tokens. Get the complete technical guide.

- Repository: [Julius Brussee/caveman](https://github.com/JuliusBrussee/caveman)
- Tags: deep-dive
- Published: 2026-07-07

---

**Caveman's MCP shrink middleware acts as a transparent proxy that intercepts list responses from any upstream MCP server and compresses prose fields using a token-efficient algorithm while preserving functional identifiers, URLs, and code tokens.**

The `caveman-shrink` middleware is a specialized component in the JuliusBrussee/caveman repository that reduces token usage in Model Context Protocol (MCP) communications. It sits between your AI client and any upstream MCP server, automatically rewriting descriptive text in `tools/list`, `prompts/list`, and `resources/list` responses without altering the underlying functionality or API contracts.

## Architecture and Proxy Flow

The middleware operates as a pure Node.js proxy that spawns the target MCP server as a child process. Located in [`src/mcp-servers/caveman-shrink/index.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/mcp-servers/caveman-shrink/index.js), the core implementation handles request forwarding and selective response transformation through three distinct stages.

### Spawning the Upstream Server

When you invoke `caveman-shrink`, the middleware uses [`src/mcp-servers/caveman-shrink/spawn-options.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/mcp-servers/caveman-shrink/spawn-options.js) to construct the proper `child_process.spawn` configuration. It takes the upstream command (e.g., `npx @modelcontextprotocol/server-filesystem /path/to/project`) and creates a child process with stdio pipes connected directly to the parent.

```javascript
// Conceptual flow from index.js
const spawn = require('child_process').spawn;
const options = require('./spawn-options.js');
const child = spawn(command, args, options);

```

This architecture ensures that the client sees a seamless MCP server while the middleware maintains full control over the data stream.

### Intercepting List Responses

The middleware parses each line of JSON output from the upstream server, identifying specific MCP method calls:

- `tools/list`
- `prompts/list`
- `resources/list`

For each object returned by these methods, [`index.js`](https://github.com/JuliusBrussee/caveman/blob/main/index.js) checks for fields matching the `CAVEMAN_SHRINK_FIELDS` environment variable (defaulting to `description`). When matching fields are found, the middleware extracts the text and passes it to the compression module before forwarding the modified payload to the client.

### The Compression Pipeline

The actual token reduction happens in [`src/mcp-servers/caveman-shrink/compress.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/mcp-servers/caveman-shrink/compress.js). This module implements the same compression algorithm used by the main Caveman skill, which:

- **Preserves** identifiers, URLs, file paths, and code-like tokens
- **Strips** filler words, hedging language, and pleasantries
- **Maintains** the semantic meaning of the description

When `CAVEMAN_SHRINK_DEBUG=1` is set, the middleware logs delta information showing the original and compressed text lengths for each processed field.

## Configuration and Environment Variables

The middleware behavior is controlled through two environment variables that require no code changes to adjust.

### CAVEMAN_SHRINK_FIELDS

This comma-separated list defines which JSON fields get compressed. By default, only `description` is processed, but you can target multiple fields:

```bash
CAVEMAN_SHRINK_FIELDS=description,summary,notes npx caveman-shrink npx @modelcontextprotocol/server-filesystem /my/repo

```

### CAVEMAN_SHRINK_DEBUG

Enable verbose logging to see compression statistics in real-time:

```bash
CAVEMAN_SHRINK_DEBUG=1 npx caveman-shrink npx @modelcontextprotocol/server-filesystem /my/repo

```

This outputs the token count reduction for each processed field, helping you tune the compression settings for your specific use case.

## Practical Implementation Examples

You can integrate the shrink middleware into any MCP client configuration. Here are the most common deployment patterns.

### Claude Code Configuration

Add the middleware to your MCP server configuration by wrapping the original command:

```json
{
  "mcpServers": {
    "fs-shrunk": {
      "command": "npx",
      "args": [
        "caveman-shrink",
        "npx",
        "@modelcontextprotocol/server-filesystem",
        "/path/to/project"
      ]
    }
  }
}

```

This configuration maintains full filesystem access while automatically compressing all tool and resource descriptions before they reach the language model.

### Command Line Usage

Run the proxy directly from your terminal to test the compression:

```bash
npx caveman-shrink npx @modelcontextprotocol/server-filesystem /my/repo

```

The terminal will display the upstream server's stderr, while stdout flows through the compression pipeline to any connected MCP client.

### Custom Field Compression

To compress non-standard fields provided by custom MCP servers:

```bash
CAVEMAN_SHRINK_FIELDS=description,documentation,help_text npx caveman-shrink node ./my-custom-server.js

```

This flexibility allows the middleware to work with any MCP-compliant server, regardless of whether it uses standard or extended field names.

## Summary

- **Transparent Proxy**: [`src/mcp-servers/caveman-shrink/index.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/mcp-servers/caveman-shrink/index.js) spawns upstream MCP servers and pipes stdio without modifying request bodies or tool execution.
- **Selective Compression**: Only `tools/list`, `prompts/list`, and `resources/list` responses are processed, targeting fields specified in `CAVEMAN_SHRINK_FIELDS`.
- **Algorithm Safety**: The [`compress.js`](https://github.com/JuliusBrussee/caveman/blob/main/compress.js) implementation preserves code identifiers, URLs, and file paths while removing prose filler words.
- **Zero Code Changes**: Configuration happens entirely through environment variables, making it compatible with any existing MCP server.
- **Debug Visibility**: Set `CAVEMAN_SHRINK_DEBUG=1` to monitor compression ratios and field transformations in real-time.

## Frequently Asked Questions

### How does the MCP shrink middleware affect tool execution performance?

The middleware adds minimal latency because it only processes list responses, not actual tool calls or request bodies. The compression happens in-memory using local JavaScript string operations, typically adding less than 1ms per processed item according to the Node.js event loop behavior in [`index.js`](https://github.com/JuliusBrussee/caveman/blob/main/index.js).

### Can I use caveman-shrink with custom MCP servers?

Yes. The middleware is server-agnostic and works with any MCP-compliant server. Since it intercepts responses at the protocol level rather than requiring server modifications, you can wrap existing servers like `@modelcontextprotocol/server-filesystem` or your own custom implementations without changing their source code.

### What fields are safe to compress with CAVEMAN_SHRINK_FIELDS?

You should only compress human-readable prose fields like `description`, `summary`, or `documentation`. Never compress fields containing code, JSON schemas, identifiers, or functional data. The default `description` field is safe because the compression algorithm in [`compress.js`](https://github.com/JuliusBrussee/caveman/blob/main/compress.js) specifically preserves code-like tokens and structural elements.

### How do I verify that compression is working correctly?

Set `CAVEMAN_SHRINK_DEBUG=1` before running the command. The middleware will output the original and compressed text lengths for each processed field to stderr, allowing you to verify that descriptions are being shortened while URLs and file paths remain intact.