Skip to main content
Glama
Thecimal

Quantified Self MCP Server

Quantified Self MCP Server

Ein lokaler Server für das Model Context Protocol (MCP), der es einem LLM – z. B. Claude Desktop – ermöglicht, deine persönlichen Gesundheits- und Finanzdaten abzufragen. Alles wird in zwei lokalen SQLite-Dateien gespeichert und direkt von der Festplatte gelesen – von einem Python-Prozess, den du kontrollierst. Keine Cloud-Datenbank, kein Dashboard, kein Drittanbieter-Dienst.

Was enthalten ist

quantified-self-mcp/
├── server.py              # the MCP server (FastMCP) — 2 tools
├── init_db.py              # loads a CSV file into the local SQLite database
├── requirements.txt
├── .gitignore              # keeps data/ and .db files out of version control
└── sample_data/
    ├── health_sample.csv   # 30 days of sample data, so you can try it immediately
    └── finance_sample.csv  # ~2 months of sample expenses

Wenn du init_db.py ausführst, wird neben server.py ein data/-Ordner erstellt, der health.db und finance.db enthält – dieser Ordner ist hier nicht enthalten, da er auf deinem Rechner aus deinen eigenen Daten erzeugt wird.

Related MCP server: apple-health-mcp

Verfügbare Tools

Tool

Rückgabe

Parameter (alle optional)

read_health_data

Tägliche Schritte, Schlafstunden, Ruhepuls

start_date, end_date (ISO YYYY-MM-DD; Standard: die letzten 30 Tage)

read_finance_data

Kategorisierte Ausgabenübersicht mit Summen

start_date, end_date, category (Standard: die letzten 90 Tage, alle Kategorien)

Beide Tools geben die passenden Zeilen plus berechnete Zusammenfassungen zurück (Durchschnitt/Min./Max. für Gesundheit, Summen pro Kategorie für Finanzen), sodass das Modell keine eigene Aggregation über viele Zeilen durchführen muss.

1. Die Umgebung einrichten

Voraussetzung: Python 3.10+.

cd quantified-self-mcp
python3 -m venv .venv
source .venv/bin/activate      # Windows: .venv\Scripts\activate
pip install -r requirements.txt

2. Deine Daten laden

Probiere es sofort mit den enthaltenen Beispieldaten aus:

python init_db.py health  sample_data/health_sample.csv
python init_db.py finance sample_data/finance_sample.csv

Um deine eigenen Daten zu verwenden, exportiere sie als CSV mit diesen Spalten und führe dann dieselben Befehle stattdessen mit deinen Dateien aus:

  • health CSV: date, steps, sleep_hours, resting_heart_rate

  • finance CSV: date, category, amount, description (description ist optional)

Datumsangaben sollten im ISO-Format vorliegen (2026-08-23); MM/DD/YYYY wird ebenfalls akzeptiert und konvertiert. Beträge/Zahlen dürfen $ und , enthalten (z. B. $1,234.56) – diese werden automatisch entfernt. Eine problematische Zeile (falsches Datum, nicht-numerischer Betrag, fehlende Kategorie usw.) wird mit einer Warnung übersprungen, anstatt den gesamten Import abzubrechen; die zuletzt ausgegebene Zeile sagt dir immer, wie viele Zeilen geladen bzw. übersprungen wurden.

Ein erneutes Ausführen von init_db.py health führt ein Upsert anhand des Datums durch (du kannst es also bedenkenlos erneut ausführen, wenn du weitere Tage hinzufügst); init_db.py finance fügt bei jedem Lauf neue Zeilen hinzu, da ein Kassenbuch keinen natürlichen eindeutigen Schlüssel hat. Füge --replace zu einem der beiden Befehle hinzu, um die Tabelle stattdessen vorher zu leeren.

3. (Optional) Allein testen

Bevor du es in einen Client einbindest, kannst du den MCP Inspector öffnen und die Tools direkt im Browser aufrufen:

fastmcp dev inspector server.py

4. Mit Claude Desktop verbinden

Claude Desktop startet lokale MCP-Server als Unterprozess und kommuniziert über stdio mit ihnen, basierend auf einer JSON-Konfigurationsdatei:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

Du kannst direkt aus der App dorthin springen: Einstellungen → Entwickler → Konfiguration bearbeiten.

Füge unter mcpServers einen Eintrag hinzu und verwende absolute Pfade – wichtig: command muss auf den Python-Interpreter innerhalb der soeben erstellten virtuellen Umgebung zeigen, nicht einfach nur python. Claude Desktop führt Server in einer minimalen Umgebung aus, die die PATH-Variable deiner Shell oder eine aktivierte venv nicht zuverlässig erbt. Ein einfaches "python" verweist daher oft auf den falschen Interpreter (oder gar keinen), und der Server startet stillschweigend nicht.

{
  "mcpServers": {
    "quantified-self": {
      "command": "/absolute/path/to/quantified-self-mcp/.venv/bin/python3",
      "args": ["/absolute/path/to/quantified-self-mcp/server.py"]
    }
  }
}

Unter Windows typischerweise:

{
  "mcpServers": {
    "quantified-self": {
      "command": "C:\\absolute\\path\\to\\quantified-self-mcp\\.venv\\Scripts\\python.exe",
      "args": ["C:\\absolute\\path\\to\\quantified-self-mcp\\server.py"]
    }
  }
}

Speichere die Datei und beende Claude Desktop vollständig und öffne es erneut (nicht nur das Fenster schließen – ein Neustart ist erforderlich, um Konfigurationsänderungen zu laden). Achte im Chat-Eingabefeld auf das Hammer-/Werkzeug-Symbol, um zu bestätigen, dass quantified-self verbunden ist.

FastMCP bringt außerdem eine CLI-Verknüpfung mit, die diese Datei für dich bearbeitet – fastmcp install claude-desktop server.py --name "Quantified Self" – einen Versuch wert (führe fastmcp install claude-desktop --help aus, um die aktuellen Flags zu sehen), aber das manuelle JSON oben funktioniert immer und ist leichter zu debuggen, wenn etwas nicht stimmt. Anthropic hat außerdem ein neueres Ein-Klick-Paketformat namens „Desktop Extension“ für lokale MCP-Server; für den persönlichen Gebrauch wie diesen nicht nötig, aber wissenswert, falls du diesen Server jemals mit jemandem teilen möchtest, der sich mit dem Bearbeiten von JSON weniger wohlfühlt.

5. (Optional) In Docker ausführen / auf Glama hosten

#5-optional-run-it-in-docker--host-it-on-glama

Ein Dockerfile ist für alle enthalten, die dieses Projekt statt in einer lokalen venv in einem Container ausführen möchten – einschließlich des Hostings auf Glama, das direkt aus dem Dockerfile eines Repositories baut, wenn eines vorhanden ist.

docker build -t quantified-self-mcp .
docker run -i --rm -v "$PWD/data:/app/data" quantified-self-mcp

Das Image basiert ausschließlich auf Python (python:3.12-slim + pip install -r requirements.txt); in diesem Projekt gibt es kein Node.js. HEALTH_DB_PATH und FINANCE_DB_PATH zeigen standardmäßig auf /data/health.db bzw. /data/finance.db im Container, sodass ein eingebundenes Volume (z. B. der /data-Mount von Glama) deine Datenbanken über erneute Deployments hinweg erhält – siehe den Abschnitt „Configuration“ am Anfang von server.py, um sie zu überschreiben.

glama.json ist bewusst minimal gehalten – es verweist Glama nur auf dieses Repository; das Dockerfile gibt tatsächlich vor, wie das Image gebaut und gestartet wird (python server.py, über stdio). Eine frühere Version von glama.json versuchte, ein generisches Buildpack manuell zu konfigurieren (ein reines debian:trixie-slim-Basisimage plus manuelle pip install-Buildschritte und cmdArguments), statt ein Dockerfile zu verwenden – dieses Image hatte keinen zuverlässig bereitgestellten Python-Interpreter, und die Plattform fiel darauf zurück, einen Node.js-Einstiegspunkt auszuführen, der in diesem Repository nicht existiert (Cannot find module '/app/server.js'). Ein Dockerfile mitzuliefern, beseitigt diese Mehrdeutigkeit.

Datenschutzmodell – was „lokal“ tatsächlich bedeutet

Es lohnt sich, hier präzise zu sein, denn genau darum geht es in diesem Projekt:

  • Beide SQLite-Datenbanken liegen ausschließlich auf deiner Festplatte, im data/-Ordner dieses Projekts. Der Server tätigt keine Netzwerkaufrufe, hat keine Telemetrie und synchronisiert nichts nach außen.

  • server.py öffnet beide Datenbanken im schreibgeschützten Modus von SQLite (nicht nur „nimmt keine Schreibvorgänge vor“ – die Verbindung ist schlicht nicht dazu in der Lage). Selbst ein fehlerhafter oder bösartiger Prompt kann keines der beiden Tools dazu bringen, deine Daten zu verändern; nur init_db.py, das du selbst im Terminal ausführst, schreibt jemals in sie.

  • Wenn ein MCP-Client eines dieser Tools aufruft, werden die für diese Abfrage zurückgegebenen Zeilen Teil des Gesprächs, das an das jeweils antwortende Modell gesendet wird – das ist der Mechanismus, mit dem MCP einem Modell Informationen bereitstellt. Wenn du Claude Desktop mit einem gehosteten Modell verwendest, bedeutet das, dass der Ausschnitt deiner Daten, nach dem du fragst, für diese Runde an Anthropic gesendet wird – genau wie alles andere, was du in den Chat eingibst.

  • „Lokal“ bedeutet hier also: Dein vollständiger Datensatz wird nie in einer Datenbank eines Drittanbieters gespeichert oder mit ihr synchronisiert, und es wird nichts übertragen, solange nicht tatsächlich ein Tool aufgerufen wird – und selbst dann nur die Zeilen, die dieser bestimmte Aufruf zurückgibt, nicht die gesamte Datenbank. Es bedeutet nicht durchgehend offline. Dafür bräuchtest du eine vollständig lokale Modell-Laufzeitumgebung (z. B. Ollama) zusammen mit einem MCP-kompatiblen Client.

Fehlerbehebung

  • Server taucht nicht in Claude Desktop auf: Überprüfe, ob command und args absolute Pfade verwenden, stelle sicher, dass der Python-Pfad der venv tatsächlich existiert, und vergewissere dich, dass du die App vollständig beendet und neu geöffnet hast. Die Logs liegen unter ~/Library/Logs/Claude (macOS) oder %APPDATA%\Claude\logs (Windows) – mcp-server-quantified-self.log zeigt die stderr-Ausgabe dieses Servers im Speziellen.

  • „No health/finance database found“ von einem Tool: Führe zuerst init_db.py für diesen Datensatz aus – die Tools erstellen absichtlich keine leeren Datenbanken automatisch, damit du nicht stillschweigend leere Antworten erhältst.

  • Änderungen an server.py scheinen keine Wirkung zu zeigen: Starte Claude Desktop neu; es startet den Serverprozess einmal pro App-Sitzung, nicht pro Nachricht.

  • Hosting auf Glama schlägt mit Cannot find module '/app/server.js' fehl: Das bedeutet, dass die Bereitstellung auf eine Node.js-Laufzeitumgebung zurückgefallen ist, statt auf Python – dieses Repository hat keine server.js. Baue aus dem enthaltenen Dockerfile (siehe „In Docker ausführen / auf Glama hosten“ oben) statt aus einer generischen Buildpack-Konfiguration, damit die Plattform zuverlässig python server.py ausführt.

Dieses Projekt erweitern

Ein paar naheliegende nächste Schritte, falls du sie umsetzen möchtest – nichts davon ist bereits gebaut, es ist nur die Richtung, in die das Muster führt:

  • Schreib Tools (log_expense, log_daily_metric), damit Einträge über das LLM hinzugefügt werden können, statt direkt über CSV/SQL.

  • Weitere Metriken – Gewicht, Workouts, Stimmung, Wasseraufnahme – jede davon ist nur eine weitere Tabelle und ein weiteres Lese-Tool.

  • Ein Tool für den Soll-Ist-Vergleich des Budgets, das die Summen von read_finance_data mit von dir definierten Zielen vergleicht.

Available Tools

3 tools
clear_metricA

Blank out (set to null) a single metric for a single day, without touching that day's other metrics. The counterpart to log_daily_metric for undoing a bad value — e.g. a mood logged for the wrong day, or a weight entered with the wrong units.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesThe day to clear a field for, formatted YYYY-MM-DD.
fieldYesWhich metric to blank out. One of: steps, sleep_hours, resting_heart_rate, weight_kg, workout_minutes, mood, water_ml.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the behavioral disclosure burden. It clearly communicates the mutation ('blank out'), the exact scope (one metric, one day), and the guarantee that other metrics are untouched. It could add permanence or no-op behavior details, but the core destructive semantics are clear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the action and scope. The examples are meaningful and help clarify intent without wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with full schema coverage and an output schema, the description covers the operation's purpose, scope, and usage context. Nothing essential is missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already documents date formatting and the allowed field values. The description adds contextual examples but no new parameter-level semantic detail, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Blank out (set to null)') and names the exact resource: a single metric for a single day. It also explicitly distinguishes itself from log_daily_metric, making the tool's purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly frames this tool as the counterpart to log_daily_metric for undoing bad values, with concrete examples. This gives clear when-to-use guidance and implies the alternative for normal metric logging.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

log_daily_metricA

Record one or more health metrics for a single day, creating that day's row if it doesn't already have one.

Only the metrics you pass are written — anything left as null is not touched, so logging just today's mood doesn't erase today's steps if they were set earlier. To undo a value logged by mistake, use clear_metric rather than trying to overwrite it with a placeholder.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesThe day to log, formatted YYYY-MM-DD.
moodNoMood rating on a 1-10 scale.
stepsNoStep count for the day. 0-200,000.
water_mlNoWater intake in millilitres. 0-10,000.
weight_kgNoBody weight in kilograms. 1-500.
sleep_hoursNoHours of sleep. 0-24.
workout_minutesNoMinutes of exercise. 0-1,440.
resting_heart_rateNoResting heart rate in bpm. 20-250.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden and succeeds: it discloses row creation, partial-write semantics, and the fact that nulls are untouched. This is exactly the kind of behavioral context an agent needs before calling a mutating tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler. The core purpose is front-loaded, and every sentence contributes either behavioral semantics or usage guidance. The description is compact yet rich.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema (per context), so return-value prose is unnecessary. The description covers creation, partial updates, null behavior, and the correct sibling for undo. Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, giving the baseline 3, but the description adds meaningful parameter behavior beyond the schema: only passed metrics are written, nulls are not touched, and at least one metric is implied. This improves the agent's understanding of how the nullable parameters actually behave.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Record one or more health metrics for a single day.' It also distinguishes itself from siblings by explicitly naming clear_metric for undo operations, so an agent can tell logging from reading or clearing without ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It clearly states when to use the tool (logging metrics for a day) and when not to ('To undo a value logged by mistake, use clear_metric'). It also explains the partial-update behavior, which prevents agents from thinking they must re-send all values.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

read_health_dataA

Read daily health metrics from the local database: steps, sleep hours, resting heart rate, weight (kg), workout minutes, mood, and water intake (ml).

ParametersJSON Schema
NameRequiredDescriptionDefault
end_dateNoLast day to include, formatted YYYY-MM-DD. Defaults to today.
start_dateNoFirst day to include, formatted YYYY-MM-DD. Defaults to 30 days before end_date. Ranges over ~10 years are rejected.

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must carry the burden. It clearly indicates the operation is a read from a local database, implying no mutation, and enumerates the data domains. It does not disclose potential behaviors like pagination, empty-result handling, or timezone assumptions, but output schema plus 'read' cover the essential safety profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence states the operation, source, and the complete list of metrics with units. There is no filler or repetition of schema details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read tool with no required parameters, a rich input schema, and an output schema, the description is nearly complete: it identifies the source and the returned metric categories. The main missing piece is explicit routing guidance versus siblings, which was already penalized under usage guidelines.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the start_date/end_date parameters have detailed descriptions including format, defaults, and the ~10-year restriction. The tool description itself adds no parameter-level information, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses the specific verb 'Read' with a clear resource, 'daily health metrics from the local database', and lists the exact metrics included. This differentiates it from the write/delete siblings log_daily_metric and clear_metric.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no explicit guidance on when to choose this tool over its siblings, such as 'use for retrieving metrics as opposed to logging or clearing them.' Although the name implies a read operation, no when-to-use or exclusion criteria are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 2 tool updatesv1.0.4
    • Addedclear_metric
    • Addedlog_daily_metric
  2. 2 tool updatesv1.0.3
    • Removedread_finance_data
    • Changedread_health_data1 field changed
      • changedInput schema / properties / start_date / description
        Previous value: -"First day to include, formatted YYYY-MM-DD.\n        Defaults to 30 days before end_date."New value: +"First day to include, formatted YYYY-MM-DD.\nDefaults to 30 days before end_date. Ranges over ~10 years are rejected."
  3. 1 tool updatev1.0.1
    • Changedread_finance_data1 field changed
      • changedInput schema / properties / category / description
        Previous value: -"Optional category name to filter to (case-insensitive,\n      exact match — e.g. \"Groceries\"). Omit to include all categories."New value: +"Optional category name to filter to (case-insensitive,\n      exact match — e.g. \"Groceries\"). A category with no matching\n      rows returns an empty \"transactions\" list, not an error — this\n      usually means a typo or a category that isn't in the ledger.\n      Omit to include all categories."
  4. 2 tool updatesv1.0.0
    • First observedread_finance_data
    • First observedread_health_data

TDQS

A4.1/5.0
Disambiguation5/5

Each tool maps to a distinct operation: reading, logging, and clearing metrics. There is no overlap or ambiguity between them.

Naming Consistency4/5

All tool names are snake_case and follow a verb-first pattern. The object names vary slightly ('health_data' vs 'daily_metric' vs 'metric'), but the intent remains clear.

Tool Count5/5

Three tools is well-scoped for a simple quantified-self server: read, log, and clear. Each tool serves a necessary purpose without redundancy.

Completeness4/5

Core workflow coverage is solid: read metrics, write metrics, and undo mistakes. Minor gaps exist, such as no way to delete an entire day or list supported metric types, but these are workable limitations.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Turns a personal-finance SQLite database into typed, schema-validated tools that an AI assistant can call directly, letting you manage accounts, transactions, budgets, debts, investments, tax estimates, and goals through natural language.
    47
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables querying personal data synced from services like Lunch Money and Strava using SQL via Claude.
    15
    1
    MIT

Latest Blog Posts

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/Thecimal/quantified-self-mcp'

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