MCP Server / token savior
token savior
MCP server for Claude Code: 97% token savings on code navigation + persistent memory engine that remembers context across sessions. 69 tools, zero external deps.
Transport
Tools (20)
Metric
Value
Query
FastAPI
CPython
find_symbol
0.01ms
get_dependencies
0.00ms
get_change_impact
0.00ms
get_function_source
0.02ms
Project
Files
Memory
Cache size
FastAPI
2,556
Django
3,714
Files
Extracts
Python
`.py`, `.pyw`
Rust
`.rs`
Java
`.java`
Gradle
`.gradle`, `.gradle.kts`
GLSL
`.glsl`, `.vert`, `.frag`, `.comp`
JSON
`.json`
YAML
`.yaml`, `.yml`
TOML
`.toml`
Dokumentation
⚡ Token Savior Recall
97% token reduction · Persistent memory · 78 MCP tools · Python 3.11+
What it does
Token Savior Recall is a Claude Code MCP server that solves two problems:
1. Token waste — Claude reads entire files to answer questions about 3 lines. Token Savior navigates your codebase by symbols, returning only what's needed. 97% reduction on 170+ real sessions.
2. Amnesia — Claude starts from zero every session. Token Savior Recall captures observations across sessions, injects relevant context at startup, and surfaces the right knowledge before you ask.
find_symbol("send_message") → 67 chars (was: 41M chars of source)
get_change_impact("LLMClient") → 16K chars (154 direct + 492 transitive deps)
get_function_source("compile") → 4.5K chars (exact source, no grep, no cat)
memory_search("auth migration") → ranked past decisions, bugs, conventions
get_backward_slice("parse_invoice", variable="total", line=42)
→ 12 lines / 130 (92% reduction)
Performance
| Metric | Value | |--------|-------| | Token reduction (navigation) | 97% | | Symbol reindex speedup | 19x (symbol-level hashing) | | Re-access savings (CSC) | 93% | | Abstraction compression L3 | 94-97% vs full source | | Program slice reduction | 92% | | Sessions tracked | 170+ | | Tokens saved | ~203M | | Estimated cost saved | $609+ | | Projects supported | 17 | | Tool count | 78 |
"Tokens saved" = estimated tokens the agent would have consumed navigating with
cat/grepversus with Token Savior Recall. Model-agnostic: the index reduces context-window pressure regardless of provider.
Query response time (sub-millisecond at 1.1M lines)
| Query | FastAPI | Django | CPython |
|-------|--------:|-------:|--------:|
| find_symbol | 0.01ms | 0.03ms | 0.08ms |
| get_dependencies | 0.00ms | 0.00ms | 0.01ms |
| get_change_impact | 0.00ms | 2.81ms | 0.45ms |
| get_function_source | 0.02ms | 0.03ms | 0.10ms |
Index build performance
| Project | Files | Lines | Index time | Memory | Cache size | |---------|------:|------:|-----------:|-------:|-----------:| | FastAPI | 2,556 | 332,160 | 5.7s | 55 MB | 6 MB | | Django | 3,714 | 707,493 | 36.2s | 126 MB | 14 MB | | CPython | 2,464 | 1,115,334 | 55.9s | 197 MB | 22 MB |
Cache is persistent — restarts skip the full build. CPython goes from 56s to under 1s on a cache hit. Symbol-level content hashing (v2.1.0) reduces the incremental reindex cost by 19x on targeted edits.
What it covers
| Language / Format | Files | Extracts |
|-------------------|-------|----------|
| Python | .py, .pyw | Functions, classes, methods, imports, dependency graph |
| TypeScript / JS | .ts, .tsx, .js, .jsx | Functions, arrow functions, classes, interfaces, type aliases |
| Go | .go | Functions, methods (receiver), structs, interfaces, type aliases |
| Rust | .rs | Functions, structs, enums, traits, impl blocks, macro_rules |
| C# | .cs | Classes, interfaces, structs, enums, methods, XML doc comments |
| Java | .java | Packages, imports, classes, interfaces, enums, records, constructors, methods |
| Gradle | .gradle, .gradle.kts | Build blocks, dependency declarations, assignments, task/settings structure |
| C / C99 / C11 | .c, .h | Functions (static/inline/extern), structs/unions/enums, typedefs, #define macros, #include, Doxygen comments, dependency graph |
| GLSL | .glsl, .vert, .frag, .comp | Functions, structs, uniforms (via C annotator) |
| Markdown / Text | .md, .txt, .rst | Sections via heading detection |
| JSON | .json | Nested key structure up to depth 4, $ref cross-references |
| YAML | .yaml, .yml | Nested key hierarchy, array markers, depth cap 4 |
| TOML | .toml | Tables, key-value pairs, nested structure |
| INI / Properties | .ini, .cfg, .properties | Sections, key-value pairs |
| Environment | .env | Variable names, values (with secret masking) |
| XML / Plist / SVG | .xml, .plist, .svg, .xhtml | Element hierarchy, attributes (including Maven pom.xml) |
| HCL / Terraform | .hcl, .tf | Blocks, nested resources, key-value pairs |
| Conf | .conf | Key-value pairs, block structure |
| Dockerfile | Dockerfile, *.dockerfile | Instructions, multi-stage builds, FROM/RUN/COPY/ENV |
| Everything else | * | Line counts (generic fallback) |
78 tools
Navigation
| Tool | What it does |
|------|-------------|
| find_symbol | Where a symbol is defined — file, line, type, 20-line preview |
| get_function_source | Full source of a function or method |
| get_class_source | Full source of a class |
| get_functions | All functions in a file or project |
| get_classes | All classes with methods and bases |
| get_imports | All imports with module, names, line |
| get_structure_summary | File or project structure at a glance |
| list_files | Indexed files with optional glob filter |
| get_project_summary | File count, packages, top classes/functions |
| search_codebase | Regex search across all indexed files |
| reindex | Force full re-index (rarely needed) |
Context & discovery
| Tool | What it does |
|------|-------------|
| get_edit_context | All-in-one: symbol source + dependencies + callers in one call (saves 3 calls) |
| get_feature_files | Find all files related to a feature keyword, then trace imports transitively |
| get_routes | Detect API routes and pages (Next.js App Router, Express, pages/api) |
| get_components | Detect React components (functions returning JSX) in .tsx/.jsx files |
| get_env_usage | Find all references to an env variable across the codebase |
Impact analysis
| Tool | What it does |
|------|-------------|
| get_dependencies | What a symbol calls/uses |
| get_dependents | What calls/uses a symbol |
| get_change_impact | Direct + transitive dependents with confidence score (1.0 = direct, 0.6/hop) and depth |
| get_call_chain | Shortest dependency path between two symbols (BFS) |
| get_file_dependencies | Files imported by a given file |
| get_file_dependents | Files that import from a given file |
| get_symbol_cluster | All functionally related symbols via label propagation community detection — one call instead of chaining dependency queries |
| get_duplicate_classes | Find duplicate Java classes by fully qualified name, or group by simple name to surface shadowed class names across files |
| get_entry_points | Score functions by likelihood of being execution entry points (routes ×3, handlers ×1.5, main ×2, zero callers) |
Git & diffs
| Tool | What it does |
|------|-------------|
| get_git_status | Branch, ahead/behind, staged, unstaged, untracked |
| get_changed_symbols | Changed files as symbol-level summaries, not diffs. Optional ref param for changes since any git ref |
| get_changed_symbols_since_ref | Deprecated -- use get_changed_symbols(ref=...) instead. Removal in v1.1.0 |
| summarize_patch_by_symbol | Compact review view — symbols instead of textual diffs |
| build_commit_summary | Compact commit summary from changed files |
Safe editing
| Tool | What it does |
|------|-------------|
| replace_symbol_source | Replace a symbol's source without touching the rest of the file |
| insert_near_symbol | Insert content before or after a symbol |
| create_checkpoint | Snapshot a set of files before editing |
| restore_checkpoint | Restore from checkpoint |
| compare_checkpoint_by_symbol | Diff checkpoint vs current at symbol level |
| list_checkpoints | List available checkpoints |
Test & run
| Tool | What it does |
|------|-------------|
| find_impacted_test_files | Infer likely impacted pytest files from changed symbols |
| run_impacted_tests | Run only impacted tests — compact summary, not raw logs |
| apply_symbol_change_and_validate | Edit + run impacted tests in one call. Optional rollback_on_failure for auto-rollback |
| apply_symbol_change_validate_with_rollback | Deprecated -- use apply_symbol_change_and_validate(rollback_on_failure=true). Removal in v1.1.0 |
| discover_project_actions | Detect test/lint/build/run commands from project files |
| run_project_action | Execute a discovered action with bounded output |
Config analysis
| Tool | What it does |
|------|-------------|
| analyze_config | Scan config files for duplicates, secrets, typos, and orphan keys |
Runs three checks (individually toggleable via the checks parameter):
- Duplicates — Same key defined twice in the same file, plus Levenshtein-based typo detection (e.g.
db_hsotvsdb_host) - Secrets — Regex patterns for known secret formats (API keys, tokens, private keys) plus Shannon entropy analysis for high-entropy strings
- Orphans — Cross-references config keys against actual code usage. Detects keys your code never reads and env vars your code expects but aren't set. Understands
os.environ,process.env,os.Getenv,std::env::var, and more.
Supported formats: .yaml, .yml, .toml, .ini, .cfg, .properties, .env, .xml, .plist, .hcl, .tf, .conf, .json
Code quality
| Tool | What it does |
|------|-------------|
| find_dead_code | Find functions/classes with zero callers (excludes entry points, tests, decorated routes) |
| find_hotspots | Rank functions by complexity score (lines, branches, nesting, parameter count) |
| find_allocation_hotspots | Rank Java functions by allocation-heavy ULL antipatterns such as object construction, collection creation, streams, boxing, and formatting |
| find_performance_hotspots | Rank Java functions by non-allocation ULL antipatterns such as blocking, locks, synchronized sections, blocking I/O, and missing cache-line padding hints |
| detect_breaking_changes | Compare current function signatures against a git ref — flags removed/renamed params, changed defaults |
Docker
| Tool | What it does |
|------|-------------|
| analyze_docker | Audit Dockerfiles: base images, exposed ports, ENV/ARG cross-reference, latest tag warnings |
Multi-project
| Tool | What it does |
|------|-------------|
| find_cross_project_deps | Cross-reference imports across projects to find shared dependencies |
Stats
| Tool | What it does |
|------|-------------|
| get_usage_stats | Cumulative token savings per project across sessions |
Project management
| Tool | What it does |
|------|-------------|
| list_projects | All registered projects and their index state |
| switch_project | Set the active project for subsequent calls |
| set_project_root | Register a new project root and trigger indexing |
vs LSP
LSP answers "where is this defined?" — token-savior answers "what breaks if I change it?"
LSP is point queries: one symbol, one file, one position. It can find where LLMClient is defined and who references it directly. Ask "what breaks transitively if I refactor LLMClient?" and LSP has nothing — the AI would need to chain dozens of find-reference calls recursively, reading files at every step.
get_change_impact("TestCase") on CPython finds 154 direct dependents and 492 transitive dependents in 0.45ms, returning 16K chars instead of reading 41M. And unlike LSP, it requires zero language servers — one binary covers Python + TS/JS + Go + Rust + C# + C/GLSL + config files + Dockerfiles out of the box.
Install
Quick start (uvx)
uvx token-savior-recall
No venv, no clone. Runs directly from PyPI.
Development install
git clone https://github.com/Mibayy/token-savior
cd token-savior
python3 -m venv .venv
.venv/bin/pip install -e ".[mcp]"
Configuration
Claude Code / Cursor / Windsurf / Cline
Add to .mcp.json (or ~/.claude/settings.json):
{
"mcpServers": {
"token-savior-recall": {
"command": "/path/to/venv/bin/python",
"args": ["-m", "token_savior.server"],
"env": {
"WORKSPACE_ROOTS": "/path/to/project1,/path/to/project2",
"TOKEN_SAVIOR_CLIENT": "claude-code",
"TELEGRAM_BOT_TOKEN": "YOUR_TELEGRAM_BOT_TOKEN",
"TELEGRAM_CHAT_ID": "YOUR_TELEGRAM_CHAT_ID"
}
}
}
}
TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID are optional — they enable the
critical-observation feed (guardrails, warnings, error patterns).
Custom MCP client (YAML example)
mcp_servers:
token-savior-recall:
command: /path/to/venv/bin/token-savior-recall
env:
WORKSPACE_ROOTS: /path/to/project1,/path/to/project2
TOKEN_SAVIOR_CLIENT: my-client
timeout: 120
connect_timeout: 30
Make the agent actually use it
AI assistants default to grep and cat even when better tools are available.
Add this to your CLAUDE.md or equivalent:
## Codebase Navigation — MANDATORY
You MUST use token-savior-recall MCP tools FIRST.
- ALWAYS start with: find_symbol, get_function_source, get_class_source,
search_codebase, get_dependencies, get_dependents, get_change_impact
- For past context: memory_search, memory_get, memory_why
- Only fall back to Read/Grep when tools genuinely don't cover it
- If you catch yourself reaching for grep to find code, STOP
Tools (75)
Core Navigation (14)
get_function_source (level=0-3) · get_class_source · find_symbol ·
get_functions · get_classes · get_imports · get_structure_summary ·
get_project_summary · list_files · search_codebase · get_routes ·
get_env_usage · get_components · get_feature_files
Memory Engine (16)
memory_save · memory_search · memory_get · memory_delete ·
memory_index · memory_timeline · memory_status · memory_top ·
memory_why · memory_doctor · memory_from_bash · memory_set_global ·
memory_mode · memory_archive · memory_maintain · memory_prompts
Advanced Context (6)
get_backward_slice · pack_context · get_relevance_cluster ·
get_call_predictions · verify_edit · find_semantic_duplicates
Dependencies (7)
get_dependencies · get_dependents · get_change_impact ·
get_call_chain · get_file_dependencies · get_file_dependents ·
get_symbol_cluster
Git & Diff (5)
get_git_status · get_changed_symbols ·
summarize_patch_by_symbol · build_commit_summary · get_edit_context
Checkpoints (6)
create_checkpoint · list_checkpoints · delete_checkpoint ·
prune_checkpoints · restore_checkpoint · compare_checkpoint_by_symbol
Edit & Validate (4)
replace_symbol_source · insert_near_symbol ·
apply_symbol_change_and_validate · find_impacted_test_files
Analysis (8)
find_hotspots · find_dead_code · detect_breaking_changes ·
find_allocation_hotspots · find_performance_hotspots ·
analyze_config · analyze_docker · run_impacted_tests
Project (7)
list_projects · switch_project · set_project_root · reindex ·
get_usage_stats · discover_project_actions · run_project_action
Memory Engine
Architecture
- Storage — SQLite WAL + FTS5 (fast full-text search, concurrent reads)
- Hooks — 8 Claude Code lifecycle hooks (SessionStart, Stop, SessionEnd, PreCompact, PreToolUse ×2, UserPromptSubmit, PostToolUse)
- Types — 12 observation types (
bugfix,guardrail,convention,warning,decision,error_pattern,note,command,research,infra,config,idea) - CLI —
ts memory {status,list,search,get,save,top,why,doctor,relink}
How it works
- SessionStart — injects a delta-based memory index (only new/changed obs)
- PreToolUse — injects file/symbol history before each relevant tool call
- UserPromptSubmit — auto-captures trigger phrases, injects relevant obs
- PostToolUse — auto-saves significant bash commands and research hints
- Stop / SessionEnd — generates a structured session summary via
claude -p
LRU Scoring
Observations are ranked by:
0.4 × recency + 0.3 × access_count + 0.3 × type_priority
Type priority: guardrail (1.0) > convention (0.9) > warning (0.8) > command (0.7) > note (0.2)
Delta injection
Only changed observations are re-injected at SessionStart. Unchanged sessions inject a single line instead of 30 observations. Estimated savings: 50-70% vs full refresh on repeated sessions.
Advanced Context (v2.1.0)
Program Slicing
get_backward_slice(name="parse_invoice", variable="total", line=42)
→ 12 lines / 130 total (92% reduction)
Returns the minimal set of instructions affecting a variable at a given line. Built on Data Dependency Graph analysis via Python AST.
Knapsack Context Packing
pack_context(query="authentication flow", budget_tokens=4000)
→ optimal symbol bundle ≤ 4000 tokens
Greedy fractional knapsack (Dantzig 1957). Scores symbols by query match + dependency proximity + recency + access count.
PageRank / Random Walk with Restart
get_relevance_cluster(name="parseInvoice", budget=10)
→ mathematically ranked relevant symbols
RWR (Tong, Faloutsos, Pan 2006) on the dependency graph. Captures indirect relevance that BFS misses.
Predictive Prefetching
Markov model on tool call sequences. After get_function_source(X),
pre-computes get_dependents(X) with 77.8% accuracy. Background daemon
threads keep the warm cache fresh without blocking.
Proof-Carrying Edits
verify_edit(symbol_name="parse_config", new_source="...")
→ EditSafety: SAFE TO APPLY
signature: preserved
exceptions: unchanged
side-effects: unchanged
Static analysis certificate attached to every apply_symbol_change_and_validate.
Never blocks the edit — surfaces risk for the agent to weigh.
Semantic Hash (AST-normalized)
find_semantic_duplicates()
→ 5 groups detected (including _build_line_offsets ×9 across annotators)
Two functions equivalent modulo variable renaming → same hash. α-conversion + docstring stripping + AST normalization. Falls back to text hash on syntax errors so non-Python annotators are still covered.
What's New in v2.1.0
Advanced Context Engine (Phase 2)
- Program slicing via backward AST analysis (92% token reduction on debug)
- Knapsack context packing — optimal bundle at fixed token budget
- PageRank / RWR on dependency graph — mathematically ranked context
- Markov predictive prefetching — 77.8% accuracy on next tool call
- Proof-carrying edits — EditSafety certificate before every write
- Semantic AST hash — cross-file duplicate detection
Core Optimizations (Phase 1)
- Symbol-level content hashing — 19x reindex speedup on targeted edits
- 2-level semantic hash (signature + body) — precise breaking change detection
- Conversation Symbol Cache (CSC) — 93% token savings on re-accessed symbols
- Lattice of Abstractions L0→L3 — 94-97% compression vs full source
Memory Engine
- 16 memory tools, 8 lifecycle hooks, 12 observation types
- LRU scoring, delta injection, TTL, semantic dedup (Jaccard ~0.85)
- Auto-promotion, contradiction detection, auto-linking
- Mode system (
code/review/debug/infra/silent) + auto-detect - CLI
ts— full memory management from any terminal - Telegram feed for critical observations
- Markdown export + git versioning
Manifest optimization
- 80 → 75 tools (-6%), 42K → 36K chars (-14%), ~1500 tokens/session saved
Refactor
_build_line_offsetsextracted to shared helper (9x dedup across annotators)
Supported languages & formats
| Language / Format | Files | Extracts |
|-------------------|-------|----------|
| Python | .py, .pyw | Functions, classes, methods, imports, dependency graph |
| TypeScript / JS | .ts, .tsx, .js, .jsx | Functions, arrow functions, classes, interfaces, type aliases |
| Go | .go | Functions, methods, structs, interfaces, type aliases |
| Rust | .rs | Functions, structs, enums, traits, impl blocks, macro_rules |
| C# | .cs | Classes, interfaces, structs, enums, methods, XML doc comments |
| C / C++ | .c, .cc, .cpp, .h, .hpp | Functions, structs/unions/enums, typedefs, macros, includes |
| GLSL | .glsl, .vert, .frag, .comp | Functions, structs, uniforms |
| JSON / YAML / TOML | config files | Nested keys, $ref cross-refs |
| INI / ENV / HCL / Terraform | config files | Sections, key-value pairs, secret masking |
| XML / Plist / SVG | markup files | Element hierarchy, attributes |
| Dockerfile | Dockerfile, *.dockerfile | Instructions, multi-stage builds, FROM/RUN/COPY/ENV |
| Markdown / Text | .md, .txt, .rst | Sections via heading detection |
| Everything else | * | Line counts (generic fallback) |
vs LSP
LSP answers "where is this defined?" — Token Savior Recall answers "what breaks if I change it, what did we learn last time, and what should we do about it?"
LSP is point queries: one symbol, one file, one position. It can find where
LLMClient is defined. Ask "what breaks transitively if I refactor
LLMClient, and did we already hit this bug six weeks ago?" and LSP has
nothing.
get_change_impact("TestCase") on CPython finds 154 direct and 492 transitive
dependents in 0.45ms, returning 16K chars instead of reading 41M. Pair it with
memory_search("TestCase refactor") and you get prior decisions, past bugs,
and conventions in the same round-trip — with zero language servers required.
Programmatic usage
from token_savior.project_indexer import ProjectIndexer
from token_savior.query_api import ProjectQueryEngine
indexer = ProjectIndexer("/path/to/project")
index = indexer.index()
engine = ProjectQueryEngine(index)
print(engine.get_project_summary())
print(engine.find_symbol("MyClass"))
print(engine.get_change_impact("send_message"))
Architecture
src/token_savior/
server.py MCP transport, tool routing
tool_schemas.py 75 tool schemas
slot_manager.py Multi-project lifecycle, incremental mtime updates
cache_ops.py JSON persistence, legacy cache migration
query_api.py ProjectQueryEngine — query methods + as_dict()
models.py ProjectIndex, LazyLines, AnnotatorProtocol, build_line_char_offsets
project_indexer.py File discovery, structural indexing, dependency graphs
memory_db.py SQLite WAL + FTS5 memory engine
program_slicer.py Backward slicing via Data Dependency Graph
context_packer.py Greedy fractional knapsack
graph_ranker.py Random Walk with Restart on dependency graph
markov_prefetcher.py Predictive prefetching, daemon warm cache
semantic_hasher.py AST-normalized semantic hash (alpha-conversion)
edit_verifier.py EditSafety static-analysis certificate
annotator.py Language dispatch
*_annotator.py Per-language annotators
Development
pip install -e ".[dev,mcp]"
pytest tests/ -v
ruff check src/ tests/
Known limitations
- Live-editing window: the index updates on query, not on save. Right after an edit you may briefly see the pre-edit version; the next git-tracked change triggers re-indexing.
- Cross-language tracing:
get_change_impactstops at language boundaries. - JSON value semantics: the JSON annotator indexes key structure, not value meaning.
- Windows paths: not tested. Contributions welcome.
- Max files: default 10,000 per project (
TOKEN_SAVIOR_MAX_FILES). - Max file size: default 1 MB (
TOKEN_SAVIOR_MAX_FILE_SIZE_MB).
License
MIT — see LICENSE.
Works with any MCP-compatible AI coding tool. Claude Code · Cursor · Windsurf · Cline · Continue · any custom MCP client