HomeAgents MCP servers
Overview
I wrote two small MCP servers for my HomeAgents platform. One gives my assistants a long term memory. The other gives them web search.
The memory server stores and searches entries in one Qdrant collection. Every entry has a domain label, so my personal assistant and my work assistant use the same storage but never read each other’s memories. The embeddings run on my own server, so remembering something costs nothing.
The search server uses my own SearXNG instance, which needs no key. It can also use Tavily for deeper search and page extraction. If the Tavily key is missing, only those tools stop. Normal search keeps working.
I built the two servers on different frameworks on purpose. I wanted to see how FastMCP and the official SDK feel side by side.
Problem
My AI assistants needed two things they could not do alone: remember things over time and search the web. I wanted both as small tool servers that any assistant can use, without paying for an API call every time a memory is stored or searched.
Approach
- I wrote two Model Context Protocol servers in Python. Each one is a self contained service with its own Dockerfile and does not depend on the other.
- I built one on FastMCP and the other on the official MCP Python SDK, to compare the two approaches in one repository.
- I made the memory server work on a single Qdrant collection and gave every entry a domain label.
- I made the search server use my own SearXNG instance first, so it needs no API key.
- I kept secrets out of both servers. Everything arrives through environment variables.
- I gave each requirements file a lower and an upper bound, so a rebuild cannot jump to a new major version.
Architecture and design decisions
- The memory server qdrant-mcp listens on port 8765. It has four tools: memory_store, memory_search, memory_delete and memory_stats.
- Every entry carries a domain field and every tool accepts an optional domain. That is how a personal assistant and a work assistant share one collection without reading each other's memories.
- Embeddings come from a local TEI service running BAAI/bge-m3 with 1024 dimensions, so recall costs CPU time and not API calls.
- The collection is created on first use, so a fresh machine works even if a setup step was skipped.
- The search server web-search-mcp listens on port 8000. It has five tools: web_search against SearXNG, plus tavily_search, tavily_extract, tavily_map and tavily_crawl.
- Both servers speak MCP over streamable HTTP. The search server runs stateless.
Reliability and performance
- When the Tavily key is empty, the four Tavily tools return a configuration error and web_search keeps working. Search gets weaker and does not break.
- Because the search server is stateless, a restart does not break connected clients.
- Version bounds in the requirements files stop a rebuild from changing behaviour by surprise.
- Neither server stores secrets.
Outcomes
- Nine tools across two independent servers run in my platform.
- Several assistants share one memory collection without mixing their context.
- Long term memory does not need a paid API, because the embeddings run locally.
- Web search works without any paid key.
- I have compared two MCP frameworks side by side in one repository.
Known gaps
- I have no numbers for speed, memory use or how many entries the collection holds.
- I have not measured how good the memory search results are.
- I do not say which of the two frameworks I prefer. The repository only shows both.
- The domain label separates memories by convention. It is not a security boundary between users.
- The servers are built for one household. I have not tested them with several users.
- I do not say which licence the repository uses.