MacroMCP
MacroMCP
LLMを、本物の記憶を持つ栄養アシスタントに変えるMCPサーバー。
人に話しかけるのと同じように話しかけます: 「鶏肉7オンスとご飯1杯」 サーバーは必要なことを尋ね、確認し、記録し、数値を読み上げます。あとで 「今週のタンパク質はどう?」 と聞くと、推測ではなくデータベースから答えます。
問題
栄養トラッキングアプリは、2つのどちらかの方法で失敗します。
手動記録型(MyFitnessPalなど)は正確ですが、消耗します。データベースを検索し、ほぼ同一の候補から6つ選び、分量を設定し、すべての材料について繰り返す。その煩わしさは、この製品の最大の特徴であると同時に、利用者が離脱する最大の原因でもあります。
LLMチャットラッパー型は、摩擦がなく、そして静かに間違えます。「鶏肉とご飯」と言えば、モデルはそれらしい数値をでっち上げ、永続化も、来歴も、検証手段もありません。1週間後に何を食べたか聞いても、見当もつきません。
MacroMCPはその中間です。理解はモデルが行う会話型の入力、強制力と計算はデータベースが行い、その間に構造化された確認ステップを挟みます。
中心となる緊張関係
厳密さと摩擦は正反対の方向を向いています。 確認の質問を1つ増やすごとにデータ品質は向上しますが、明日ログを記録する可能性はわずかに下がります。設計作業のほとんどは、やりとりのターン数を犠牲にせずに正確さを買うことです。
2つ目の組織原則:
強制力はシステムプロンプトではなく、サーバー側にあるべきです。 「量を決して推測するな」というプロンプトは、しばらくは守られますが、長い会話の40ターン目あたりで静かに機能しなくなります。問題の具体的なリスト付きで拒否を返すコミット関数は、失敗し得ません。プロンプトは口調と質問の言い回しを担当し、データベースは表現可能なものを担当します。
仕組み
入力: パース → 分類 → 解決 → 確認 → コミット → 読み上げ
パースは、発話を構造化されたドラフトに変換します。その役割は転写と分割であり、推論ではありません。「鶏肉とご飯」は、ほとんどのフィールドが空の2つの項目を生成します。それが正しい出力です。
2つの不変条件があり、どちらもコミット時に強制されます:
スパン網羅性。 すべての項目は、あなたが言ったことの文字範囲を指し示します。項目を生成しなかった食品を含むテキストは報告されるため、項目の欠落は、3か月後の週間合計で気づくのではなく、機械的に検出されます。
アンカーなし項目の禁止。 スパンがない項目は幻覚であり、拒否されます。これは特に、モデルがあなたが言及していない調理油を親切に追加するのを防ぎます。
分類は、各ギャップを種類ごとにタグ付けするため、アシスタントは一般的な「どれくらい?」ではなく、的を絞った質問をします。この分類体系が興味深い部分です:
ギャップ | 例 | 重要な理由 |
曖昧な容器 | 「ボウル」「カップ」 | 計量カップですか、それとも食器棚のカップですか? |
曖昧な次元 | 「8オンス」 | 牛乳なら液体、鶏肉なら重量。食品によって決まります。 |
調理状態 | 「ご飯」 | 乾燥 vs 調理済みは約3倍。最大の単一エラー要因。 |
調理油 | 「フライパンで焼いた」 | 日常的に省略され、日常的に100〜200kcal |
バリエーション | 「鶏肉」「牛乳」 | 胸肉 vs もも肉は脂肪が2倍の差 |
複合食品 | 「サンドイッチ」 | 分解するか、さもなくば推測です |
数量の適用範囲 | 「卵2個とソーセージ」 | 「2」は両方に掛かりますか? |
重要性ゲートが、これを尋問にするのを防ぎます。各ギャップには、最も有力な解釈間のカロリー差が含まれます。閾値未満なら、最も良い解釈を採用し、推定とマークし、ターンを使いません。ブラックコーヒーの容器vs計量はノイズですが、ご飯では200kcalの差です。
解決は、グラムとマクロ栄養素密度を生成します。確認は、全体の計画を1つのブロックで表示し、すべての未解決の質問を1ターンで尋ねます — シリアル式の質問が、トラッキングアプリが使われなくなる原因です。
コミットはゲートです。未解決の項目、アンカーなしの項目、欠落したスパン、未解決の重要ギャップ、および一貫性チェックに失敗するマクロを拒否します。
読み上げは、コミット済みエントリをグラム、項目別マクロ、食事合計、1日合計とともに返します。アシスタントはサーバーが計算した数値を報告するため、長い会話の途中でドラフトがずれていた場合、ここで明らかになります。
保存: 4つのレベル
meals the eating event. "chicken and rice", dinner, Aug 19
meal_logs one submission. eaten_at + logged_at
log_items one named thing. "cheeseburger", fraction 1/2
item_ingredients bun 60g, patty 113g, cheese 19g各レベルが存在する理由:
meals(食事) — 食事イベントには名前があり、複数回記録できるからです。「ソースを忘れた」は、2回目の夕食を作るのではなく、食事に付随します。これはまた、食事が所有されるレベルでもあります — 後述の「マルチユーザー」を参照。
meal_logs(食事ログ) — 忘れ物は普通のことであり、いつ食べたかといつシステムに伝えたかは、別々に記録する価値のある異なる事実だからです。
log_items(ログ項目) — ポーション割合がここに存在するからです。「ハンバーガー半分とフライドポテト全部」は、割合がログに載っていると表現できません。複合食品にも名前が付くため、読み上げは3行を自分で再構成する代わりに「チーズバーガー、263kcal」と言います。
item_ingredients(項目材料) — チーズバーガーは、バンズとパティとチーズだからです。すべての項目には材料があり、単純なものも含みます — 「ご飯1杯」は材料が1つの項目です — これはラッパー行1つ分のコストで、どこにもポリモーフィズムのない単一のロールアップ経路を買います。
mealsより下のものはすべて追記のみです。修正は、古い行を置き換える新しい行です。meals.nameは、ログ全体で唯一の可変フィールドです。
クエリ
モデルは決して計算をしません。 すべての合計、平均、トレンドはSQLで計算され、構造化JSONとして返されます。40個の数値を合計するLLMは、時々静かに誤ります。それはデータベースを持つことの意味全体を無にします。
ロールアップは材料 → 項目 → ログ → 食事 → 日の順に進み、全体を通して丸めず、表示時に一度だけ丸めます。合計に明らかに足りない構成要素は、単一の誤ったエントリよりも速く信頼を破壊します。
マルチユーザー
MacroMCPはシングルユーザーとして始まり、現在は小規模グループ向けに構築されています — 1つのセルフホストインスタンスを共有する家族や数人の友人であり、パブリックなマルチテナント製品ではありません。
すべての食事はユーザーによって所有されます。 meals.user_idが信頼の源泉です。その下のすべて(meal_logs、log_items、item_ingredients)は、独自のコピーを持つ代わりに、それを結合することでスコープされます。コミットパス上のすべての関数 — commit_log、rename_meal、supersede_log、find_attachable_meals — は、呼び出し元ユーザーのIDを明示的な引数として受け取り、staging_idがモデルから信頼されるのではなくサーバー発行であるのと同じように、何かをする前に所有権をチェックします。
マルチユーザーが買うもの: 2人がログ、重複検出、トレンドを衝突させることなく1つのインスタンスを共有できます。SamがLukeが5分前に記録したのと同じ鶏肉とご飯を記録しても、それは重複ではありません。Lukeの火曜日の合計が、Samのものと静かに統合されることはありません。
意図的に含めないもの: 認証。このスキーマにはパスワードもトークンもありません — user_idは与えられた通りに信頼され、実際に誰が呼んでいるのかを解決すること(APIキー、ログインセッション、人ごとに1つのMCPサーバー)は、データベースの決定ではなくAPIレイヤーの決定です。共有モデルもありません。ユーザーは互いに完全に分離されており、お互いのログを見られる家族メンバーではありません。共有可視性が重要だと思われた場合、それはこれをやり直すのではなく、その上に追加される機能です。
クロスユーザーガードが適用されたものの完全なリストとその理由、および今のところ行レベルセキュリティをスキップする背後にあるトレードオフについては、docs/design-notes.mdを参照してください。
v0の賭け
参照データベースなし。 USDAの取り込みも、Open Food Factsも、バーコードパスも、ポーション表もありません。マクロ栄養素密度はモデル自身の知識またはあなたから来て、材料に保存されます。
これは本物の賭けなので、両方の側面を示します。
賛成: 現代のモデルは、鶏の胸肉が約165kcal/100gであり、調理済みご飯1杯が約158gであることを知っています。それを調べるにはレイテンシがかかり、入力が遅ければ入力は行われません。取り込みパイプライン全体が不要になります。そして履歴は記録時に凍結されます — 上流のデータソースが過去のログの内容を静かに変更することはできません。
反対: 数値を外部で相互検証するものがありません。残された唯一の自動チェックはアトウォーターの式 — kcal ≈ 4×タンパク質 + 4×炭水化物 + 9×脂肪 — で、数字の桁違いや一貫性のない推測は検出できますが、自己整合的な誤答は検出できません。100kcal/100gともっともらしいマクロで入力されたベーグルはコミットされます。実際のベーグルは約270です。それが検出されるのは確認ステップであり、確認ブロックがグラムだけでなくマクロを表示する理由です。
賭けを生き延び可能にする2つのこと:
マクロは絶対値ではなく100gあたりで送信されます。 「鶏肉は100gあたり165kcal」は想起であり、「鶏肉213gは351kcal」は計算です。モデルは前者では信頼でき、後者では信頼できません。100gあたりにすることで、サーバーがすべての乗算を行うため、項目の割合も機能し続けます。
来歴はすべての材料に記録されます: llm_knowledge(LLM知識)、llm_estimate(LLM推定)、またはuser_stated(ユーザー指定)。v_daily_data_qualityは、1日のカロリーのうち各由来が占める割合を報告します。80%モデル推測の日は、80%ラベル読み取りの日とは異なる信頼に値し、どちらを経験したかを教えてくれるのはこれだけです。
注: バーコード検索は以下の延期リストにあり、これは別の切り口ではなく、この同じ賭けの下流にあります — 参照データベース自体がないため、UPC→マクロ検索テーブルはありません。それを構築することが、両方の延期を同時に解除することです。
知っておく価値のある設計判断
ステージングはコンテキストウィンドウ内にあります。 ドラフトテーブルもRedisもありません。会話がすでに進行中の状態を保持しています。ライトスルー付きRedisが次のステップとして計画されています。コミットゲートはそれが実装されても変わりません。なぜなら、テーブルを読むのではなく、ペイロードを引数として受け取るようになっているからです。
重複は時計ではなく内容で識別されます。 (meal, timestamp)キーは「あ、あとバナナ」— そこにある最も一般的な記録パターン — を拒否することになります。代わりに: 解決済み材料をハッシュし、ウィンドウ内で既存行のタイムスタンプと比較し、1ユーザーにスコープします。2つのスコープ(同じ食事 / 別の食事)、両方ともソフトです。なぜなら、1日に2つの同一プロテインシェイクは実際にあるからです。
冪等性は1つの一意な列から得られます。 サーバーはstaging_idを発行し、それは全ユーザー間でUNIQUEです。リトライ、エージェントループの再発火、並行呼び出しはすべて、複製する代わりに既存エントリを返します。
付随は決して静かに行われません。 「ソースを忘れた」を間違った食事に付随させることは、誤った食事を作るよりも悪いです。なぜなら、すでに正しかった食事を壊すからです。サーバーは呼び出し元自身の食事内で候補を提案します。単一一致でも確認が必要です。
名前は再生成されません。 忘れたソースを追加しても、「鶏肉とご飯」は「鶏肉とご飯」のままであり、「鶏肉、ご飯、チリソース」にはなりません。あなたの下で変わる名前は、少し不完全な名前よりも悪いです。
日付の切り替わりは深夜0時ではなく午前4時です。 午前1時30分の間食は、あなたがまだ起きている日のものに属します。log_dateはコミット時に具体化され、食事の最初のログから導出されるため、食事が2日間に分割されることは決してありません。
精度は正確さではありません。 目分量のポーションに対する正確な有理数演算も、依然としてestimated(推定)として記録されます。システムが一方を他方に偽装することは決してありません。
意図的にv0に含めないもの
バーコード検索、およびそれが依存する参照食品データベース。USDA/OFF の取り込みも UPC ルックアップテーブルもない — これは上記の「参照データベースなし」と同じ切り口であり、 別々の欠落ではない。
前回の解決結果の再利用(「前回と同じ?」) — 主要な摩擦の解消策であり、 これがないと毎回の食事で完全な確認コストがかかる
バッチ追跡(1つの料理の分割割合の合計が ≤ 1 になることを強制するものはない)
レシピテンプレート
微量栄養素 — 復活させる場合は、元の形式に戻すのではなく、別のロングフォーマットの テーブルを追加すること。マクロとミクロでは形状とクエリパターンが異なるため
認証とユーザー間共有 — 上記の「マルチユーザー」を参照。
user_idによるスコープは存在する。user_idが実際に誰であるかを検証することや、 ユーザーが互いのログを共有して参照できるという概念は存在しない。
スタック
FastAPI + Postgres 16。小規模なマルチユーザー構成、セルフホスト。MCP 経由で公開されているため、 任意の MCP クライアントをフロントエンドにできる。
実行方法
MCP サーバー(server/)は薄いアダプターである。docs/intake-agent.md の契約から各ツールを登録し、
起動時にこのプロセスの user_id を一度だけ解決し、呼び出しのたびに対応する SQL 関数またはビューを呼び出す。
それ以外の独自ロジックは持たない — すべての不変条件が実際に強制されるのは依然としてデータベース側である。
サーバープロセス1つ = ユーザー1人(server/config.py を参照)。これが docs/design-notes.md の
「呼び出しはどのようにして user_id に解決されるのか」という問いに対する答えである。MCP では特に、
各人が自分のサーバーインスタンスを実行する。これは Claude Desktop/Code が設定されたツールごとに
1つのサブプロセスを起動するのと同じ方法だ。
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
createdb macromcp # first time only
psql -d macromcp -f db/schema.sql # first time only
psql -d macromcp -c "INSERT INTO users (username, display_name) VALUES ('luke','Luke');"
cp .env.example .env # edit MACROMCP_USERNAME to match the user you just created
export $(cat .env | xargs)
python -m server.serverMCP クライアント(Claude Desktop、Claude Code、OpenAI Realtime の関数呼び出しブリッジ)を、
その環境で python -m server.server に向けると、docs/intake-agent.md のすべてのツールが有効になる。
docs/intake-agent.md に記載されている GPT Realtime mini の音声フロントエンドはまだ接続されていない。
このサーバーがエンドツーエンドで有用になるには、その前に 何らかの MCP 対応または関数呼び出し対応
クライアントがあればよい。
ファイル
db/schema.sql— 完全な DDL、マルチユーザー用コミットゲート、ロールアップビュー。PG16 でクリーンに読み込まれる。db/tests.sql— 18件の不変条件テスト(コア13件、クロスユーザー分離チェック5件)。すべて成功する。docs/design-notes.md— 設計根拠の全体像、マルチユーザーのトレードオフ、注意すべき点。docs/intake-agent.md— 会話型フロントエンド(GPT Realtime mini)向けのシステムプロンプトとツール/関数呼び出し契約。fn_commit_logのペイロードにフィールド単位で一致している。docs/erd/— スキーマ図(まだシングルユーザーの構成を表示しており、マルチユーザー向けには未再生成)。server/— ツール契約を実装する MCP サーバー(db.pyPostgres アクセス、models.pyペイロード検証、tools.pyビジネスロジック、server.pyツール登録)。過去のシングルユーザーデザインの履歴:
git log db/schema.sql.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Cloud-hosted MCP server for durable AI memory
MCP server for AI dialogue using various LLM models via AceDataCloud
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/lukew0824/MacroMCPv2'
If you have feedback or need assistance with the MCP directory API, please join our Discord server