Skip to main content

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.

await cache.list_keys(prefix=None, include_expired=False)

Return TTL cache keys as a sorted list of strings.

  • prefix — only return keys starting with this string; None (default) returns all keys
  • include_expired — include expired entries; defaults to False (fresh keys only)

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_date — date 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.

await cache.list_series(prefix=None)

Return distinct time series IDs as a sorted list of strings.

  • prefix — only return series IDs starting with this string; None (default) returns all 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
cache_list_keys(prefix, include_expired) List TTL cache keys, optionally filtered by prefix
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
timeseries_list_series(prefix) List time series IDs, optionally filtered by prefix
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

Metadata

Release files for mcp-cache 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-cache 0.2.2
File Size Uploaded Provenance
mcp_cache-0.2.2.tar.gz 18.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-cache 0.2.2
File Interpreter ABI Platform
mcp_cache-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 27.5 kB

Release files / mcp_cache-0.2.2.tar.gz

Download URL mcp_cache-0.2.2.tar.gz
Size 18.7 kB
Tags Source
SHA-256 checksum
How to use checksums
6b483c42c403129ff82a3e86fa479f989894acaa2b7138f11e022dd5130e8d13
BLAKE2b-256 checksum
How to use checksums
c55b88566250716ae07301f552c5ed948a96546525e488c82dd52bffd764fc19
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Release files / mcp_cache-0.2.2-py3-none-any.whl

Download URL mcp_cache-0.2.2-py3-none-any.whl
Size 8.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e78f6276a9e6b349ac03d8f78a218c854e66b9aa7231a5d3977afbf475eae5a5
BLAKE2b-256 checksum
How to use checksums
89ef07a3eb0f4f3e14e17c2b242ea3741c9bff7d859b658269843013f1e6f323
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.12

Security for mcp-cache 0.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page