Time Tracking MCP

Time Tracking MCP

Enables natural language time tracking through Claude with markdown file storage. Supports multi-company tracking, flexible time parsing, auto-calculated summaries, and commitment warnings all through conversational input.

Category
Visit Server

README

Time Tracking MCP

Natural language time tracking for Claude Desktop using Model Context Protocol (MCP).

Features

  • Natural Language Input - Just say "2h on security review"
  • Markdown Storage - Human-readable files you can edit anywhere
  • Multi-Company Support - Track time across multiple clients/companies
  • Flexible Time Parsing - "2h", "90 minutes", "yesterday afternoon"
  • Auto-calculated Summaries - Weekly totals and commitment tracking
  • Smart Tagging - Auto-categorize by #development, #meeting, #admin
  • Commitment Warnings - Stay within your hour limits
  • Project Tracking - Automatically group time by project

Quick Start

1. Install

git clone <repo-url> time-tracking-mcp
cd time-tracking-mcp
npm install
npm run build

2. Set Up Time Tracking Directory

mkdir -p ~/Documents/time-tracking/HeliMods
mkdir -p ~/Documents/time-tracking/Stellantis

Create ~/Documents/time-tracking/HeliMods/config.json:

{
  "company": "HeliMods",
  "commitments": {
    "development": { "limit": 20, "unit": "hours/week" },
    "meeting": { "limit": 5, "unit": "hours/week" },
    "total": { "limit": 25, "unit": "hours/week" }
  },
  "projects": {
    "Time Tracking MCP": {
      "tags": ["development", "mcp", "typescript"],
      "commitment": "development"
    },
    "Conduit MCP": {
      "tags": ["development", "security"],
      "commitment": "development"
    }
  },
  "tagMappings": {
    "dev": "development",
    "sync": "meeting"
  }
}

See docs/example-config.json for a complete example.

3. Configure Claude Desktop

For Claude Desktop App

Edit ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "TimeTracking": {
      "command": "/path/to/node",
      "args": ["/path/to/time-tracking-mcp/dist/server.js"],
      "env": {
        "TIME_TRACKING_DIR": "/Users/you/Documents/time-tracking",
        "COMPANIES": "HeliMods,Stellantis",
        "COMPANY_ABBREVIATIONS": "HeliMods:HM:helimods,Stellantis:STLA:stellantis"
      }
    }
  }
}

Find your paths:

  • Node: which node
  • Project: Use full absolute path to this directory

For Claude Code CLI

Edit ~/.config/claude-code/settings.json:

{
  "mcpServers": {
    "TimeTracking": {
      "command": "node",
      "args": ["/path/to/time-tracking-mcp/dist/server.js"],
      "env": {
        "TIME_TRACKING_DIR": "/Users/you/Documents/time-tracking",
        "COMPANIES": "HeliMods,Stellantis",
        "COMPANY_ABBREVIATIONS": "HeliMods:HM:helimods,Stellantis:STLA:stellantis"
      }
    }
  }
}

4. Restart Claude

Close and reopen Claude Desktop or restart Claude Code CLI.

5. Test It

You: "Just spent 2 hours on Time Tracking MCP"
Claude: "Logged! Added 2h for Time Tracking MCP at 14:30.
        You're at 10.6h this week (42% of 25h limit)."

Usage

Just talk naturally to Claude:

You: "Just spent 2 hours on Conduit security review"
Claude: "Logged! You're at 23.5h / 25h (94%)"

You: "How am I tracking this week?"
Claude: "Week 42 Summary:
        • Total: 23.5h / 25h (94%)
        • Development: 18.0h / 20h (90%)
        • Meetings: 5.5h / 5h (110%) ⚠️"

You: "Client meeting yesterday 90 minutes"
Claude: "Logged 1.5h for client meeting on Oct 16 ✓"

You: "Show me this week's report"
Claude: [Detailed weekly report with breakdown by day, project, and tags]

See docs/usage-examples.md for more examples and advanced features.

How It Works

flowchart TD
    A[User: '2h on security review'] --> B[Claude parses natural language]
    B --> C{MCP Tool<br/>log_time}
    C --> D[Validates parameters<br/>task, duration, time]
    D --> E[Markdown Manager]
    E --> F[Appends to weekly file]
    F --> G[~/Documents/time-tracking/<br/>company/2025-W42.md]
    G --> H[Recalculates summary]
    H --> I[Returns status to user]

    style A fill:#e1f5ff
    style C fill:#fff4e1
    style E fill:#ffe1f5
    style G fill:#e1ffe1
    style I fill:#e1f5ff

File Structure

~/Documents/time-tracking/
  HeliMods/
    config.json
    2025-W42.md
    2025-W43.md
  Stellantis/
    config.json
    2025-W42.md

Week File Example

# Time Tracking - HeliMods - Week 42 (Oct 14-20, 2025)

## Summary
- **Total:** 23.5h / 25h (94%)
- **Development:** 18.0h / 20h (90%)
- **Meetings:** 5.5h / 5h (110%) ⚠️

**By Project:**
• Time Tracking MCP: 6.4h
• Conduit MCP: 12.0h

---

## 2025-10-17 Friday (10.1h)

- 19:00 add project tracking (1.0h) #mcp
- 18:02 development (1.0h)
- 17:28 HeliMods update (1.0h)
- 22:59 client meeting (1.5h)
- 06:46 documentation (0.3h) #development
- 05:52 MCP server (1.0h) #development

You can edit these files directly!

Configuration

Environment Variables

Variable Description Default
TIME_TRACKING_DIR Where to store markdown files ~/Documents/time-tracking
COMPANIES Comma-separated list of companies default
COMPANY_ABBREVIATIONS Company name abbreviations for quick entry (format: Company:abbr1:abbr2,Company2:abbr3) None
DISPLAY_TIMEZONE_OFFSET Hours offset from UTC for display 0
DISPLAY_TIMEZONE_STRING Timezone name for display UTC
FLEXIBLE_DURATION_PARSING Enable flexible duration parsing in markdown false

Timezone Examples

"env": {
  "DISPLAY_TIMEZONE_OFFSET": "10",
  "DISPLAY_TIMEZONE_STRING": "AEST"
}

Common timezones:

  • Sydney/Melbourne: 10 (AEST) or 11 (AEDT)
  • London: 0 (GMT) or 1 (BST)
  • New York: -5 (EST) or -4 (EDT)
  • Los Angeles: -8 (PST) or -7 (PDT)

Flexible Duration Parsing (Experimental)

When FLEXIBLE_DURATION_PARSING=true, the markdown parser accepts multiple formats:

Supported formats:

  • Standard: (2h), (2.5h)
  • Minutes: (30m), (90m)
  • Natural: (2 hours), (90 minutes)

How it works:

  1. Manual edits can use any format
  2. On next recalculation, entries normalize to standard (Xh) format
  3. Invalid durations are silently ignored

Default (false): Only strict (Xh) format is parsed, protecting against accidental format corruption.

Company Configuration

Each company directory should have a config.json:

{
  "company": "Company Name",
  "commitments": {
    "development": { "limit": 15, "unit": "hours/week" },
    "meeting": { "limit": 5, "unit": "hours/week" },
    "admin": { "limit": 3, "unit": "hours/week" },
    "total": { "limit": 23, "max": 30, "unit": "hours/week" }
  },
  "projects": {
    "Project Name": {
      "tags": ["development", "security"],
      "commitment": "development"
    }
  },
  "tagMappings": {
    "dev": "development",
    "sync": "meeting"
  }
}

Configuration options:

  • commitments: Define hour limits per category

    • limit: Your target weekly hours for this commitment (e.g., 23h/week)
    • max (optional): Hard maximum hours for overflow tracking (e.g., 30h buffer)
      • Shows ⚠️ OVERFLOW when between limit and max
      • Shows 🚨 EXCEEDED MAX when over max
      • Useful for tracking occasional overages without constant warnings
    • unit: Typically "hours/week"
    • total commitment: Should equal the sum of other commitment limits (e.g., 15 + 5 + 3 = 23)
  • projects: Group related work

    • Automatically categorized by tags
    • Maps to commitment categories
  • tagMappings: Create shortcuts

    • Map informal tags to formal commitment names

Understanding Commitments vs Tags

Commitments track against hour limits and trigger warnings:

  • Defined in config.json with specific limits
  • Example: development: 20h/week, meeting: 5h/week
  • Tags mapped to commitments count against those limits
  • Exceeding commitment limits shows ⚠️ warnings

Tags provide visibility without commitment enforcement:

  • All tagged hours count toward your total weekly limit
  • Only tags mapped to commitments count against specific commitment limits
  • Unmapped tags (like #learn, #research, #admin) are tracked for visibility but don't trigger warnings
  • Great for tracking activities that don't fit formal commitments

Example:

Weekly total: 25h limit
- 20h with #development tag → counts against development commitment (20h limit)
- 2h with #learn tag → counts toward total (25h), no specific commitment
- 3h with #meeting tag → counts against meeting commitment (5h limit)

Result: 25h total, development at limit, meeting under limit, #learn visible in reports

This lets you track all your time while only enforcing limits on specific commitment categories.

Configuration Relationships

erDiagram
    CONFIG ||--o{ COMMITMENT : defines
    CONFIG ||--o{ PROJECT : contains
    CONFIG ||--o{ TAG_MAPPING : has

    PROJECT ||--o{ TAG : "auto-applies"
    PROJECT ||--o| COMMITMENT : "maps to"

    TIME_ENTRY ||--o{ TAG : tagged
    TAG ||--o| COMMITMENT : "counts toward"

    TIME_ENTRY }o--|| PROJECT : "grouped by"
    TIME_ENTRY }o--|| COMMITMENT : "tracked against"

    COMMITMENT {
        string name "development, meeting, etc"
        number limit "20h/week"
        number max "optional hard limit"
        string unit "hours/week"
    }

    PROJECT {
        string name "Time Tracking MCP"
        array tags "development, mcp"
        string commitment "development"
    }

    TAG {
        string name "development, meeting, learn"
        boolean mapped "true if in commitment"
    }

    TAG_MAPPING {
        string informal "dev, sync"
        string formal "development, meeting"
    }

    TIME_ENTRY {
        string task "security review"
        number duration "2h"
        datetime time "14:30"
        array tags "development, security"
    }

Multi-Company Usage

Prefix Pattern

You: "hm 2h on security review"     # HeliMods
You: "stla 1h client meeting"       # Stellantis

Suffix Pattern

You: "2h on security review for HeliMods"
You: "1h meeting for Stellantis"

Company-Specific Queries

You: "Status for HeliMods"
You: "Show me Stellantis report"

Default Company Behavior

When company is clear from input: Uses the specified company (via prefix, suffix, or explicit mention)

When company is ambiguous: For safety, Claude will prompt you to clarify which company you mean rather than automatically defaulting. This prevents accidentally logging time to the wrong company.

First company as fallback: The first company in your COMPANIES list is used only when the intent is genuinely unclear and you don't specify otherwise. However, Claude is designed to ask rather than assume.

Natural Language Examples

Logging Time

  • "2h on security review"
  • "Just finished 90 minutes on client meeting"
  • "Spent half an hour on email"
  • "Yesterday afternoon I did 3 hours of code review"

Checking Status

  • "How many hours this week?"
  • "Am I over my limit?"
  • "What did I work on today?"
  • "Show me this week's breakdown"

Getting Reports

  • "Show me this week's report"
  • "Generate last week's report"
  • "Weekly summary for Stellantis"

Tools Available

Claude automatically uses these MCP tools when you interact naturally:

  • log_time - Log a completed task
  • status - Quick weekly status check
  • check_hours - Detailed breakdown (today/week/month)
  • weekly_report - Generate formatted report

You never call these directly - just talk to Claude naturally!

Development

See DEVELOPMENT.md for developer documentation.

npm run build        # Compile TypeScript
npm run dev          # Development mode (auto-reload)
npm run rebuild      # Clean build
npm run release      # Create new version

Why MCP?

Traditional time tracking tools require context switching and structured input. With MCP:

  1. Stay in Claude - No app switching
  2. Natural language - No forms or timers
  3. Voice-friendly - Mac dictation works perfectly
  4. Portable data - Plain markdown files
  5. AI-enhanced - Claude understands your intent

Troubleshooting

Claude doesn't respond to time tracking

  1. Check Claude config has correct paths (use absolute paths, not ~)
  2. Verify npm run build completed successfully
  3. Restart Claude completely
  4. Check logs: ~/Library/Logs/Claude/mcp*.log

"No module found" errors

npm run rebuild

Wrong timezone

Update DISPLAY_TIMEZONE_OFFSET in your Claude config.

Files not being created

  • Ensure TIME_TRACKING_DIR exists and is writable
  • Use full absolute paths in configuration
  • Check file permissions

Changes not taking effect after rebuild

If you've modified and rebuilt the MCP server (npm run build) but Claude still exhibits old behavior:

  1. Restart Claude completely

    • Claude Desktop: Quit the app (Cmd+Q), then relaunch
    • Claude Code CLI: Exit the session (Ctrl+C), then run claude again
  2. Why this happens: MCP servers run as separate processes. When you rebuild, the compiled JavaScript in dist/ updates, but Claude is still running the old cached version until you restart.

  3. After restart: Changes will take effect immediately. You can verify by checking that new behavior works as expected.

Versioning

This project uses commit-and-tag-version for semantic versioning.

Commit message format:

feat: add support for monthly reports
fix: correct duration parsing for fractional hours
perf: optimize summary calculations

License

MIT

Author

Mark Wharton

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured