Skip to main content

Reusable SQLite-backed cache for MCP servers — TTL and incremental time series strategies

Project description

mcp-cache

A reusable SQLite-backed cache for MCP (Model Context Protocol) servers. Zero dependencies — pure Python stdlib.

Two caching strategies:

  • TTL cache — store any JSON-serializable value for N seconds
  • Time series cache — store date-keyed observations and automatically fetch only missing date ranges

Installation

pip install mcp-cache

Or from source:

git clone https://github.com/cmaurer/mcp-cache
cd mcp-cache
pip install -e .

Requires Python 3.10+.

Quick start

TTL cache

from mcp_cache import MCPCache

cache = MCPCache("~/.cache/myserver.db", default_ttl=300)

async def get_quote(symbol: str) -> dict:
    return await cache.get_or_fetch(
        key=f"quote:{symbol}",
        fetch_fn=lambda: api.fetch_quote(symbol),
        ttl=60,  # override default; omit to use default_ttl
    )

fetch_fn is called only on a cache miss or after the TTL expires. The result is stored as JSON and returned on subsequent calls within the TTL window.

Time series cache

observations = await cache.get_timeseries(
    series_id="T10YIE",
    start_date="2020-01-01",
    end_date="2024-12-31",
    fetch_fn=lambda s, e: fred_api.get_series("T10YIE", s, e),
)
# Returns list of {"date": "YYYY-MM-DD", "value": float} dicts, newest first

On the first call the full range is fetched. On subsequent calls only gaps are fetched — requesting a wider range re-uses the already-cached portion and fetches only the missing edges.

Custom key names are supported for APIs that don't use "date" / "value":

observations = await cache.get_timeseries(
    series_id="prices",
    start_date="2024-01-01",
    end_date="2024-06-30",
    fetch_fn=my_fetch,
    date_key="timestamp",
    value_key="close",
)

API reference

MCPCache(db_path, default_ttl)

Parameter Type Default Description
db_path str | Path "mcp_cache.db" Path to SQLite file. ~ is expanded. Parent dirs are created automatically.
default_ttl int 300 Default TTL in seconds for get_or_fetch.

TTL cache methods

await cache.get_or_fetch(key, fetch_fn, ttl=None)

Return the cached value for key if it exists and is still fresh. Otherwise call fetch_fn(), store the result, and return it.

  • key — cache key string
  • fetch_fn — async callable that returns a JSON-serializable value
  • ttl — per-call TTL override in seconds; uses default_ttl if omitted

await cache.invalidate(key)

Remove a specific entry from the TTL cache. No-op if the key does not exist.

await cache.clear_expired()

Delete all expired TTL entries. Returns the number of entries removed.


Time series methods

await cache.get_timeseries(series_id, start_date, end_date, fetch_fn, date_key="date", value_key="value")

Return cached observations for series_id in [start_date, end_date].

  • series_id — identifier for the series
  • start_date, end_datedate objects or ISO strings ("YYYY-MM-DD")
  • fetch_fn(start, end) — async callable receiving ISO date strings; must return a list of dicts containing date_key and optionally value_key
  • date_key, value_key — key names in the returned dicts (default "date", "value")

Returns a list of {date_key: str, value_key: float | None} dicts sorted newest first. None values are preserved — they represent real data points (e.g. non-trading days).

await cache.invalidate_series(series_id)

Remove all cached observations and range records for a series.


Diagnostics

await cache.stats()

Returns a dict with cache counts:

{
    "ttl_cache":  {"total": 12, "fresh": 10, "expired": 2},
    "timeseries": {"series": 3, "observations": 1500, "fetched_ranges": 6},
    "db_path":    "/home/user/.cache/myserver.db",
}

Using with an MCP server

from mcp_cache import MCPCache

_cache = MCPCache("~/.cache/myserver.db")

@server.tool()
async def get_price_history(symbol: str, start: str, end: str) -> list[dict]:
    return await _cache.get_timeseries(
        series_id=symbol,
        start_date=start,
        end_date=end,
        fetch_fn=lambda s, e: data_provider.fetch(symbol, s, e),
    )

Using with Claude Desktop

Install the package:

pip install mcp-cache

Add the server to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "cache": {
      "command": "mcp-cache"
    }
  }
}

Restart Claude Desktop. The following tools will be available:

Tool Description
cache_get(key) Return a cached value, or null if missing/expired
cache_set(key, value, ttl) Store a JSON value for ttl seconds (default 300)
cache_invalidate(key) Remove a specific entry
cache_clear_expired() Delete all expired entries
timeseries_store(series_id, observations, range_start, range_end) Store date-keyed observations
timeseries_get(series_id, start_date, end_date) Query cached observations
timeseries_invalidate(series_id) Clear all data for a series
cache_stats() Return entry counts and db path

The cache database is stored at ~/.cache/mcp_cache.db.

Development

pip install -e ".[dev]"
pytest

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_cache-0.2.0.tar.gz (11.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_cache-0.2.0-py3-none-any.whl (3.4 kB view details)

Uploaded Python 3

File details

Details for the file mcp_cache-0.2.0.tar.gz.

File metadata

  • Download URL: mcp_cache-0.2.0.tar.gz
  • Upload date:
  • Size: 11.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mcp_cache-0.2.0.tar.gz
Algorithm Hash digest
SHA256 dd38e436e6675652006347498b24bc4755de53a5e43c9e91fa3490e13775bd64
MD5 7e4e144c05b2ed2c4211b22e537fc815
BLAKE2b-256 e6ac8251bf2a01ee81c346e69b650599d72fa0a89bac70200c7348b2eadbecc8

See more details on using hashes here.

File details

Details for the file mcp_cache-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: mcp_cache-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 3.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mcp_cache-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 134c358f29a24c6bb4e631aed0ffd01e63446d49663b298e4315cbf625e02a7d
MD5 ad6922a4b16b93915482aa2c8c45c5e3
BLAKE2b-256 2b0cc348b9ac8615cbc2382ed0faf71a9a638349399d5407d2b20b5c2f11067d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page