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 stringfetch_fn— async callable that returns a JSON-serializable valuettl— per-call TTL override in seconds; usesdefault_ttlif 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 keysinclude_expired— include expired entries; defaults toFalse(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 seriesstart_date,end_date—dateobjects or ISO strings ("YYYY-MM-DD")fetch_fn(start, end)— async callable receiving ISO date strings; must return a list of dicts containingdate_keyand optionallyvalue_keydate_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
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_cache-0.2.2.tar.gz.
File metadata
- Download URL: mcp_cache-0.2.2.tar.gz
- Upload date:
- Size: 18.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b483c42c403129ff82a3e86fa479f989894acaa2b7138f11e022dd5130e8d13
|
|
| MD5 |
9ca0d5cf986cb47103aeef58b1a00576
|
|
| BLAKE2b-256 |
c55b88566250716ae07301f552c5ed948a96546525e488c82dd52bffd764fc19
|
File details
Details for the file mcp_cache-0.2.2-py3-none-any.whl.
File metadata
- Download URL: mcp_cache-0.2.2-py3-none-any.whl
- Upload date:
- Size: 8.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e78f6276a9e6b349ac03d8f78a218c854e66b9aa7231a5d3977afbf475eae5a5
|
|
| MD5 |
c1724f08ac99ff5307340ad2cf748246
|
|
| BLAKE2b-256 |
89ef07a3eb0f4f3e14e17c2b242ea3741c9bff7d859b658269843013f1e6f323
|