Skip to main content
Glama

Time Tracking MCP

by markwharton
CLAUDE.md4.89 kB
# Development Principles for Claude Code This document provides guidance for Claude Code when working on this codebase. ## DRY Principle (Don't Repeat Yourself) **Single Source of Truth**: Every piece of knowledge should have one authoritative representation in the system. ### Core Philosophy When you find yourself copying code between files, stop and create a shared utility instead. If logic appears in multiple places, it should be extracted to a single location and imported where needed. ### Application in Time Tracking MCP #### Example 1: Report Formatting ```typescript // ✅ GOOD: Create shared formatting utilities // src/utils/report-formatters.ts export function formatProjectBreakdown(byProject: Record<string, number>): string { if (Object.keys(byProject).length === 0) return ''; let output = `**By Project:**\n`; const sorted = Object.entries(byProject).sort((a, b) => b[1] - a[1]); for (const [project, hours] of sorted) { output += `• ${project}: ${hours.toFixed(1)}h\n`; } return output + '\n'; } // Import and use in multiple tools import { formatProjectBreakdown } from '../utils/report-formatters.js'; response += formatProjectBreakdown(summary.byProject); ``` ```typescript // ❌ BAD: Copy-paste the same formatting logic // check-hours.ts if (Object.keys(summary.byProject).length > 0) { response += `**By Project:**\n`; const sortedProjects = Object.entries(summary.byProject) .sort((a, b) => b[1] - a[1]); for (const [project, hours] of sortedProjects) { response += `• ${project}: ${hours.toFixed(1)}h\n`; } } // weekly-report.ts - DUPLICATE CODE! if (Object.keys(summary.byProject).length > 0) { response += `**By Project:**\n`; const sortedProjects = Object.entries(summary.byProject) .sort((a, b) => b[1] - a[1]); for (const [project, hours] of sortedProjects) { response += `• ${project}: ${hours.toFixed(1)}h\n`; } } ``` #### Example 2: Derive from Configuration ```typescript // ✅ GOOD: Derive list from single source const companies = TimeTrackingEnvironment.getCompanies(); const companyCount = companies.length; const isMultiCompany = companyCount > 1; // ❌ BAD: Hardcode assumptions const isMultiCompany = true; // Don't hardcode - derive from config ``` ### Benefits 1. **Automatic updates**: Change formatting once, applies everywhere 2. **No sync issues**: Can't forget to update duplicates 3. **Less maintenance**: One place to fix bugs 4. **Easier testing**: Test formatting logic once, not N times ### Common Patterns #### Share formatting utilities - Report section formatters (projects, tags, commitments) - Duration formatters (already done well with `formatDuration`) - Status indicators and emojis #### Derive data from source of truth - Company lists from environment - Valid commitment names from config schema - Available tags from project definitions #### Extract repeated logic - Sorting and filtering operations - Validation rules - Calculation methods ### When Duplication Is Acceptable Sometimes duplication is okay: - **Different contexts**: Test fixtures vs production data - **Performance**: Pre-computed values for hot paths - **Coupling concerns**: Tools shouldn't share mutable state The key question: *"If this logic changes, should both places change?"* - **Yes** → Don't duplicate, extract to shared utility - **No** → Duplication may be appropriate ### Refactoring Checklist When you add or modify code: 1. ✅ Is this logic already elsewhere? → Extract to utility 2. ✅ Will this logic be needed elsewhere? → Make it reusable from the start 3. ✅ Can this be derived from existing data? → Don't store separately 4. ✅ Is there a simpler abstraction? → Consider before implementing ## Code Organization - **src/utils/** - Shared utilities and helpers - **src/services/** - Business logic and core operations - **src/tools/** - MCP tool implementations (should be thin, delegate to services/utils) - **src/types/** - TypeScript type definitions Keep tools thin - they should orchestrate, not implement. Heavy logic belongs in services or utils. ## Markdown Formatting ### Multi-line Bold/Italic Lists When creating lists with bold or italic text that should appear on separate lines, add **two spaces** at the end of each line to force a line break in Markdown. **Example (note the two spaces at end of lines 1 and 2):** ```markdown **Last Updated:** 2025-10-15 **Document Purpose:** Define standards **Owner:** Development Team ``` **Without double spaces**, these lines will run together in rendered Markdown. The spaces are invisible but critical for proper rendering. **When to use:** - Document headers with multiple metadata fields - Lists of properties or attributes that should stack vertically - Status indicators that should appear on separate lines

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/markwharton/time-tracking-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server