Introduction
"How much did I code today?"
"What was my project breakdown last week?"
If you're a developer using WakaTime, these questions probably sound familiar. But opening a browser to check the dashboard feels like unnecessary friction.
I've been automating my daily retrospectives with AI, and having access to "how I spent my time" data makes those reflections much more accurate. While GitHub commit history is helpful, it doesn't capture the full picture—actual coding time, language breakdowns, project-by-project focus levels. If AI Agents could access WakaTime's rich data, the quality of automated retrospectives would improve dramatically.
So I built an MCP (Model Context Protocol) server to make WakaTime data directly accessible to AI Agents. Now agents can answer questions like "show me this week's coding time by project" and incorporate that data into retrospective reports.
This article walks through the implementation of wakatime-mcp and explains the key technical points of building an MCP server.
What is wakatime-mcp?
wakatime-mcp is an MCP server implementation that exposes WakaTime API functionality via the MCP protocol.
Features
It provides two tools:
1. wakatime_summaries
Fetches daily summaries for a specified date range, with optional project filtering and timezone support.
{
"tool": "wakatime_summaries",
"arguments": {
"start": "2025-01-01",
"end": "2025-01-07",
"project": "my-project",
"timezone": "Asia/Tokyo"
}
}
2. wakatime_today
Fetches today's summary. Defaults to Asia/Tokyo timezone.
{
"tool": "wakatime_today",
"arguments": {
"project": "my-project",
"timezone": "Asia/Tokyo"
}
}
No Installation Required
Using npx, you can run it directly without installation:
export WAKATIME_API_KEY="YOUR_API_KEY"
npx -y github:geeknees/wakatime-mcp
To add it to your AI Agent's MCP configuration:
{
"command": "npx",
"args": ["-y", "github:geeknees/wakatime-mcp"],
"env": {
"WAKATIME_API_KEY": "YOUR_API_KEY"
}
}
You can get your WakaTime API Key from the WakaTime settings page.
Implementation Deep Dive
The entire implementation is about 170 lines of TypeScript—surprisingly concise. Here are the key technical points.
1. WakaTime API Authentication
WakaTime uses a slightly unusual authentication method. Instead of Bearer tokens, it requires Base64-encoding the API key and passing it as a Basic auth header:
export function basicAuthHeaderFromApiKey(apiKey: string): string {
const b64 = Buffer.from(apiKey, "utf8").toString("base64");
return `Basic ${b64}`;
}
Simple, but easy to miss if you don't read the docs carefully.
2. MCP Protocol Implementation
The @modelcontextprotocol/sdk makes MCP server implementation remarkably straightforward. You basically register two handlers:
const server = new Server(
{ name: "wakatime-mcp", version: "0.0.1" },
{ capabilities: { tools: {} } }
);
// 1. Handler that returns available tools
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "wakatime_summaries",
description: "Fetches WakaTime daily summaries for a date range",
inputSchema: { /* JSON Schema */ }
},
// ...
]
}));
// 2. Handler that executes tool calls
server.setRequestHandler(CallToolRequestSchema, async (req) => {
const { name, arguments: args } = req.params;
// Tool execution logic
});
The stdio communication is handled entirely by StdioServerTransport, so you don't need to worry about protocol details:
await server.connect(new StdioServerTransport());
3. Timezone-Aware Date Handling
For the "today" summary, we need to account for timezones. Node.js's Intl.DateTimeFormat makes this straightforward:
export function todayYmd(tz = "Asia/Tokyo"): string {
const parts = new Intl.DateTimeFormat("en-CA", {
timeZone: tz,
year: "numeric",
month: "2-digit",
day: "2-digit",
}).formatToParts(new Date());
const y = parts.find((p) => p.type === "year")?.value;
const m = parts.find((p) => p.type === "month")?.value;
const d = parts.find((p) => p.type === "day")?.value;
return `${y}-${m}-${d}`;
}
Using the en-CA locale automatically gives us YYYY-MM-DD formatting—a nice little trick.
4. Symlink Support for npx Execution
When running via npx, the entry point is often invoked through a symlink. To handle this, we use realpath to resolve the actual file path:
export function shouldRunMain(importMetaUrl: string, argv1?: string): boolean {
if (!argv1) return false;
const argvUrl = pathToFileURL(argv1).href;
if (importMetaUrl === argvUrl) return true;
try {
const argvRealUrl = pathToFileURL(realpathSync(argv1)).href;
const importMetaRealPath = realpathSync(fileURLToPath(importMetaUrl));
const importMetaRealUrl = pathToFileURL(importMetaRealPath).href;
return importMetaRealUrl === argvRealUrl;
} catch {
return false;
}
}
Without this, npx github:geeknees/wakatime-mcp wouldn't trigger the main function. Small detail, but crucial.
5. Type-Safe Validation with Zod
Input validation uses Zod for runtime type checking:
const SummariesInput = z.object({
start: z.string().min(1),
end: z.string().min(1),
project: z.string().optional(),
timezone: z.string().optional(),
});
// Usage
const input = SummariesInput.parse(args ?? {});
This gives you both runtime validation and TypeScript type inference—great developer experience.
Real-World Usage
Here's how it works in practice for automated retrospectives.
Daily Retrospectives
Combining GitHub commit history with WakaTime coding time provides much more accurate daily reflections:
AI Agent: Tell me about your work today
User: Create today's retrospective
AI Agent: (executes wakatime_today)
You coded for 5 hours 23 minutes today:
- TypeScript: 3h 45m
- Markdown: 1h 15m
- JSON: 23m
Main project was wakatime-mcp, and looking at your GitHub commits,
you were working on MCP implementation and documentation.
Weekly Reports
It's also useful for weekly work analysis:
User: Generate last week's work summary
AI Agent: (executes wakatime_summaries)
Work time for January 13-19, 2025:
Total coding: 28h 15m
By project:
- wakatime-mcp: 12h 30m (new development)
- my-app: 8h 45m (feature additions)
- docs: 7h 00m (documentation)
By language:
- TypeScript: 18h 20m
- Python: 6h 30m
- Markdown: 3h 25m
The data clearly shows you focused on new MCP server
development last week.
Integration with Custom Skills
When combined with custom skills like Obsidian Daily Summary, you can generate comprehensive retrospectives that include WakaTime data alongside GitHub activity and meeting notes, providing deeper insights.
Conclusion
Building an MCP server is simpler than you might think. With @modelcontextprotocol/sdk, you can create something functional in just a few hours. The key points:
- Understand the protocol: Once you grasp MCP basics, the SDK handles the heavy lifting
- Leverage existing APIs: Most services provide APIs—just expose them via MCP
- Practical use cases: AI Agent integration opens up new possibilities for data utilization
wakatime-mcp is publicly available as a general-purpose tool for any WakaTime user. Give it a try!
Links
- GitHub: https://github.com/geeknees/wakatime-mcp
- WakaTime API Documentation: https://wakatime.com/developers
Why not build an MCP server for a service you use? I hope this article helps you get started.
Top comments (0)