get_touch_stats
Retrieve aggregate keyboard and mouse activity statistics for the last 1 to 24 hours, including keystroke counts, mouse clicks, scrolls, idle gaps, and active typing minutes. Use for activity reports, idle detection, or fatigue tracking.
Instructions
Return aggregate keyboard and mouse activity stats over the last N hours.
Returns counts: keystrokes (count only — no contents), mouse clicks, scrolls, idle gaps, active-typing minutes.
USE WHEN: producing activity reports, idle detection, or fatigue tracking.
BEHAVIOR: pure read. Privacy guarantee as in get_recent_touch_events.
PARAMETERS: hours: lookback window. Range 1-24. Default 1.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| hours | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- The actual implementation of get_touch_stats — queries the SQLite activity DB for keystroke count, average WPM, backspaces, mouse clicks, scrolls, and corrections over a configurable hours window.
@mcp_app.tool() def get_touch_stats(hours: float = 8.0) -> str: """Get typing and mouse usage statistics over the last N hours. Returns keystroke count, average WPM, click/scroll counts, and correction count. Args: hours: How many hours back to analyze (default 8). """ hours = max(0.1, min(hours, 168.0)) # cap at 1 week conn = _get_db() if not conn: return "No activity database found." try: cutoff = time.time() - (hours * 3600) # Keyboard stats key_rows = conn.execute( "SELECT payload FROM events WHERE modality = 'keys' " "AND event_type = 'typing_burst' AND timestamp > ?", (cutoff,), ).fetchall() total_chars = 0 total_bursts = len(key_rows) wpms = [] total_backspaces = 0 for row in key_rows: p = json.loads(row["payload"]) total_chars += p.get("char_count", 0) total_backspaces += p.get("backspace_count", 0) wpm = p.get("wpm", 0) if wpm > 0: wpms.append(wpm) avg_wpm = sum(wpms) / len(wpms) if wpms else 0 # Mouse stats clicks = conn.execute( "SELECT COUNT(*) as c FROM events WHERE modality = 'flow' " "AND event_type = 'click' AND timestamp > ?", (cutoff,), ).fetchone()["c"] scrolls = conn.execute( "SELECT COUNT(*) as c FROM events WHERE modality = 'flow' " "AND event_type = 'scroll' AND timestamp > ?", (cutoff,), ).fetchone()["c"] # Corrections corrections = conn.execute( "SELECT COUNT(*) as c FROM events WHERE modality = 'keys' " "AND event_type = 'correction_detected' AND timestamp > ?", (cutoff,), ).fetchone()["c"] conn.close() lines = [ f"=== Touch Stats (last {hours:.0f} hours) ===\n", f"Typing bursts: {total_bursts}", f"Total characters: {total_chars}", f"Average WPM: {avg_wpm:.0f}", f"Total backspaces: {total_backspaces}", f"Mouse clicks: {clicks}", f"Mouse scrolls: {scrolls}", f"Corrections detected: {corrections}", ] return "\n".join(lines) except Exception as e: return f"Error calculating stats: {e}" - Function signature and docstring for get_touch_stats; takes hours (float, default 8.0) and returns a string with typing speed, click counts, correction rate.
@mcp_app.tool() def get_touch_stats(hours: float = 8.0) -> str: """Get typing and mouse usage statistics over the last N hours. Returns keystroke count, average WPM, click/scroll counts, and correction count. Args: hours: How many hours back to analyze (default 8). """ - glama/server.py:634-648 (registration)Glama registry stub registration of get_touch_stats via @mcp_app.tool() decorator (returns a stub message telling users to connect to the local daemon).
@mcp_app.tool() def get_touch_stats(hours: int = 1) -> str: """Return aggregate keyboard and mouse activity stats over the last N hours. Returns counts: keystrokes (count only — no contents), mouse clicks, scrolls, idle gaps, active-typing minutes. USE WHEN: producing activity reports, idle detection, or fatigue tracking. BEHAVIOR: pure read. Privacy guarantee as in get_recent_touch_events. PARAMETERS: hours: lookback window. Range 1-24. Default 1. """ return _LOCAL_ONLY_MSG - The mcp_app instance and _get_db() helper used by get_touch_stats to connect to the SQLite activity database.
mcp_app = FastMCP("ContextPulse Touch") _DB_PATH = ACTIVITY_DB_PATH def _get_db() -> sqlite3.Connection | None: if not _DB_PATH.exists(): return None conn = sqlite3.connect(str(_DB_PATH), timeout=5) conn.row_factory = sqlite3.Row return conn - scripts/canary_health_check.py:227-229 (registration)Health-check invocation of get_touch_stats with a 0.01-hour lookback to verify the tool works.
("touch", "get_recent_touch_events", touch.get_recent_touch_events, {"seconds": 1}), ("touch", "get_touch_stats", touch.get_touch_stats, {"hours": 0.01}), ("touch", "get_correction_history", touch.get_correction_history, {"limit": 1}),