Inspiration

Most AI assistants reset every session. That is fine for one-off questions. It breaks down when you want a coworker that remembers how you work, what you decided last week, and what still needs follow-up.

At John CEO, we build private AI coworkers for business users - on Telegram for solo use and Slack for teams. Memory is not a nice-to-have for us. Each customer gets a private workspace where context should survive restarts, not evaporate when a chat window closes. That product vision drew us to the Qwen Cloud Hackathon (Track 1: MemoryAgent): a chance to prototype semantic memory exposed as standard agent tools.

John CEO: Qwen Memory MCP is a standalone learning experiment, not a product announcement. The code is MIT-licensed in a separate repo. John CEO does not use it in production today. Production memory stays on each client's individually isolated workspace. We built this to learn, stress-test ranking and recall ideas, and share what we found.

What we built

An MCP server that gives any agent four memory tools:

Tool Purpose
memory_write Store durable memory with Qwen-derived summary, tags, salience, kind
memory_search Semantic retrieval ranked by similarity + salience + recency + reinforcement
memory_recall_context Pack the best memories into a fixed token budget for the model
memory_forget Consolidate related memories and decay stale, low-value ones

Design goals: durable, semantic, scoped per user, simple MCP integration.

How we built it

Stack (all in ap-southeast-1, Singapore):

  • Qwen Cloud (DashScope): text-embedding-v3 for embeddings; qwen-plus for analyze (salience, tags, summary) and consolidate (merge clusters, flag outdated facts)
  • Alibaba Function Compute: public HTTPS endpoint, custom Node runtime, VPC-attached to RDS
  • Alibaba RDS MySQL 8.0: persistent memory store (john-ceo-rds, database qwen_memory)
  • MCP over HTTP: Streamable HTTP at POST /mcp with Bearer auth; health at GET /health

We kept Qwen API calls in a single file ([src/qwen.ts](https://github.com/John-CEO-HQ/qwen-memory-mcp/blob/main/src/qwen.ts)) and MySQL persistence in [src/memory/mysql-store.ts](https://github.com/John-CEO-HQ/qwen-memory-mcp/blob/main/src/memory/mysql-store.ts)). Deploy scripts live under deploy/ (Serverless Devs s.yaml, RDS bootstrap, FC deploy).

Offline development uses a deterministic FakeIntelligence so tests and npm run demo work without network. Integration tests and npm run verify:deployed exercise the live stack.

What we learned

  1. Ranking travels well. Combining similarity, salience, recency, and reinforcement improved recall more than storage brand or centralized vs local shape.

  2. Token budgets matter as much as retrieval. memory_recall_context was not an afterthought. Real agents hit context limits fast. Packing the best memories beats dumping top search hits into the prompt.

  3. Semantic search changes the product feel. Keyword search fails on "how do I like client drafts?" when the stored memory says "keep external emails under three short paragraphs." Embeddings bridge that gap.

  4. Centralized MCP vs workspace memory taught us tradeoffs we already feel in John CEO production: per-user ids are fast to demo; audience-aware recall (DM vs channel vs team) needs structural scoping, not just better search.

  5. Maintenance is not optional. Forget and decay passes prevent memory from growing forever.

Challenges we faced

  1. Cold starts on serverless. First MCP call after idle on Function Compute can take 10-20 seconds. We document this for judges and built health checks that tolerate warm-up.

  2. MCP over HTTP is not plain JSON. Responses may arrive as Server-Sent Events. Our first smoke scripts assumed curl | jq would suffice. They did not. We added a small Node parser in scripts/parse-mcp-response.mjs so verification handles both shapes.

  3. Regional alignment. As a European team building for global users, we kept DashScope international endpoint, compute, and RDS in the same region (ap-southeast-1) outside mainland China.

  4. Isolation from our private product codebase. The module must split cleanly into its own MIT repo with zero imports from proprietary John CEO code. That constraint shaped every file boundary.

What's next

Algorithmic ideas from this experiment (ranking, token-budget packing, scoped recall) may inform John CEO's production john-scoped memory plugin. We documented a future wiring blueprint but have not implemented Qwen or this MCP server in the live product. After judging we will rotate demo credentials and optionally tear down cloud resources.

Built With

Share this project:

Updates