Model Context Protocol server for ActivityWatch time tracking data
SaferSkills independently audited Activitywatch Mcp Server (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.
A Model Context Protocol (MCP) server that connects to ActivityWatch, allowing LLMs like Claude to interact with your time tracking data.
<a href="https://glama.ai/mcp/servers/msnzvab06f"> <img width="380" height="200" src="https://glama.ai/mcp/servers/msnzvab06f/badge" alt="ActivityWatch Server MCP server" /> </a>
You can install the ActivityWatch MCP server either from npm or by building it yourself.
# Global installation
npm install -g activitywatch-mcp-server
# Or install locally
npm install activitywatch-mcp-server git clone https://github.com/8bitgentleman/activitywatch-mcp-server.git
cd activitywatch-mcp-server npm install npm run build%APPDATA%\Claude\claude_desktop_config.json~/Library/Application Support/Claude/claude_desktop_config.json {
"mcpServers": {
"activitywatch": {
"command": "activitywatch-mcp-server",
"args": []
}
}
}If you built from source, use:
{
"mcpServers": {
"activitywatch": {
"command": "node",
"args": ["/path/to/activitywatch-mcp-server/dist/index.js"]
}
}
}Make sure to build the image first with:
version=$(npm pkg get version | tr -d '"')
podman build . -t activitywatch-mcp-server:${version}This example uses the override for Activity Watch not being available on 127.0.0.1 (see next section). If not required, you may omit the AW_API_BASE environment variable.
{
"mcpServers": {
"activitywatch-mcp-server": {
"command": "/usr/bin/podman",
"args": [
"run",
"--rm",
"--interactive",
"--userns=keep-id",
"-e",
"AW_API_BASE",
"localhost/activitywatch-mcp-server:1.2.1"
],
"env": {
"AW_API_BASE": "http://mydesktop.local:5600/api/0"
}
}
}
}If you want to run this MCP server from inside Windows Subsystem for Linux, for instance within a container, the AW server running in Windows will not be available at 127.0.0.1. To override the standard localhost connection, use the environment variable AW_API_BASE or the --aw-api-base flag, as below:
# Using environment variable
export AW_API_BASE=http://mydesktop.local:5600/api/0
node dist/index.js
# Or using command-line flag
node dist/index.js --aw-api-base=http://mydesktop.local:5600/api/0NOTE: The AW server may be fussy about the name used to connect to it, but it will accept a name that matches the computer name where it is running with a .local suffix.
Here are some example queries you can try in Claude:
used the most today?"
specific setting in ActivityWatch?"
Lists all available ActivityWatch buckets with optional type filtering.
Parameters:
type (optional): Filter buckets by type (e.g., "window", "web", "afk")includeData (optional): Include bucket data in responseRun a query in ActivityWatch's query language (AQL).
Parameters:
timeperiods: Time period(s) to query formatted as array of strings. For dateranges, use format: ["2024-10-28/2024-10-29"]
query: Array of query statements in ActivityWatch Query Language, where eachitem is a complete query with statements separated by semicolons
name (optional): Name for the query (used for caching)IMPORTANT: Each query string should contain a complete query with multiple statements separated by semicolons.
Example request format:
{
"timeperiods": ["2024-10-28/2024-10-29"],
"query": ["events = query_bucket('aw-watcher-window_UNI-qUxy6XHnLkk'); RETURN = events;"]
}Note that:
timeperiods should have pre-formatted date ranges with slashesquery array is a complete query with all statementsGet raw events from an ActivityWatch bucket.
Parameters:
bucketId: ID of the bucket to fetch events fromstart (optional): Start date/time in ISO formatend (optional): End date/time in ISO formatlimit (optional): Maximum number of events to returnGet ActivityWatch settings from the server.
Parameters:
key (optional): Get a specific settings key instead of all settingsActivityWatch uses a simple query language. Here are some common patterns:
// Get window events
window_events = query_bucket(find_bucket("aw-watcher-window_"));
RETURN = window_events;
// Get only when not AFK
afk_events = query_bucket(find_bucket("aw-watcher-afk_"));
not_afk = filter_keyvals(afk_events, "status", ["not-afk"]);
window_events = filter_period_intersect(window_events, not_afk);
RETURN = window_events;
// Group by app
window_events = query_bucket(find_bucket("aw-watcher-window_"));
events_by_app = merge_events_by_keys(window_events, ["app"]);
RETURN = sort_by_duration(events_by_app);
// Filter by app name
window_events = query_bucket(find_bucket("aw-watcher-window_"));
code_events = filter_keyvals(window_events, "app", ["Code"]);
RETURN = code_events;The server connects to the ActivityWatch API at http://localhost:5600 by default. If your ActivityWatch instance is running on a different host or port, you can override it as described in the Override ActivityWatch server host/port section above.
If ActivityWatch isn't running, the server will show connection errors. Make sure ActivityWatch is running and accessible at the specified host/port address (http://localhost:5600 unless you have overridden it).
If you're encountering query errors:
If Claude reports errors when running queries through this MCP server, it's likely due to formatting issues. Make sure your query follows this exact format in your prompts:
{
"timeperiods": ["2024-10-28/2024-10-29"],
"query": ["events = query_bucket('aw-watcher-window_UNI-qUxy6XHnLkk'); RETURN = events;"]
}Common issues:
within an array)
in one string**
#### The Most Common Formatting Issue
The most frequent error is when Claude splits each query statement into its own array element like this:
{
"query": [
"browser_events = query_bucket('aw-watcher-web');",
"afk_events = query_bucket('aw-watcher-afk');",
"RETURN = events;"
],
"timeperiods": ["2024-10-28/2024-10-29"]
}This is INCORRECT. Instead, all statements should be in a single string within the array:
{
"timeperiods": ["2024-10-28/2024-10-29"],
"query": ["browser_events = query_bucket('aw-watcher-web'); afk_events = query_bucket('aw-watcher-afk'); RETURN = events;"]
}#### When Prompting Claude
When prompting Claude, be very explicit about the format and use examples. For instance, say:
"Run a query with timeperiods as ["2024-10-28/2024-10-29"] and query as ["statement1; statement2; RETURN = result;"]. Important: Make sure ALL query statements are in a single string within the array, not split into separate array elements."
Contributions are welcome! Please feel free to submit a Pull Request.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.