I've been running a custom MCP server connected to Claude.ai for several months as part of a proprietary SEO intelligence platform. The setup works well for structured data queries — rankings, crawl issues, keyword gaps — but session memory was the weak point.
I had a flat markdown file that stored project context: open tasks, doctrine, session history. It loaded at the start of every session via a get_context tool. The problem? Updating it required manually editing the file on the server after every session. It kept drifting.
The fix was simpler than I expected.
I added a single append-only tool called update_context to my FastMCP server. It takes one argument — a plain text summary of what happened in the session. The tool auto-injects the date and appends a dated entry to the Session History section of the context file.
python
from datetime import datetime
from pathlib import Path
@mcp.tool()
def update_context(entry: str) -> str:
"""
Appends a dated session history entry to the context file.
Date is auto-injected — pass only the summary text.
Format: "[what was done]. Next: [what to monitor or do next]."
"""
context_path = Path.home() / "project-context.md"
today = datetime.now().strftime("%Y-%m-%d")
formatted = f"\n**{today}:** {entry}"
content = context_path.read_text()
marker = "## Session History"
if marker not in content:
return "Error: Session History section not found."
insert_point = content.rfind("\n**2025-")
if insert_point == -1:
insert_point = content.find(marker) + len(marker)
else:
end_of_line = content.find("\n", insert_point + 1)
insert_point = end_of_line
new_content = content[:insert_point] + formatted + content[insert_point:]
context_path.write_text(new_content)
return f"Context updated: {formatted.strip()}"
Now at the end of every Claude session I just say "log this session" and Claude calls the tool directly. No copy-pasting, no opening files, no forgetting.
The full memory stack looks like this:
-
get_context— loads the flat markdown file at session start (project history, open TODOs, doctrine) -
update_context— appends session summary at session end - DuckDB — structured queryable data (rankings, crawl data, keyword gaps)
- Claude.ai native memory — personal preferences and recurring facts
Three complementary layers, no RAG, no vector database, no additional infrastructure.
Why not RAG?
I evaluated it. For a single-project setup with well-curated context, RAG is overkill. The flat file loads instantly, costs nothing, and you control exactly what the model knows. RAG earns its place when you have hundreds of unstructured documents you need to search semantically. I'm not there yet.
The flat file + append tool beats RAG for the majority of single-project use cases.
The whole append tool is about 30 lines of Python. If you're already running a FastMCP server and maintaining a context file manually, this is a straightforward upgrade worth doing.
Happy to answer questions in the comments.
Top comments (0)