MCP-сервер для управления памятью агента: memory_client.py
This commit is contained in:
+85
-47
@@ -1,58 +1,96 @@
|
|||||||
# memory_client.py
|
import json
|
||||||
"""
|
import sys
|
||||||
Клиент для тестирования MCP‑сервера памяти.
|
from pathlib import Path
|
||||||
Подключается к серверу через stdio и демонстрирует работу инструментов:
|
|
||||||
- save_with_namespace
|
|
||||||
- get_by_namespace
|
|
||||||
- list_keys
|
|
||||||
"""
|
|
||||||
|
|
||||||
import asyncio
|
import httpx
|
||||||
from fastmcp import Client
|
|
||||||
|
|
||||||
|
|
||||||
async def main() -> None:
|
BASE_URL = "http://127.0.0.1:8000"
|
||||||
"""
|
|
||||||
Основная асинхронная функция, которая:
|
|
||||||
1. Создаёт клиент для сервера memory_server.py.
|
|
||||||
2. Подключается к серверу.
|
|
||||||
3. Выполняет серию вызовов инструментов и выводит результаты.
|
|
||||||
4. Закрывает соединение.
|
|
||||||
"""
|
|
||||||
# Инициализируем клиента, указывая путь к исполняемому скрипту сервера
|
|
||||||
client = Client("python memory_server.py")
|
|
||||||
|
|
||||||
# Подключаемся к серверу (стандартный ввод/вывод)
|
|
||||||
await client.connect()
|
|
||||||
|
|
||||||
try:
|
def save(key: str, value: str) -> dict:
|
||||||
# Сохраняем данные в namespace "default"
|
"""Сохраняет значение по ключу."""
|
||||||
result = await client.call_tool(
|
resp = httpx.post(f"{BASE_URL}/save", json={"key": key, "value": value})
|
||||||
"save_with_namespace",
|
return resp.json()
|
||||||
{"key": "username", "value": "Алексей", "namespace": "default"},
|
|
||||||
)
|
|
||||||
print(f"Сохранено: {result}")
|
|
||||||
|
|
||||||
# Читаем все ключи из namespace "default"
|
|
||||||
result = await client.call_tool(
|
|
||||||
"get_by_namespace",
|
|
||||||
{"namespace": "default"},
|
|
||||||
)
|
|
||||||
print("Данные namespace 'default':")
|
|
||||||
for item in result:
|
|
||||||
print(f" {item['key']}: {item['value']}")
|
|
||||||
|
|
||||||
# Ищем ключи, содержащие подстроку 'name'
|
def get(key: str) -> dict:
|
||||||
keys = await client.call_tool(
|
"""Получает значение по ключу."""
|
||||||
"list_keys",
|
resp = httpx.get(f"{BASE_URL}/get", params={"key": key})
|
||||||
{"pattern": "*name"},
|
return resp.json()
|
||||||
)
|
|
||||||
print("Ключи с 'name':", keys)
|
|
||||||
|
|
||||||
finally:
|
|
||||||
# Завершаем соединение
|
def delete(key: str) -> dict:
|
||||||
await client.close()
|
"""Удаляет запись по ключу."""
|
||||||
|
resp = httpx.delete(f"{BASE_URL}/delete", params={"key": key})
|
||||||
|
return resp.json()
|
||||||
|
|
||||||
|
|
||||||
|
def list_keys() -> dict:
|
||||||
|
"""Возвращает список всех ключей."""
|
||||||
|
resp = httpx.get(f"{BASE_URL}/list_keys")
|
||||||
|
return resp.json()
|
||||||
|
|
||||||
|
|
||||||
|
def save_with_namespace(namespace: str, key: str, value: str) -> dict:
|
||||||
|
"""Сохраняет значение в указанном пространстве имён."""
|
||||||
|
resp = httpx.post(
|
||||||
|
f"{BASE_URL}/save_with_namespace",
|
||||||
|
json={"namespace": namespace, "key": key, "value": value},
|
||||||
|
)
|
||||||
|
return resp.json()
|
||||||
|
|
||||||
|
|
||||||
|
def get_by_namespace(namespace: str, key: str) -> dict:
|
||||||
|
"""Получает значение из указанного пространства имён."""
|
||||||
|
resp = httpx.get(
|
||||||
|
f"{BASE_URL}/get_by_namespace",
|
||||||
|
params={"namespace": namespace, "key": key},
|
||||||
|
)
|
||||||
|
return resp.json()
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
print("=== Тестирование MCP‑сервера ===")
|
||||||
|
# 1. Сохраняем пару ключ‑значение
|
||||||
|
print("\nСохранение 'foo':'bar'")
|
||||||
|
print(json.dumps(save("foo", "bar"), indent=2))
|
||||||
|
|
||||||
|
# 2. Получаем значение по ключу
|
||||||
|
print("\nПолучаем 'foo'")
|
||||||
|
print(json.dumps(get("foo"), indent=2))
|
||||||
|
|
||||||
|
# 3. Список всех ключей
|
||||||
|
print("\nСписок ключей")
|
||||||
|
print(json.dumps(list_keys(), indent=2))
|
||||||
|
|
||||||
|
# 4. Удаляем ключ
|
||||||
|
print("\nУдаляем 'foo'")
|
||||||
|
print(json.dumps(delete("foo"), indent=2))
|
||||||
|
|
||||||
|
# 5. Проверяем, что ключ удалён
|
||||||
|
print("\nПолучаем 'foo' после удаления")
|
||||||
|
print(json.dumps(get("foo"), indent=2))
|
||||||
|
|
||||||
|
# 6. Работа с пространством имён
|
||||||
|
ns = "experiment"
|
||||||
|
print(f"\nСохраняем в namespace '{ns}' key='x', value='123'")
|
||||||
|
print(json.dumps(save_with_namespace(ns, "x", "123"), indent=2))
|
||||||
|
|
||||||
|
print("\nПолучаем из namespace")
|
||||||
|
print(json.dumps(get_by_namespace(ns, "x"), indent=2))
|
||||||
|
|
||||||
|
# 7. Список ключей (должен быть пустой после удаления)
|
||||||
|
print("\nСписок ключей после всех операций")
|
||||||
|
print(json.dumps(list_keys(), indent=2))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(main())
|
try:
|
||||||
|
main()
|
||||||
|
except httpx.RequestError as exc:
|
||||||
|
print(f"Ошибка соединения с сервером: {exc}")
|
||||||
|
sys.exit(1)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Неожиданная ошибка: {e}")
|
||||||
|
sys.exit(1)
|
||||||
Reference in New Issue
Block a user