Skip to main content
Glama
The Context-Saver

The Context-Saver

by Gatsuke

The Context-Saver is an MCP Gateway/Router: one Model Context Protocol server that multiplexes all of your other MCP servers, and hands the model only the tool schemas it needs for the current turn. Connect one thing. Get everything. Burn almost nothing.

CI npm license node MCP

Why · Quick Start (60 s) · How it works · The 8 meta-tools · Configuration · Auth · Real numbers · FAQ



The pain point

You installed one MCP server and it was magic. Then you added a second. A third. Ten. Now, before you type a single word, every server has injected its full tool schema into your context window:

  • 10 servers ≈ 15,000–20,000 tokens burned per session — you pay for it on every request, on every provider

  • the model sees hundreds of tools at once and starts hallucinating workflows that don't exist ("let me just use db_migrate_hotfix…")

  • your $200/mo API plan is quietly funding a 20k-token preamble you never asked for

  • add a server, and your entire team's prompts get worse

This is one of the most common complaints on developer forums right now. The schemas aren't the problem — loading them all upfront is.

Related MCP server: AISIX AI Gateway

The idea

Don't connect 10 servers to Claude Code / Cursor / whatever. Connect one: the Context-Saver gateway.

flowchart LR
    subgraph before["❌ Direct: N servers"]
        L1[Claude Code]
        S1[Server A<br/>40 tools<br/>~4.7k tok]
        S2[Server B<br/>25 tools<br/>~2.9k tok]
        S3[Server C<br/>12 tools<br/>~1.4k tok]
        SD[Dots ×7 more]
        L1 -->|full schemas<br/>ALL AT ONCE| S1
        L1 --> S2
        L1 --> S3
        L1 -.-> SD
    end
flowchart LR
    subgraph after["✅ With the Context-Saver gateway"]
        L2[Claude Code]
        GW[Context-Saver Gateway<br/>8 fixed meta-tools<br/>~1.3k tok — CONSTANT]
        U1[Server A]
        U2[Server B]
        U3[Server C]
        U4[Server …]
        L2 -->|one connection| GW
        GW -.->|lazy: schemas only<br/>when actually needed| U1
        GW -.-> U2
        GW -.-> U3
        GW -.-> U4
    end

The gateway speaks MCP on one side and is an MCP client on the other. It indexes every upstream's tools, then serves the model a fixed menu of 8 meta-tools. When a prompt arrives, suggest_tools ranks the catalog against the prompt and returns the matched tools with their schemas in the same response — so one cheap call replaces the entire upfront burn.

Why schemas stay fixed but the model still knows what exists: the 8 meta-tools include a compact catalog (list_tools: name + one-line description, no schemas) and search_tools. The model can see what exists for ~2–3k tokens on a 90-tool setup, then load the exact schema it wants, when it wants it.

Quick Start in 60 Seconds

1 — Declare your upstream servers (the only file you'll ever edit):

mkdir -p ~/.context-saver
cp servers.example.json ~/.context-saver/servers.json
$EDITOR ~/.context-saver/servers.json   # point at *your* servers

2 — Connect your host to the gateway instead of N servers.

Local (stdio — Claude Code, Cursor, VS Code, any MCP host):

npx context-saver-mcp            # that's the whole server
// e.g. Claude Code / claude_desktop_config.json
{
  "mcpServers": {
    "context-saver": { "command": "npx", "args": ["-y", "context-saver-mcp"] }
  }
}

Remote (Streamable HTTP + SSE, zero-copy-paste-JSON-for-auth) — step 3 only if you want the OAuth popup instead of a static key:

npx context-saver-mcp --transport http --port 6480 --auth oauth
# stderr prints:
#   OAuth 2.1 (PKCE) ready: /oauth/authorize (popup) · /oauth/token
#   listening on http://127.0.0.1:6480/mcp

Point any MCP host (or your whole team) at http://<host>:6480/mcp. No API keys in client JSON — the host pops the login page (see it rendered), the user enters the access code, PKCE completes, done.

That's the whole setup. Ask your agent something and watch it call suggest_tools first instead of drowning in 92 schemas.

How it works

Architecture

flowchart TB
    subgraph client["MCP host (Claude Code, Cursor, VS Code, …)"]
        M[model]
    end

    subgraph gw["context-saver-mcp — the single-file gateway"]
        direction TB
        T1["stdio transport (local)"]
        T2["Streamable HTTP + SSE (remote)<br/>sessions · idle sweeping · DELETE"]
        AUTH["Auth: none | apikey | OAuth 2.1 + PKCE<br/>RFC 8414 / 9728 discovery · popup login"]
        META["8 fixed meta-tools<br/>(~1.3k tokens, CONSTANT)"]
        IDX["Catalog index + token accounting<br/>persisted cache (~/.context-saver/cache.json)"]
        POOL["Lazy connection pool<br/>timeouts · 1 reconnect-replay<br/>circuit breakers · EMA latency"]
    end

    subgraph upstreams["Your existing MCP servers — unmodified"]
        U1["stdio<br/>npx … / uvx …"]
        U2["Streamable HTTP"]
        U3["legacy SSE"]
    end

    M --> T1
    M --> T2
    T2 --> AUTH
    T1 --> META
    T2 --> META
    META --> IDX
    META --> POOL
    POOL --> U1
    POOL --> U2
    POOL --> U3

One turn, end to end

sequenceDiagram
    autonumber
    participant U as You
    participant M as Model
    participant G as Context-Saver gateway
    participant W as Upstream (e.g. weather)

    U->>M: "What's the weather forecast for Kuala Lumpur tomorrow?"
    M->>G: suggest_tools { prompt }
    Note over G: scores the 92-tool catalog<br/>against the prompt (IDF-weighted)
    G-->>M: matches + schemas of the top tools<br/>272 tokens — the ONLY schemas loaded
    M->>G: call_tool { server: "weather", tool: "get_forecast", arguments }
    G->>W: MCP tools/call (lazy-dials if idle)
    W-->>G: result
    G-->>M: result (passed through, errors normalized)
    Note over M: total context cost this turn: gateway 1.3k + 272<br/>direct-connect would have burned 8.3k

The 8 meta-tools

Tool

What it does

Token cost

list_servers

Upstream registry + health + circuit state

tiny, fixed

list_tools

Compact catalog — names + one-liners, no schemas

~30 tok per 10 tools

search_tools

Keyword search with reasons and per-tool schema cost

tiny

suggest_tools

The core trick: prompt → ranked matches with schemas in one response

~200–300 tok

get_tool_schema

Load exactly one full JSON schema

the schema, only when needed

call_tool

Execute on the upstream (timeout, reconnect, breaker)

passthrough

gateway_status

Health + the live context-savings report

tiny

reload_config

Hot-reload servers.json without a restart

tiny

Fixed menu. The footprint never grows as you add upstreams — that's the whole point. (The instructions shipped to the host model teaches it this workflow.)

Configuration

One file, searched in this order: --config <path> → CS_CONFIG → ~/.context-saver/servers.json → ./servers.json. See servers.example.json and the machine-checked docs/config-schema.schema.json.

{
  "defaults": { "callTimeoutMs": 60000, "breakerThreshold": 3 },
  "servers": [
    { "name": "github",     "type": "http",  "url": "https://mcp.github.com/mcp",
      "headers": { "authorization": "Bearer ${GITHUB_MCP_TOKEN}" } },   // ${ENV} expanded — no secrets in the file
    { "name": "filesystem", "type": "stdio", "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "~/projects"],
      "exclude": ["write_*"] },                                          // glob tool filtering
    { "name": "sqlite",     "type": "stdio", "command": "uvx",
      "args": ["mcp-server-sqlite", "--db-path", "~/data/app.db"] },
    { "name": "legacy",      "type": "sse",  "url": "http://10.0.0.4:8901/sse", "disabled": true }
  ]
}

Every upstream gets: per-call timeout (default 60 s), connect timeout (15 s), one automatic reconnect+replay on transport death, and a circuit breaker (3 consecutive failures → open → fast-fail for 30 s → half-open probe) so one dead server can never stall your agent's turn. ${VAR} expansion works in command, args, env, url, headers and cwd.

reload_config (or SIGHUP in HTTP mode) applies edits live: unchanged upstreams keep their connections, changed ones are swapped, removed ones are disconnected — and a broken file never takes down the running setup.

Zero-friction auth (OAuth popup, no keys in JSON)

Remote mode supports three auth levels — pick per deployment:

Mode

Setup

Who it's for

none (default)

—

localhost / private network behind a VPN

apikey

CS_API_KEY=… (checked in constant time)

personal remote, single user

oauth

CS_ACCESS_CODE=… (+ CS_TOKEN_SECRET, CS_PUBLIC_URL behind TLS)

teams — the "viral" path: no API keys in client config files, ever

The oauth mode is a built-in OAuth 2.1 authorization server with everything MCP hosts expect:

  • /.well-known/oauth-protected-resource (RFC 9728) + /.well-known/oauth-authorization-server (RFC 8414) discovery

  • WWW-Authenticate: Bearer resource_metadata=… on 401 (so Claude / Cursor auto-discover the flow)

  • Popup login page — user types the access code, no API keys, no JSON

  • PKCE (S256) mandatory, single-use 120 s codes, rotating refresh tokens, HMAC-signed access tokens

  • Dynamic client registration (RFC 7591) for hosts that use it

Details and threat model: SECURITY.md.

Real numbers (measured, not marketing)

From the captured demo session (92 tools across 6 upstreams — scripts/gif-session.mjs + the at scale integration test):

Direct-connect

Context-Saver gateway

Tool schemas in context, before first prompt

8,295 tokens

0 (catalog metadata only)

Fixed menu the model always sees

— (grows with every server)

1,322 tokens, constant

suggest_tools for a weather prompt

—

272 tokens incl. the 2 schemas it needed

Session total after a real forecast call

8,295

1,594 → 84 % saved

Idle turn cost

8,295 tokens, every request

~0 marginal

At ~$3/M input tokens, one heavy user burning 8.3k tokens on every request, 50 requests/day pays ≈ $37/month for schemas alone. The same usage through the gateway: ~$6. Scaling is linear: add servers, the direct-connect column grows, the gateway column stays ~1.3k + what you actually load.

Resilience you get for free

  • Lazy everything — upstreams that are never called never spawn a process or open a socket; cold starts serve the persisted catalog instantly

  • One bad server can't hurt you — timeouts, breakers and normalized errors per upstream; the audit even has a test where a nonexistent binary fast-fails while weather keeps answering

  • did you mean UX — unknown server/tool typos get Levenshtein suggestions instead of dead ends

  • Sane HTTP server semantics — session ids, 400/404/405/413 handling, CORS, /health, idle-session sweeping, clean shutdown (no hanging keep-alive sockets — that was a real bug we fixed)

  • Stdout is sacred — in stdio mode all logging goes to stderr; no-console is a lint rule because one stray console.log corrupts the JSON-RPC stream

Contributing & Good First Issues

The entire server is one readable, section-bounded file (~2,000 lines, no build step) — read sections 1–11 top to bottom and you've read the whole product. CONTRIBUTING.md maps sections to starter issues.

Current good-first-issues:

  • Prompt ranking is TF-IDF, not embeddings (§5) — deterministic and dependency-free, but a pluggable Scorer interface would let people add smarter rankers

  • resources / prompts passthrough (§7) — the gateway multiplexes tools only today

  • OAuth state persistence (§8) — codes/refresh tokens are in-memory per process; a pluggable store would enable multi-instance deployments

  • IdP delegation (§8) — "Continue with GitHub" login option behind the popup

  • Upstream include/exclude tests on Windows (§3) — glob behavior across path separators

Node ≥ 18.19, zero runtime dependencies beyond @modelcontextprotocol/sdk + zod, npm test runs 42 tests in ~20 s.

FAQ

Does this break the host's tool discovery? No — it replaces it. The model sees 8 stable meta-tools (fewer than most single servers) plus a compact catalog. MCP tools/list pagination is honored upstream; nothing is truncated silently.

Is the ranking "AI"? It's honest engineering: tokenization, stopwording, camelCase/snake_case splitting and IDF weighting — deterministic, testable, no API calls. For most prompts it lands the right tool; search_tools/list_tools cover the rest, and the model always stays in control.

What about latency? One extra hop on the LAN/localhost. Lazy connections mean a cold upstream pays its connect time once, on first use; hot calls add ~1 ms of routing.

Can it multiplex resources and prompts? Not yet — tools only in 1.0.0 (see good first issues; the section-bounded codebase makes this a contained change).

Why OAuth instead of just an API key? Both work (apikey mode is one env var). OAuth mode exists because copying bearer tokens into local client JSON is the #1 friction killing MCP tool adoption in teams — the popup flow means a new teammate connects in one click.

Single file — isn't that bad engineering? It's a feature: npx context-saver-mcp downloads one readable artifact with no build step, every section is exported for testing, and the audit trail shows fixes landing in a single file with full test coverage. The tests/ tree is where the structure lives.


MIT © Gatsuke · Built because 20k tokens of schemas before breakfast is 19k too many.

Available Tools

8 tools
call_toolExecute an upstream toolA

Run a tool on an upstream MCP server. Arguments are passed through unmodified and validated by the upstream against the schema you loaded. Timeouts, one automatic reconnect, and a circuit breaker protect your turn from stuck upstreams.

Inputs: tool (required), server (required), arguments.

gateway_statusGateway health & savings reportA
Read-onlyIdempotent

Health of every upstream (status, latency, error counts, breaker state) plus the context-savings report: tokens a direct connection would burn vs. tokens this session actually spent.

Inputs: no named parameters.

get_tool_schemaLoad one full tool schemaA
Read-onlyIdempotent

Fetch the complete JSON schema (and annotations) of exactly ONE upstream tool — the precise, lazy-loading primitive. Prefer suggest_tools when you only have a vague prompt; call this when you already know the tool.

Inputs: tool (required), server (required).

list_serversList upstream MCP serversA
Read-onlyIdempotent

List the upstream MCP servers multiplexed by this gateway, with health, circuit-breaker state and tool counts. Cheap: call this first to orient yourself.

Inputs: no named parameters.

list_toolsCompact tool catalogA
Read-only

List upstream tools COMPACTLY (name + one-line description, no JSON schemas). Optionally filter to one server. Set refresh=true to force a live re-index.

Inputs: server, refresh.

reload_configHot-reload the upstream registryA

Re-read servers.json and apply changes WITHOUT restarting the gateway: new servers appear, removed ones are disconnected, unchanged ones keep their connections. Fails safely — a broken config leaves the current setup running.

Inputs: no named parameters.

search_toolsKeyword search across all toolsA
Read-only

Search every upstream tool by keywords. Returns ranked matches with reasons and per-tool schema cost. Schemas are NOT included — load the ones you need with get_tool_schema.

Inputs: query (required), top_k, include_schemas.

suggest_toolsPrompt-aware tool suggestions (the context saver)A
Read-onlyIdempotent

THE core trick: pass the user's current prompt. Ranks the catalog against it and returns the best-matching upstream tools WITH their full JSON schemas in this single response — so one cheap call replaces loading every schema. Default top_k=4 keeps context lean; raise it for complex multi-tool tasks.

Inputs: prompt (required), top_k, auto_load.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 8 tools

    Disambiguation4/5

    The tools are mostly distinct: discovery is split into list_tools (compact list), search_tools (keyword search), suggest_tools (prompt-ranked with schemas), and get_tool_schema (single schema load), with clear boundaries. The main overlap is list_servers vs gateway_status, both of which expose upstream health/circuit-breaker state, though the descriptions differentiate cheap orientation from detailed status reporting.

    Naming Consistency4/5

    All names use snake_case and most follow a predictable verb_object pattern: list_servers, list_tools, search_tools, suggest_tools, get_tool_schema, call_tool, reload_config. gateway_status is the one noun-phrase outlier, a minor deviation rather than a pattern break.

    Tool Count5/5

    Eight tools is well-scoped for a gateway that needs to orient, discover, load schemas, invoke upstream tools, report health, and reload config. Each tool has a clear role in the workflow, and there is no obvious padding.

    Completeness4/5

    The surface covers the core gateway lifecycle: list servers/tools, search and suggest tools, fetch schemas, call upstream tools, report status, and reload configuration. Minor gaps remain around explicit server connection management, circuit-breaker reset, or MCP resources/prompts if those upstream capabilities are in scope.

    Maintenance

    ActivityNo data
    ResponsivenessSyncing

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      A
      quality
      A
      maintenance
      A multiplexing gateway that aggregates multiple MCP servers into a single port, significantly reducing context token usage through a Meta-MCP discovery system. It enables dynamic tool discovery and invocation across various transport protocols including stdio, HTTP, and SSE.
      15
      84
      -
    • A
      license
      A
      quality
      B
      maintenance
      Self-hosted MCP gateway that registers upstream MCP servers and fronts them behind one governed Streamable HTTP endpoint: per-tool access control by caller API key, guardrails over tool arguments and results, rate limits, and usage logs. The same Rust gateway also proxies LLM and A2A agent traffic.
      1
      216
      Apache 2.0
    • A
      license
      A
      quality
      D
      maintenance
      Enables connecting multiple downstream MCP servers into a single gateway, with unified tool search, namespacing, and deferred loading to preserve context window.
      2
      6
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      Enables agents to connect through a single gateway that has a decision model pick which MCP tools and playbooks are relevant to each request, so the LLM only sees the few schemas it needs, and to then invoke those tools on the underlying servers. This cuts tool-selection cost and prompt size dramatically when many MCP servers are connected.
      2
      4
      MIT