Tracking MCP
by mindfullabai
README.md
# Tracking MCP
[](https://pypi.org/project/tracking-mcp/)
[](https://pypi.org/project/tracking-mcp/)
[](https://github.com/mindfullabai/tracking-mcp/blob/main/LICENSE)
[](https://pypi.org/project/tracking-mcp/)
[](https://github.com/mindfullabai/tracking-mcp/stargazers)
**Generic MCP server for tracking any entity type with schema-less JSON Hybrid storage.**
Track body weight, daily scorecards, fitness sessions, books, or any custom entity without defining rigid schemas. Auto-discovery, self-documenting, and SQL-queryable.
## Features
- **Schema-less Design**: Track any entity type (weight, scorecard, fitness, books, custom) without ALTER TABLE
- **Auto-Discovery**: Entity types automatically registered on first use
- **Self-Documenting**: MCP Resources expose schema examples and usage guides
- **SQL-Queryable**: Use `json_extract()` for advanced analytics
- **Local-First**: Privacy-friendly, zero external dependencies
- **Hybrid Storage**: SQLite with JSON columns for flexibility + performance
- **CRUD Operations**: Insert, update, query, delete via MCP Tools
- **Built-in Prompts**: Pre-configured templates for common tracking scenarios
## Installation
### Using uvx (Recommended)
```bash
# Run directly without installation
uvx tracking-mcp
# Or install globally
pip install tracking-mcp
```
### From Source
```bash
git clone https://github.com/mindfullabai/tracking-mcp.git
cd tracking-mcp
pip install -e .
```
### Initialize Database
Database is auto-created on first use at the path specified in `DB_PATH` environment variable (defaults to `~/tracking.db`).
## Quick Start
### Claude Desktop Configuration
Add to your Claude Desktop MCP settings (`.mcp.json` or `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
```json
{
"mcpServers": {
"tracking-mcp": {
"type": "stdio",
"command": "uvx",
"args": ["tracking-mcp"],
"env": {
"DB_PATH": "/path/to/your/data/tracking.db"
}
}
}
}
```
**Alternative (with pip install)**:
```json
{
"mcpServers": {
"tracking-mcp": {
"type": "stdio",
"command": "tracking-mcp",
"env": {
"DB_PATH": "/path/to/your/data/tracking.db"
}
}
}
}
```
### Basic Usage
From Claude Desktop, you can now:
```
Track my weight: 72.5kg today
```
```
Show me my weight trend for the last 30 days
```
```
Log workout: HYROX for 45 minutes today
```
## MCP Server Specification
### Tools (4)
#### 1. `track_event`
Insert or update tracking event for any entity type.
**Parameters**:
- `entity_type` (string, required): Entity type (e.g., 'weight', 'scorecard', 'fitness', 'book', or custom)
- `date` (string, required): Event date in YYYY-MM-DD format
- `data` (object, required): Entity-specific data (schema-free JSON)
- `entity_id` (string, optional): Unique ID for entity instance (e.g., 'book_atomic_habits')
**Example**:
```python
track_event(
entity_type="weight",
date="2026-01-14",
data={"weight_kg": 72.8, "day_type": "MAR", "source": "manual"}
)
```
#### 2. `query_events`
Query tracking events with filters.
**Parameters**:
- `entity_type` (string, optional): Filter by entity type
- `entity_id` (string, optional): Filter by entity ID
- `start_date` (string, optional): Start date (inclusive)
- `end_date` (string, optional): End date (inclusive)
- `limit` (integer, optional): Maximum results (default: 100)
**Example**:
```python
query_events(
entity_type="weight",
start_date="2025-12-15",
end_date="2026-01-14",
limit=30
)
```
#### 3. `delete_event`
Delete tracking event by ID.
**Parameters**:
- `event_id` (integer, required): Event ID to delete
#### 4. `list_entity_types`
Get all registered entity types with schema examples.
**Returns**: JSON array of entity types with descriptions and schema examples.
### Resources (3)
#### 1. `tracking://schema/entity_types`
List of all registered entity types with schema examples (JSON).
#### 2. `tracking://docs/usage`
Usage guide for tracking new entity types dynamically (Markdown).
#### 3. `tracking://stats/summary`
Current statistics: total events, entity types, date range, events by type (JSON).
### Prompts (3)
#### 1. `track-weight`
Template for tracking body weight.
**Arguments**: `weight_kg`, `date`
#### 2. `track-workout`
Template for logging workout session.
**Arguments**: `workout_type`, `duration_min`, `date`
#### 3. `query-trend`
Get trend data for entity type over date range.
**Arguments**: `entity_type`, `days` (default: 30)
## Database Schema
### `tracking_events` Table
| Column | Type | Description |
|--------|------|-------------|
| `id` | INTEGER PRIMARY KEY | Auto-increment ID |
| `entity_type` | TEXT | Entity type ('weight', 'scorecard', etc.) |
| `entity_id` | TEXT | Optional unique ID for entity instances |
| `date` | DATE | Event date (YYYY-MM-DD) |
| `data` | JSON | Schema-free JSON data |
| `created_at` | TIMESTAMP | Auto-generated creation timestamp |
| `updated_at` | TIMESTAMP | Auto-updated modification timestamp |
**Indexes**: `entity_type`, `date`, `entity_id`
### `entity_types` Table
| Column | Type | Description |
|--------|------|-------------|
| `entity_type` | TEXT PRIMARY KEY | Entity type name |
| `description` | TEXT | Human-readable description |
| `schema_example` | JSON | Example JSON schema |
| `created_at` | TIMESTAMP | Registration timestamp |
| `updated_at` | TIMESTAMP | Last update timestamp |
**Pre-seeded entity types**: `weight`, `scorecard`, `fitness`, `book`
## Advanced Usage Examples
### Track Custom Entity Type
```python
# Sleep quality tracking (auto-registered)
track_event(
entity_type="sleep_quality",
date="2026-01-14",
data={
"hours": 7.5,
"quality_score": 8,
"dreams": True,
"interruptions": 2,
"notes": "Felt refreshed"
}
)
```
### Track Entity with Unique ID
```python
# Reading progress for specific book
track_event(
entity_type="book",
entity_id="book_atomic_habits",
date="2026-01-14",
data={
"title": "Atomic Habits",
"author": "James Clear",
"current_page": 150,
"total_pages": 320,
"rating": 5
}
)
```
### Query with Filters
```python
# Get all weight entries for January 2026
query_events(
entity_type="weight",
start_date="2026-01-01",
end_date="2026-01-31"
)
# Get all entries for specific book
query_events(
entity_type="book",
entity_id="book_atomic_habits"
)
```
### Update Existing Event
To update an event, call `track_event()` with the same `entity_type` + `date` (+ `entity_id` if used). The tool will automatically UPDATE instead of INSERT.
## SQL Analytics
Since data is stored in SQLite with JSON columns, you can run advanced analytics:
### Weight Trend (Last 30 Days)
```sql
SELECT
date,
json_extract(data, '$.weight_kg') as weight,
json_extract(data, '$.delta_kg') as delta
FROM tracking_events
WHERE entity_type = 'weight'
AND date >= date('now', '-30 days')
ORDER BY date DESC;
```
### Scorecard Weekly Average
```sql
SELECT
strftime('%Y-W%W', date) as week,
AVG(CAST(json_extract(data, '$.total_score') AS INTEGER)) as avg_score,
COUNT(*) as days
FROM tracking_events
WHERE entity_type = 'scorecard'
AND date >= date('now', 'weekday 0', '-7 days')
GROUP BY week;
```
### Fitness Volume by Workout Type (This Month)
```sql
SELECT
json_extract(data, '$.workout_type') as type,
COUNT(*) as sessions,
SUM(CAST(json_extract(data, '$.duration_min') AS INTEGER)) as total_minutes,
AVG(CAST(json_extract(data, '$.duration_min') AS INTEGER)) as avg_minutes
FROM tracking_events
WHERE entity_type = 'fitness'
AND date >= date('now', 'start of month')
GROUP BY type;
```
## Project Structure
```
tracking-mcp/
├── data/
│ ├── tracking.db # SQLite database
│ └── schema.sql # Database schema
├── tracking_mcp/
│ ├── tracking_server.py # MCP server implementation
│ └── __init__.py
├── tests/
│ └── test_server.py
├── pyproject.toml
├── LICENSE
├── CHANGELOG.md
└── README.md
```
## Architecture Decisions
### Why JSON Hybrid (SQLite + JSON)?
- ✅ **Flexibility**: Add new entity types without schema migrations
- ✅ **Performance**: SQLite indexes + `json_extract()` for fast queries
- ✅ **SQL-queryable**: Standard SQL for analytics
- ❌ **EAV alternative**: Too many JOINs, poor performance for analytics
### Why Custom MCP vs Official SQLite MCP?
- ✅ **Auto-discovery**: New entity types registered automatically
- ✅ **Self-documenting**: Resources expose schemas and usage
- ✅ **Dynamic**: No rigid schema required
- ❌ **Official SQLite MCP**: Requires predefined schema
### Why SQLite vs PostgreSQL?
- ✅ **Zero setup**: File-based, no server required
- ✅ **Local-first**: Privacy-friendly for personal tracking
- ✅ **Sufficient**: Perfect for single-user personal use
- ❌ **PostgreSQL**: Unnecessary overhead for personal tracking
## Development
### Run Tests
```bash
pytest
```
### Code Quality
```bash
# Format code
black mcp_server/
# Lint
ruff check mcp_server/
```
### Install Development Dependencies
```bash
pip install -e ".[dev]"
```
## Troubleshooting
### RuntimeWarning: coroutine 'main' was never awaited
If you see this error when running the server:
```
<coroutine object main at 0x...>
RuntimeWarning: coroutine 'main' was never awaited
```
This was fixed in version 1.0.1. Update to the latest version:
```bash
pip install --upgrade tracking-mcp
# or with uvx
uvx --refresh tracking-mcp
```
**Root cause**: Python CLI entry points from setuptools expect synchronous `main()` functions. Version 1.0.1+ includes a sync wrapper that properly handles the async MCP server.
## Version History
See [CHANGELOG.md](CHANGELOG.md) for version history.
**Current version**: 1.0.1 (Async entry point fix)
## Related Projects
- **[viz-mcp](https://github.com/mariomosca/viz-mcp)**: Companion MCP server for auto-generating data visualizations from tracking data
- **work-hub**: Personal productivity system using tracking-mcp for daily scorecard and habit tracking
## License
MIT License - see [LICENSE](LICENSE) file for details.
## Author
**Mario Mosca** - [GitHub](https://github.com/mariomosca)
## Contributing
Contributions welcome! Please open an issue or pull request.
## Support
For issues, questions, or feature requests, please open an issue on GitHub:
https://github.com/mariomosca/tracking-mcp/issues
TDQS
A3.7/5.0
Scored across 4 tools
Disambiguation5/5
Each tool targets a distinct action: deleting, tracking, querying events, or listing entity types. No overlap.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern in snake_case (e.g., delete_event, track_event).
Tool Count5/5
4 tools is well-scoped for a tracking server, covering essential operations without bloat.
Completeness4/5
Core CRUD is present (create/update via track_event, read via query_events, delete via delete_event), plus entity type discovery. Minor gap: no explicit get single event, but query_events with filters can serve that purpose.
Maintenance
ActivityInactive
ResponsivenessNo issues