feat: replace custom memory MCP with Cognee remote server

- Remove memory_mcp.py (stdio markdown-file memory)
- Add Cognee MCP as remote Streamable HTTP toolset at 192.168.86.2:8003/mcp
- Filter to only remember/recall/forget tools via allowed_tools
- Update system prompt: Memory section moved to top priority with
  explicit 'call recall FIRST' instructions and examples
- Add COGNEE_MCP_URL env var to docker-compose
- Remove /memory volume mount (no longer needed)
- Rewrite memory tests to use Cognee HTTP client fixture
- 28/28 tests passing
This commit is contained in:
Shane
2026-08-23 08:10:42 -04:00
parent f80b9ebe3d
commit c815bcb485
6 changed files with 89 additions and 226 deletions
+40
View File
@@ -19,6 +19,7 @@ WEB_BASE_URL = os.environ.get("VOICE_WEB_URL", "https://localhost:8090")
TOKEN_URL = os.environ.get("VOICE_TOKEN_URL", "http://127.0.0.1:8091/token")
GEMMA_BASE_URL = os.environ.get("GEMMA_BASE_URL", "http://192.168.86.2:8023/v1").rstrip("/")
GEMMA_MODEL = os.environ.get("GEMMA_MODEL", "gemma-4-e4b")
COGNEE_MCP_URL = os.environ.get("COGNEE_MCP_URL", "http://192.168.86.2:8003/mcp")
# Path to the agent's venv python inside the container (has mcp, livekit.agents)
CONTAINER_PYTHON = "/opt/voice-agent/.venv/bin/python"
@@ -134,3 +135,42 @@ asyncio.run(main())
return data["text"], data["isError"]
return _call
@pytest.fixture(scope="session")
def cognee_client():
"""Factory that calls tools on the remote Cognee MCP server (Streamable HTTP).
Returns (result_text, is_error). Uses the mcp client library from the
agent venv inside the container.
"""
def _call(tool_name: str, args: dict | None = None) -> tuple[str, bool]:
code = f"""
import asyncio, json
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def main():
async with streamablehttp_client({COGNEE_MCP_URL!r}) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool({tool_name!r}, {json.dumps(args or {})})
text = ""
for block in result.content:
if getattr(block, "type", None) == "text":
text += block.text
print(json.dumps({{"text": text, "isError": bool(result.isError)}}))
asyncio.run(main())
"""
proc = docker_exec_python(code, timeout=120, check=False)
if proc.returncode != 0:
raise AssertionError(
f"Cognee MCP call {tool_name} failed (rc={proc.returncode}): "
f"stderr={proc.stderr[-800:]}"
)
data = json.loads(proc.stdout.strip().splitlines()[-1])
return data["text"], data["isError"]
return _call
+19 -31
View File
@@ -46,42 +46,30 @@ def test_time_get(mcp_client_factory):
@pytest.mark.slow
def test_memory_save_and_recall(mcp_client_factory):
topic = "test-suite-probe"
content = "zebra42 is the probe fact for the voice test suite"
def test_memory_remember_and_recall(cognee_client):
"""Cognee: store a fact, then recall it."""
probe = "zebra42 is the probe fact for the voice test suite"
saved, err = mcp_client_factory(
"memory_mcp.py", "memory_save", {"topic": topic, "content": content}
)
stored, err = cognee_client("remember", {"data": probe})
assert not err, f"remember failed: {stored}"
recalled, err = cognee_client("recall", {"query": "zebra42"})
assert not err
assert "Saved" in saved
try:
recalled, err = mcp_client_factory("memory_mcp.py", "memory_recall", {"query": "zebra42"})
assert not err
assert "zebra42" in recalled
assert topic in recalled # recall output is tagged with the topic name
finally:
# Clean up: remove the probe file so repeated runs stay green.
from conftest import docker_exec
docker_exec("rm", "-f", "/memory/test-suite-probe.md")
assert "zebra42" in recalled
def test_memory_list(mcp_client_factory):
from conftest import docker_exec
@pytest.mark.slow
def test_memory_forget(cognee_client):
"""Cognee: store a fact, verify recall, then forget it."""
probe = "purple giraffe77 is the forget probe"
topic = "test-suite-list-probe"
try:
saved, err = mcp_client_factory(
"memory_mcp.py", "memory_save", {"topic": topic, "content": "listing probe"}
)
assert not err
listed, err = mcp_client_factory("memory_mcp.py", "memory_list", {})
assert not err
assert topic in listed
finally:
docker_exec("rm", "-f", "/memory/test-suite-list-probe.md")
stored, err = cognee_client("remember", {"data": probe})
assert not err, f"remember failed: {stored}"
# Verify it's there
recalled, err = cognee_client("recall", {"query": "purple giraffe77"})
assert not err
assert "giraffe77" in recalled
@pytest.mark.slow