Chronicle Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Chronicle Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
<div align="center">
Secure, local-first Model Context Protocol (MCP) server for browser history
</div>
# 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| 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 |
pip install chronicle-mcppipx install chronicle-mcp# Pull the latest image
docker pull ghcr.io/nikolasil/chronicle-mcp:latest
# Run the server
docker run -p 8080:8080 ghcr.io/nikolasil/chronicle-mcpgit clone https://github.com/nikolasil/chronicle-mcp.git
cd chronicle-mcp
pip install -e .brew tap nikolasil/chronicle-mcp
brew install chronicle-mcp#### 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#### 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"
) -> strExample:
# 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"
) -> strExample:
# 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"
) -> strExample:
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"
) -> strExample:
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"
) -> strExample:
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() -> strExample:
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
) -> strExample:
# 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
) -> strExample:
search_by_domain("github.com", browser="chrome")#### get_browser_stats
Get browsing statistics for the browser database.
def get_browser_stats(browser: str = "chrome") -> strExample:
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"
) -> strExample:
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"
) -> strExample:
# 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
) -> strExample:
# 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
) -> strExample:
# 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() -> strExample:
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() -> strExample:
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"
) -> strExample:
# 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"
) -> strExample:
# Get all downloads
get_downloads(browser="chrome")
# Search downloads
get_downloads(query="pdf", browser="firefox")#### 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/healthResponse:
{
"status": "healthy",
"service": "chronicle-mcp",
"version": "1.4.0",
"timestamp": "2024-01-15T10:30:00+00:00"
}ChronicleMCP can be configured using environment variables or a config file.
| 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 |
Create ~/.config/chronicle-mcp/config.toml:
[default]
browser = "chrome"
limit = 10
format = "markdown"
log_level = "INFO"token, session, key, password, auth, sid, access_tokenChronicleMCP 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 |
chronicle-mcp list-browsers to see detected browserssearch_history_by_datelimit parameter# 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# Run MCP server (stdio mode)
python -m chronicle_mcp mcp
# Run HTTP server
python -m chronicle_mcp http --port 8080# Linting
ruff check .
# Formatting
ruff format .
# Type checking
mypy chronicle_mcp/Contributions are welcome! Please read our Contributing Guide for details.
MIT License - See LICENSE file for details.
<div align="center">
Built with ❤️ for AI agents and developers
</div>
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.