# caveman-shrink MCP Middleware: How It Compresses Tool Descriptions for Token Efficiency

> Discover how caveman-shrink MCP middleware compresses tool descriptions to improve token efficiency. Learn about its sentinel-based protection system for smarter API calls.

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

---

**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`](https://github.com/JuliusBrussee/caveman/blob/main/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`](https://github.com/JuliusBrussee/caveman/blob/main/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:

1. **Spawning**: Executes the upstream server command (e.g., `npx @modelcontextprotocol/server-filesystem`) via Node.js `child_process.spawn`
2. **Request pass-through**: Client requests flow unmodified to the upstream server
3. **Response buffering**: Line-buffered JSON-RPC responses are parsed and analyzed
4. **Selective transformation**: Only responses containing `tools`, `prompts`, `resources`, or `resourceTemplates` arrays trigger compression

### Interception Points

The `transformResponse` function in [`index.js`](https://github.com/JuliusBrussee/caveman/blob/main/index.js) specifically targets four array types in JSON-RPC results:
- `tools`
- `prompts` 
- `resources`
- `resourceTemplates`

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`](https://github.com/JuliusBrussee/caveman/blob/main/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`, and `the` to reduce token count without semantic loss
- **Filler elimination**: Removes conversational padding like `sure`, `just`, and `basically` that LLMs ignore
- **Hedging deletion**: Cuts tentative prefixes such as `I will` or `basically` from command descriptions
- **Whitespace normalization**: Collapses multiple spaces and normalizes punctuation spacing

### Sentinel Protection Strategy

Critical technical content is protected through a placeholder system:

1. **Pattern matching**: Identifies code fences (```), inline code (`...`), URLs, file paths, constant-style identifiers (SCREAMING_SNAKE_CASE), and enum strings
2. **Placeholder substitution**: Replaces protected sections with numbered sentinels before text processing
3. **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/call` RPC responses** (high-risk for downstream consumers expecting exact formatting)

## Practical Implementation Examples

### Running the Proxy

Register caveman-shrink in your MCP client configuration:

```json
{
  "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:

```javascript
// 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:

```javascript
// 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:

```bash
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**: `compressDescriptionsInPlace` handles 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`](https://github.com/JuliusBrussee/caveman/blob/main/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.js`](https://github.com/JuliusBrussee/caveman/blob/main/src/mcp-servers/caveman-shrink/compress.js) removes articles, filler words, and hedging phrases while protecting code blocks, URLs, and identifiers via sentinel placeholders
- Configuration via `CAVEMAN_SHRINK_FIELDS` allows customization of which fields to compress, with `CAVEMAN_SHRINK_DEBUG` providing visibility into byte savings
- The `compressDescriptionsInPlace` helper 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`](https://github.com/JuliusBrussee/caveman/blob/main/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.