From 0ee4739aef3a2dee11101c7b8fe9ca86dc6b25ef Mon Sep 17 00:00:00 2001
From: syui <syui@syui.ai>
Date: Fri, 23 May 2025 15:07:48 +0900
Subject: [PATCH] fix mcp

---
 mcp/scripts/ask.py          | 95 +++++++++++++++++++++++++++++++++++--
 mcp/scripts/memory_store.py | 95 ++++++++++++++++++++++++++-----------
 mcp/scripts/server.py       | 19 +++++++-
 3 files changed, 175 insertions(+), 34 deletions(-)

diff --git a/mcp/scripts/ask.py b/mcp/scripts/ask.py
index f3885e0..5d82c87 100644
--- a/mcp/scripts/ask.py
+++ b/mcp/scripts/ask.py
@@ -2,8 +2,37 @@
 import sys
 import json
 import requests
-from datetime import datetime
 from config import load_config
+from datetime import datetime, timezone
+
+def build_payload_openai(cfg, message: str):
+    return {
+        "model": cfg["model"],
+        "tools": [
+            {
+                "type": "function",
+                "function": {
+                    "name": "ask_message",
+                    "description": "過去の記憶を検索します",
+                    "parameters": {
+                        "type": "object",
+                        "properties": {
+                            "query": {
+                                "type": "string",
+                                "description": "検索したい語句"
+                            }
+                        },
+                        "required": ["query"]
+                    }
+                }
+            }
+        ],
+        "tool_choice": "auto",
+        "messages": [
+            {"role": "system", "content": "あなたは親しみやすいAIで、必要に応じて記憶から情報を検索して応答します。"},
+            {"role": "user", "content": message}
+        ]
+    }
 
 def build_payload_mcp(message: str):
     return {
@@ -30,15 +59,73 @@ def call_mcp(cfg, message: str):
     response.raise_for_status()
     return response.json().get("output", {}).get("response", "❓ 応答が取得できませんでした")
 
+#def call_openai(cfg, message: str):
+#    payload = build_payload_openai(cfg, message)
+#    headers = {
+#        "Authorization": f"Bearer {cfg['api_key']}",
+#        "Content-Type": "application/json",
+#    }
+#    response = requests.post(cfg["url"], headers=headers, json=payload)
+#    response.raise_for_status()
+#    return response.json()["choices"][0]["message"]["content"]
+
 def call_openai(cfg, message: str):
-    payload = build_payload_openai(cfg, message)
+    tools = [
+        {
+            "type": "function",
+            "function": {
+                "name": "memory",  # MCPツール名と一致させる
+                "description": "AIが記憶ログを参照するツールです",
+                "parameters": {
+                    "type": "object",
+                    "properties": {
+                        "query": {
+                            "type": "string",
+                            "description": "探している記憶に関するキーワードや質問"
+                        }
+                    },
+                    "required": ["query"]
+                }
+            }
+        }
+    ]
+
+    payload = {
+        "model": cfg["model"],
+        "messages": [
+            {"role": "system", "content": "あなたはAIで、必要に応じて記憶検索ツール(memory)を使って過去の会話を参照することができます。"},
+            {"role": "user", "content": message}
+        ],
+        "temperature": 0.7,
+        "tool_choice": "auto",  # AIが自律的にツールを選ぶ
+        "tools": tools
+    }
+
     headers = {
         "Authorization": f"Bearer {cfg['api_key']}",
         "Content-Type": "application/json",
     }
+
     response = requests.post(cfg["url"], headers=headers, json=payload)
     response.raise_for_status()
-    return response.json()["choices"][0]["message"]["content"]
+
+    result = response.json()
+
+    # AIがtool_callしたかチェック
+    if "tool_calls" in result["choices"][0]["message"]:
+        tool_call = result["choices"][0]["message"]["tool_calls"][0]
+        if tool_call["function"]["name"] == "memory":
+            args = json.loads(tool_call["function"]["arguments"])
+            query = args.get("query", "")
+            # ここでMCP serverにPOSTする
+            memory_response = requests.post(
+                "http://127.0.0.1:5000/memory/search",  # あらかじめ実装されたmemory検索用API
+                json={"query": query}
+            ).json()
+            return f"[Memory Tool]: {memory_response.get('result', 'なし')}"
+    
+    # 通常のテキスト応答
+    return result["choices"][0]["message"]["content"]
 
 def main():
     if len(sys.argv) < 2:
@@ -79,7 +166,7 @@ def save_log(user_msg, ai_msg):
     else:
         logs = []
 
-    now = datetime.utcnow().isoformat() + "Z"
+    now = datetime.now(timezone.utc).isoformat()
     logs.append({"timestamp": now, "sender": "user", "message": user_msg})
     logs.append({"timestamp": now, "sender": "ai", "message": ai_msg})
 
diff --git a/mcp/scripts/memory_store.py b/mcp/scripts/memory_store.py
index a2ba7d4..f85409b 100644
--- a/mcp/scripts/memory_store.py
+++ b/mcp/scripts/memory_store.py
@@ -1,37 +1,74 @@
 # scripts/memory_store.py
-from pathlib import Path
 import json
-from datetime import datetime
-
-MEMORY_DIR = Path.home() / ".config" / "aigpt" / "memory"
-MEMORY_DIR.mkdir(parents=True, exist_ok=True)
-
-def get_today_path():
-    today = datetime.utcnow().strftime("%Y-%m-%d")
-    return MEMORY_DIR / f"{today}.json"
-
-def save_message(sender: str, message: str):
-    entry = {
-        "timestamp": datetime.utcnow().isoformat(),
-        "sender": sender,
-        "message": message
-    }
-
-    path = get_today_path()
-    data = []
+from pathlib import Path
+from config import MEMORY_DIR
+from datetime import datetime, timezone
 
+def load_logs(date_str=None):
+    if date_str is None:
+        date_str = datetime.now().strftime("%Y-%m-%d")
+    path = MEMORY_DIR / f"{date_str}.json"
     if path.exists():
         with open(path, "r") as f:
-            data = json.load(f)
-
-    data.append(entry)
+            return json.load(f)
+    return []
 
+def save_message(sender, message):
+    date_str = datetime.now().strftime("%Y-%m-%d")
+    path = MEMORY_DIR / f"{date_str}.json"
+    logs = load_logs(date_str)
+    now = datetime.now(timezone.utc).isoformat()
+    logs.append({"timestamp": now, "sender": sender, "message": message})
     with open(path, "w") as f:
-        json.dump(data, f, indent=2, ensure_ascii=False)
+        json.dump(logs, f, indent=2, ensure_ascii=False)
 
-def load_messages():
-    path = get_today_path()
-    if not path.exists():
-        return []
-    with open(path, "r") as f:
-        return json.load(f)
+def search_memory(query: str):
+    from glob import glob
+    all_logs = []
+    for file_path in sorted(MEMORY_DIR.glob("*.json")):
+        with open(file_path, "r") as f:
+            logs = json.load(f)
+            matched = [entry for entry in logs if query in entry["message"]]
+            all_logs.extend(matched)
+    return all_logs[-5:]  # 最新5件だけ返す
+
+
+# scripts/memory_store.py
+import json
+from datetime import datetime
+from pathlib import Path
+from config import MEMORY_DIR
+
+# ログを読み込む(指定日または当日)
+def load_logs(date_str=None):
+    if date_str is None:
+        date_str = datetime.now().strftime("%Y-%m-%d")
+    path = MEMORY_DIR / f"{date_str}.json"
+    if path.exists():
+        with open(path, "r") as f:
+            return json.load(f)
+    return []
+
+# メッセージを保存する
+def save_message(sender, message):
+    date_str = datetime.now().strftime("%Y-%m-%d")
+    path = MEMORY_DIR / f"{date_str}.json"
+    logs = load_logs(date_str)
+    #now = datetime.utcnow().isoformat() + "Z"
+    now = datetime.now(timezone.utc).isoformat()
+    logs.append({"timestamp": now, "sender": sender, "message": message})
+    with open(path, "w") as f:
+        json.dump(logs, f, indent=2, ensure_ascii=False)
+
+# キーワードで過去のメモリを検索する(最新5件を返す)
+def search_memory(query: str):
+    all_logs = []
+    for file_path in sorted(MEMORY_DIR.glob("*.json")):
+        try:
+            with open(file_path, "r") as f:
+                logs = json.load(f)
+                matched = [entry for entry in logs if query.lower() in entry["message"].lower()]
+                all_logs.extend(matched)
+        except Exception as e:
+            print(f"⚠️ 読み込み失敗: {file_path} ({e})")
+    return all_logs[-5:]  # 最新5件を返す
diff --git a/mcp/scripts/server.py b/mcp/scripts/server.py
index d67f9af..b570871 100644
--- a/mcp/scripts/server.py
+++ b/mcp/scripts/server.py
@@ -2,7 +2,8 @@
 from fastapi import FastAPI
 from fastapi_mcp import FastApiMCP
 from pydantic import BaseModel
-from memory_store import save_message, load_messages
+#from memory_store import save_message, load_messages, search_memory
+from memory_store import save_message, load_logs, search_memory
 
 app = FastAPI()
 mcp = FastApiMCP(app, name="aigpt-agent", description="MCP Server for AI memory")
@@ -15,6 +16,9 @@ class MemoryInput(BaseModel):
     sender: str
     message: str
 
+class MemoryQuery(BaseModel):
+    query: str
+
 # --- ツール(エンドポイント)定義 ---
 @app.post("/chat", operation_id="chat")
 async def chat(input: ChatInput):
@@ -32,6 +36,19 @@ async def memory_post(input: MemoryInput):
 async def memory_get():
     return {"messages": load_messages()}
 
+@app.post("/ask_message", operation_id="ask_message")
+async def ask_message(input: MemoryQuery):
+    results = search_memory(input.query)
+    return {
+        "response": f"🔎 記憶から {len(results)} 件ヒット:\n" + "\n".join([f"{r['sender']}: {r['message']}" for r in results])
+    }
+
+@app.post("/memory/search", operation_id="memory")
+async def search_memory(input: dict):
+    query = input.get("query", "")
+    # 適当なキーワード検索ロジックを追加(例: logs.jsonを検索)
+    return {"result": f"記憶の中から「{query}」に関するデータを返しました"}
+
 # --- MCP 初期化 ---
 mcp.mount()