https://github.com/pozii/tokensaver
MCP server that cuts AI agent token costs by up to 97% — compression, caching, pruning, web extraction
https://github.com/pozii/tokensaver
ai claude context-compression cost-reduction fastmcp llm mcp mcp-server openai python token-optimization
Last synced: about 1 month ago
JSON representation
MCP server that cuts AI agent token costs by up to 97% — compression, caching, pruning, web extraction
- Host: GitHub
- URL: https://github.com/pozii/tokensaver
- Owner: pozii
- License: apache-2.0
- Created: 2026-06-21T13:09:25.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-06-21T13:19:20.000Z (about 1 month ago)
- Last Synced: 2026-06-21T15:12:55.920Z (about 1 month ago)
- Topics: ai, claude, context-compression, cost-reduction, fastmcp, llm, mcp, mcp-server, openai, python, token-optimization
- Language: Python
- Homepage:
- Size: 32.2 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# TokenSaver MCP
**Cut your AI API costs by up to 97% — without changing a single prompt.**
[](LICENSE)
[](https://www.python.org)
[](https://modelcontextprotocol.io)
[](#running-tests)
An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that gives AI agents ten tools to measure, compress, cache, and prune token usage — so developers on limited plans can do more with less.
---
## Why TokenSaver?
Every API call sends more tokens than necessary. Conversation history accumulates. Web pages arrive as raw HTML. Tool results get re-fetched on every turn. System prompts bloat over iterations.
TokenSaver intercepts each of these patterns and fixes them at the agent level — no model changes, no prompt engineering, no plan upgrades.
| Scenario | Before | After | Saved |
|---|---:|---:|---:|
| 10-turn conversation history | 40,000 tokens | 8,000 tokens | **80%** |
| Webpage fetch (raw HTML) | 22,000 tokens | 1,200 tokens | **94%** |
| Bloated system prompt | 600 tokens | 220 tokens | **63%** |
| Repeated tool call (cached) | 1,500 tokens | 50 tokens | **97%** |
---
## Tools
| Tool | What it does |
|---|---|
| `count_tokens` | Measure token cost before sending — decide whether to compress first |
| `compress_context` | Shrink long text or conversation history with offline LSA summarization |
| `cache_store` / `cache_get` / `cache_invalidate` | Persist tool results to disk with TTL — never run the same lookup twice |
| `extract_webpage` | Fetch a URL and return only the readable content, not raw HTML |
| `summarize_file` | Get a structural + content summary of any file or directory |
| `prune_conversation` | Remove filler turns and compress old messages in conversation history |
| `optimize_prompt` | Shorten verbose system prompts while preserving constraints |
| `advise_context_window` | Diagnose token bloat and get targeted recommendations |
All tools work **fully offline** — no API key required for core features.
---
## Installation
```bash
git clone https://github.com/pozii/tokensaver.git
cd tokensaver
pip install -e .
```
> **Python 3.11+ required.** On first use, `compress_context` will auto-download the NLTK `punkt_tab` tokenizer (~2 MB) if not already present.
---
## How it connects to your AI client
TokenSaver has no URL and runs no background server by default. It uses **stdio transport**: the AI client reads your config, spawns `python -m tokensaver` as a child process, and talks to it through stdin/stdout. You never open a port or start anything manually — the client does it for you when it launches.
```
Your AI client ──spawn──▶ python -m tokensaver ──stdio──▶ tools available
```
The alternative is **SSE transport**, where you start the server yourself on a local port and the client connects over HTTP. This is useful for multi-agent setups or when multiple clients share the same server instance.
---
## Setup
### Claude Desktop
Config file location:
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"tokensaver": {
"command": "python",
"args": ["-m", "tokensaver"]
}
}
}
```
Save the file and restart Claude Desktop. The tokensaver tools will appear in the tool list.
### Claude Code
```bash
claude mcp add tokensaver -- python -m tokensaver
```
Or add manually to `~/.claude/settings.json`:
```json
{
"mcpServers": {
"tokensaver": {
"command": "python",
"args": ["-m", "tokensaver"]
}
}
}
```
### OpenCode
Config file: `~/.config/opencode/config.json`
```json
{
"mcp": {
"servers": {
"tokensaver": {
"type": "local",
"command": ["python", "-m", "tokensaver"]
}
}
}
}
```
### Any MCP-compatible client (SSE mode)
Start the server once:
```bash
python -m tokensaver --transport sse --port 8765
```
Then point your client at:
```
http://localhost:8765/sse
```
### Fixing Python path issues
If your system has multiple Python versions and `python` resolves to the wrong one, use the full path:
```bash
# Find the right Python
which python3 # macOS / Linux
where python # Windows
```
Then use the full path in your config:
```json
{
"mcpServers": {
"tokensaver": {
"command": "/usr/local/bin/python3",
"args": ["-m", "tokensaver"]
}
}
}
```
```json
{
"mcpServers": {
"tokensaver": {
"command": "C:\\Python314\\python.exe",
"args": ["-m", "tokensaver"]
}
}
}
```
---
## Usage
### Recommended workflow
```
Each turn:
1. count_tokens → How large is my current context?
2. advise_context_window → Am I approaching the model's limit?
Before expensive tool calls:
3. cache_get → Did I already run this?
When fetching web content:
4. extract_webpage → Clean text, not raw HTML
When history grows long:
5. prune_conversation → Drop filler turns, compress old ones
6. compress_context → Shrink large injected context blocks
When writing system prompts:
7. optimize_prompt → Remove redundant phrasing
```
### Tool reference
count_tokens — measure before you send
```json
{
"content": "Some long text or list of messages...",
"model": "claude-sonnet-4",
"include_message_overhead": true
}
```
Returns `token_count`, `encoding_used`, `model`. Accepts a plain string or an OpenAI-format message list.
compress_context — shrink long text
```json
{
"text": "3,000-token context block...",
"target_tokens": 600,
"mode": "extractive"
}
```
`extractive` (default) uses LSA sentence ranking — free, offline, no API call.
`abstractive` uses `claude-haiku` for higher quality — requires `ANTHROPIC_API_KEY`.
Returns `compressed`, `original_tokens`, `compressed_tokens`, `reduction_pct`.
cache_store / cache_get / cache_invalidate — skip repeated work
```python
# Standard pattern: check before running
key = cache_key("extract_webpage", {"url": "https://example.com"})
hit = cache_get(key=key)
if not hit["hit"]:
result = extract_webpage(url="https://example.com")
cache_store(key=key, value=str(result), ttl_seconds=3600)
```
Cache is stored on disk at `~/.tokensaver/cache/` and survives server restarts.
extract_webpage — content, not markup
```json
{
"url": "https://example.com/article",
"max_tokens": 2000,
"include_links": false,
"include_metadata": true
}
```
Uses [trafilatura](https://github.com/adbar/trafilatura) with BeautifulSoup as fallback. Returns `content`, `title`, `token_count`, `truncated`.
summarize_file — understand code without reading it all
```json
{
"path": "/home/user/myproject",
"mode": "both",
"max_tokens": 500,
"file_extensions": [".py", ".md"],
"max_depth": 3
}
```
`mode` options: `"structure"` (tree only), `"content"` (summarized text), `"both"`.
prune_conversation — clean up history
```json
{
"messages": [...],
"max_output_tokens": 2000,
"keep_last_n": 4,
"prune_strategy": "hybrid"
}
```
`"remove"` drops filler turns ("Sure!", "Got it.").
`"compress"` summarizes older turns in place.
`"hybrid"` does both — recommended for most cases.
Returns the pruned `messages` list, `original_tokens`, `pruned_tokens`, counts of removed/compressed turns.
optimize_prompt — shorter system prompts
```json
{
"prompt": "Please make sure to always answer questions...",
"optimization_level": "medium",
"preserve_constraints": true,
"output_format": "prose"
}
```
`"light"` removes filler phrases. `"medium"` deduplicates sentences. `"aggressive"` restructures.
`preserve_constraints: true` always keeps sentences containing `never`, `must`, `always`, `do not`.
advise_context_window — know what to fix
```json
{
"model": "gpt-4o",
"current_tokens": 110000,
"messages": [...],
"target_utilization": 0.75
}
```
Returns `status` (`"ok"` / `"warning"` / `"critical"`), `headroom_tokens`, prioritized `recommendations`, and a per-turn breakdown sorted by token cost.
Supports: GPT-4o, GPT-4o-mini, Claude 3–4 series, Gemini 1.5/2.0/2.5, O1/O3, Llama 3, Mistral.
---
## Optional: LLM-backed summarization
For higher-quality abstractive compression on very large texts (>5,000 tokens):
```bash
pip install "tokensaver-mcp[llm]"
```
Set `ANTHROPIC_API_KEY` in your environment or a `.env` file, then use `mode: "abstractive"` in `compress_context`.
---
## Running Tests
```bash
pip install -e ".[dev]"
python -m pytest tests/ -v
```
38 tests — all offline, no API key or network required.
---
## Project Structure
```
src/tokensaver/
server.py # FastMCP app, tool registration
models.py # Context window table, shared types
tools/
counter.py # count_tokens
compress.py # compress_context
cache.py # cache_store / cache_get / cache_invalidate
extractor.py # extract_webpage
summarizer.py # summarize_file
pruner.py # prune_conversation
optimizer.py # optimize_prompt
advisor.py # advise_context_window
utils/
token_utils.py # tiktoken wrapper
text_utils.py # sentence splitting, deduplication
```