ChronicleMCP
Table of Contents
- Quick Start
- Features
- Installation
- Usage
- Configuration
- Security & Privacy
- Supported Browsers
- Troubleshooting
- Development
- Contributing
- License
Quick Start
# Install
pip install chronicle-mcp
# Run MCP server (stdio mode for AI agents like Claude, Cursor)
chronicle-mcp mcp
# Or start an HTTP server
chronicle-mcp http --port 8080
# Check available browsers
chronicle-mcp list-browsers
Features
| Feature | Description |
|---|---|
| 🔒 Privacy-First | All data stays on your machine. No cloud sync, no data collection. |
| 🌐 Multi-Browser | Chrome, Firefox, Edge, Brave, Safari, Vivaldi, Opera support |
| 🔍 Multiple Search Tools | Search by query, date range, domain, or recent history |
| 📊 Output Formats | Markdown (default) or JSON |
| ⚡ Fast Performance | Built with Python and SQLite |
| 🔐 Secure | URL sanitization removes sensitive query parameters |
| 🐳 Docker Support | Run as a container |
| 🔧 CLI Interface | Full command-line control |
| 🌐 HTTP API | RESTful API for integrations |
| 🔖 Bookmarks | Read bookmarks from all supported browsers |
| ⬇️ Downloads | Track download history from all supported browsers |
Installation
pip (Recommended)
pip install chronicle-mcp
pipx (Isolated Installation)
pipx install chronicle-mcp
Docker
# Pull the latest image
docker pull ghcr.io/nikolasil/chronicle-mcp:latest
# Run the server
docker run -p 8080:8080 ghcr.io/nikolasil/chronicle-mcp
From Source
git clone https://github.com/nikolasil/chronicle-mcp.git
cd chronicle-mcp
pip install -e .
Homebrew (macOS)
brew tap nikolasil/chronicle-mcp
brew install chronicle-mcp
Usage
CLI Commands
chronicle-mcp mcp
Run the MCP server for AI agents.
# Stdio mode (default for AI assistants)
chronicle-mcp mcp
# SSE mode for HTTP clients
chronicle-mcp mcp --sse --port 8080
| Option | Description |
|---|---|
--sse |
Use SSE transport instead of stdio |
--host |
Host to bind (SSE mode only) |
--port |
Port to listen on (SSE mode only) |
chronicle-mcp http
Start a long-running HTTP REST API server.
# Default (foreground, port 8080)
chronicle-mcp http
# Custom port
chronicle-mcp http --port 9000
# Daemon mode
chronicle-mcp http --port 8080 --daemon
# Different browser
chronicle-mcp http --browser firefox
| Option | Description |
|---|---|
--host |
Host to bind (default: 127.0.0.1) |
--port |
Port to listen on (default: 8080) |
--browser |
Default browser (default: chrome) |
--foreground |
Run in foreground (default: true) |
--daemon |
Run as daemon |
chronicle-mcp status
Check if the server is running.
chronicle-mcp status --port 8080
chronicle-mcp logs
View server logs.
chronicle-mcp logs --port 8080 --lines 100
chronicle-mcp version
Show version information.
chronicle-mcp version
chronicle-mcp list-browsers
List available browsers on the system.
chronicle-mcp list-browsers
# Output: Available browsers: chrome, edge
chronicle-mcp completion
Generate shell completion scripts.
# Bash
chronicle-mcp completion bash >> ~/.bashrc
# Zsh
chronicle-mcp completion zsh >> ~/.zshrc
# Fish
chronicle-mcp completion fish > ~/.config/fish/completions/chronicle-mcp.fish
MCP Tools
search_history
Search browser history for keywords in titles or URLs.
def search_history(
query: str,
limit: int = 5,
browser: str = "chrome",
format_type: str = "markdown"
) -> str
Example:
# Markdown output (default)
search_history("python tutorial", limit=10, browser="chrome")
# JSON output
search_history("github", limit=5, format_type="json")
get_recent_history
Get recent browsing history from the last N hours.
def get_recent_history(
hours: int = 24,
limit: int = 20,
browser: str = "chrome",
format_type: str = "markdown"
) -> str
Example:
# Last 24 hours
get_recent_history(hours=48, limit=20)
count_visits
Count total visits to a specific domain.
def count_visits(
domain: str,
browser: str = "chrome"
) -> str
Example:
count_visits("github.com", browser="chrome")
# Output: Visits to 'github.com' in chrome: 42
list_top_domains
Get the most visited domains.
def list_top_domains(
limit: int = 10,
browser: str = "chrome",
format_type: str = "markdown"
) -> str
Example:
list_top_domains(limit=20)
search_history_by_date
Search history within a date range.
def search_history_by_date(
query: str,
start_date: str, # ISO format: YYYY-MM-DD
end_date: str, # ISO format: YYYY-MM-DD
limit: int = 10,
browser: str = "chrome",
format_type: str = "markdown"
) -> str
Example:
search_history_by_date(
"python",
start_date="2024-01-01",
end_date="2024-12-31",
limit=20
)
list_available_browsers
Returns a list of browsers with detected history databases.
def list_available_browsers() -> str
Example:
list_available_browsers()
# Output: Available browsers: chrome, edge, firefox, brave
delete_history
Delete history entries matching a query.
def delete_history(
query: str,
limit: int = 100,
browser: str = "chrome",
confirm: bool = False
) -> str
Example:
# Preview what would be deleted (default)
delete_history("spam.com", browser="chrome")
# Actually delete
delete_history("spam.com", browser="chrome", confirm=True)
search_by_domain
Search history within specific domain(s).
def search_by_domain(
domain: str,
query: str = None,
limit: int = 20,
browser: str = "chrome",
format_type: str = "markdown",
exclude_domains: list[str] = None
) -> str
Example:
search_by_domain("github.com", browser="chrome")
get_browser_stats
Get browsing statistics for the browser database.
def get_browser_stats(browser: str = "chrome") -> str
Example:
get_browser_stats(browser="firefox")
# Returns JSON with total visits, domains, date range, etc.
get_most_visited_pages
Get the most visited individual pages.
def get_most_visited_pages(
limit: int = 20,
browser: str = "chrome",
format_type: str = "markdown"
) -> str
Example:
get_most_visited_pages(limit=10, browser="chrome")
export_history
Export history to CSV or JSON format.
def export_history(
format_type: str = "csv",
limit: int = 1000,
query: str = None,
browser: str = "chrome"
) -> str
Example:
# Export to CSV
export_history(format_type="csv", limit=1000, browser="chrome")
# Export to JSON
export_history(format_type="json", limit=500, browser="firefox")
search_history_advanced
Advanced search with multiple options including regex and fuzzy matching.
def search_history_advanced(
query: str,
limit: int = 20,
browser: str = "chrome",
format_type: str = "markdown",
exclude_domains: list[str] = None,
sort_by: str = "date",
use_regex: bool = False,
use_fuzzy: bool = False,
fuzzy_threshold: float = 0.6
) -> str
Example:
# Fuzzy search
search_history_advanced("pythn tutorial", use_fuzzy=True, fuzzy_threshold=0.7)
# Regex search
search_history_advanced(r"github\.com/.*/issues/\d+", use_regex=True)
sync_history
Sync history between browsers.
def sync_history(
source_browser: str,
target_browser: str,
merge_strategy: str = "latest",
dry_run: bool = True
) -> str
Example:
# Preview sync
sync_history("chrome", "firefox", dry_run=True)
# Actually sync
sync_history("chrome", "firefox", dry_run=False)
list_available_bookmarks
Returns a list of browsers with detected bookmarks.
def list_available_bookmarks() -> str
Example:
list_available_bookmarks()
# Output: Available browsers with bookmarks: chrome, edge, firefox
list_available_downloads
Returns a list of browsers with detected downloads history.
def list_available_downloads() -> str
Example:
list_available_downloads()
# Output: Available browsers with downloads: chrome, edge, firefox
get_bookmarks
Get bookmarks from a browser.
def get_bookmarks(
query: str = None,
limit: int = 50,
browser: str = "chrome",
format_type: str = "markdown"
) -> str
Example:
# Get all bookmarks
get_bookmarks(browser="chrome")
# Search bookmarks
get_bookmarks(query="python", browser="firefox")
get_downloads
Get downloads history from a browser.
def get_downloads(
query: str = None,
limit: int = 50,
browser: str = "chrome",
format_type: str = "markdown"
) -> str
Example:
# Get all downloads
get_downloads(browser="chrome")
# Search downloads
get_downloads(query="pdf", browser="firefox")
HTTP API
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Health check |
| GET | /ready |
Readiness check |
| GET | /metrics |
Basic metrics |
| GET | /metrics/prometheus |
Prometheus metrics |
| GET | /api/browsers |
List available browsers |
| POST | /api/search |
Search history |
| POST | /api/recent |
Recent history |
| POST | /api/count |
Count domain visits |
| POST | /api/top-domains |
Top domains |
| POST | /api/search-date |
Search by date |
| POST | /api/delete |
Delete history entries |
| POST | /api/domain-search |
Search by domain |
| POST | /api/stats |
Browser statistics |
| POST | /api/most-visited |
Most visited pages |
| POST | /api/export |
Export history |
| POST | /api/advanced-search |
Advanced search |
| POST | /api/sync |
Sync between browsers |
| GET | /api/bookmarks |
List available bookmarks |
| POST | /api/bookmarks/query |
Query bookmarks |
| GET | /api/downloads |
List available downloads |
| POST | /api/downloads/query |
Query downloads |
| POST | /api/compare-periods |
Compare browsing periods |
| POST | /api/productivity |
Analyze productivity |
| POST | /api/suggest-categories |
Suggest URL categories |
| POST | /api/visualization |
Export visualization data |
| POST | /api/insights |
Generate insights report |
| POST | /api/subscribe |
Subscribe to history changes |
| POST | /api/unsubscribe |
Unsubscribe from history |
| POST | /api/subscription-status |
Get subscription status |
| POST | /api/find-duplicates |
Find duplicate entries |
| POST | /api/delete-duplicates |
Delete duplicate entries |
Request/Response Examples
POST /api/search
curl -X POST http://localhost:8080/api/search \
-H "Content-Type: application/json" \
-d '{"query": "python tutorial", "limit": 10, "browser": "chrome", "format": "markdown"}'
Response:
{
"results": [
{
"title": "Python Tutorial",
"url": "https://docs.python.org/3/tutorial/",
"timestamp": "2024-01-15T10:30:00+00:00"
}
],
"count": 1
}
GET /health
curl http://localhost:8080/health
Response:
{
"status": "healthy",
"service": "chronicle-mcp",
"version": "1.4.0",
"timestamp": "2024-01-15T10:30:00+00:00"
}
Configuration
ChronicleMCP can be configured using environment variables or a config file.
Environment Variables
| Variable | Description | Default |
|---|---|---|
CHRONICLE_CONFIG |
Path to config file | ~/.config/chronicle-mcp/config.toml |
CHRONICLE_PORT |
Default port | 8080 |
CHRONICLE_HOST |
Default host | 127.0.0.1 |
CHRONICLE_BROWSER |
Default browser | chrome |
Config File
Create ~/.config/chronicle-mcp/config.toml:
[default]
browser = "chrome"
limit = 10
format = "markdown"
log_level = "INFO"
Security & Privacy
- Local-Only: All data stays on your machine
- URL Sanitization: Sensitive query parameters are automatically removed:
token,session,key,password,auth,sid,access_token
- Temp Files: History is copied to temporary files that are cleaned up after each query
- No Data Collection: Your browsing data is never sent to any server
- Error Messages: No sensitive file paths are exposed
Supported Browsers
ChronicleMCP supports reading history from the following browsers:
| Browser | Version | Windows | macOS | Linux |
|---|---|---|---|---|
| Chrome | 120+ | %LocalAppData%\Google\Chrome\User Data\Default\History |
~/Library/Application Support/Google/Chrome/Default/History |
~/.config/google-chrome/Default/History |
| Edge | 120+ | %LocalAppData%\Microsoft\Edge\User Data\Default\History |
~/Library/Application Support/Microsoft Edge/Default/History |
~/.config/microsoft-edge/Default/History |
| Firefox | 121+ | %AppData%\Mozilla\Firefox\Profiles\*.default\places.sqlite |
~/Library/Mozilla/Firefox/Profiles/*.default/places.sqlite |
~/.mozilla/firefox/*.default/places.sqlite |
| Brave | 1.30+ | %LocalAppData%\BraveSoftware\Brave-Default\History |
~/Library/Application Support/BraveSoftware/Brave-Default/History |
~/.config/BraveSoftware/Brave-Default/History |
| Safari | 16+ | N/A | ~/Library/Safari/History.db |
N/A |
| Vivaldi | 6.0+ | %LocalAppData%\Vivaldi\Default\History |
~/Library/Application Support/Vivaldi/Default/History |
~/.config/vivaldi/Default/History |
| Opera | 105+ | %AppData%\Opera Software\Opera Stable\History |
~/Library/Application Support/com.operasoftware.Opera/History |
~/.config/opera/History |
Troubleshooting
"Browser history not found"
- Ensure the browser is installed
- Check that Chrome/Edge isn't currently open (locks the database)
- Run
chronicle-mcp list-browsersto see detected browsers
"Permission denied"
- Check file permissions on the browser's history database
- On Windows, ensure the browser is closed before querying
Empty results
- Try a more specific search term
- Check the date range for
search_history_by_date - Verify the browser has history data
Performance issues
- Large history databases may take longer to query
- Consider reducing the
limitparameter
Development
Running Tests
# Run all tests
pytest
# Verbose output
pytest -v
# Specific test file
pytest tests/unit/
# Single test
pytest -k test_name
# With coverage
pytest --cov=chronicle_mcp
Development Server
# Run MCP server (stdio mode)
python -m chronicle_mcp mcp
# Run HTTP server
python -m chronicle_mcp http --port 8080
Code Quality
# Linting
ruff check .
# Formatting
ruff format .
# Type checking
mypy chronicle_mcp/
Contributing
Contributions are welcome! Please read our Contributing Guide for details.
License
MIT License - See LICENSE file for details.
Built with ❤️ for AI agents and developers
Metadata
Release files for chronicle-mcp 1.5.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| chronicle_mcp-1.5.3.tar.gz | 74.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| chronicle_mcp-1.5.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 162.4 kB
Release files / chronicle_mcp-1.5.3.tar.gz
| Download URL | chronicle_mcp-1.5.3.tar.gz |
|---|---|
| Size | 74.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7002bb8af79e33f4575f6f8a4978458751719315fcef23d381c01ff314df8412
|
|
BLAKE2b-256 checksum How to use checksums |
ced5b08862b16a63478ed24a4977750c0e6e7c37ae4672726853ae99ddeb940f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / chronicle_mcp-1.5.3-py3-none-any.whl
| Download URL | chronicle_mcp-1.5.3-py3-none-any.whl |
|---|---|
| Size | 87.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2960742f60e3303b96e6561524f32188bf7788d3f0cef50c85bb28a16378c7c1
|
|
BLAKE2b-256 checksum How to use checksums |
a58888277110cdd97338a7a2c03cdea79291f1cb32eed3adefcd4fea56ba0f53
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Security for chronicle-mcp 1.5.3
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.