Context Minifier & State Guard — MCP middleware proxy that reduces token waste, prevents tool attrition, and eliminates context rot
Project description
MCP Spine
Context Minifier & State Guard — A local-first MCP middleware proxy that reduces token waste, prevents tool attrition, and eliminates context rot.
MCP Spine sits between your LLM client (Claude Desktop, etc.) and your MCP servers, providing security hardening, intelligent tool routing, schema compression, and file state tracking — all through a single proxy.
Why
LLM agents using MCP tools face three problems:
- Token waste — Tool schemas consume thousands of tokens per request. With 40+ tools loaded, you're burning context on JSON schemas before the conversation even starts.
- Context rot — In long sessions, LLMs revert to editing old file versions they memorized earlier, silently overwriting your latest changes.
- No security boundary — MCP servers run with full access. There's no audit trail, no rate limiting, no secret scrubbing between the LLM and your tools.
MCP Spine solves all three.
Features
Stage 1: Security Proxy
- JSON-RPC message validation and sanitization
- Secret scrubbing (AWS keys, GitHub tokens, bearer tokens, private keys, connection strings)
- Per-tool and global rate limiting with sliding windows
- Path traversal prevention with symlink-aware jail
- Command injection guards for server spawning
- HMAC-fingerprinted SQLite audit trail
- Circuit breakers on failing servers
- Declarative security policies from config
Stage 2: Semantic Router
- Local vector embeddings using
all-MiniLM-L6-v2(no API calls, no data leaves your machine) - ChromaDB-backed tool indexing
- Query-time routing: only the most relevant tools are sent to the LLM
spine_set_contextmeta-tool for explicit context switching- Keyword overlap + recency boost reranking
- Background model loading — tools work immediately, routing activates when ready
Stage 3: Schema Minification
- 4 aggression levels (0=off, 1=light, 2=standard, 3=aggressive)
- Level 2 achieves 61% token savings on tool schemas
- Strips
$schema, titles,additionalProperties, parameter descriptions, defaults - Preserves all required fields and type information
Stage 4: State Guard
- Watches project files via
watchfiles - Maintains SHA-256 manifest with monotonic versioning
- Injects compact state pins into tool responses
- Prevents LLMs from editing stale file versions
Human-in-the-Loop
require_confirmationpolicy flag for destructive tools- Spine intercepts the call, shows the arguments, and waits for user approval
spine_confirm/spine_denymeta-tools for the LLM to relay the decision- Per-tool granularity via glob patterns
Quick Start
# Install core
pip install -e .
# Install with semantic routing (optional)
pip install -e ".[ml]"
# Generate config
mcp-spine init
# Edit spine.toml to add your MCP servers, then:
mcp-spine verify # validate config
mcp-spine serve # start the proxy
Claude Desktop Integration
Replace all your individual MCP server entries with a single Spine entry:
{
"mcpServers": {
"spine": {
"command": "python",
"args": ["-u", "-m", "spine.cli", "serve", "--config", "/path/to/spine.toml"],
"cwd": "/path/to/mcp-spine"
}
}
}
The -u flag ensures unbuffered stdout, preventing pipe hangs on Windows.
Example Config
[spine]
log_level = "info"
audit_db = "spine_audit.db"
# Add as many servers as you need
[[servers]]
name = "filesystem"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"]
timeout_seconds = 120
[[servers]]
name = "github"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
env = { GITHUB_TOKEN = "ghp_..." }
timeout_seconds = 60
# Semantic routing — filter to top-K tools per request
[routing]
max_tools = 20
rerank = true
# Schema minification — 61% token savings at level 2
[minifier]
level = 2
# State guard — prevent context rot
[state_guard]
enabled = true
watch_paths = ["/path/to/project"]
# Human-in-the-loop — require approval for destructive tools
[[security.tools]]
pattern = "write_file"
action = "allow"
require_confirmation = true
[[security.tools]]
pattern = "delete_file"
action = "allow"
require_confirmation = true
# Security
[security]
scrub_secrets_in_logs = true
audit_all_tool_calls = true
global_rate_limit = 120
per_tool_rate_limit = 60
[security.path]
allowed_roots = ["/path/to/project"]
denied_patterns = ["**/.env", "**/*.key", "**/*.pem"]
Security Model
The Spine is designed with defense-in-depth. Every layer assumes the others might fail.
| Threat | Mitigation |
|---|---|
| Prompt injection via tool args | Input validation on all JSON-RPC messages; tool name and method allowlists |
| Path traversal | All file paths resolved and jailed to allowed_roots; symlink-aware |
| Secret leakage in logs | Automatic regex-based scrubbing of AWS keys, GitHub tokens, bearer tokens, private keys, connection strings |
| Runaway agent loops | Per-tool and global rate limiting with sliding windows |
| Command injection via server spawn | Command allowlist; shell metacharacter blocking; PureWindowsPath basename extraction for paths with spaces/parens |
| Denial of service | Message size limits (10MB); schema depth limits; circuit breakers on failing servers |
| Sensitive file access | Deny-list patterns for .env, .key, .pem, .ssh/, .aws/ files |
| Tool abuse | Policy-based tool blocking, audit logging, and human-in-the-loop confirmation |
| Log tampering | HMAC fingerprints on every audit entry |
| Env var exposure | Fail-closed resolution: undefined ${VAR} raises an error |
| Destructive operations | require_confirmation flag pauses execution until user approves |
Audit Trail
Every tool call is logged to SQLite with tamper-evident fingerprints:
mcp-spine audit --last 50 # Recent entries
mcp-spine audit --security-only # Security events only
mcp-spine audit --tool write_file # Filter by tool
Architecture
Client ◄──stdio──► MCP Spine ◄──stdio──► Filesystem Server
│ GitHub Server
│ Any MCP Server
┌───┴───┐
│SecPol │ ← Rate limits, path jail, secret scrub
│Router │ ← Semantic routing (local embeddings)
│Minify │ ← Schema compression (61% savings)
│Guard │ ← File state pinning (SHA-256)
│HITL │ ← Human-in-the-loop confirmation
└───────┘
Startup Sequence
The Spine uses a two-phase background initialization:
- Instant handshake (~2ms) — Responds to
initializeimmediately - Background init — Connects servers concurrently, sets ready as soon as any server has tools
- ML loading — Semantic router model loads in a separate background task; routing activates silently when done
This ensures Claude Desktop never times out, even with slow servers or large ML models.
Windows Support
MCP Spine is battle-tested on Windows with specific hardening for:
- MSIX sandbox paths for Claude Desktop config and logs
npx.cmdresolution viashutil.which()- Paths with spaces (
C:\Users\John Doe\...) and parentheses (C:\Program Files (x86)\...) PureWindowsPathfor cross-platform basename extraction- UTF-8 encoding without BOM for config file generation
- Unbuffered stdout (
-uflag) to prevent pipe hangs
Project Structure
mcp-spine/
├── pyproject.toml
├── spine/
│ ├── cli.py # Click CLI (init, serve, verify, audit)
│ ├── config.py # TOML config loader with validation
│ ├── proxy.py # Core proxy event loop
│ ├── protocol.py # JSON-RPC message handling
│ ├── transport.py # Server pool, circuit breakers, concurrent startup
│ ├── audit.py # Structured logging + SQLite audit trail
│ ├── router.py # Semantic routing (ChromaDB + sentence-transformers)
│ ├── minifier.py # Schema pruning (4 aggression levels)
│ ├── state_guard.py # File watcher + SHA-256 manifest + pin injection
│ └── security/
│ ├── secrets.py # Credential detection & scrubbing
│ ├── paths.py # Path traversal jail
│ ├── validation.py # JSON-RPC message validation
│ ├── commands.py # Server spawn guards
│ ├── rate_limit.py # Sliding window throttling
│ ├── integrity.py # SHA-256 + HMAC fingerprints
│ ├── env.py # Fail-closed env var resolution
│ └── policy.py # Declarative security policies
├── tests/
│ ├── test_security.py # 93 security tests
│ ├── test_config.py # Config validation tests
│ ├── test_minifier.py # Schema minification tests
│ └── test_state_guard.py # State guard tests
└── configs/
└── example.spine.toml
Tests
# Run all tests
pytest
# Security tests only
pytest tests/test_security.py -v
# End-to-end tests
python test_e2e.py
98 tests covering security, config validation, schema minification, state guard, and Windows path edge cases.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_spine-0.1.0.tar.gz.
File metadata
- Download URL: mcp_spine-0.1.0.tar.gz
- Upload date:
- Size: 48.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bca0342fbfa03cd21fcc08ac49c141bbf171285bd54c7f1c369655296f93a201
|
|
| MD5 |
bdfce7d6b10a83f20249436add2d045d
|
|
| BLAKE2b-256 |
66501723b6d690635f1119563dbbc05ea3c6b46d91b46d0905c690cfde74074d
|
File details
Details for the file mcp_spine-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mcp_spine-0.1.0-py3-none-any.whl
- Upload date:
- Size: 49.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96f9b2c55d94084646524ad676af3492f30814577aaa060d3d4f234a4a7d8b9a
|
|
| MD5 |
ae97ce97b121b2380e13b9f8b439ff9c
|
|
| BLAKE2b-256 |
61766d060eeaea65e1beca72100b41d466850bba9821b0320a6236bfec985360
|