diff --git a/resources/mappings.json b/resources/mappings.json
new file mode 100644
index 0000000..df6b4a7
--- /dev/null
+++ b/resources/mappings.json
@@ -0,0 +1,8 @@
+[
+  { "regex": "^open (.+) in editor$", "tool": "file.open", "keys": ["path"] },
+  { "regex": "^list containers$", "tool": "docker.list", "keys": [] },
+  { "regex": "^compose up (.+)$", "tool": "docker.compose.up", "keys": ["service"] }
+ ,{ "regex": "^save snapshot (.+)$", "tool": "kom.memory.v1.save_context", "keys": ["key"] }
+ ,{ "regex": "^load snapshot (.+)$", "tool": "kom.memory.v1.recall_context", "keys": ["key"] }
+ ,{ "regex": "^warm cache (.+)$", "tool": "kom.memory.v1.warm_cache", "keys": ["namespace"] }
+]
diff --git a/src/cli/KompanionApp.cpp b/src/cli/KompanionApp.cpp
index 49f6dcd..858642c 100644
--- a/src/cli/KompanionApp.cpp
+++ b/src/cli/KompanionApp.cpp
@@ -879,6 +879,30 @@ int main(int argc, char** argv) {
                                "key", "session:last");
   parser.addOption(keyOption);
 
+  // Warm cache + rehydrate helpers
+  QCommandLineOption warmCacheOption(QStringList() << "--warm-cache",
+                                     "Warm precomputed embeddings (policy or ad-hoc). Use with --policy or --id.");
+  parser.addOption(warmCacheOption);
+  QCommandLineOption policyOption(QStringList() << "--policy",
+                                  "Policy file (YAML/JSON) describing namespaces, model, limit, window_days.",
+                                  "path");
+  parser.addOption(policyOption);
+  QCommandLineOption idOption(QStringList() << "--id",
+                              "Explicit item id for ad-hoc warm cache (use with --stdin or -r).",
+                              "id");
+  parser.addOption(idOption);
+  QCommandLineOption rehydrateOption(QStringList() << "--rehydrate",
+                                     "Compose a rehydration frame: snapshot + top-K search for --text.");
+  parser.addOption(rehydrateOption);
+  QCommandLineOption textQOption(QStringList() << "--text",
+                                 "Text query for rehydrate/search.",
+                                 "q");
+  parser.addOption(textQOption);
+  QCommandLineOption kOption(QStringList() << "-k",
+                             "Top-K for rehydrate/search.",
+                             "k", "8");
+  parser.addOption(kOption);
+
   parser.addPositionalArgument("tool", "Tool name to invoke.");
   parser.addPositionalArgument("payload", "Optional JSON payload or file path (use '-' for stdin).", "[payload]");
 
@@ -894,6 +918,8 @@ int main(int argc, char** argv) {
   const bool runMcp = parser.isSet(mcpServeOption);
   const bool snapSave = parser.isSet(snapshotSaveOption);
   const bool snapLoad = parser.isSet(snapshotLoadOption);
+  const bool warmCache = parser.isSet(warmCacheOption);
+  const bool rehydrate = parser.isSet(rehydrateOption);
 
   std::optional<std::string> configDsn = readDsnFromConfig();
   const char* envDsn = std::getenv("PG_DSN");
@@ -974,6 +1000,89 @@ int main(int argc, char** argv) {
     }
   }
 
+  // Warm cache
+  if (warmCache) {
+    const QString ns = parser.value(nsNameOption);
+    const QString id = parser.value(idOption);
+    const QString policyPath = parser.value(policyOption);
+    const QString model = parser.value(QStringLiteral("--model")); // optional generic pass-through
+    const int limit = parser.value(limitOption).toInt();
+
+    if (!id.isEmpty()) {
+      // Ad-hoc enqueue: upsert_and_embed with single item from stdin/-r/payload
+      std::string raw; QString err;
+      if (!resolveRequestPayload(parser, parser.positionalArguments(), requestOption, stdinOption, raw, &err)) {
+        qerr << (err.isEmpty() ? QStringLiteral("Failed to read content for --id") : err) << "\n"; return 1;
+      }
+      std::ostringstream req;
+      req << "{\"namespace\":\"" << ns.toStdString() << "\",\"model\":\"" << model.toStdString() << "\",\"items\":[{\"id\":\"" << id.toStdString() << "\",\"text\":" << raw << "}]}";
+      std::cout << server.dispatch("kom.memory.v1.upsert_and_embed", req.str()) << std::endl;
+      return 0;
+    }
+
+    if (!policyPath.isEmpty()) {
+      // Minimal policy parser (YAML/JSON): namespaces, model, limit, window_days
+      QFile f(policyPath); if (!f.open(QIODevice::ReadOnly|QIODevice::Text)) { qerr << "Cannot open policy" << "\n"; return 1; }
+      const QString pol = QString::fromUtf8(f.readAll());
+      // Extract namespaces as lines starting with '-'
+      QStringList nss;
+      QRegularExpression rxNs("^\\s*-\\s*([A-Za-z0-9_:\\-]+)\\s*$");
+      for (const QString &line : pol.split('\n')) {
+        auto m = rxNs.match(line); if (m.hasMatch()) nss << m.captured(1);
+      }
+      if (nss.isEmpty() && !ns.isEmpty()) nss << ns;
+      // Extract window_days
+      int windowDays = 0; {
+        QRegularExpression rx("window_days\\s*:\\s*([0-9]+)"); auto m = rx.match(pol); if (m.hasMatch()) windowDays = m.captured(1).toInt();
+      }
+      // Extract model
+      QString pModel = model; if (pModel.isEmpty()) { QRegularExpression rx("model\\s*:\\s*([A-Za-z0-9_:\\-]+)"); auto m = rx.match(pol); if (m.hasMatch()) pModel = m.captured(1); }
+      // Extract limit
+      int pLimit = limit>0?limit:10; { QRegularExpression rx("limit\\s*:\\s*([0-9]+)"); auto m = rx.match(pol); if (m.hasMatch()) pLimit = m.captured(1).toInt(); }
+
+      // Compute since timestamp if windowDays>0
+      QString since;
+      if (windowDays > 0) {
+        const auto now = QDateTime::currentDateTimeUtc();
+        since = now.addDays(-windowDays).toString(Qt::ISODate);
+      }
+      for (const QString &nsv : nss) {
+        std::ostringstream req;
+        req << "{\"namespace\":\"" << nsv.toStdString() << "\"";
+        if (!pModel.isEmpty()) req << ",\"model\":\"" << pModel.toStdString() << "\"";
+        if (!since.isEmpty()) req << ",\"since\":\"" << since.toStdString() << "\"";
+        req << ",\"limit\":" << pLimit << "}";
+        std::cout << server.dispatch("kom.memory.v1.warm_cache", req.str()) << std::endl;
+      }
+      return 0;
+    }
+
+    // Simple case: call warm_cache once for ns
+    std::ostringstream req;
+    req << "{\"namespace\":\"" << ns.toStdString() << "\"";
+    if (!model.isEmpty()) req << ",\"model\":\"" << model.toStdString() << "\"";
+    req << ",\"limit\":" << (limit>0?limit:10) << "}";
+    std::cout << server.dispatch("kom.memory.v1.warm_cache", req.str()) << std::endl;
+    return 0;
+  }
+
+  // Rehydrate composition
+  if (rehydrate) {
+    const QString ns = parser.value(nsNameOption);
+    const QString key = parser.value(keyOption);
+    const QString text = parser.value(textQOption);
+    bool ok=false; int k = parser.value(kOption).toInt(&ok); if (!ok || k<=0) k=8;
+    // Recall snapshot
+    std::ostringstream r1; r1 << "{\"namespace\":\"" << ns.toStdString() << "\",\"key\":\"" << key.toStdString() << "\"}";
+    const std::string snapshot = server.dispatch("kom.memory.v1.recall_context", r1.str());
+    // Search
+    std::ostringstream r2; r2 << "{\"namespace\":\"" << ns.toStdString() << "\",\"query\":{\"text\":\"" << detail::json_escape(text.toStdString()) << "\",\"k\":" << k << "}}";
+    const std::string matches = server.dispatch("kom.memory.v1.search_memory", r2.str());
+    // Compose
+    std::cout << "{\"snapshot\":" << snapshot << ",\"search\":" << matches << "}" << std::endl;
+    return 0;
+  }
+
   // DB inspection helpers (exclusive)
   if (parser.isSet(dbNsOption)) {
     return dbListNamespaces(qout) ? 0 : 1;
diff --git a/src/mcp/HandlersMemory.hpp b/src/mcp/HandlersMemory.hpp
index 6a01453..8ff7bea 100644
--- a/src/mcp/HandlersMemory.hpp
+++ b/src/mcp/HandlersMemory.hpp
@@ -713,8 +713,8 @@ inline std::string embed_text(const std::string& reqJson) {
         }
         os << ']';
     }
-    os << "]}";
-    return os.str();
+  os << "]}";
+  return os.str();
 }
 
 /**
@@ -733,15 +733,19 @@ inline std::string warm_cache(const std::string& reqJson) {
     std::string model = detail::extract_string_field(reqJson, "model");
     int limit = 10;
     if (auto lim = detail::extract_int_field(reqJson, "limit")) { if (*lim > 0) limit = *lim; }
+    std::string key = detail::extract_string_field(reqJson, "key");
+    auto tags = detail::parse_string_array(reqJson, "tags");
+    std::string since = detail::extract_string_field(reqJson, "since");
 
     auto nsRow = detail::database().findNamespace(nsName);
     if (!nsRow) {
-        return std::string("{\"queued\":0}");
+        return std::string("{\\\"queued\\\":0}");
     }
 
-    // Fetch recent items
-    std::vector<std::string> tags; // empty
-    auto rows = detail::database().fetchContext(nsRow->id, std::nullopt, tags, std::nullopt, limit);
+    // Fetch recent items with optional filters
+    std::optional<std::string> keyOpt; if (!key.empty()) keyOpt = key;
+    std::optional<std::string> sinceOpt; if (!since.empty()) sinceOpt = since;
+    auto rows = detail::database().fetchContext(nsRow->id, keyOpt, tags, sinceOpt, limit);
     if (rows.empty()) {
         return std::string("{\"queued\":0}");
     }
@@ -779,7 +783,18 @@ inline std::string warm_cache(const std::string& reqJson) {
         detail::database().upsertEmbeddings(std::vector<ki::EmbeddingRow>{emb});
         persisted++;
     }
-    std::ostringstream os; os << "{\"queued\":" << persisted << "}"; return os.str();
+  std::ostringstream os; os << "{\"queued\":" << persisted << "}"; return os.str();
+}
+
+/** delete_context (stub MVP)
+ * Request: { namespace, key?, tags? }
+ * Response: { deleted: 0 }
+ * Note: Full deletion (soft-delete) can be added in DAL later.
+ */
+inline std::string delete_context(const std::string& reqJson) {
+    const std::string nsName = detail::extract_string_field(reqJson, "namespace");
+    if (nsName.empty()) return detail::error_response("bad_request","namespace is required");
+    return std::string("{\\\"deleted\\\":0}");
 }
 
 } // namespace Handlers
diff --git a/src/mcp/RegisterTools.hpp b/src/mcp/RegisterTools.hpp
index 820b768..404388d 100644
--- a/src/mcp/RegisterTools.hpp
+++ b/src/mcp/RegisterTools.hpp
@@ -8,6 +8,7 @@ inline void register_default_tools(KomMcpServer& server) {
     server.registerTool("echo", Handlers::echo);
     server.registerTool("kom.memory.v1.save_context", Handlers::save_context);
     server.registerTool("kom.memory.v1.recall_context", Handlers::recall_context);
+    server.registerTool("kom.memory.v1.delete_context", Handlers::delete_context);
     server.registerTool("kom.memory.v1.embed_text", Handlers::embed_text);
     server.registerTool("kom.memory.v1.upsert_memory", Handlers::upsert_memory);
     server.registerTool("kom.memory.v1.search_memory", Handlers::search_memory);
diff --git a/src/mcp/ToolSchemas.json b/src/mcp/ToolSchemas.json
index 4010b3b..660b955 100644
--- a/src/mcp/ToolSchemas.json
+++ b/src/mcp/ToolSchemas.json
@@ -162,6 +162,25 @@
             "additionalProperties": false
           }
         },
+        "delete_context": {
+          "description": "Delete stored context entries filtered by key and/or tags.",
+          "input": {
+            "type": "object",
+            "properties": {
+              "namespace": { "type": "string" },
+              "key": { "type": "string" },
+              "tags": { "$ref": "#/$defs/stringList" }
+            },
+            "required": ["namespace"],
+            "additionalProperties": false
+          },
+          "output": {
+            "type": "object",
+            "properties": { "deleted": { "type": "integer" } },
+            "required": ["deleted"],
+            "additionalProperties": false
+          }
+        },
         "embed_text": {
           "description": "Return embedding vectors for provided text inputs.",
           "input": {
@@ -400,6 +419,41 @@
             "additionalProperties": false
           }
         },
+        "upsert_and_embed": {
+          "description": "Upsert items and compute embeddings for each item (ord=0 chunk).",
+          "input": {
+            "type": "object",
+            "properties": {
+              "namespace": { "type": "string" },
+              "model": { "type": "string" },
+              "items": {
+                "type": "array",
+                "items": {
+                  "type": "object",
+                  "properties": {
+                    "id": { "type": "string" },
+                    "text": { "type": "string" },
+                    "tags": { "$ref": "#/$defs/stringList" },
+                    "metadata": { "type": "object" }
+                  },
+                  "required": ["text"],
+                  "additionalProperties": false
+                }
+              }
+            },
+            "required": ["namespace","items"],
+            "additionalProperties": false
+          },
+          "output": {
+            "type": "object",
+            "properties": {
+              "upserted": { "type": "integer" },
+              "embedded": { "type": "integer" }
+            },
+            "required": ["upserted","embedded"],
+            "additionalProperties": false
+          }
+        },
         "kom.local.v1.backup.export_encrypted": {
           "description": "Queue an encrypted backup export for the requested namespaces.",
           "input": {
