@yugabytedb/meko-mcp 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +152 -27
  2. package/assets/hooks-handlers/codex-session-end.sh +4 -69
  3. package/assets/hooks-handlers/cursor-session-start.sh +19 -1
  4. package/assets/hooks-handlers/lib/capture-notices.js +321 -0
  5. package/assets/hooks-handlers/lib/capture-state.js +2079 -0
  6. package/assets/hooks-handlers/lib/capture-status-cli.js +82 -0
  7. package/assets/hooks-handlers/lib/capture.js +1578 -299
  8. package/assets/hooks-handlers/lib/checkpoint-timer.js +444 -81
  9. package/assets/hooks-handlers/lib/kiro-handler.js +738 -0
  10. package/assets/hooks-handlers/lib/terminal-handoff.js +418 -0
  11. package/assets/hooks-handlers/session-end.sh +3 -34
  12. package/assets/scripts/meko-statusline.sh +41 -1
  13. package/assets/skills/meko-mcp-tools/SKILL.md +72 -125
  14. package/assets/skills/meko-mcp-tools/references/_sections.md +2 -2
  15. package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +12 -13
  16. package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +15 -12
  17. package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +25 -1
  18. package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +19 -77
  19. package/assets/skills/meko-mcp-tools/references/tools-overview.md +8 -7
  20. package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +22 -1
  21. package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +1 -1
  22. package/assets/skills/meko-mcp-tools-desktop/SKILL.md +8 -8
  23. package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +1 -1
  24. package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +1 -1
  25. package/assets/skills/meko-mcp-tools-desktop/references/tools-agent-id-conventions.md +6 -1
  26. package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +6 -5
  27. package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +4 -4
  28. package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +7 -6
  29. package/assets/skills/meko-select-datapack-desktop/SKILL.md +1 -1
  30. package/assets/skills/meko-select-datapack-desktop/references/cookbook.md +3 -3
  31. package/bin/create-meko-setup.mjs +48 -10
  32. package/lib/capture-status.mjs +67 -0
  33. package/lib/clients/aliases.mjs +5 -0
  34. package/lib/clients/claude-desktop.mjs +120 -5
  35. package/lib/clients/codex.mjs +6 -3
  36. package/lib/clients/index.mjs +2 -0
  37. package/lib/clients/kiro.mjs +705 -0
  38. package/lib/config.mjs +90 -0
  39. package/lib/installer.mjs +1 -0
  40. package/lib/migrate/adapters/codex.mjs +490 -0
  41. package/lib/migrate/id.mjs +28 -3
  42. package/lib/migrate/orchestrator.mjs +34 -7
  43. package/lib/migrate.mjs +4 -2
  44. package/lib/prompt.mjs +16 -1
  45. package/package.json +4 -4
@@ -4,184 +4,123 @@ description: Behavioral guide for AI agents using Meko MCP tools. Triggers when
4
4
  license: MIT
5
5
  metadata:
6
6
  author: Meko
7
- version: "3.0.2"
7
+ version: "3.1.0"
8
8
  tags: mcp, tools, datapack, memory, conversation, rag, meko
9
9
  ---
10
10
 
11
11
  # Meko MCP Tools — Agent Behavioral Guide
12
12
 
13
- Meko is agent-native data infrastructure that enables continuous learning from context windows through collective memory and shared knowledge. This skill teaches you how to use Meko's 23 MCP tools.
14
-
13
+ Meko is agent-native data infrastructure that enables continuous learning from context windows through collective memory and shared knowledge. This skill teaches you how to use Meko's 23 MCP tools available in production.
15
14
 
16
15
  **Read this first.** On Claude Code, conversation capture is automatic (SessionStart / PreCompact / SessionEnd hooks) and the Meko server extracts durable memories from the captured turns on its own. Facts the user states in conversation are saved for you — you do **not** proactively call `memory_add` for them. Your active jobs are: **recall** what's already known (`memory_search`, `knowledgebase_search`), and the **few** save cases automatic extraction cannot reach. Details below.
17
16
 
18
- ## What Meko enables
17
+ ## Non-negotiable operating contracts
19
18
 
20
- Meko turns your volatile context window into persistent, shareable knowledge:
19
+ Apply these rules before the longer guidance below. They are service-contract safeguards, not suggestions.
21
20
 
22
- - **Personal memory** — Store who the user is, their preferences, role, and working style. Private to you (scoped per-user; readable across all of your agents). Survives across sessions.
23
- - **Team-shared knowledge** — Important memories can be promoted with `memory_promote` (after explicit confirmation) or from the Cloud UI's Learnings tab. Uploaded documents arrive through **Add Knowledge**. The resulting content is visible to every datapack member and queryable via `knowledgebase_search`.
24
- - **Conversation history** — Preserve full dialog exchanges with reasoning traces for audit, replay, and learning transfer.
25
- - **Decision traces** — Capture how and why decisions were made, enabling debugging and continuous improvement.
21
+ ### 1. Distinguish failure from an empty search
26
22
 
27
- ## When to use this skill
23
+ Inspect the response envelope before its contents:
28
24
 
29
- - You are calling tools on a Meko MCP server
30
- - You need to decide what to store, where, and how (personal memory vs. team-shared knowledge)
31
- - You want to search the team's shared knowledge base (`knowledgebase_search`)
32
- - You are managing datapacks
33
- - You want to understand `agent_id` conventions, or `datapack_id` routing
25
+ 1. If `error` or an error-shaped `detail` is present, the search **failed** and its findings are **unknown**. Say exactly that. Never say "nothing was found," "no results," or "the store is empty."
26
+ 2. Do not retry quota (`free_tier_limit_reached`) or permission errors. Report the error and stop. Retry only documented transient failures, with a bounded backoff.
27
+ 3. Only a successful response with an explicit empty `results` array proves a legitimate empty search.
34
28
 
35
- ## `agent_id` — multi-agent identity
29
+ ### 2. Treat `memory_get_all` as a recent window, never an export
36
30
 
37
- `agent_id` identifies which agent wrote a memory or conversation. It is **not a constant**. On Cloud Meko today, different agents (Claude Code, Cursor, Claude Desktop — and different projects within each) each use their own `agent_id`, and the Cloud UI renders the value as a badge on every row.
31
+ `memory_get_all` returns roughly 20 recent rows plus a `total`; it is not a listing tool. Inspect the row count against `total`, and never state or imply you have listed everything — the only trustworthy count is `total`. Calling it more than once does not add up to a complete export: a second call with `promoted=true` (or any other variant) is just another recent window, not the remaining rows, so two calls are still not a full listing. Do not invent `limit`, `offset`, `page`, or `page_size` arguments—the tool rejects pagination. Use targeted `memory_search` or `memory_get_by_id` for older or exact content. If the user needs a complete export, report that MCP currently has no complete enumeration path.
38
32
 
39
- **Three buckets:**
33
+ ### 3. Separate retrieval breadth from reader context
40
34
 
41
- - **Project bucket** — `<client>:<repo-basename>`, e.g. `claude_code:meko-mcp-server`. The default for almost every memory in a coding session. The hook derives it from the cwd and injects it via SessionStart `additionalContext`.
42
- - **Common bucket** — `meko_agent`. The cross-project bucket for facts any agent should see regardless of project (user identity, global preferences). Empty / missing `agent_id` lands here automatically; you can also pass it explicitly.
43
- - **Loose name** — non-coding clients (Claude Desktop, generic MCP) use a stable client name like `claude_desktop`. Not relevant in this skill (Claude Code is a coding agent).
35
+ Retrieve up to about 25 candidates for recall, preserve relevance order, and pass at most the top 10 useful evidence items to final reasoning. Never paste all 25–30 results into the reader by default. Raise the reader window only after measuring misses outside the top 10. When dated claims conflict, resolve recency only among claims about the same entity and field; do not sort the whole result set by date.
44
36
 
45
- ```
46
- agent_id = "claude_code:meko-mcp-server" # this session's project bucket
47
- agent_id = "meko_agent" # cross-project facts
48
- ```
37
+ If no candidate supports an answer, abstain: say the retrieved evidence does not cover it. Never fill the slot with a guess, and when the task offers fixed options, choose the one that *means* "not enough information" rather than defaulting to any particular option.
38
+
39
+ ### 4. Verify writes and enforce real isolation
49
40
 
50
- The SessionStart hook injects the project-bucket value into the first-turn `additionalContext`. Use that value verbatim for project-scoped Meko MCP calls in this session; do not re-derive it. Use `meko_agent` explicitly when you want a write to land in the cross-project bucket.
41
+ - A success-shaped write response is not proof. Read back memories and conversations. For artifacts, compute SHA-256 locally, require the matching `content_hash`, then read back important bytes. A missing hash means the upload is unconfirmed.
42
+ - `agent_id` attributes writes; it is not an access boundary. Put projects, tenants, or security domains that must not co-discover content in separate datapacks.
43
+
44
+ ## `agent_id` — multi-agent identity
45
+
46
+ Use the SessionStart-injected `agent_id` verbatim. It normally has shape `<client>:<repo-basename>`. Use `meko_agent` only for deliberately cross-project writes; empty write IDs also route there.
51
47
 
52
48
  **Read scoping varies by tool:**
53
- - `memory_search` / `memory_get_all` — scoped to `(datapack_id, user_id)`. **`agent_id` does not filter memory reads:** one call returns all of your memories for this user across every `agent_id` (the tool passes `meko_agent_id=None` to mem0, so `agent_id` scopes the Langfuse trace, not the result set). No need to fan out per agent_id or read the `meko_agent` bucket separately — a single search already includes it.
49
+ - `memory_search` / `memory_get_all` — scoped to `(datapack_id, user_id)`; `agent_id` does not filter results. Do not fan out reads by agent.
54
50
  - `conversation_get` — agent-owned: pass the exact `agent_id` that created the conversation; any other value returns `agent_id_mismatch`.
55
- - `conversation_list` — returns the datapack's conversations for your user regardless of `agent_id` (the argument is trace-attribution only, like memory reads).
56
- - `knowledgebase_search` — scoped to `(datapack_id)` only. `agent_id` on the request is **ignored**; you see the team's shared knowledge regardless of what you pass. Includes uploaded documents and memories that the user promoted via the UI's "Promote to Knowledge" flow.
51
+ - `conversation_list` — user/datapack scoped; `agent_id` is trace attribution only.
52
+ - `knowledgebase_search` — datapack scoped; `agent_id` is ignored.
57
53
 
58
- See `tools-agent-id-conventions.md` for the full model, including how promotion works and how to phrase broad-query responses to the user.
54
+ See `tools-agent-id-conventions.md` for the full model, including how promotion works and how to phrase broad-query responses to the user. Legacy IDs remain readable through the same personal-memory read.
59
55
 
60
- Some pre-existing rows in real datapacks use the older `agent_id="agent"` constant or other ad-hoc shapes (`claude_code`, `cursor:<slug>`). They remain readable — query them with `agent_id="agent"` explicitly. New writes should follow the schema above.
56
+ ## Use Meko for durable memory, not as a replacement for project files
61
57
 
62
- ## Critical: Use Meko, not local storage
58
+ Use Meko for durable facts that must survive sessions, be found by meaning, or be shared across agents. Keep source code, exact artifacts, canonical specifications, and whole documents in their normal file or artifact stores; use exact lookup when identity is known. Do not create an ad-hoc local "agent memory" file as a substitute for Meko.
63
59
 
64
- **Meko is the memory store — never write memories to local files, markdown notes, or any file-based memory system.** Meko's memory is persistent across all agents, sessions, and team members; local files are not. On Claude Code, memory reaches Meko two ways, and neither is a local file:
60
+ On Claude Code, memory reaches Meko two ways:
65
61
 
66
62
  - **Automatic capture + extraction** (the dominant path) — the hooks capture this session's turns and the server extracts memories from them. Facts the user states are stored without any tool call from you.
67
63
  - **Explicit `memory_add`** (the narrow path) — only for the cases extraction can't reach (see "When to call memory_add" below).
68
64
 
69
- To recall, call `memory_search` on the MCP server, NOT read local files. If a Meko read/write call fails, you may fall back to local storage and tell the user — but Meko is always the first choice.
65
+ For meaning-based recall, call `memory_search`. For an exact known filename, key, hash, or complete document, use the corresponding direct file or artifact lookup. If a Meko call fails, report the failure; do not silently replace durable shared memory with a private local note.
70
66
 
71
67
  ## When spawning subagents
72
68
 
73
- Subagents (dispatched via the `Agent` / `Task` tool) do **not** receive the SessionStart `additionalContext` block. If they touch Meko, they either invoke tools with a nil-UUID `conversation_id` (orphaned from the parent's trace) or guess an `agent_id` / fabricate a `conversation_id` (split namespace, broken trace). A 2026-04-30 probe found 5 orphan memories written by a general-purpose subagent.
74
-
75
- ### Rule (parent's responsibility)
76
-
77
- **Every spawn prompt MUST prepend an inherited-context block** with the parent's actual `agent_id` and `conversation_id`:
69
+ Subagents do not receive SessionStart context. Every spawn prompt must include:
78
70
 
79
71
  ```
80
72
  Meko context (inherited from parent session):
81
73
  - agent_id: "<parent's agent_id, verbatim>"
82
74
  - conversation_id: "<parent's conversation_id>"
83
- - Use these for all Meko MCP calls. Consult the meko-mcp-tools skill first for anything novel; do not re-derive these values.
75
+ - Use these verbatim for all Meko MCP calls.
84
76
  ```
85
77
 
86
- Both values come from the SessionStart `additionalContext` that was injected into your first turn. Pass them through verbatim — the `agent_id` is not a fixed constant; it reflects the client + project the parent is running in.
87
-
88
- **Default: inject unconditionally.** The skill-listing heuristic (subagent seeing `meko-agent-skills:meko-mcp-tools` in its available skills) is unreliable, and injecting a 4-line block costs nothing. Don't try to predict whether the subagent will touch Meko — inject always.
89
-
90
- ### What the subagent does with it
91
-
92
- The subagent treats the block as authoritative. Apply this hierarchy in order:
93
-
94
- 1. **Default: reuse the inherited `conversation_id`.** The parent decides scope. Do NOT re-derive these values. Do NOT create a fresh conversation on a "feels separate" judgment — a separate-feeling task is not an explicit signal.
95
- 2. **Exception: create a new conversation only when the spawn prompt (or user) explicitly says so.** An explicit signal means the parent's prompt says something like "use a fresh conversation" or "start your own conversation scope," or the user directly asks for one. Absent that signal, reuse.
96
-
97
- Whichever path applies, always use the inherited `agent_id` as-is — do not replace it, slugify it, or fall back to a constant.
98
-
99
- If the inherited block is **absent**, the subagent MUST NOT guess — see the self-diagnosis subsection below.
100
-
101
- ### You may be a subagent — self-diagnosis
102
-
103
- **Tell-tale signs:**
104
- - You did NOT receive a SessionStart `additionalContext` block naming a Meko `conversation_id`.
105
- - You see `meko-agent-skills:meko-mcp-tools` in your available skills but no watermark / inherited-context reference in your initial prompt.
106
- - Your spawn prompt mentions you were "spawned" / "dispatched" / "launched" by a parent, or mentions a `Task` / `Agent` tool.
107
-
108
- **What to do:**
109
- - Look for a `Meko context (inherited from parent session):` block in the spawn prompt. If present, use those values verbatim for every Meko MCP call.
110
- - If absent, **refuse to invoke Meko write tools** and respond to the parent with a clarification request: ask for the parent's `agent_id` and `conversation_id`. The parent can re-dispatch with the block prepended.
111
-
112
- **What NOT to do:**
113
- - Do NOT fall back to the nil UUID (`"00000000-0000-0000-0000-000000000000"`) for `conversation_id` — that's an orphan-write pattern.
114
- - Do NOT invent an `agent_id`. The right value is whatever the parent is using (typically `claude_code:<repo-basename>`); don't assume `"agent"`, `"claude-code"`, `"meko_agent"`, or a different basename. Ask.
115
- - Do NOT silently create your own conversation to "just get moving" — ask the parent.
78
+ Reuse the inherited conversation unless the parent or user explicitly requests a fresh scope. Always reuse the inherited agent ID.
116
79
 
117
- Subagents cannot auto-discover the parent's watermark today: Claude Code does not expose a `CLAUDE_PARENT_SESSION_ID` env var or any equivalent marker file to subagent processes (see the spike note in `skills/hooks-handlers/lib/capture.js`). Prompt injection is the only enforcement mechanism.
80
+ **You may be the subagent.** If no SessionStart context named a `conversation_id`, assume you are one and look for the block above in your prompt. If it is absent, do not guess, invent IDs, use the nil UUID, or write — ask the parent for both values.
118
81
 
119
82
  ## Core principle: capture is automatic — recall, don't re-store
120
83
 
121
- Meko is your long-term memory, but on Claude Code you do **not** build it by hand. The hooks capture every turn of this session and the server extracts durable memories from them automatically. **A fact the user states in conversation — name, role, preferences, org conventions, corrections, casual asides — is already saved. Calling `memory_add` for it just duplicates what extraction stored.** (Verified empirically: the server extracts conversationally-stated facts verbatim, including multi-fact turns and precise multi-clause facts.)
84
+ On Claude Code, hooks capture user turns and the server extracts durable memories. Do not duplicate facts the user states with `memory_add`.
122
85
 
123
- So your Meko reflexes are:
124
-
125
- 1. **Recall first.** When the user asks what's known, or before you act on something they may have an opinion about, search — don't assume.
126
- 2. **Save only what capture can't reach** (the three narrow cases below).
127
- 3. **Never** re-store a fact the user just said. **Never** write memories to local files.
86
+ Recall first; save only what capture cannot reach; never re-store a just-stated fact.
128
87
 
129
88
  ### When the user shares information
130
89
 
131
90
  | Signal in conversation | What to do |
132
91
  |---|---|
133
92
  | User states a fact about themselves, their team, tools, or preferences | **Nothing — automatic capture + extraction stores it.** Just answer. |
134
- | User corrects your behavior or negates a prior fact ("actually, we use Nomad now") | The new fact is captured automatically, but extraction is **additive** — it does not remove the old one. If a stale, contradicted memory must not survive, `memory_search` for it and `memory_update` / `memory_delete_by_id`. |
93
+ | User corrects a prior fact | Capture adds the correction but may retain the old fact; find and update/delete the stale memory when it must not survive. |
135
94
  | User explicitly says "remember this" / "save this to memory" | `memory_add` (verbatim). This is the clearest explicit-save case. |
136
- | A durable fact appears only in YOUR output or a tool result, never in the user's words | `memory_add`. Extraction reads only the **user** turn, so facts you derive or a tool surfaces are never captured otherwise. |
137
- | User asks "what do you know about X?" | Two surfaces: `memory_search` (one call — all your personal memories for this user, every agent) then `knowledgebase_search` (team-shared knowledge). |
95
+ | A durable fact appears only in assistant output or a tool result | `memory_add`; automatic extraction reads the user turn. |
96
+ | User asks "what do you know about X?" | Search both production retrieval surfaces: `memory_search` for personal context, then `knowledgebase_search` for shared datapack knowledge when relevant. |
138
97
  | User asks "what do we (as a team) know about X?" or about uploaded documents | `knowledgebase_search` (returns uploaded docs + promoted memories). |
139
- | User asks to share specific private memories with the team | Follow the `memory_promote` confirmation workflow below. Never promote based on a fuzzy search result or implied consent. |
98
+ | User asks to share private memories | Follow the exact-ID `memory_promote` confirmation workflow below. |
140
99
  | User provides structured/tabular data (CSV, data dictionary) | Not natively supported via MCP. Point the user at the UI's Add Knowledge upload; do not `memory_add` row-by-row. |
141
100
  | User wants to add documents to the team's knowledge base | Point them at the Cloud UI flow — Datapack → Actions → **Add Knowledge** (PDF/TXT/MD/JSON/MP4, 5MB each, 10/batch). MCP ingestion tools are not available on Cloud. |
142
101
 
143
- ### When to call memory_add (the whole list)
144
-
145
- Automatic capture handles the rest, so explicit `memory_add` is reserved for exactly three cases:
146
-
147
- 1. **Explicit request** — the user says "remember this" / "save this."
148
- 2. **Output-only / tool-derived fact** — a durable fact that lives only in the assistant's output or a tool result, never in a user turn (extraction only sees the user turn).
149
- 3. **Overwriting correction** — a prior fact was negated and the stale memory must not survive (extraction is additive; pair `memory_add`/`memory_update` with a `memory_delete_by_id` of the old one).
102
+ ### When to call memory_add
150
103
 
151
- When you do call it, store the fact verbatim in the user's own words; do not summarize.
104
+ Use it only for an explicit save request, an output/tool-derived durable fact, or a correction whose stale predecessor must be replaced. Store one focused fact verbatim; for corrections, update/delete the stale record.
152
105
 
153
106
  ## Automatic conversation capture
154
107
 
155
- The Meko plugin automatically captures conversations via three mechanisms that coordinate through a shared watermark file:
156
-
157
- 1. **Background checkpoint timer** — runs every 10 minutes, captures new exchanges without interrupting the agent
158
- 2. **PreCompact hook** — fires before context compaction, captures everything before compaction discards context
159
- 3. **SessionEnd hook** — fires at session end, captures remaining exchanges
160
-
161
- All three are handled automatically. **Do NOT set up CronCreate for conversation capture** — it interrupts running tool calls and causes disruptive retry cycles.
108
+ Background, PreCompact, and SessionEnd hooks capture the conversation automatically. Do not create a separate capture cron.
162
109
 
163
110
  ### What to do at session start
164
111
 
165
- The SessionStart hook has already done the setup for you:
166
-
167
- 1. **Created a Meko conversation** — `conversation_id` is injected into `additionalContext` on the first turn. Use that value for all subsequent MCP tool calls that accept `conversation_id`.
168
- 2. **Echoed the session's `agent_id`** — also injected into `additionalContext`. Use the injected value verbatim for project-scoped Meko tool calls. It's a per-session value derived from the cwd (shape: `claude_code:<repo-basename>`), not a constant. For genuinely cross-project facts, write with `agent_id="meko_agent"` (the common bucket) instead.
169
- 3. **Preloaded recent memories** — `additionalContext` may include a `### Memories from prior sessions` block. Inspect it before acting so you don't re-ask questions the user has already answered.
170
-
171
- If `additionalContext` is absent or empty (hook failed, MCP unavailable), ask the user for their `agent_id` — do not invent one. See `tools-agent-id-conventions.md`.
112
+ Use the injected `conversation_id` and `agent_id` verbatim and inspect any preloaded memories. If injection is absent, do not invent values; ask for the missing identity or create a conversation only when the applicable workflow permits it.
172
113
 
173
114
  ### Before potentially destructive actions
174
115
 
175
- Before any action that deletes, overwrites, or restructures user content — `Write` overwriting an existing file, large `Edit` deletions, `rm` / `rm -rf`, `git reset --hard`, destructive SQL (`DROP`, `TRUNCATE`, `DELETE` without `WHERE`) — run a `memory_search` for relevant feedback:
116
+ When Meko is available and the user may have stored relevant preferences, search for them before deleting, overwriting, or restructuring user content:
176
117
 
177
118
  ```
178
119
  memory_search(query="destructive <action type> preferences feedback",
179
120
  agent_id=<your agent_id>, conversation_id=<session_conversation_id>)
180
121
  ```
181
122
 
182
- A single `memory_search` already covers everything you and other agents wrote for this user — `agent_id` doesn't filter memory reads. Also consider a `knowledgebase_search` for team-wide guidance if the action is one the team has promoted policy on.
183
-
184
- If a relevant feedback memory exists (e.g., "always ask before deleting content"), confirm with the user before proceeding. If the search is empty, proceed, but treat the action as irreversible and prefer a dry-run / preview when one is available.
123
+ A single search covers all of this user's agents. Memory is supplemental evidence, not authorization: a relevant preference can require more caution, but an empty search never authorizes destruction. Follow host approval rules and prefer previews.
185
124
 
186
125
  ### Capture rules
187
126
 
@@ -199,26 +138,39 @@ In the examples below, `<your-agent-id>` means the value the SessionStart hook i
199
138
  ### memory_add — correct call pattern
200
139
 
201
140
  Only for the three narrow cases in "When to call memory_add" above — not for facts the user stated in conversation (those are captured automatically). The example below is an explicit "remember this" save:
141
+
202
142
  ```
203
143
  memory_add(
204
144
  text="Remember: deploy scripts must be run from the repo root, never a subdir",
205
145
  agent_id="<your-agent-id>",
206
146
  conversation_id="<session_conversation_id>")
207
147
  ```
148
+
208
149
  Required parameters: `text`, `conversation_id`. On **writes**, `conversation_id` must be a real UUID (from `conversation_create` or the SessionStart hook) — writes attached to a nil/empty conversation are orphaned in Langfuse traces. NEVER pass `"current"` or other non-UUID values. `agent_id` is technically optional — empty/missing routes the write into the `meko_agent` common bucket — but for project-scoped facts pass the SessionStart-injected value verbatim.
209
150
 
151
+ **Write one coherent fact per memory**, with the identifiers a later search will use — never a transcript or multi-topic dump; focused memories retrieve better and read far faster.
152
+
210
153
  ### memory_search — correct call pattern
154
+
211
155
  ```
212
156
  memory_search(
213
157
  query="user role",
214
158
  agent_id="<your-agent-id>",
215
159
  conversation_id="<session_conversation_id>")
216
160
  ```
217
- Required parameters: `query`, `agent_id`, `conversation_id`. On **`memory_search`** specifically, `conversation_id` is used only for Langfuse trace nesting — it does NOT filter results. Pass the session's UUID so the search span appears under the active conversation in Observe; passing `""` is accepted and means "don't nest under any trace." For conversation-scoped filtering use the separate `run_id` parameter.
218
161
 
219
- `agent_id` does not filter what `memory_search` returns — a single call already surfaces everything you and every other agent wrote for this user in the datapack, including the `meko_agent` common bucket and any other project's rows. There's no need to repeat the search per agent_id. Use `run_id` if you want to narrow to a single conversation/run.
162
+ Required parameters: `query`, `agent_id`, `conversation_id`. On **`memory_search`** specifically, `conversation_id` is used only for Langfuse trace nesting — it does NOT filter results. Pass the session's UUID so the search span appears under the active conversation in Observe; passing `""` is accepted and means "don't nest under any trace."
163
+
164
+ `agent_id` does not filter what `memory_search` returns — one call covers every agent's rows for this user, including the `meko_agent` bucket (see Read scoping above).
165
+
166
+ Evidence going into reasoning follows operating contract 3 (retrieve ≤ ~25, pass ≤ ~10).
167
+
168
+ ### memory_get_all — recent-window pattern
169
+
170
+ Follow operating contract 2: a ~20-row recent window plus an honest `total` — no pagination, no completeness claims. Use targeted `memory_search` or `memory_get_by_id` instead.
220
171
 
221
172
  ### knowledgebase_search — correct call pattern
173
+
222
174
  ```
223
175
  knowledgebase_search(
224
176
  query="...",
@@ -227,13 +179,16 @@ knowledgebase_search(
227
179
  datapack_id="<datapack UUID>",
228
180
  limit=10)
229
181
  ```
182
+
230
183
  Required parameters: `query`, `agent_id`, `conversation_id`, `datapack_id`. `datapack_id` has no default here. `agent_id` is ignored for filtering — results are the team's shared knowledge on the datapack regardless of what you pass.
231
184
 
185
+ For recalling working memories — especially recently-changed facts — prefer `memory_search`; the knowledge base is the team's publish/archive surface.
186
+
232
187
  ### memory_promote — explicit confirmation required
233
188
 
234
- `memory_promote` is destructive and non-idempotent: it makes selected content visible to the datapack, moves the memories and graph context into shared knowledge, and evicts the private mem0 records. There is no MCP rollback.
189
+ `memory_promote` is destructive and non-idempotent: it makes selected content visible to the datapack, moves the memories into shared knowledge, and evicts the private records. There is no MCP rollback.
235
190
 
236
- 1. Use `memory_search` or `memory_get_all` to obtain exact memory UUIDs. Never pass relation or graph-edge IDs.
191
+ 1. Use `memory_search` or `memory_get_all` to obtain exact memory UUIDs from the `id` field. Never pass any other identifier.
237
192
  2. Present each exact candidate memory and its UUID to the user.
238
193
  3. State that promotion is one-way, team-visible, and removes the private records.
239
194
  4. Obtain explicit confirmation for those exact candidates before calling `memory_promote`.
@@ -246,7 +201,7 @@ The Cloud UI's Learnings tab remains an alternative user-driven path.
246
201
  ### Critical parameter rules
247
202
 
248
203
  - **agent_id**: Per-session value, injected via `additionalContext` by the SessionStart hook. Shape: `<client>:<repo-basename>`. Pass verbatim on project-scoped writes and reads. Pass `"meko_agent"` for the cross-project common bucket (or empty/omit — server rewrites empty to `meko_agent`). Ignored on `knowledgebase_search`. See `tools-agent-id-conventions.md`.
249
- - **conversation_id**: Behavior varies by tool. On write tools (`memory_add`, `conversation_add_message`) pass a real UUID from `conversation_create` or the SessionStart hook — a nil/empty value orphans the Langfuse trace. On `memory_search` it's used only for trace nesting (not for filtering), and empty-string is accepted; on `memory_get_all` and most read tools, still pass the session UUID when you have one. Never pass `"current"` or other non-UUID junk — only a real UUID or an intentionally empty string where the tool allows it.
204
+ - **conversation_id**: the conversation's ID *is* its trace ID, so every call carrying it becomes a span under that conversation in the Observe hub. On write tools (`memory_add`, `conversation_add_message`) pass a real UUID from `conversation_create` or the SessionStart hook — a nil/empty value orphans the trace. On `memory_search` it only nests the trace (it does not filter), and empty-string is accepted; on `memory_get_all` and most read tools, still pass the session UUID when you have one. Never pass `"current"` or other non-UUID junk.
250
205
  - **When in doubt about optional parameters, omit them.** The server has sensible defaults.
251
206
 
252
207
  ### Verify after writing
@@ -255,6 +210,7 @@ Never confirm a successful save to the user without first validating via a read-
255
210
 
256
211
  - **After `memory_add`**: call `memory_search` with a distinctive token from the stored text (a name, UUID, rare phrase — not a common word). Assert the new memory appears in the results. Only then tell the user it was saved.
257
212
  - **After `conversation_add_message`**: call `conversation_get(include_messages=true)` with the returned `conversation_id`. Assert `message_count` > 0 and that the new message is in the returned list.
213
+ - **After `artifact_put`**: operating contract 4 — the locally-computed SHA-256 must match the returned `content_hash` (a rate-limited or errored put carries **none**); read back important artifacts via `artifact_get` and compare bytes.
258
214
  - **On verification failure**: tell the user the save did not succeed — do **not** claim it did. Include the verification-failure detail (empty search, missing message, HTTP error) so they can act — wrong datapack, scope mismatch, expired API key are the common causes.
259
215
 
260
216
  ### First-run connection test
@@ -276,24 +232,15 @@ On the first Meko tool call in a fresh session (no prior Meko tool call since pr
276
232
 
277
233
  **Reporting.** This is user-visible — the whole point is to give the user concrete proof. On success: `"Meko connection OK (canary round-trip succeeded)"`. On failure, name the failing step and include the raw error: `"Meko canary failed at memory_add: <error>. Likely causes: wrong datapack, expired API key, server unreachable."`
278
234
 
279
- ## Key concepts
235
+ ## Budgeting calls
280
236
 
281
- 1. **23 tools in 6 groups**: Memory (8 — including `memory_promote`), Conversation (6), Knowledge Base (1 — `knowledgebase_search`), Datapack (5), Artifacts (2 — `artifact_put`, `artifact_get`), Observability (1 — `track_token_usage`). KB ingestion is UI-only (Datapack → Actions → Add Knowledge); raw SQL is not exposed. See `tools-overview.md`.
282
- 2. **datapack_id routing**: DB, RAG, and memory tools accept optional `datapack_id` (default datapack if omitted). `knowledgebase_search` is the exception: `datapack_id` is **required** there.
283
- 3. **agent_id is multi-agent**: Each client+project uses its own `agent_id` (shape `<client>:<repo-basename>`). Writes are attributed to `(datapack_id, user_id, agent_id)`. Personal **memory** reads (`memory_search`, `memory_get_all`) are NOT filtered by `agent_id` — one call returns all of your memories for this user across every agent, scoped to `(datapack_id, user_id)`. Empty/missing `agent_id` on a write lands in the `meko_agent` common bucket. `knowledgebase_search` ignores `agent_id` entirely and returns the team-shared knowledge on the datapack. See `tools-agent-id-conventions.md`.
284
- 4. **Personal memory vs. team-shared knowledge**: Un-promoted memories (`mem0_collection`) are scoped per-user — readable across all of your agents, but no other user can see them. With explicit confirmation, `memory_promote` moves exact memories into Shared Knowledge; the Cloud UI's Learnings tab is an alternative. Promoted content is visible to every datapack member (user_id filter stripped). `knowledgebase_search` is the MCP read path for both Shared Knowledge and uploaded documents. See `tools-memory-vs-conversation.md`.
285
- 5. **conversation_id IS the Langfuse trace ID**: every MCP tool call inside a conversation becomes a span under that trace. Observable in the Meko UI's Observe hub (`/observe-hub?project=<langfuse_pid>&session=<conversation_id>`) or directly from a datapack's Conversations tab via the **Open in Observe** button. See `tools-memory-vs-conversation.md`.
286
- 6. **Adding documents or growing a knowledge base is UI-only on Cloud today**: users upload files via Datapack → Actions → **Add Knowledge** (PDF/TXT/MD/JSON/MP4, 5MB each). The MCP ingestion tools are not available on Cloud. See `tools-rag-workflow.md`.
287
- 7. **Conversation dedup**: `conversation_add_message` supports seed-based deterministic trace IDs to prevent duplicates.
288
- 8. **Memory latencies are not cheap**: observed on prod 2026-05-07 — `memory_add` 12-21s/call (calls OpenAI), `memory_search` 2-6s/call. Budget accordingly.
289
- 9. **Known limitations**: see `tools-known-limitations.md` before attempting write operations on tools that appear in the catalog but aren't available on Cloud.
290
- 10. **Error recovery**: Connection errors are common with memory tools — see `tools-troubleshooting.md` for retry strategies and fallbacks.
237
+ `memory_add` takes ~10s for a one-line fact and ~20-30s for document-sized text; `memory_search` ~2-6s. Sustained bulk ingest throttles to roughly per-call latency — run large ingests as background jobs. `memory_search`, `knowledgebase_search`, and `memory_add` also draw from **lifetime per-user quotas** on Free/Standard tiers, so budget latency *and* call count. `datapack_id` is optional on most tools (default datapack) but **required** on `knowledgebase_search`. See `tools-known-limitations.md`.
291
238
 
292
239
  ## Reference sections
293
240
 
294
241
  | File | What it covers |
295
242
  |------|---------------|
296
- | `tools-overview.md` | Complete catalog of all 23 tools with decision tree |
243
+ | `tools-overview.md` | Complete catalog of all 23 tools available in production, with decision tree |
297
244
  | `tools-cookbook.md` | Per-tool examples with correct parameters, responses, and error cases |
298
245
  | `tools-memory-vs-conversation.md` | When to use memory tools vs conversation tools |
299
246
  | `tools-datapack-workflow.md` | Datapack lifecycle and datapack_id routing |
@@ -301,4 +248,4 @@ On the first Meko tool call in a fresh session (no prior Meko tool call since pr
301
248
  | `tools-agent-id-conventions.md` | Naming rules and constraints for agent_id |
302
249
  | `tools-conversation-dedup.md` | Seed-based trace deduplication |
303
250
  | `tools-troubleshooting.md` | Error recovery, retry strategies, stuck pipeline diagnosis |
304
- | `tools-known-limitations.md` | Broken tools, missing capabilities, permission gaps |
251
+ | `tools-known-limitations.md` | Lifetime quotas, the `memory_get_all` window, `run_id` scoping, missing capabilities |
@@ -6,7 +6,7 @@ description: Maps reference files to their topics for the meko-mcp-tools skill
6
6
  # Reference Sections
7
7
 
8
8
  ## Tool Selection & Catalog
9
- - [tools-overview.md](tools-overview.md) — Complete catalog of all 23 tools with a decision tree
9
+ - [tools-overview.md](tools-overview.md) — Complete catalog of all 23 tools available in production, with a decision tree
10
10
 
11
11
  ## Tool-Specific Guidance
12
12
  - [tools-memory-vs-conversation.md](tools-memory-vs-conversation.md) — Decision framework: memory_add vs conversation_create/conversation_add_message
@@ -26,4 +26,4 @@ description: Maps reference files to their topics for the meko-mcp-tools skill
26
26
 
27
27
  ## Troubleshooting & Limitations
28
28
  - [tools-troubleshooting.md](tools-troubleshooting.md) — Error recovery, retry strategies, stuck pipeline diagnosis
29
- - [tools-known-limitations.md](tools-known-limitations.md) — Broken tools, missing capabilities, permission gaps
29
+ - [tools-known-limitations.md](tools-known-limitations.md) — Lifetime quotas, the `memory_get_all` window, `run_id` scoping, missing capabilities
@@ -16,7 +16,7 @@ Each memory is written under an `agent_id` (stored on the row, shown as the UI b
16
16
 
17
17
  **Discover the value at session start.** The SessionStart hook injects the chosen `agent_id` into the first-turn `additionalContext` based on the cwd's repo basename. Use that value verbatim — do not re-derive it. If the block is absent, fall back to `<client>:<basename(cwd)>` or ask the user.
18
18
 
19
- For genuinely cross-project facts ("the user's name is Amiram", "the user prefers dark mode") write with `agent_id="meko_agent"` so their attribution clearly identifies the common cross-project bucket.
19
+ For genuinely cross-project facts ("the user's name is Alice", "the user prefers dark mode") write with `agent_id="meko_agent"` so their attribution clearly identifies the common cross-project bucket.
20
20
 
21
21
  **Pick a value that matches the running client — don't invent another client's shape.** A Claude Desktop session that writes with `agent_id="claude_code"` (or `claude_code:something`) creates rows the UI will attribute to Claude Code — a misleading badge for both clients. Use the pattern from the table that matches the client you're actually running under.
22
22
 
@@ -37,10 +37,8 @@ Pre-existing data in real datapacks includes a mix of legacy shapes — `agent`,
37
37
 
38
38
  Filter tuple: `(datapack_id, user_id)`. `agent_id` is **not** applied on memory reads.
39
39
 
40
- - `user_id` is **always enforced**: you can only see memories you wrote (or that other team members shared with you via promotion — see below). One user cannot read another team member's un-promoted memories directly from MCP.
41
- - `agent_id` does **not** filter results. A single `memory_search` returns your memories for this user across *every* `agent_id`: a memory written under `agent_id="cursor:foo"` IS returned by a search passing `agent_id="claude_code:meko-mcp-server"` — or empty, or any value. The tool passes `meko_agent_id=None` to mem0, so `agent_id` scopes only the Langfuse trace, not the result set. There is nothing to "fan out"; one call already sees all of your agents' memories (including the `meko_agent` common bucket).
42
-
43
- Empirically verified 2026-07-23 on Cloud prod: memories written under two distinct `agent_id`s were both returned by a `memory_search` passing a third, never-written `agent_id` (and by one passing empty string).
40
+ - `user_id` is **always enforced**: you can only see memories you wrote (or content shared via promotion). One user cannot read another's un-promoted memories from MCP.
41
+ - `agent_id` does **not** filter results: a memory written under `agent_id="cursor:foo"` IS returned to a search passing any other value. It scopes only the call's trace. One call sees all of your agents' memories, including the `meko_agent` bucket — nothing to fan out.
44
42
 
45
43
  ### Personal conversation reads — `conversation_get`, `conversation_list`
46
44
 
@@ -63,7 +61,7 @@ The originating `agent_id` is preserved in each result's `metadata_filters.agent
63
61
  memory_add(agent_id=X, text=...)
64
62
  │
65
63
  ▼
66
- mem0_collection ── personal memories, tagged (datapack, user, agent)
64
+ memory_store ── personal memories, tagged (datapack, user, agent)
67
65
  │
68
66
  │ memory_promote (exact UUIDs + explicit confirmation)
69
67
  │ or UI "Promote to Knowledge" (Learnings tab)
@@ -83,18 +81,19 @@ knowledgebase_search(agent_id=anything, query=...)
83
81
 
84
82
  ## When to use what — broad-query guidance
85
83
 
86
- If the user asks "what do you know about X?":
87
-
88
- 1. **`memory_search(agent_id="<your agent_id>", query="X")`** — returns all of your personal memories for this user, across every `agent_id` (your project bucket, the `meko_agent` common bucket, and any other project's rows). One call is the whole personal surface — `agent_id` doesn't filter memory reads, so there's nothing to fan out.
89
- 2. **`knowledgebase_search(agent_id="<anything>", datapack_id="<datapack>", query="X")`** — returns team-shared knowledge. Useful when the answer may have been promoted by the user or a teammate.
90
-
91
- Always tell the user what scope you searched, so they understand why the answer is or isn't there. Example wording: "I found this in your personal memories" vs. "I found this in your team's shared knowledge."
84
+ If the user asks "what do you know about X?": one `memory_search` covers the whole personal surface (every `agent_id`, nothing to fan out), then `knowledgebase_search` for team-shared knowledge. Tell the user which surface each finding came from.
92
85
 
93
86
  ## Optional sub-scoping
94
87
 
95
88
  Optional parameters can narrow a call further:
96
89
  - `user_id` — explicitly scope writes/reads to a specific end-user if your agent serves multiple (rare in Claude Code; more common in API products)
97
- - `run_id` — per-execution run
90
+ - `run_id` — on `memory_search` and the delete tools it is a **read/delete
91
+ filter** on the row's `meko_conversation_id`, so pass a *conversation id* to
92
+ scope the call to that conversation (consistent scoping landed in
93
+ MEKO-473/MEKO-474, #271). On `memory_add` it is Langfuse trace metadata only
94
+ and is not persisted as the conversation id, so scope writes with
95
+ `conversation_id` — a row written with `memory_add(run_id=X)` is not findable
96
+ via `memory_search(run_id=X)`.
98
97
 
99
98
  Available on `memory_add`, `memory_search`, `memory_get_all`, `memory_delete_all`, `conversation_create`, `conversation_list`.
100
99
 
@@ -8,7 +8,7 @@ Every tool example below shows the correct parameters, expected response, and co
8
8
 
9
9
  ## Memory Tools
10
10
 
11
- **Critical:** Pass your session's `agent_id` on every memory *write* (the value from the SessionStart `additionalContext`, e.g. `claude_code:meko-mcp-server`) — it is stored on the row and rendered as the UI badge. Note that `agent_id` labels writes but does **not** filter personal reads: a single `memory_search` / `memory_get_all` returns all of your memories for this user across every `agent_id` (see the `memory_search` note below). For genuinely cross-project facts, write with `agent_id="meko_agent"` so the row lands in the common bucket.
11
+ **Critical:** Pass your session's `agent_id` on every memory *write* (from the SessionStart `additionalContext`) — it is stored on the row as attribution. It does **not** filter reads: one `memory_search` / `memory_get_all` returns all of your memories across every `agent_id`. For cross-project facts, write with `agent_id="meko_agent"`.
12
12
 
13
13
  ### memory_add
14
14
 
@@ -22,12 +22,13 @@ memory_add(agent_id="<your-agent-id>",
22
22
 
23
23
  **Response:**
24
24
  ```json
25
- {"results": [{"id": "mem-uuid-123", "memory": "User Amiram is VP of Product at YugabyteDB. Prefers concise responses."}]}
25
+ {"results": [{"id": "mem-uuid-123", "memory": "Deploy scripts must be run from the repo root, never a subdir."}]}
26
26
  ```
27
27
 
28
28
  **What NOT to store via memory_add:**
29
29
  - Full conversations (use `conversation_create` + `conversation_add_message`)
30
30
  - Large documents (use the UI's Datapack → Actions → Add Knowledge upload flow)
31
+ - Multi-topic dumps (transcripts, mixed logs + decisions) — store **one coherent fact per memory**, with the identifiers a later search will use
31
32
 
32
33
  **Common errors:**
33
34
  - `syntax error at or near "-"` — legacy error from the pre-multi-tenancy schema when `agent_id` became part of a PostgreSQL identifier. No longer applies on Cloud (agent_id is a TEXT column value, any string is accepted). If you hit it on a deployment that still uses the old schema, use underscores instead of hyphens.
@@ -43,7 +44,9 @@ memory_add(agent_id="<your-agent-id>",
43
44
  memory_search(query="What programming language does the team use?", agent_id="agent", conversation_id="<uuid>")
44
45
  ```
45
46
 
46
- **Cross-conversation discovery.** `memory_search` returns hits across every stored conversation for the `(datapack_id, user_id)` pair, across all agents (the tool intentionally passes `meko_agent_id=None` to mem0, so the `agent_id` argument scopes the trace but does not filter results). When a hit references an interesting conversation, follow up with `conversation_list` to browse the associated threads and `conversation_get` to read a specific one — the memory hit's `meko_conversation_id` field is the id to fetch. Pass `run_id` on the search itself to narrow to a single conversation up front.
47
+ **Cross-conversation discovery.** `memory_search` returns hits across every stored conversation for the `(datapack_id, user_id)` pair, across all agents (`agent_id` scopes the call's trace, not the results). When a hit references an interesting conversation, follow up with `conversation_list` to browse the associated threads and `conversation_get` to read a specific one — the memory hit's `meko_conversation_id` field is the id to fetch. For a deliberately cross-conversation search leave `run_id` off; to scope a search to a single conversation instead, pass `run_id=<conversation_id>` (it filters on `meko_conversation_id` — see `tools-known-limitations.md`).
48
+
49
+ **Relevance floor.** Vector-matched `results` below `MEMORY_SEARCH_MIN_SCORE` (mem0's cosine-similarity score, default `0.5`) are dropped as weak matches rather than returned. A query can come back with fewer results than `limit`, or an empty list, when nothing clears the bar; that means no sufficiently relevant memory, not a broken call.
47
50
 
48
51
  **Response:**
49
52
  ```json
@@ -55,6 +58,8 @@ memory_search(query="What programming language does the team use?", agent_id="ag
55
58
  memory_search(query="user preferences", agent_id="agent", conversation_id="<uuid>", limit=5)
56
59
  ```
57
60
 
61
+ **Evidence cap (SKILL.md operating contract 3): reason over at most ~10 results, no matter how many were retrieved or requested.** If asked to "use everything," still select the ~10 most relevant and say that you did.
62
+
58
63
  ---
59
64
 
60
65
  ### memory_get_all
@@ -117,9 +122,7 @@ memory_promote(memory_ids=["mem-uuid-123", "mem-uuid-456"],
117
122
  {"inserted_ids": ["mem-uuid-123"], "updated_ids": ["mem-uuid-456"], "not_found_ids": []}
118
123
  ```
119
124
 
120
- Get exact UUIDs from the `id` field of `memory_search` / `memory_get_all` results; never use graph relation IDs. Before the call, show the user each exact memory and UUID, explain that promotion is team-visible, one-way, and evicts the private records, then obtain explicit confirmation for those candidates. Pass the active `conversation_id` and intended `agent_id` / `datapack_id`; on legacy schemas that expose `scope`, use `write`, not `admin`.
121
-
122
- On 403, authentication, or permission failure, report the error and stop — do not escalate scope, change datapacks, or alter identity. After a successful call, `knowledgebase_search` may verify shared visibility, but it is not a rollback mechanism.
125
+ Get exact UUIDs from the `id` field of `memory_search` / `memory_get_all` results (never any other identifier), and follow the confirmation checklist in SKILL.md before calling. On 403 or any auth failure, report and stop — never escalate scope, change datapacks, or alter identity.
123
126
 
124
127
  ---
125
128
 
@@ -145,8 +148,6 @@ conversation_create(agent_id="agent",
145
148
 
146
149
  **When to use:** Add a user/assistant exchange to an existing conversation. **All fields must be verbatim** — never summarize or rephrase.
147
150
 
148
- Leave `index_for_search` at its default (`False`). Conversation-cache embedding is currently a WorkbenchLM-only feature — the inference gateway opts in on its own turns; agent-harness conversations should not opt in.
149
-
150
151
  ```
151
152
  conversation_add_message(conversation_id="conv-uuid-123", agent_id="agent",
152
153
  input="Why is the auth middleware returning 401?",
@@ -225,7 +226,7 @@ knowledgebase_search(
225
226
 
226
227
  Unlike memory tools, `datapack_id` has no default — you must pass it explicitly.
227
228
 
228
- **Response (empty KB, verified 2026-05-07):**
229
+ **Response (empty KB):**
229
230
  ```json
230
231
  {"results": [], "count": 0}
231
232
  ```
@@ -267,6 +268,7 @@ Save the `content_hash` — it's the retrieval key for `artifact_get`.
267
268
  **Common errors:**
268
269
  - `invalid_base64` — `content_base64` is not valid base64; decode the file before passing it.
269
270
  - `artifact_too_large` — file exceeds 5 MiB (default). Set `MEKO_MAX_ARTIFACT_UPLOAD_BYTES` to raise the limit.
271
+ - `PAT_RATE_LIMITED` — burst uploads throttle; the error carries **no `content_hash`**, which mimics silent write loss. Pace bulk uploads, back off ~60s. The `content_hash` is the plain SHA-256 of the bytes — compute it locally and verify important artifacts with an `artifact_get` read-back.
270
272
 
271
273
  ---
272
274
 
@@ -321,20 +323,21 @@ For large files use the `local_path` value to read the file with normal file too
321
323
 
322
324
  ```
323
325
  datapack_create(name="analytics_prod")
324
- datapack_list() # returns datapack_id for each datapack
326
+ datapack_list(conversation_id="<session conversation id>") # returns datapack_id for each datapack
325
327
  datapack_describe(datapack_id="<uuid>", include_status=True)
326
328
  ```
327
329
 
328
330
  ### datapack_update / datapack_delete
329
331
 
330
- `datapack_update` renames or edits the description of a datapack. Both `name` and `description` are optional; pass at least one. If both are omitted the tool returns `nothing_to_update` without hitting the API.
332
+ `datapack_update` renames a datapack, edits its description, and/or opts it in/out of conversation-search embedding. `name`, `description`, and `conversation_search_opt_out` are all optional; pass at least one. If none are provided the tool returns `nothing_to_update` without hitting the API.
331
333
 
332
- The server refuses to rename the caller's `meko_default_datapack` — a rename call against that datapack returns `"meko_default_datapack cannot be renamed"`. Description edits on the default datapack are still allowed. Passing `description=""` does NOT clear an existing description; clearing is not supported via MCP.
334
+ The server refuses to rename the caller's `meko_default_datapack` — a rename call against that datapack returns `"meko_default_datapack cannot be renamed"`. Description edits on the default datapack are still allowed. Passing `description=""` does NOT clear an existing description; clearing is not supported via MCP. Conversation-search embedding is on by default; `conversation_search_opt_out=True` stops future turns from being indexed (already-cached turns are unaffected) and is restricted to the datapack's owner or a maintainer. This is best-effort, not a hard guarantee — a transient database error on the live embed path's opt-out check fails open, so a turn can occasionally still get embedded for an opted-out datapack.
333
335
 
334
336
  ```
335
337
  datapack_update(datapack_id="<uuid>", name="renamed-datapack")
336
338
  datapack_update(datapack_id="<uuid>", description="new description")
337
339
  datapack_update(datapack_id="<uuid>", name="x", description="y")
340
+ datapack_update(datapack_id="<uuid>", conversation_search_opt_out=True)
338
341
  datapack_delete(datapack_id="<uuid>") # Irreversible!
339
342
  ```
340
343
 
@@ -2,6 +2,30 @@
2
2
 
3
3
  These are current limitations of the Meko MCP tools. Know them upfront to avoid wasted tool calls.
4
4
 
5
+ ## Lifetime request quotas by tier
6
+
7
+ `memory_search`, `knowledgebase_search`, and `memory_add` are quota-gated **per user, lifetime** — not per minute or per day. Default caps by plan:
8
+
9
+ | Tier | memory_search | knowledgebase_search | memory_add |
10
+ |---|---:|---:|---:|
11
+ | Free | 1,000 | 1,000 | 10,000 |
12
+ | Standard | 5,000 | 5,000 | 30,000 |
13
+ | Pro / Enterprise | uncapped | uncapped | uncapped |
14
+
15
+ When the cap is reached the tool returns an error object with code `free_tier_limit_reached` (on every tier; the `tier` field names the capped tier) and **no `results` key**.
16
+
17
+ - **Do not retry** — the cap is lifetime.
18
+ - **Budget searches**: polling, verify read-backs, and per-item sweeps all draw from one pool.
19
+ - **Never report this error as "no results"** — it is a failed search; see `tools-troubleshooting.md`.
20
+
21
+ ## memory_get_all returns a fixed recent window — it has NO pagination
22
+
23
+ One call returns roughly the **20 most recent rows**; the response's `total` reports the true count. Scoping arguments do not narrow the window, and paging parameters are rejected — there is no way to reach older rows through this tool. A second call with `promoted=true` returns the recent window of promoted rows, not the remaining personal rows; neither call alone nor the two together is a complete listing. Follow SKILL.md operating contract 2: state the gap when `total` exceeds rows returned, never claim a complete enumeration, and use `memory_search` or `memory_get_by_id` for anything specific.
24
+
25
+ ## run_id is a read/delete filter on the conversation id, not a write key
26
+
27
+ `memory_search(run_id=<conversation_id>)` and the memory delete tools filter on the row's `meko_conversation_id`, so passing a conversation id there correctly scopes the call to that one conversation — a supported, reliable way to read a single conversation's memories (read/write/delete scoping was made consistent in MEKO-473/MEKO-474, #271). The one gotcha is on the write side: `memory_add`'s own `run_id` is Langfuse trace metadata only and is **not** persisted as the row's conversation id, so a row written with `memory_add(run_id=X)` is not findable via `memory_search(run_id=X)`. Scope writes with `conversation_id`, then filter the matching read by that same id.
28
+
5
29
  ## No delete tools for RAG artifacts
6
30
 
7
31
  There are no MCP tools to:
@@ -25,7 +49,7 @@ To **query** a built index, use `knowledgebase_search` — it returns both uploa
25
49
  `memory_add` passes text through Mem0's fact extraction pipeline. This works well for:
26
50
  - Facts: "Alice works at Acme Corp"
27
51
  - Preferences: "User prefers dark mode"
28
- - Entity relationships: "Amiram reports to Karthik"
52
+ - Entity relationships: "Alice reports to Bob"
29
53
 
30
54
  It works **poorly** for:
31
55
  - CSV rows or tabular data — columns and rows get dropped