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.
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) or11(AEDT) - London:
0(GMT) or1(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:
- Manual edits can use any format
- On next recalculation, entries normalize to standard
(Xh)format - 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
limitandmax - Shows 🚨 EXCEEDED MAX when over
max - Useful for tracking occasional overages without constant warnings
- Shows ⚠️ OVERFLOW when between
unit: Typically "hours/week"totalcommitment: 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.jsonwith 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:
- Stay in Claude - No app switching
- Natural language - No forms or timers
- Voice-friendly - Mac dictation works perfectly
- Portable data - Plain markdown files
- AI-enhanced - Claude understands your intent
Troubleshooting
Claude doesn't respond to time tracking
- Check Claude config has correct paths (use absolute paths, not
~) - Verify
npm run buildcompleted successfully - Restart Claude completely
- 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_DIRexists 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:
-
Restart Claude completely
- Claude Desktop: Quit the app (Cmd+Q), then relaunch
- Claude Code CLI: Exit the session (Ctrl+C), then run
claudeagain
-
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. -
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
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
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.
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.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
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.
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.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
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.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.