nocci MCP Server Specification (Draft v0.4.1)
最終更新: 2026-05-04 ステータス: Draft(実装着手) 準拠: Model Context Protocol 対応コードベース: nocci main branch (Next.js 15 + AWS CDK + DynamoDB 単一テーブル)
1. 概要
nocci MCP サーバーは、ユーザー自身の美容/ウェルネスログ(コスメ・サプリ・体調記録)を、Claude Desktop / その他 MCP 対応 AI アシスタントから安全に参照できるようにするインターフェースです。
「ユーザーが nocci に記録したデータを、ユーザーの AI アシスタントが読み取り、文脈に合った美容アドバイスや振り返りを返す」というユースケースを想定しています。
2. なぜ nocci が MCP を提供するのか
既存の美容/ウェルネスアプリは、ユーザーのデータをアプリ内に閉じ込めてきました。一方、ユーザーは Claude や ChatGPT と日常的に会話しており、そこで美容相談もしています。しかし AI アシスタントには「そのユーザーが実際に何を使い、肌の調子がどう変動したか」のコンテキストがありません。
nocci MCP は、このコンテキストの分断を解消する規格です。ユーザーがログを記録する場所(nocci)と、相談する場所(AI アシスタント)を、ユーザー自身のコントロール下で接続します。
3. 設計原則
- Read-only first:v1.0 では参照のみ。書き込みは将来検討。
- User-scoped:認証トークンに紐づく
actorId(GUEST#{uuid}またはUSER#{cognitoSub})のデータのみ返す。 - Privacy-first:他人のデータには絶対にアクセスできない。
- Stateless:サーバー側で AI クライアントの会話状態を保持しない。
- Narrative over score:レポートは数値スコアではなく文章として返す(nocci の差別化②)。
- 薬機法準拠:医療的アドバイスや断定表現を含めない(後述)。
- JST 統一:日付境界はすべて JST(UTC+9)。既存実装と整合。
4. アーキテクチャ上の位置づけ
nocci の既存コードベースに対する変更点:
infra/functions/
mcp/ ← 新規追加
index.ts MCP HTTP エンドポイント (Streamable HTTP)
protocol.ts JSON-RPC 2.0 ルーティング
tools/
get_recent_logs.ts
get_latest_weekly_report.ts
get_correlations.ts
list_items.ts
_shared/
db.ts 既存 listLogs / listItems / getLatestAiReport を再利用
report.ts 既存 generateWeeklyReport を correlations 抽出に再利用
auth.ts 既存 verifyToken を再利用(JWT)
rate-limit.ts 既存 isUserRateLimited を MCP にも適用
DynamoDB 側の追加は v0.1 ではなし(既存のキー設計をそのまま参照)。将来的に MCP 専用の長寿命 API キーを実装する場合は MCP_KEY#{keyHash} の SK パターンを追加。
5. 認証
v0.1: 既存 JWT を流用
ユーザーは nocci アプリ内「設定 → MCP連携」画面で自分の JWT を表示・コピーできる。AI アシスタント側の MCP クライアント設定に Authorization: Bearer <jwt> ヘッダとして貼り付け。
- ゲストトークン(HS256):発行から 1 年間有効(
issueGuestTokenの挙動) - Cognito トークン(RS256):短命(要 refresh)。v0.1 ではゲスト想定が中心。
v1.0 以降: 専用 MCP API キー
DynamoDB に MCP_KEY#{sha256(key)} を追加し、ユーザー単位で複数発行・個別失効可能に。Authorization: Bearer mcp_<base64key> 形式。
6. エンドポイント
POST https://nocciapp.com/mcp
Transport: Streamable HTTP (MCP 標準)
Content-Type: application/json
Accept: application/json, text/event-stream
レート制限:既存 isUserRateLimited を流用(5分ウィンドウあたり 60 回)。
6.1 Claude Desktop からの接続 (mcp-remote ブリッジ)
Claude Desktop は現時点で MCP の HTTP transport を直接サポートしていないため、
mcp-remote ブリッジを介して接続する。
npx が初回実行時に自動でダウンロードするので、ユーザー側の事前準備は不要。
claude_desktop_config.json への記述例:
{
"mcpServers": {
"nocci": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://nocciapp.com/mcp",
"--header",
"Authorization: Bearer mcp_<上で発行したキー>"
]
}
}
}
設定ファイルの場所:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
将来 Claude Desktop が MCP の HTTP transport を直接サポートした時点で、
ブリッジ無しの { url, headers } 形式へ切り替え可能。サーバー側の API は変えない。
7. ツール
7.1 get_recent_logs
ユーザーが記録した最近の日次ログを返す。AI 側の文脈把握の起点。itemId は denormalize してアイテム名・種別・ブランド情報をインライン展開する(追加クエリを不要にするため)。
パラメータ:
| 名前 | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
days |
integer (1–30) | No | 7 | 過去何日分 |
include_items |
boolean | No | true | アイテム情報を denormalize するか |
返り値:
{
"generated_at": "2026-05-04T05:00:00.000Z",
"period": { "from": "2026-04-27", "to": "2026-05-04" },
"user_timezone": "Asia/Tokyo",
"tier": "free",
"logs": [
{
"date": "2026-05-04",
"condition": "good",
"skin": "good",
"sleep": "6-7",
"memo": "肌の調子が安定している",
"usedItems": [
{
"itemId": "item_abc123",
"name": "ビタミンC 1000mg",
"type": "supplement",
"brand": "Now Foods",
"category": null,
"timeSlots": ["morning"],
"dose": 1,
"doseUnit": "粒"
}
]
}
]
}
include_items: false の場合、usedItems は {itemId, timeSlots, dose?, doseUnit?} のみ。
enum 制約(既存スキーマと完全一致):
condition,skin:"good" | "ok" | "bad"sleep:"<5" | "5-6" | "6-7" | "7+"timeSlots[i]:"morning" | "noon" | "evening" | "night"type:"cosmetic" | "supplement"doseUnit:"錠" | "粒" | "包" | "ml" | "g" | "滴" | "本" | "回"
旧データの
sleep: "<6"等は DB レイヤーで<5に自動マイグレーション済み。MCP は新形式のみを返す。
7.2 get_latest_weekly_report
直近の週次 AI レポートを返す。nocci 差別化②「narrative型レポート」をそのまま AI クライアント側にコンテキストとして渡す。
無料ユーザーは月曜生成の7日分析、有料ユーザーは日次生成の30日分析。
パラメータ:なし
返り値:
{
"generated_at": "2026-05-04T05:00:00.000Z",
"result_hash": "a1b2c3d4e5f60708",
"available": true,
"report": {
"date": "2026-05-04",
"periodFrom": "2026-04-28",
"periodTo": "2026-05-04",
"summary": "今週は肌コンディションが安定していました。睡眠時間も6時間以上を維持できた日が多めです。",
"insights": [
"今週7日中5日、睡眠が6時間以上でした",
"ビタミンB群を毎日摂取できていた一週間でした"
],
"advice": "来週も現在の睡眠リズムを継続できると良さそうです。",
"suggestions": [
{
"careCategory": "保湿ケア",
"logBasis": "今週7日中5日肌がgoodだったので、来週は保湿の継続にも注目できそうです",
"label": "参考情報"
}
],
"generatedAt": "2026-05-04T03:00:00.000Z",
"model": "claude-haiku-4-5-20251001"
},
"tier": "free"
}
未生成の場合 (available: false のときは result_hash を含めない):
{
"generated_at": "2026-05-04T05:00:00.000Z",
"available": false,
"reason": "not_generated",
"tier": "free"
}
AI クライアントへの注意:
suggestions[].careCategoryはスキンケアカテゴリのみ。サプリ・成分名・商品名は含まれない。suggestions[].labelは常に"参考情報"固定。- このデータを引用する際、AI クライアント側は断定表現に変換しない。
7.3 get_correlations
ログから観察される傾向(相関の候補)を返す。nocci 差別化①「横断記録による相関の可視化」を外部公開するコアツール。
検出される傾向は以下の3種:
- 睡眠(<5h)× 全体コンディション
- アイテム使用 vs 非使用 × 肌コンディション
- 習慣サプリ(pinned)の摂取漏れ × 全体コンディション
検出には最低 3 日以上の記録と、絶対差 25〜30 % 以上が必要。
パラメータ:
| 名前 | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
days |
integer (1–14) | No | 7 | 観察期間 |
min_confidence |
enum | No | "low" |
"low" / "medium" / "high" 以上を返す |
返り値:
{
"generated_at": "2026-05-04T05:00:00.000Z",
"result_hash": "a1b2c3d4e5f60708",
"observation_period": { "from": "2026-04-28", "to": "2026-05-04" },
"days_recorded": 6,
"correlations": [
{
"title": "睡眠が短い日にコンディションが低め",
"body": "5時間未満の日は67%が不調(3日中2日)、それ以外は20%(5日中1日)でした。",
"confidence": "medium"
}
],
"disclaimer": "観察的傾向であり因果関係を示すものではありません。記録日数が少ない場合は精度が下がります。"
}
7.4 list_items
ユーザーの登録アイテム(コスメ・サプリ)の一覧を返す。AI クライアントが「あなたのスタックは何?」のような質問に即答できるようにする。get_recent_logs の補助的役割。
パラメータ:
| 名前 | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
type |
enum | No | 全種別 | "cosmetic" または "supplement" |
include_archived |
boolean | No | false | isActive: false のアイテムも含める |
返り値:
{
"generated_at": "2026-05-04T05:00:00.000Z",
"items": [
{
"itemId": "item_abc123",
"name": "ビタミンC 1000mg",
"type": "supplement",
"category": null,
"brand": "Now Foods",
"isActive": true,
"pinned": true,
"defaultDose": 1,
"doseUnit": "粒",
"notes": "朝食後に摂取",
"startDate": "2026-02-01"
}
]
}
意図的に除外するフィールド:
reminderTimes、janCode、PK/SK/createdAt/updatedAt。
7.5 AI クライアント向け補足: generated_at と result_hash の使い方
すべてのツールのレスポンス最上位に generated_at (ISO8601) が含まれます。これはサーバーが
レスポンスを組み立てた時刻で、レイテンシ計測やログ用途を想定しています。
加えて get_correlations と get_latest_weekly_report(available: true のとき)は
result_hash を返します。これは結果本体の SHA-256 ハッシュ先頭 16 文字(64bit)で、
generated_at の時刻揺れの影響を受けません。サーバー側に格納されているデータが
変わらない限り、何度呼んでも同じ値が返ります。
推奨される使い方:
同じ会話内で同じツールが繰り返し呼ばれた場合、AI クライアントは前回のレスポンスと
result_hashを比較することで、結果が変わっていないかを O(1) で判定できます。 同一の場合、再呼び出しせず前回の結果を再利用することで、ユーザー体験の冗長性と レイテンシを改善できます。
result_hashはgenerated_atの時刻揺れの影響を受けないため、サーバー側で同じデータが 格納されている限り同じ値を返します。
list_items と get_recent_logs には result_hash を付けていません。前者は
個人情報的な内容を含み AI クライアント側のキャッシュ滞留を抑えたいため、後者は
日付計算の都合上「同じ呼び出しでも翌日には別結果」になりやすいためです。
8. エラーハンドリング
MCP 標準のエラーコードに加え、以下を定義:
| コード | 意味 |
|---|---|
INSUFFICIENT_DATA |
分析に必要なログ件数(最低 3 日)に達していない |
RATE_LIMITED |
5分ウィンドウあたりの上限を超過 |
INVALID_TOKEN |
JWT または API キーが無効・失効 |
REPORT_NOT_GENERATED |
AI レポートがまだ生成されていない |
9. 薬機法・コンテンツ安全性に関する制約
nocci は美容/ウェルネスアプリとして、薬機法および景品表示法を遵守した表現ルールを内部で定めています。MCP 経由でデータを取得する AI クライアントも、以下の制約を理解した上で扱う必要があります:
- レポート・相関の本文にサプリメント・成分名の推奨は含まれない
- スキンケアの
suggestionsはカテゴリ名のみ(例:「保湿ケア」「日焼け止め」) - 断定表現(「〜の原因です」「使わないでください」等)は使わない
10. ライセンス
- 本仕様ドキュメント:CC0 / Public Domain
- サーバー実装コード:クローズド
- 本番 MCP エンドポイント利用:nocci 利用規約に準拠
11. 変更履歴
| 日付 | バージョン | 変更内容 |
|---|---|---|
| 2026-05-04 | 0.4.1 | Claude Desktop 接続には mcp-remote ブリッジが必要であることを明記。§6 に接続例を追記。 |
| 2026-05-04 | 0.4 | 全ツールに generated_at、get_correlations と get_latest_weekly_report に result_hash を追加。AI クライアントによる結果キャッシュ判定を可能に。 |
| 2026-05-04 | 0.3 | 4ツール構成で確定 |
付録: 実装メモ
get_recent_logsのtierはgetProfile(actorId).entitlements.premiumから導出get_latest_weekly_reportは既存getLatestAiReport(actorId)をそのまま使うget_correlationsはlistLogs+listItems→generateWeeklyReport→report.insightsをマップlist_itemsは既存listItems(actorId)をそのまま使い、isActiveでフィルタ + 不要フィールド除去- 認証は既存
verifyToken→toActorIdの流れに乗せる - JST 日付計算は
const jstNow = new Date(Date.now() + 9 * 60 * 60 * 1000)
本仕様ドキュメントはCC0 / Public Domainで公開されています。自由に参照・引用・実装可能です。
Last updated: 2026-05-04