Skip to main content
Glama
msuther898

context-saver

by msuther898
README.md
# context-saver

[![CI](https://github.com/msuther898/context-saver/actions/workflows/ci.yml/badge.svg)](https://github.com/msuther898/context-saver/actions/workflows/ci.yml)
[![npm version](https://badge.fury.io/js/context-saver.svg)](https://www.npmjs.com/package/context-saver)

**MCP proxy that reduces context usage through semantic tool routing.**

## The Problem

MCP tools consume massive amounts of context tokens before conversations even start:

| Server | Tools | Tokens |
|--------|-------|--------|
| Notion | 14 | ~16,500 |
| Google Drive | 99 | ~18,000 |
| Chrome DevTools | 29 | ~5,800 |
| **Total** | **142** | **~40,300** |

That's **40k tokens** gone before you ask a single question.

## The Solution

context-saver sits between Claude Code and your MCP servers, using vector embeddings to surface only relevant tools on-demand.

```
Claude Code ──► context-saver ──► Backend MCP Servers
                    │
                    ▼
                LanceDB
             (tool embeddings)
```

**Results:**

| Mode | Initial Tokens | Tools Available |
|------|----------------|-----------------|
| Before | ~40,000 | All 142 |
| Standard | ~8,000 | All 142 |
| **Lite** | **~500** | All 142 (on-demand) |

## Quick Start

### 1. Install

```bash
npm install -g context-saver
```

### 2. Create Config

Create `~/.context-saver/config.json`:

```json
{
  "embedding": {
    "provider": "openai",
    "model": "text-embedding-3-small"
  },
  "discovery": {
    "liteMode": true
  },
  "backends": {
    "filesystem": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"]
    }
  }
}
```

### 3. Set API Key

```bash
export OPENAI_API_KEY="sk-..."
```

### 4. Add to Claude Code

Add to your Claude Code MCP settings (`~/.claude/settings.json`):

```json
{
  "mcpServers": {
    "context-saver": {
      "command": "npx",
      "args": ["context-saver"]
    }
  }
}
```

### 5. Use It

In Claude Code, use `discover_tools` to find what you need:

```
> discover_tools("update notion pages")

Found 3 relevant tools:

1. notion-update-page (notion)
   Update a Notion page's content
   Parameters: page_id*, content*
   Relevance: 94%

2. notion-fetch (notion)
   Fetch a Notion page by ID
   Parameters: page_id*
   Relevance: 87%
...
```

## Configuration

### Full Example

```json
{
  "version": "1.0",

  "embedding": {
    "provider": "openai",
    "model": "text-embedding-3-small",
    "dimensions": 1536,
    "apiKey": "${OPENAI_API_KEY}"
  },

  "storage": {
    "path": "~/.context-saver/lancedb",
    "reindexOnStart": false
  },

  "discovery": {
    "defaultTopK": 5,
    "minSimilarity": 0.3,
    "liteMode": true
  },

  "backends": {
    "notion": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@anthropic/mcp-server-notion"],
      "env": {
        "NOTION_API_KEY": "${NOTION_API_KEY}"
      }
    },
    "google-drive": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@anthropic/mcp-server-google-drive"]
    }
  }
}
```

### Options

#### `embedding`

| Option | Default | Description |
|--------|---------|-------------|
| `provider` | `"openai"` | Embedding provider (see below) |
| `model` | varies | Model name |
| `dimensions` | varies | Embedding dimensions |
| `apiKey` | env var | API key (supports env var syntax) |

**Supported Providers:**

| Provider | Model | Dimensions | API Key |
|----------|-------|------------|---------|
| `openai` | `text-embedding-3-small` | 1536 | `OPENAI_API_KEY` |
| `gemini` | `text-embedding-004` | 768 | `GOOGLE_API_KEY` |
| `cohere` | `embed-english-v3.0` | 1024 | `COHERE_API_KEY` |
| `ollama` | `nomic-embed-text` | 768 | None (local) |
| `local` | `Xenova/all-MiniLM-L6-v2` | 384 | None (local) |

**Local embeddings (no API key needed):**
```json
{
  "embedding": {
    "provider": "local",
    "model": "Xenova/all-MiniLM-L6-v2",
    "dimensions": 384
  }
}
```

#### `discovery`

| Option | Default | Description |
|--------|---------|-------------|
| `defaultTopK` | `5` | Default number of tools returned |
| `minSimilarity` | `0.3` | Minimum similarity threshold (0-1) |
| `liteMode` | `false` | **Maximum savings**: only expose `discover_tools` initially |

#### `storage`

| Option | Default | Description |
|--------|---------|-------------|
| `path` | `~/.context-saver/lancedb` | LanceDB storage location |
| `reindexOnStart` | `false` | Force reindex on every startup |

#### `backends`

Each backend can be:

**STDIO** (local process):
```json
{
  "type": "stdio",
  "command": "npx",
  "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"],
  "env": { "KEY": "value" }
}
```

**Remote** (HTTP - coming soon):
```json
{
  "type": "remote",
  "url": "https://mcp.example.com",
  "headers": { "Authorization": "Bearer ..." }
}
```

## Built-in Tools

context-saver exposes six meta-tools:

### `discover_tools`
Semantic search for relevant tools.
```
discover_tools({ query: "search google drive", limit: 5 })
```

### `list_all_tools`
List all available tools grouped by server.
```
list_all_tools()
```

### `tool_info`
Get detailed information about a specific tool including full parameter schema.
```
tool_info({ tool_name: "notion-update-page" })
```

### `similar_tools`
Find tools similar to one you already know.
```
similar_tools({ tool_name: "read_file", limit: 5 })
```

### `tools_by_category`
List tools filtered by category.
```
tools_by_category({ category: "filesystem" })
```
Categories: `filesystem`, `documents`, `spreadsheets`, `presentations`, `images`, `calendar`, `messaging`, `database`, `browser`, `version-control`

### `server_stats`
Get statistics about context-saver including connected backends, indexed tools, and usage stats.
```
server_stats()
```

## Lite Mode

For maximum token savings, enable `liteMode`:

```json
{
  "discovery": {
    "liteMode": true
  }
}
```

In lite mode:
- Only `discover_tools` and `list_all_tools` are exposed initially (~500 tokens)
- All backend tools are still available and routed correctly
- Use `discover_tools` to find what you need

## How It Works

1. **Startup**: Connects to all backend MCP servers and indexes their tools
2. **Indexing**: Creates embeddings for each tool using OpenAI
3. **Storage**: Stores embeddings in LanceDB for fast vector search
4. **Discovery**: When you call `discover_tools`, performs cosine similarity search
5. **Routing**: Tool calls are routed to the correct backend server

## Development

```bash
git clone https://github.com/msuther898/context-saver.git
cd context-saver
npm install
npm run build
npm start
```

### Project Structure

```
src/
├── index.ts              # Entry point
├── server.ts             # MCP server + handlers
├── client-pool.ts        # Backend connections
├── config/               # Config types + loader
├── discovery/
│   ├── indexer.ts        # Tool indexing with synonyms
│   └── search.ts         # Vector search + re-ranking
├── embeddings/
│   ├── index.ts          # Provider factory
│   ├── openai.ts         # OpenAI embeddings
│   ├── gemini.ts         # Google Gemini embeddings
│   ├── cohere.ts         # Cohere embeddings
│   ├── ollama.ts         # Ollama local embeddings
│   └── local.ts          # Transformers.js embeddings
└── storage/
    └── lancedb.ts        # LanceDB vector storage
```

## Roadmap

- [x] Ollama embeddings support
- [x] Local embeddings (transformers.js)
- [x] Gemini embeddings support
- [x] Cohere embeddings support
- [x] Usage tracking and popularity boosting
- [x] Re-ranking with multiple signals
- [x] Category-based tool filtering
- [ ] Remote HTTP backend support
- [ ] Tool result caching
- [ ] Persistent usage stats

## License

MIT

## Credits

Built by [@msuther898](https://github.com/msuther898) with Claude.