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
+28 -30
View File
@@ -38,7 +38,6 @@ GEMMA_MODEL = os.environ.get("GEMMA_MODEL", "gemma-4-e4b")
GEMMA_API_KEY = os.environ.get("GEMMA_API_KEY", "not-needed")
WEB_MCP_ENABLED = os.environ.get("WEB_MCP_ENABLED", "true").lower() in ("1", "true", "yes")
FIRECRAWL_BASE = os.environ.get("FIRECRAWL_BASE", "http://192.168.86.2:3002")
MEMORY_DIR = os.environ.get("MEMORY_DIR", "/memory")
SKILLS_DIR = os.environ.get("SKILLS_DIR", "/skills")
SYSTEM_PROMPT = textwrap.dedent("""\
@@ -63,6 +62,20 @@ SYSTEM_PROMPT = textwrap.dedent("""\
- Never write more than three sentences in a row.
- Never read back URLs, file paths, or technical identifiers.
# Memory (CRITICAL — ALWAYS call these tools directly, never dispatch)
When the user asks about personal information, past conversations, or
anything you might have stored, you MUST call recall FIRST before
answering. Do NOT say "I don't have that info" without calling recall.
When the user tells you something to remember or shares a preference,
you MUST call remember. Do NOT just say "okay I'll remember that."
- User says "what's my name?" → CALL recall with query="my name"
- User says "do you remember who I am?" → CALL recall with query="user identity name"
- User says "remember my coffee order is oat milk latte" → CALL remember
with data="User's coffee order is an oat milk latte"
- User says "forget that I like blue" → CALL forget to remove it
After calling remember, confirm briefly ("Got it, I'll remember that").
If recall returns nothing, then say you don't have that info yet.
# Weather & Time
You can check the weather for any location. Use get_weather when the user
asks about current conditions, temperature, or forecasts. It returns a
@@ -72,38 +85,23 @@ SYSTEM_PROMPT = textwrap.dedent("""\
# Background Tasks (dispatch_task) — USE FOR ALL NON-TRIVIAL TASKS
For ANY task that is not a simple one-sentence answer from your own
knowledge, you MUST call dispatch_task. This includes: looking up news,
researching topics, checking current events, prices, sports scores,
writing something, summarizing, comparing options, planning, or anything
that takes more than a couple seconds to think through. Do NOT use
web_search or web_scrape directly; always dispatch instead.
The only things you answer inline are: weather (get_weather), time
(get_time), memory operations, and trivial facts you already know.
knowledge and NOT a memory operation, you MUST call dispatch_task.
This includes: looking up news, researching topics, checking current
events, prices, sports scores, writing something, summarizing, comparing
options, planning, or anything that takes more than a couple seconds to
think through. Do NOT use web_search or web_scrape directly; always
dispatch instead. Memory recall/remember is NEVER a dispatch task —
call those tools directly.
Examples:
- User says "what's the latest news?" → CALL dispatch_task with
description="Find the top 5 international news headlines today"
- User says "look up the price of a PS5" → CALL dispatch_task with
description="Find the current retail price of a PlayStation 5"
- User says "plan a weekend trip to Denver" → CALL dispatch_task with
description="Plan a two-day weekend trip to Denver including activities"
After calling dispatch_task, tell the user "I'll get on that for you"
and keep the conversation going. The result comes back automatically — when
you receive it, share the findings naturally in your conversational style.
You can have multiple tasks running at once.
# Memory (CRITICAL — always use these tools)
You MUST call memory_save whenever the user tells you something to remember,
shares a preference, or says "remember that...". Do NOT just say "okay I'll
remember that" without actually calling the tool. Always call it.
- User says "remember my coffee order is oat milk latte" → CALL memory_save
with topic="coffee order", content="oat milk latte"
- User says "what did I tell you about my birthday?" → CALL memory_recall
with query="birthday"
- User says "list everything you remember about me" → CALL memory_list
After calling memory_save, confirm briefly ("Got it, I'll remember that")
but do NOT say "I saved it to my memory file" or similar.
If a recall returns nothing, just say you don't have that info yet.
# Skills
You have a skill library of learned procedures. Use skill_recall when you need
to perform a task you've done before — it will give you the steps. When you
@@ -383,19 +381,19 @@ def build_mcp_toolsets() -> list[mcp.MCPToolset]:
)
logger.info("Weather MCP toolset enabled (wttr.in)")
memory_mcp_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), "memory_mcp.py")
cognee_url = os.environ.get("COGNEE_MCP_URL", "http://192.168.86.2:8003/mcp")
toolsets.append(
mcp.MCPToolset(
id="memory",
mcp_server=mcp.MCPServerStdio(
command=python_bin,
args=[memory_mcp_script],
env={**os.environ, "MEMORY_DIR": "/memory"},
client_session_timeout_seconds=30,
mcp_server=mcp.MCPServerHTTP(
url=cognee_url,
transport_type="streamable_http",
allowed_tools=["remember", "recall", "forget"],
client_session_timeout_seconds=60,
),
)
)
logger.info("Memory MCP toolset enabled (%s)", MEMORY_DIR)
logger.info("Memory MCP toolset enabled (Cognee at %s)", cognee_url)
skills_mcp_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), "skills_mcp.py")
toolsets.append(