AI + Tools + Data: A learning project exploring Model Context Protocol architecture through personal health logging.
LLM chats have short context and weak long-term memory. When I log personal data (food, exercise, metrics) directly in ChatGPT or Claude:
- Data doesn't persist robustly across sessions
- Hard to query over longer time ranges
- Can't be reused by other agents or tools
MCMe is a Model Context Protocol (MCP) server that:
- Stores structured personal health data (food, workouts) in SQLite
- Exposes that data to LLMs as tools, not chat history
- Works across desktop (Claude Desktop, VS Code) and mobile (Claude mobile via remote MCP)
This is primarily a learning + portfolio project to internalize the "LLM ↔ MCP ↔ data" architecture pattern.
┌─────────────────────────────────────┐
│ Claude Desktop / Mobile / VS Code │
│ (LLM normalizes user intent) │
└──────────────┬──────────────────────┘
│ MCP Protocol (stdio/HTTP)
▼
┌─────────────────────────────────────┐
│ MCMe MCP Server │
│ ┌─────────────────────────────┐ │
│ │ Tools (Zod validated) │ │
│ │ - log_food_entry │ │
│ │ - log_workout_entry │ │
│ │ - get_daily_summary │ │
│ │ - get_trends │ │
│ └──────────┬──────────────────┘ │
│ ▼ │
│ ┌─────────────────────────────┐ │
│ │ Database Client (SQLite) │ │
│ └─────────────────────────────┘ │
└──────────────┬──────────────────────┘
▼
┌──────────┐
│ mcme.db │
└──────────┘
Key Design Principle: The LLM does all natural language parsing. MCMe tools accept only structured, ISO-formatted data (timestamps, enums). This keeps the MCP server simple and focused.
- Food entries: Description, estimated calories, tags
- Workout entries: Type, duration, intensity, notes
- Supports backdating (log yesterday's meals)
- Daily summaries: All meals and workouts for a specific date
- Trends: Aggregates over date ranges (avg calories/day, workouts/week, breakdown by type)
- SQLite with WAL mode for persistence
- Type-safe with TypeScript + Zod validation
- Stdio transport for local development (Claude Desktop, VS Code)
- HTTP/SSE transport ready for remote deployment (mobile access)
npm installnpm run init-dbThis creates mcme.db with the schema.
npm run buildFor Claude Desktop / VS Code:
Add to your MCP settings (e.g., ~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"mcme": {
"command": "node",
"args": ["/absolute/path/to/mcme/dist/server.js"]
}
}
}Replace /absolute/path/to/mcme with your actual project path.
Open Claude Desktop or VS Code and try:
Log breakfast: oats with milk and banana, around 400 calories at 8am today
The LLM will convert this to:
{
"tool": "log_food_entry",
"arguments": {
"timestamp": "2026-03-03T08:00:00Z",
"description": "oats with milk and banana",
"estimated_calories": 400,
"tags": ["breakfast"]
}
}Query your data:
What did I eat yesterday?
Show me my workout trends for the last 7 days
Log a meal or snack.
Input:
{
timestamp: string; // ISO 8601 (e.g., "2026-03-03T08:00:00Z")
description: string; // What you ate
estimated_calories?: number;
tags?: string[]; // e.g., ["breakfast", "high-protein"]
}Output:
{
"success": true,
"id": "uuid",
"message": "Logged food entry: oats with milk and banana"
}Log an exercise session.
Input:
{
timestamp: string; // ISO 8601
type: "run" | "walk" | "weights" | "yoga" | "cycling" | "swimming" | "other";
duration_minutes: number;
intensity: "low" | "medium" | "high";
notes?: string;
}Output:
{
"success": true,
"id": "uuid",
"message": "Logged workout: run for 30 minutes"
}Get all entries for a specific date.
Input:
{
date: string; // YYYY-MM-DD (e.g., "2026-03-03")
}Output:
{
"date": "2026-03-03",
"total_calories": 2100,
"meals": [
{
"time": "08:00",
"description": "oats with milk",
"estimated_calories": 400,
"tags": ["breakfast"]
}
],
"workouts": [
{
"time": "18:00",
"type": "run",
"duration_minutes": 30,
"intensity": "medium",
"notes": null
}
]
}Get aggregate statistics over a date range.
Input:
{
from: string; // YYYY-MM-DD
to: string; // YYYY-MM-DD
}Output:
{
"period": { "from": "2026-02-24", "to": "2026-03-03", "days": 7 },
"food": {
"total_entries": 21,
"days_logged": 7,
"total_calories": 14700,
"avg_calories_per_day": 2100
},
"workouts": {
"total_workouts": 5,
"days_with_workouts": 5,
"avg_per_week": 5.0,
"by_type": { "run": 3, "weights": 2 }
}
}# Watch mode (auto-restart on changes)
npm run dev
# Run tests
npm test
# Lint
npm run lint
# Format code
npm run formatSee docs/SETUP.md for instructions on deploying to Fly.io or Railway for remote access from Claude mobile.
mcme/
├── src/
│ ├── server.ts # MCP server entry point
│ ├── db/
│ │ ├── schema.sql # Database schema
│ │ └── client.ts # SQLite client + queries
│ ├── tools/
│ │ ├── log-food.ts # Food logging tool
│ │ ├── log-workout.ts # Workout logging tool
│ │ ├── get-daily-summary.ts
│ │ └── get-trends.ts
│ └── utils/
│ └── date-utils.ts # Date validation helpers
├── docs/
│ ├── ARCHITECTURE.md # Design decisions
│ ├── SETUP.md # Deployment guide
│ └── DECISIONS.md # ADR-style decision log
└── tests/ # Unit tests
As a Product Manager working with AI-native products, I wanted to:
- Internalize MCP architecture: Understand how LLMs interact with external data stores via tools
- Practice "AI-first" API design: How do you design schemas and error messages that LLMs can understand?
- Demonstrate future-facing skills: MCP is an emerging pattern for agentic systems; this shows hands-on experience
For more on the product thinking behind this project, see docs/PM-NOTES.md.
- Usable v0 for personal health logging
- Clean, portfolio-ready code
- Learning MCP end-to-end
- Multi-user support
- Complex nutrition analysis (macros, micronutrients)
- Web UI (chat is the interface)
- Production-grade security (bearer token is sufficient for personal use)
MIT © Eddy Horwood
Built with:
- Model Context Protocol by Anthropic
- better-sqlite3
- Zod for schema validation
Status: v0 (local dev ready) • Remote deployment guide coming soon