MCP Spine
MCP Spine is a local-first MCP middleware proxy that reduces token waste, prevents context rot, and adds security hardening through intelligent tool routing, schema compression, and file state tracking.
Security Hardening: Acts as a security boundary between LLM clients and MCP servers with JSON-RPC validation, secret scrubbing (e.g., AWS keys, GitHub tokens), rate limiting, path traversal prevention, command injection guards, and HMAC-fingerprinted audit logging.
Semantic Tool Routing: Uses local vector embeddings (no data leaves your machine) to present only the most relevant tools to the LLM based on the current task. Guide routing explicitly via the
spine_set_contextmeta-tool.Schema Minification: Compresses tool schemas by up to 61% by stripping non-essential metadata while preserving required fields and type information.
State Guard: Monitors project files via a SHA-256 manifest and injects state pins to prevent LLMs from editing stale file versions, eliminating context rot.
Human-in-the-Loop (HITL): Intercepts destructive tool calls (e.g.,
write_file) and requires explicit user confirmation viaspine_confirm/spine_denybefore execution.Tool Output Memory: Caches the last 50 tool results with deduplication and TTL expiration. Use
spine_recallto query cached outputs by keyword, tool name, or recency — preventing context loss when tools are swapped.Flexible Transport: Connects to both local
stdioand remote HTTP/SSE MCP servers.Diagnostics & Monitoring: Includes a
doctorCLI command, live dashboard, usage analytics, and audit log querying for operational insights.
Provides search capabilities through the Brave Search API, enabling AI agents to perform web searches and retrieve information from the internet.
Provides filesystem access tools for reading, writing, and managing files within specified project directories through the MCP filesystem server.
Enables interaction with GitHub repositories and APIs, allowing AI agents to manage code, issues, pull requests, and other GitHub resources.
Provides database interaction capabilities through SQLite, enabling AI agents to execute queries, manage data, and perform database operations.
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.
Install
pip install mcp-spine
# With semantic routing (optional)
pip install mcp-spine[ml]Quick Start
# Generate config
mcp-spine init
# Diagnose your setup
mcp-spine doctor --config spine.toml
# Validate config
mcp-spine verify --config spine.toml
# Start the proxy
mcp-spine serve --config spine.tomlClaude 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.
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 switchingKeyword 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, defaultsPreserves all required fields and type information
Stage 4: State Guard
Watches project files via
watchfilesMaintains 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 toolsSpine intercepts the call, shows the arguments, and waits for user approval
spine_confirm/spine_denymeta-tools for the LLM to relay the decisionPer-tool granularity via glob patterns
Tool Output Memory
Ring buffer caching last 50 tool results
Deduplication by tool name + argument hash
TTL expiration (1 hour default)
spine_recallmeta-tool to query cached resultsPrevents context loss when semantic router swaps tools between turns
SSE Transport
Connect to remote MCP servers over HTTP/SSE alongside local stdio servers
No external dependencies (uses stdlib urllib)
Supports custom headers for authentication
Diagnostics
# Check your setup
mcp-spine doctor --config spine.toml
# Live monitoring dashboard
mcp-spine dashboard
# Usage analytics
mcp-spine analytics --hours 24
# Query audit log
mcp-spine audit --last 50
mcp-spine audit --security-only
mcp-spine audit --tool write_fileExample Config
[spine]
log_level = "info"
audit_db = "spine_audit.db"
# Add as many servers as you need — they start concurrently
[[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 = 180
[[servers]]
name = "sqlite"
command = "uvx"
args = ["mcp-server-sqlite", "--db-path", "/path/to/database.db"]
timeout_seconds = 60
[[servers]]
name = "memory"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-memory"]
timeout_seconds = 60
[[servers]]
name = "brave-search"
command = "node"
args = ["/path/to/node_modules/@modelcontextprotocol/server-brave-search/dist/index.js"]
env = { BRAVE_API_KEY = "your_key" }
timeout_seconds = 60
# Remote server via SSE
# [[servers]]
# name = "remote-tools"
# transport = "sse"
# url = "https://your-server.com/sse"
# headers = { Authorization = "Bearer token" }
# timeout_seconds = 30
# Semantic routing
[routing]
max_tools = 15
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 for destructive tools
[[security.tools]]
pattern = "write_file"
action = "allow"
require_confirmation = true
[[security.tools]]
pattern = "write_query"
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
Defense-in-depth — every layer assumes the others might fail.
Threat | Mitigation |
Prompt injection via tool args | Input validation, tool name allowlists |
Path traversal | Symlink-aware jail to |
Secret leakage | Automatic scrubbing of AWS keys, tokens, private keys |
Runaway agent loops | Per-tool + global rate limiting |
Command injection | Command allowlist, shell metacharacter blocking |
Denial of service | Message size limits, circuit breakers |
Sensitive file access | Deny-list patterns for |
Tool abuse | Policy-based blocking, audit logging, HITL confirmation |
Log tampering | HMAC fingerprints on every audit entry |
Destructive operations |
|
Architecture
Client ◄──stdio──► MCP Spine ◄──stdio──► Filesystem Server
│ ◄──stdio──► GitHub Server
│ ◄──stdio──► SQLite Server
│ ◄──stdio──► Memory Server
│ ◄──stdio──► Brave Search
│ ◄──SSE────► Remote 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
│Memory │ ← Tool output cache
└───────┘Startup Sequence
Instant handshake (~2ms) — Responds to
initializeimmediatelyConcurrent server startup — All servers connect in parallel via
asyncio.gatherProgressive readiness — Tools available as soon as any server connects
Late server notification —
tools/listChangedsent when slow servers finishBackground ML loading — Semantic router activates silently when model loads
Windows Support
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 extractionEnvironment variable merging (config env extends, not replaces, system env)
UTF-8 encoding without BOM
Unbuffered stdout (
-uflag) to prevent pipe hangs
Project Structure
mcp-spine/
├── pyproject.toml
├── spine/
│ ├── cli.py # Click CLI (init, serve, verify, audit, dashboard, analytics, doctor)
│ ├── 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
│ ├── memory.py # Tool output cache (ring buffer + dedup + TTL)
│ ├── dashboard.py # Live TUI dashboard (Rich)
│ ├── sse_client.py # SSE transport client for remote servers
│ └── 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 # Security tests
│ ├── test_config.py # Config validation tests
│ ├── test_minifier.py # Schema minification tests
│ ├── test_state_guard.py # State guard tests
│ ├── test_proxy_features.py # HITL, dashboard, analytics tests
│ └── test_memory.py # Tool output memory tests
├── configs/
│ └── example.spine.toml # Complete reference config
└── .github/
└── workflows/
└── ci.yml # GitHub Actions: test + lint + publishTests
pytest tests/ -v135+ tests covering security, config validation, schema minification, state guard, HITL policies, dashboard queries, analytics, tool memory, and Windows path edge cases.
CI runs on every push: Windows + Linux, Python 3.11/3.12/3.13.
License
MIT
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Donnyb369/mcp-spine'
If you have feedback or need assistance with the MCP directory API, please join our Discord server