MCP-сервер для управления памятью агента: добавлен solution.py
This commit is contained in:
+136
@@ -0,0 +1,136 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# MCP-сервер для управления памятью агента
|
||||
# Используем FastMCP, pydantic и python-dotenv
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from fastmcp import MCPServer, MCPRequest, MCPResponse
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
# Загружаем переменные окружения из .env
|
||||
load_dotenv()
|
||||
|
||||
# Путь к файлу хранения данных
|
||||
DATA_FILE = Path(os.getenv("MEMORY_DATA_FILE", "memory_data.json"))
|
||||
|
||||
# ---------------------
|
||||
# Модели данных
|
||||
# ---------------------
|
||||
class MemoryItem(BaseModel):
|
||||
key: str = Field(..., description="Ключ памяти")
|
||||
value: Any = Field(..., description="Значение памяти")
|
||||
namespace: Optional[str] = Field(None, description="Опциональное пространство имён")
|
||||
|
||||
# ---------------------
|
||||
# Хранилище памяти
|
||||
# ---------------------
|
||||
class MemoryStore:
|
||||
def __init__(self, file_path: Path):
|
||||
self.file_path = file_path
|
||||
self._data: Dict[str, Any] = {}
|
||||
self._load()
|
||||
|
||||
def _load(self) -> None:
|
||||
if self.file_path.exists():
|
||||
try:
|
||||
with self.file_path.open("r", encoding="utf-8") as f:
|
||||
self._data = json.load(f)
|
||||
except Exception:
|
||||
self._data = {}
|
||||
else:
|
||||
self._data = {}
|
||||
|
||||
def _save(self) -> None:
|
||||
with self.file_path.open("w", encoding="utf-8") as f:
|
||||
json.dump(self._data, f, ensure_ascii=False, indent=2)
|
||||
|
||||
def save(self, key: str, value: Any) -> None:
|
||||
self._data[key] = value
|
||||
self._save()
|
||||
|
||||
def get(self, key: str) -> Any:
|
||||
return self._data.get(key)
|
||||
|
||||
def delete(self, key: str) -> bool:
|
||||
if key in self._data:
|
||||
del self._data[key]
|
||||
self._save()
|
||||
return True
|
||||
return False
|
||||
|
||||
def list_keys(self) -> List[str]:
|
||||
return list(self._data.keys())
|
||||
|
||||
def save_with_namespace(self, key: str, value: Any, namespace: str) -> None:
|
||||
ns_key = f"{namespace}:{key}"
|
||||
self.save(ns_key, value)
|
||||
|
||||
def get_by_namespace(self, key: str, namespace: str) -> Any:
|
||||
ns_key = f"{namespace}:{key}"
|
||||
return self.get(ns_key)
|
||||
|
||||
# ---------------------
|
||||
# MCP-обработчики
|
||||
# ---------------------
|
||||
class MemoryMCPHandler:
|
||||
def __init__(self, store: MemoryStore):
|
||||
self.store = store
|
||||
|
||||
async def handle(self, request: MCPRequest) -> MCPResponse:
|
||||
# Ожидаем, что payload содержит "action" и параметры
|
||||
payload = request.payload
|
||||
action = payload.get("action")
|
||||
if not action:
|
||||
return MCPResponse(error="Missing action")
|
||||
|
||||
try:
|
||||
if action == "save":
|
||||
key = payload["key"]
|
||||
value = payload["value"]
|
||||
self.store.save(key, value)
|
||||
return MCPResponse(result="ok")
|
||||
elif action == "get":
|
||||
key = payload["key"]
|
||||
value = self.store.get(key)
|
||||
return MCPResponse(result=value)
|
||||
elif action == "delete":
|
||||
key = payload["key"]
|
||||
success = self.store.delete(key)
|
||||
return MCPResponse(result=success)
|
||||
elif action == "list_keys":
|
||||
keys = self.store.list_keys()
|
||||
return MCPResponse(result=keys)
|
||||
elif action == "save_with_namespace":
|
||||
key = payload["key"]
|
||||
value = payload["value"]
|
||||
namespace = payload["namespace"]
|
||||
self.store.save_with_namespace(key, value, namespace)
|
||||
return MCPResponse(result="ok")
|
||||
elif action == "get_by_namespace":
|
||||
key = payload["key"]
|
||||
namespace = payload["namespace"]
|
||||
value = self.store.get_by_namespace(key, namespace)
|
||||
return MCPResponse(result=value)
|
||||
else:
|
||||
return MCPResponse(error="Unknown action")
|
||||
except KeyError as e:
|
||||
return MCPResponse(error=f"Missing parameter: {e}")
|
||||
except Exception as e:
|
||||
return MCPResponse(error=str(e))
|
||||
|
||||
# ---------------------
|
||||
# Запуск сервера
|
||||
# ---------------------
|
||||
async def main():
|
||||
store = MemoryStore(DATA_FILE)
|
||||
handler = MemoryMCPHandler(store)
|
||||
server = MCPServer(handler=handler, host=os.getenv("HOST", "0.0.0.0"), port=int(os.getenv("PORT", 8000)))
|
||||
await server.serve()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import asyncio
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user