# MCP おもてなしQR プロジェクト - Claude作業メモ
## 📋 プロジェクト概要
**プロジェクト名**: omotenashi-mcp-server
**目的**: ChatGPT から動画生成APIを呼び出し、Widget UIで結果を表示する
**技術スタック**: Node.js, Express, MCP SDK 1.22.0, React
---
## 🔧 環境情報
### サーバー環境(MCPサーバー)
- **ホスト**: `omotenashiqr.com` (SSH接続可能)
- **場所**: `/home/ubuntu/mcp-omotenashi/`
- **起動方法**: PM2プロセスマネージャー
- **プロセス名**: `mcp-omotenashi`
- **ポート**: 8001
- **Node.js**: v20.19.5
- **プロトコル**: MCP (Model Context Protocol) 2024-11-05
- **外部公開**: Nginx経由 HTTPS(Let's Encrypt SSL)
- **.env場所**: `/home/ubuntu/mcp-omotenashi/.env`
### サーバー環境(おもてなしQR本体 - Flask)
- **ホスト**: `omotenashiqr.com` (同じサーバー)
- **場所**: `/home/ubuntu/omotenashiqr_production/`
- **起動方法**: Gunicorn(デーモンモード)
- **プロセス**: `gunicorn -c gunicorn.conf.py wsgi:application --daemon`
- **ポート**: 5000(内部)、443/80(Nginx経由)
- **Python**: 3.12
- **外部公開**: Nginx経由 HTTPS(Let's Encrypt SSL)
- **.env場所**: `/home/ubuntu/omotenashiqr_production/.env`
- **重要**: MCPサーバーからAPIを呼び出すため、この.envに `MCP_API_KEY` が必要
### ローカル環境(Windows)
- **場所**: `C:\Users\utaka\`
- **Node.js**: v22.14.0
- **npm**: 10.9.2
- **SSH接続**: `ssh omotenashiqr.com` で接続可能
---
## 🚀 重要なコマンド
### MCPサーバー操作
```bash
# サーバーにSSH接続
ssh omotenashiqr.com
# プロジェクトディレクトリに移動
cd /home/ubuntu/mcp-omotenashi
# サーバー再起動
pm2 restart mcp-omotenashi --update-env
# ログ確認
pm2 logs mcp-omotenashi --lines 20
# サーバー状態確認
pm2 status
# 構文チェック(必ず再起動前に実行)
node --check server.mjs
```
### おもてなしQR本体(Flask/Gunicorn)操作
```bash
# プロセス確認
ps aux | grep gunicorn | grep -v grep
# Gunicorn再起動(正しい方法)
cd /home/ubuntu/omotenashiqr_production
pkill -f gunicorn # 既存プロセスを停止
source venv/bin/activate && gunicorn -c gunicorn.conf.py wsgi:application --daemon
# ログ確認
tail -f /home/ubuntu/omotenashiqr_production/logs/app.log
# .env変更後は必ずGunicorn再起動
# 理由: Gunicornは起動時に環境変数を読み込むため、再起動しないと反映されない
```
### ⚠️ 重要な注意事項
**Flask本体の.envを変更した場合、必ずGunicornを再起動すること!**
- MCPサーバーからの認証に使う `MCP_API_KEY` は `/home/ubuntu/omotenashiqr_production/.env` に設定
- この値を変更したら、Gunicornを再起動しないと反映されない
- PM2の `--update-env` のような仕組みはGunicornにはない
### Git操作
```bash
# 現在のブランチ: feature/add-web-ui
cd /home/ubuntu/mcp-omotenashi
# 状態確認
git status
# 変更をステージング
git add server.mjs web/src/
# コミット
git commit -m "コミットメッセージ"
# プッシュ
git push origin feature/add-web-ui
# ログ確認
git log --oneline -10
# 特定のコミットに戻す(緊急時)
git revert <commit-id>
```
---
## ⚠️ 必ず守るべきルール
### 1. バックアップファイルは作らない
- ❌ `server.mjs.backup` のようなファイルを作成しない
- ✅ Git でバージョン管理しているので不要
- ✅ `git log` と `git revert` で過去に戻せる
### 2. 変更前の必須チェック
```bash
# ① 構文チェック
node --check server.mjs
# ② 問題なければコミット
git add server.mjs
git commit -m "変更内容"
# ③ サーバー再起動
pm2 restart mcp-omotenashi
# ④ ログ確認
pm2 logs mcp-omotenashi --lines 20
```
### 3. エラー時の対応
```bash
# プロセスが落ちた場合
pm2 restart mcp-omotenashi
# コードに問題がある場合
git log --oneline
git revert <commit-id>
pm2 restart mcp-omotenashi
```
---
## 📁 ファイル構成
```
/home/ubuntu/mcp-omotenashi/
├── server.mjs (1014行) ← メインサーバーコード
├── package.json
├── .env (環境変数)
├── web/
│ └── src/
│ ├── video-qr-widget.html (本番用・従来UI)
│ ├── video-qr-react.html (本番用・React UI)
│ └── display-modes-demo.html (実験用)
├── README.md
└── DEPLOY.md
```
### 主要ファイル
#### `server.mjs`
- **行数**: 1014行
- **コメント**: 日本語で詳細に記載済み
- **構成**:
- モジュールインポート
- 環境変数読み込み
- MCPサーバー作成関数
- 3つのツール登録
- 3つのWidgetリソース登録
- Expressサーバー設定
- セッション管理
- エンドポイント定義
#### `.env`
```env
MCP_API_KEY=(ChatGPTからの認証用)
OMOTENASHI_SESSION_TOKEN=(おもてなしQR API用)
BASE_API_URL=https://omotenashiqr.com/api/v2
MCP_PORT=8001
```
---
## 🛠️ 登録済みツール(3つ)
### 1. `generate_complete_video` (本番・従来UI)
- **目的**: テキストから動画生成(音声→動画→QRコード一括生成)
- **Widget**: `video-qr-widget.html`(従来のシンプルUI)
- **15言語対応**: ja, en, zh, zh-TW, ko, th, es, it, fr, de, ru, ms, id, vi, fil
### 2. `generate_video_react` (本番・React UI) ★推奨
- **目的**: `generate_complete_video` と同じ機能
- **Widget**: `video-qr-react.html`(React製のカッコいいUI)
- **特徴**:
- グラデーション背景
- アニメーション付き
- BGM/字幕/縦動画バッジ表示
- URLコピー機能
- **15言語対応**: 同上
### 3. `display_modes_demo` (実験用)
- **目的**: Display Modes(full-width, inline, compact)のデモ
- **Widget**: `display-modes-demo.html`(React実装)
- **用途**: OpenAI Apps SDK の Display Modes を学習・確認
---
## 🎨 Widget の仕組み
### データの流れ
```
1. ChatGPT → MCP Server (ツール呼び出し)
↓
2. MCP Server → おもてなしQR API (動画生成リクエスト)
↓
3. おもてなしQR API → MCP Server (動画URL + QRコード)
↓
4. MCP Server → ChatGPT
- content: チャット画面に表示するテキスト
- structuredContent: Widget に渡すデータ
- _meta.openai/outputTemplate: Widget の URI
↓
5. ChatGPT → Widget HTML を読み込み
↓
6. Widget HTML: window.openai.toolOutput からデータ取得
↓
7. Widget: openai:set_globals イベントで非同期データを受信
↓
8. Widget: React で動的にUIを描画
```
### 重要な実装パターン
#### ツール定義の必須項目
```javascript
server.registerTool(
'ツール名',
{
_meta: {
"openai/outputTemplate": "ui://widget/ファイル名.html", // 必須
"openai/widgetAccessible": true, // 必須
"openai/resultCanProduceWidget": true // 必須
},
title: 'ツール名',
description: 'ChatGPTが理解できる詳細な説明(機能を明記)',
inputSchema: z.object({ /* パラメータ定義 */ }),
outputSchema: z.object({ /* 出力定義 */ }),
},
async (args, extra) => {
// ツールの実行ロジック
return {
content: [{ type: 'text', text: '結果テキスト' }],
structuredContent: { /* Widget に渡すデータ */ },
_meta: {
"openai/outputTemplate": "ui://widget/ファイル名.html",
"openai/widgetAccessible": true,
"openai/resultCanProduceWidget": true
}
};
}
);
```
#### Widgetリソース登録の必須項目
```javascript
server.registerResource(
"リソース名",
"ui://widget/ファイル名.html", // ツールの outputTemplate と一致させる
{
"openai/widgetCSP": {
"resource_domains": [
"https://unpkg.com", // React CDN など
// 動画/画像の外部ドメイン
]
},
"openai/widgetPrefersBorder": true
},
async () => ({
contents: [{
uri: "ui://widget/ファイル名.html",
mimeType: "text/html+skybridge", // 必須(固定値)
text: widgetHtml変数, // readFileSync で読み込んだHTML
_meta: {
"openai/widgetDescription": "Widget の説明",
"openai/widgetDomain": "https://chatgpt.com"
}
}]
})
);
```
#### Widget HTML の必須パターン(React)
```javascript
// openai:set_globals イベントリスナー(非同期データ受信用)
window.addEventListener('openai:set_globals', (event) => {
const newData = event.detail?.toolOutput || window.openai?.toolOutput;
if (newData && Object.keys(newData).length > 0) {
// データを受信したら状態を更新
setData(newData);
}
});
```
#### **重要**: `createMcpServer()` の最後に必ず `return server;` を書く
```javascript
const createMcpServer = () => {
const server = new McpServer(/* ... */);
// ツール登録
server.registerTool(/* ... */);
// Widgetリソース登録
server.registerResource(/* ... */);
// ★これを忘れると Widget が見つからないエラーになる
return server;
};
```
---
## 💡 よくある問題と解決方法
### 問題1: Widget が表示されない
**原因**: Widget HTML がデータ受信前に表示される
**解決**: `openai:set_globals` イベントリスナーを実装
### 問題2: Resource not found エラー
**原因1**: `createMcpServer()` に `return server;` がない
**原因2**: Widget リソース登録の URI とツールの outputTemplate が不一致
**解決**: URI を統一し、return server を追加
### 問題3: 構文エラーでサーバーが起動しない
**原因**: JavaScript の構文ミス
**解決**:
```bash
node --check server.mjs
# エラーメッセージを確認して修正
git revert <前のコミットID> # 緊急時
pm2 restart mcp-omotenashi
```
### 問題4: セッションが切れる
**原因**: サーバー再起動やタイムアウト
**解決**: ChatGPT 側で再接続(自動的に行われる)
### 問題5: 動画生成時に401エラー「無効なAPIキーです」
**症状**: ChatGPTから動画生成すると `API request failed: 401 - {"error":"無効なAPIキーです","success":false}`
**原因**: `/home/ubuntu/omotenashiqr_production/.env` に `MCP_API_KEY` が設定されていない、または値が間違っている
**解決**:
```bash
# 1. Flask本体の.envにMCP_API_KEYが存在するか確認
ssh omotenashiqr.com
grep 'MCP_API_KEY' /home/ubuntu/omotenashiqr_production/.env
# 2. なければ追加(値はMCPサーバーの.envと同じにする)
echo '' >> /home/ubuntu/omotenashiqr_production/.env
echo '# MCP Server API Key' >> /home/ubuntu/omotenashiqr_production/.env
echo 'MCP_API_KEY=64aba08fb385ee5599f3e233f4e52b573aa88d5e7be36df34baec0dfeff5e1fb' >> /home/ubuntu/omotenashiqr_production/.env
# 3. Gunicornを再起動(必須!)
cd /home/ubuntu/omotenashiqr_production
pkill -f gunicorn
source venv/bin/activate && gunicorn -c gunicorn.conf.py wsgi:application --daemon
# 4. プロセス確認
ps aux | grep gunicorn | grep -v grep
```
**重要**:
- MCPサーバー(Node.js)の.env: `/home/ubuntu/mcp-omotenashi/.env`
- Flask本体の.env: `/home/ubuntu/omotenashiqr_production/.env`
- **両方に同じ `MCP_API_KEY` が必要**
- Flask側の認証コード: `if mcp_api_key != os.getenv('MCP_API_KEY'): return error_response("無効なAPIキーです", 401)`
---
## 📝 開発フロー
### 新ツール追加の手順
```bash
# 1. Widget HTML を作成
# C:\Users\utaka\new-widget.html を作成
# 2. サーバーにアップロード
scp C:\Users\utaka\new-widget.html omotenashiqr.com:~/mcp-omotenashi/web/src/
# 3. server.mjs を編集
ssh omotenashiqr.com
cd /home/ubuntu/mcp-omotenashi
# 4. Widget HTML 読み込みを追加(ファイル先頭付近)
const newWidgetHtml = fs.readFileSync('./web/src/new-widget.html', 'utf-8');
# 5. ツール登録を追加(createMcpServer 内)
server.registerTool('new_tool', { /* 設定 */ }, async (args) => { /* 処理 */ });
# 6. Widget リソース登録を追加(createMcpServer 内、return server の前)
server.registerResource('new-widget', 'ui://widget/new-widget.html', { /* 設定 */ }, async () => ({ /* HTML返却 */ }));
# 7. 必ず return server; があることを確認
# 8. 構文チェック
node --check server.mjs
# 9. Git コミット
git add server.mjs web/src/new-widget.html
git commit -m "Add new_tool with Widget UI"
# 10. サーバー再起動
pm2 restart mcp-omotenashi
# 11. ログ確認
pm2 logs mcp-omotenashi --lines 20
# 12. ChatGPT でテスト
# 13. 問題なければプッシュ
git push origin feature/add-web-ui
```
---
## 🔍 デバッグ方法
### ログの見方
```bash
# リアルタイムログ監視
pm2 logs mcp-omotenashi
# 最新20行
pm2 logs mcp-omotenashi --lines 20 --nostream
# エラーログのみ
pm2 logs mcp-omotenashi --err --lines 50
```
### ログの重要なメッセージ
```
✓ MCP Server is running on port 8001 ← 起動成功
[MCP] Session initialized with ID: xxx ← セッション確立
[DEBUG] POST /mcp - Body: {...} ← リクエスト受信
[REACT_VIDEO] API Request: {...} ← 動画生成API呼び出し
[ERROR] ... ← エラー発生
```
---
## 📊 現在の状態(最終更新: 2025-11-18)
### ファイル統計
- **server.mjs**: 1014行(日本語コメント付き)
- **ツール数**: 3つ(本番2 + 実験1)
- **Widget数**: 3つ
### Git情報
- **ブランチ**: `feature/add-web-ui`
- **最新コミット**: `43a86cd` (Fix: createMcpServer に return server を追加)
- **リモート**: `origin/feature/add-web-ui` (最新にプッシュ済み)
### サーバー状態
- **PM2プロセス**: `mcp-omotenashi` (online)
- **再起動回数**: 69回(開発中の再起動含む)
- **メモリ使用量**: 約16-18MB
---
## 🎯 今後の拡張予定
### やりたいこと候補
- [ ] 既存ツールの Widget を React 版に統一
- [ ] 動画編集機能の追加
- [ ] プレビュー機能の実装
- [ ] エラーハンドリングの強化
- [ ] テスト環境の構築(検討中、現時点では本番のみ)
### やらないこと
- ❌ バックアップファイルの作成(Git で管理)
- ❌ テスト環境の常設(小規模プロジェクトのため)
- ❌ ローカル開発環境の構築(現時点では不要)
---
## 📚 参考リンク
### MCP関連
- **MCP公式ドキュメント**: https://modelcontextprotocol.io/
- **MCP SDK GitHub**: https://github.com/modelcontextprotocol/sdk
- **MCP仕様**: https://spec.modelcontextprotocol.io/
### OpenAI Apps SDK
- **公式ドキュメント**: https://developers.openai.com/apps-sdk/
- **Design Guidelines**: https://developers.openai.com/apps-sdk/concepts/design-guidelines
- **Widget UI**: https://developers.openai.com/apps-sdk/build/custom-ux
- **Quickstart**: https://developers.openai.com/apps-sdk/quickstart
- **サンプル(pizzaz)**: https://github.com/openai/openai-apps-sdk-examples
### React
- **React公式**: https://react.dev/
- **CDN**: https://unpkg.com/react@18/umd/react.production.min.js
---
## 🤝 Claude へのメッセージ
### 接続が切れた後の再開時
1. このファイル(`claude.md`)を読んで状況を把握してください
2. 最新のコミットを確認: `git log --oneline -5`
3. サーバー状態を確認: `pm2 status`
4. 必要に応じてログ確認: `pm2 logs mcp-omotenashi --lines 20 --nostream`
### 重要な約束
- **バックアップファイルは作らない**(Git で管理)
- **変更前に必ず `node --check server.mjs`**
- **変更後は必ず Git コミット**
- **サーバー再起動は `pm2 restart mcp-omotenashi`**
- **`createMcpServer()` の最後に `return server;` があることを確認**
---
## 📞 緊急時の対応
### サーバーが起動しない
```bash
# 1. ログ確認
pm2 logs mcp-omotenashi --err --lines 50
# 2. 構文チェック
node --check server.mjs
# 3. 前のコミットに戻す
git log --oneline -5
git revert <commit-id>
pm2 restart mcp-omotenashi
# 4. それでもダメなら最新のstableコミットに戻す
git reset --hard 43a86cd # 最後に動いていたコミット
pm2 restart mcp-omotenashi
```
### ChatGPT から接続できない
```bash
# 1. サーバー状態確認
pm2 status
# 2. 再起動
pm2 restart mcp-omotenashi
# 3. Nginx 確認(必要に応じて)
sudo systemctl status nginx
# 4. ポート確認
netstat -tlnp | grep 8001
```
---
**このファイルは Claude が作業を再開する際の重要なリファレンスです。**
**変更や追加があれば随時更新してください。**