From 12d3c164f3dda8896f75bb47509ebbb0d47e1c2d Mon Sep 17 00:00:00 2001 From: lonpatovaadelina Date: Mon, 25 May 2026 12:40:39 +0000 Subject: [PATCH] =?UTF-8?q?MCP-=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D1=83=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=B0=D0=BC=D1=8F=D1=82=D1=8C=D1=8E?= =?UTF-8?q?=20=D0=B0=D0=B3=D0=B5=D0=BD=D1=82=D0=B0:=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20solution.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../solution.py | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 solutions/69f8e929da860fb4533faa2a_MCP-сервер_для_управления_памятью_агента/solution.py diff --git a/solutions/69f8e929da860fb4533faa2a_MCP-сервер_для_управления_памятью_агента/solution.py b/solutions/69f8e929da860fb4533faa2a_MCP-сервер_для_управления_памятью_агента/solution.py new file mode 100644 index 0000000..c2633c7 --- /dev/null +++ b/solutions/69f8e929da860fb4533faa2a_MCP-сервер_для_управления_памятью_агента/solution.py @@ -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())