@yugabytedb/meko-mcp 2.0.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 (65) hide show
  1. package/README.md +183 -33
  2. package/assets/hooks-handlers/codex-session-end.sh +13 -0
  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 +1653 -225
  8. package/assets/hooks-handlers/lib/checkpoint-timer.js +455 -50
  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 -24
  12. package/assets/hooks-handlers/session-start.sh +8 -1
  13. package/assets/hooks-handlers/test_checkpoint_timer.sh +162 -0
  14. package/assets/scripts/meko-statusline.sh +41 -1
  15. package/assets/scripts/package-desktop-skill.sh +32 -1
  16. package/assets/skills/meko-mcp-tools/SKILL.md +90 -137
  17. package/assets/skills/meko-mcp-tools/references/_sections.md +3 -5
  18. package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +31 -28
  19. package/assets/skills/meko-mcp-tools/references/tools-conversation-dedup.md +5 -7
  20. package/assets/skills/meko-mcp-tools/references/tools-conversation-reasoning.md +50 -0
  21. package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +69 -49
  22. package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +6 -6
  23. package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +29 -5
  24. package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +29 -92
  25. package/assets/skills/meko-mcp-tools/references/tools-overview.md +42 -40
  26. package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +1 -2
  27. package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +18 -11
  28. package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +10 -9
  29. package/assets/skills/meko-mcp-tools-desktop/SKILL.md +51 -44
  30. package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +6 -6
  31. package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +2 -2
  32. package/assets/skills/meko-mcp-tools-desktop/references/tools-agent-id-conventions.md +34 -25
  33. package/assets/skills/meko-mcp-tools-desktop/references/tools-conversation-reasoning.md +50 -0
  34. package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +63 -37
  35. package/assets/skills/meko-mcp-tools-desktop/references/tools-known-limitations.md +4 -4
  36. package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +19 -22
  37. package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +42 -40
  38. package/assets/skills/meko-mcp-tools-desktop/references/tools-rag-workflow.md +1 -2
  39. package/assets/skills/meko-mcp-tools-desktop/references/tools-troubleshooting.md +3 -17
  40. package/assets/skills/meko-select-datapack-desktop/SKILL.md +31 -21
  41. package/assets/skills/meko-select-datapack-desktop/references/cookbook.md +8 -8
  42. package/assets/skills/meko-select-datapack-desktop/references/role-display-future.md +41 -0
  43. package/assets/skills/meko-select-datapack-desktop/references/troubleshooting.md +1 -1
  44. package/bin/create-meko-setup.mjs +93 -16
  45. package/lib/capture-status.mjs +67 -0
  46. package/lib/clients/aliases.mjs +5 -0
  47. package/lib/clients/claude-code.mjs +8 -4
  48. package/lib/clients/claude-desktop.mjs +133 -4
  49. package/lib/clients/codex.mjs +29 -11
  50. package/lib/clients/common.mjs +2 -0
  51. package/lib/clients/cursor.mjs +7 -2
  52. package/lib/clients/index.mjs +2 -0
  53. package/lib/clients/kiro.mjs +705 -0
  54. package/lib/config.mjs +90 -0
  55. package/lib/detect.mjs +7 -2
  56. package/lib/installer.mjs +1 -0
  57. package/lib/migrate/adapters/codex.mjs +490 -0
  58. package/lib/migrate/id.mjs +28 -3
  59. package/lib/migrate/orchestrator.mjs +34 -7
  60. package/lib/migrate.mjs +4 -2
  61. package/lib/prompt.mjs +17 -2
  62. package/lib/url-selection.mjs +55 -0
  63. package/package.json +4 -4
  64. package/assets/skills/meko-mcp-tools/references/tools-scope-permissions.md +0 -71
  65. package/assets/skills/meko-mcp-tools-desktop/references/tools-scope-permissions.md +0 -71
@@ -4,13 +4,13 @@
4
4
 
5
5
  When MCP clients have built-in Langfuse hooks (Cursor, Claude Code), both the client hook and the MCP server may write a trace for the same message → duplicate traces, doubled message counts, corrupted conversation retrieval.
6
6
 
7
- **WRONG:** Neither `seed` nor `trace_id` provided → both sides generate random IDs → two traces per message.
7
+ **WRONG:** No `seed` provided → both sides generate random trace IDs → two traces per message.
8
8
 
9
9
  ## Solution: Use seed for deterministic trace IDs
10
10
 
11
11
  ```
12
12
  conversation_add_message(
13
- scope="write", conversation_id="conv-uuid", agent_id="my_agent",
13
+ conversation_id="conv-uuid", agent_id="my_agent",
14
14
  input="What is our Q3 revenue?",
15
15
  output="Q3 revenue was $4.2M, up 15% from Q2.",
16
16
  seed="conv-uuid:my_agent:What is our Q3 revenue?"
@@ -19,11 +19,10 @@ conversation_add_message(
19
19
 
20
20
  Both sides hash the same seed string to produce the same trace ID. Langfuse treats the second write as an upsert → exactly one trace.
21
21
 
22
- ## Priority Rules
22
+ ## Trace ID Rules
23
23
 
24
- 1. **`trace_id`** — if provided, used directly (highest precedence)
25
- 2. **`seed`** — if provided, hashed to produce deterministic trace ID
26
- 3. **Neither** — random trace ID generated
24
+ 1. **`seed`** — if provided, hashed to produce a deterministic trace ID
25
+ 2. **Not provided** — a random trace ID is generated
27
26
 
28
27
  ## Choosing a Good Seed
29
28
 
@@ -41,7 +40,6 @@ seed = f"{conversation_id}:{agent_id}:{message_index}"
41
40
  |----------|-----|
42
41
  | Client hook + MCP server both write to Langfuse | `seed` |
43
42
  | Only the MCP server writes (no client hook) | Neither (random is fine) |
44
- | Migrating from another system with existing IDs | `trace_id` |
45
43
  | Replaying messages idempotently | `seed` |
46
44
 
47
45
  ## session_id on conversation_create
@@ -0,0 +1,50 @@
1
+ # Authoring `reasoning` and `plan` on `conversation_add_message`
2
+
3
+ `conversation_add_message` accepts two optional fields — `reasoning` and `plan` — that capture *why* the assistant replied the way it did and *what* concrete steps it took. They are stored side-by-side on the per-turn `Reasoning` observation in Langfuse, independently, so consumers can read or render either one on its own.
4
+
5
+ Provide them on the large majority of substantive turns. Skip both only for genuinely trivial acknowledgements (a one-word reply, a pure restatement). Do not fabricate deliberation — but in practice, almost every substantive reply has at least a one-line *why* and a one-step plan.
6
+
7
+ ## `reasoning`
8
+
9
+ A short paragraph (1–3 sentences) of the **why**. Plain English. Explain which trade-off you weighed, which user fact tipped the decision, why this answer beat the alternatives. Inline markdown (`**bold**`, `*italics*`, `` `code` ``) is fine.
10
+
11
+ Do NOT include a `**Plan:**` heading inside `reasoning` — put steps in the `plan` field instead.
12
+
13
+ ## `plan`
14
+
15
+ A list of 2 to 4 concrete actions taken for this turn. Each entry is a single imperative sentence, like a checklist item. Pass a list of strings.
16
+
17
+ Do NOT pre-number entries. Do NOT include a `**Plan:**` heading inside the strings — `plan` is stored as a structured array on the observation's `metadata.plan`, independent of `reasoning`.
18
+
19
+ ## Two examples
20
+
21
+ ### Example A — database recommendation
22
+
23
+ ```
24
+ reasoning:
25
+ "The user cares about low latency and predictable cost.
26
+ Option A wins on latency but costs more per month; option
27
+ B is cheaper but adds 30 ms p99. Latency was their top
28
+ priority, so I picked Option A."
29
+
30
+ plan: [
31
+ "Recommend Option A and call out the latency advantage.",
32
+ "Show the monthly cost delta in clear numbers.",
33
+ "Flag the cost difference so the user can decide if it fits."
34
+ ]
35
+ ```
36
+
37
+ ### Example B — book pick for a long flight
38
+
39
+ ```
40
+ reasoning:
41
+ "The user wants a non-fiction book for a six-hour flight
42
+ and does not enjoy business memoirs. *Sapiens* fits the
43
+ time slot, is non-fiction, and is not a memoir."
44
+
45
+ plan: [
46
+ "Recommend *Sapiens* as the main pick.",
47
+ "Offer *Bad Blood* as a non-memoir backup.",
48
+ "Skip founder memoirs per the user's stated dislike."
49
+ ]
50
+ ```
@@ -1,38 +1,34 @@
1
1
  # Tool Cookbook — Complete Usage Examples
2
2
 
3
- Every tool example below shows the correct parameters, expected response, and common errors. Use `scope="read"` for reads and `scope="write"` for writes — never `"all"` or any other value.
3
+ Every tool example below shows the correct parameters, expected response, and common errors.
4
4
 
5
- > **Note on `agent_id` in the examples below.** Where you see `agent_id="agent"` in an example, substitute **your** session's `agent_id` — the value the SessionStart hook injected into `additionalContext`. For Claude Code that's `claude_code:<repo-basename>` (e.g. `claude_code:meko-mcp-server`); for Cursor, `cursor:<repo-basename>`; for Claude Desktop, the bare client name `claude_desktop`. For genuinely cross-project facts (user identity, global preferences) write/read with `agent_id="meko_agent"` — the common bucket the server stores empty/missing values into. See `tools-agent-id-conventions.md`.
5
+ > **Note on `agent_id` in the examples below.** Where you see `agent_id="agent"` in an example, substitute **your** session's `agent_id` — the value the SessionStart hook injected into `additionalContext`. For Claude Code that's `claude_code:<repo-basename>` (e.g. `claude_code:meko-mcp-server`); for Cursor, `cursor:<repo-basename>`; for Claude Desktop, the bare client name `claude_desktop`. For genuinely cross-project facts (user identity, global preferences) write with `agent_id="meko_agent"` — the common bucket the server stores empty/missing values into. See `tools-agent-id-conventions.md`.
6
6
 
7
7
  ---
8
8
 
9
9
  ## Memory Tools
10
10
 
11
- **Critical:** Pass your session's `agent_id` on every memory call (the value from the SessionStart `additionalContext`, e.g. `claude_code:meko-mcp-server`). Personal writes are scoped strictly by `agent_id` — other agents won't see your writes on personal reads unless they pass the same exact value. For genuinely cross-project facts, write with `agent_id="meko_agent"` so any agent can pick them up.
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
 
15
15
  **When to use:** NOT for facts the user states in conversation — those are saved automatically by conversation capture + server-side extraction. Reserve `memory_add` for the three cases extraction can't reach: (1) the user explicitly says "remember this"; (2) a durable fact that lives only in your output or a tool result, never in a user turn; (3) overwriting a negated/corrected fact (pair with `memory_delete_by_id`, since extraction is additive).
16
16
 
17
17
  ```
18
- memory_add(scope="write", agent_id="<your-agent-id>",
18
+ memory_add(agent_id="<your-agent-id>",
19
+ conversation_id="<uuid from conversation_create or the SessionStart hook>",
19
20
  text="Remember: deploy scripts must be run from the repo root, never a subdir.")
20
21
  ```
21
22
 
22
23
  **Response:**
23
24
  ```json
24
- {"results": [{"id": "mem-uuid-123", "memory": "User Amiram is VP of Product at YugabyteDB. Prefers concise responses."}]}
25
- ```
26
-
27
- **With user scoping:**
28
- ```
29
- memory_add(scope="write", agent_id="agent", user_id="amiram",
30
- text="Prefers Python for backend, Go for infrastructure.")
25
+ {"results": [{"id": "mem-uuid-123", "memory": "Deploy scripts must be run from the repo root, never a subdir."}]}
31
26
  ```
32
27
 
33
28
  **What NOT to store via memory_add:**
34
29
  - Full conversations (use `conversation_create` + `conversation_add_message`)
35
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
36
32
 
37
33
  **Common errors:**
38
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.
@@ -45,9 +41,13 @@ memory_add(scope="write", agent_id="agent", user_id="amiram",
45
41
  **When to use:** Find relevant memories by meaning. Always try this before asking the user to repeat information.
46
42
 
47
43
  ```
48
- memory_search(scope="read", query="What programming language does the team use?", agent_id="agent")
44
+ memory_search(query="What programming language does the team use?", agent_id="agent", conversation_id="<uuid>")
49
45
  ```
50
46
 
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.
50
+
51
51
  **Response:**
52
52
  ```json
53
53
  {"results": [{"id": "mem-uuid-123", "memory": "Team uses Python for backend", "score": 0.89}]}
@@ -55,22 +55,19 @@ memory_search(scope="read", query="What programming language does the team use?"
55
55
 
56
56
  **With limit:**
57
57
  ```
58
- memory_search(scope="read", query="user preferences", agent_id="agent", limit=5)
58
+ memory_search(query="user preferences", agent_id="agent", conversation_id="<uuid>", limit=5)
59
59
  ```
60
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
+
61
63
  ---
62
64
 
63
65
  ### memory_get_all
64
66
 
65
- **When to use:** List everything stored for an agent. Useful at session start to load context.
67
+ **When to use:** List all of your memories for this user — across every `agent_id` (`agent_id` does not filter the result). Useful at session start to load context.
66
68
 
67
69
  ```
68
- memory_get_all(scope="read", agent_id="agent")
69
- ```
70
-
71
- **With user scoping:**
72
- ```
73
- memory_get_all(scope="read", agent_id="agent", user_id="amiram")
70
+ memory_get_all(agent_id="agent", conversation_id="<uuid>")
74
71
  ```
75
72
 
76
73
  ---
@@ -78,7 +75,7 @@ memory_get_all(scope="read", agent_id="agent", user_id="amiram")
78
75
  ### memory_get_by_id
79
76
 
80
77
  ```
81
- memory_get_by_id(scope="read", memory_id="mem-uuid-123", agent_id="agent")
78
+ memory_get_by_id(memory_id="mem-uuid-123", agent_id="agent", conversation_id="<uuid>")
82
79
  ```
83
80
 
84
81
  ---
@@ -88,7 +85,7 @@ memory_get_by_id(scope="read", memory_id="mem-uuid-123", agent_id="agent")
88
85
  **When to use:** Overwrite a specific memory's text. Requires the memory UUID.
89
86
 
90
87
  ```
91
- memory_update(scope="write", memory_id="mem-uuid-123", text="Updated: Team uses Go for all new services", agent_id="agent")
88
+ memory_update(memory_id="mem-uuid-123", text="Updated: Team uses Go for all new services", agent_id="agent", conversation_id="<uuid>")
92
89
  ```
93
90
 
94
91
  ---
@@ -96,21 +93,39 @@ memory_update(scope="write", memory_id="mem-uuid-123", text="Updated: Team uses
96
93
  ### memory_delete_by_id
97
94
 
98
95
  ```
99
- memory_delete_by_id(scope="write", memory_id="mem-uuid-123", agent_id="agent")
96
+ memory_delete_by_id(memory_id="mem-uuid-123", agent_id="agent", conversation_id="<uuid>")
100
97
  ```
101
98
 
102
99
  ---
103
100
 
104
101
  ### memory_delete_all
105
102
 
106
- **Destructive. Requires admin scope.** Deletes all memories for the agent.
103
+ **Destructive.** Deletes all memories for the agent. For removing a single memory, prefer `memory_delete_by_id` — `memory_delete_all` wipes the entire agent scope in the datapack.
107
104
 
108
105
  ```
109
- memory_delete_all(scope="admin", agent_id="agent")
106
+ memory_delete_all(agent_id="agent", conversation_id="<uuid>")
110
107
  ```
111
108
 
112
109
  ---
113
110
 
111
+ ### memory_promote
112
+
113
+ **When to use:** The user asks to share or promote specific memories to the team's knowledge base — the MCP counterpart of the Cloud UI's "Promote to Knowledge" flow. One-way: promoted memories become team-visible via `knowledgebase_search` and are evicted from the private memory store. Requires the caller to be a datapack **owner or maintainer**; viewers and contributors get a 403 permission error.
114
+
115
+ ```
116
+ memory_promote(memory_ids=["mem-uuid-123", "mem-uuid-456"],
117
+ agent_id="agent", conversation_id="<uuid from conversation_create>")
118
+ ```
119
+
120
+ **Response:**
121
+ ```json
122
+ {"inserted_ids": ["mem-uuid-123"], "updated_ids": ["mem-uuid-456"], "not_found_ids": []}
123
+ ```
124
+
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.
126
+
127
+ ---
128
+
114
129
  ## Conversation Tools
115
130
 
116
131
  ### conversation_create
@@ -118,7 +133,7 @@ memory_delete_all(scope="admin", agent_id="agent")
118
133
  **When to use:** Start storing a multi-turn exchange. Do this when the session contains valuable dialog worth preserving.
119
134
 
120
135
  ```
121
- conversation_create(scope="write", agent_id="agent", user_id="amiram",
136
+ conversation_create(agent_id="agent",
122
137
  title="Debugging the auth middleware")
123
138
  ```
124
139
 
@@ -133,23 +148,19 @@ conversation_create(scope="write", agent_id="agent", user_id="amiram",
133
148
 
134
149
  **When to use:** Add a user/assistant exchange to an existing conversation. **All fields must be verbatim** — never summarize or rephrase.
135
150
 
136
- Pass `index_for_search=True` on substantive turns so this conversation is embedded into the shared conversation-history cache (searchable later via `conversation_search` / `contextual_prominence_search`). This isn't limited to WorkbenchLM — pass it for agent-harness conversations too.
137
-
138
151
  ```
139
- conversation_add_message(scope="write", conversation_id="conv-uuid-123", agent_id="agent",
152
+ conversation_add_message(conversation_id="conv-uuid-123", agent_id="agent",
140
153
  input="Why is the auth middleware returning 401?",
141
154
  output="The token validation is checking the wrong issuer claim...",
142
- reasoning="Checked the middleware source, found issuer mismatch between config and JWT...",
143
- index_for_search=True)
155
+ reasoning="Checked the middleware source, found issuer mismatch between config and JWT...")
144
156
  ```
145
157
 
146
158
  **With dedup seed (use when client hooks also write to Langfuse):**
147
159
  ```
148
- conversation_add_message(scope="write", conversation_id="conv-uuid-123", agent_id="agent",
160
+ conversation_add_message(conversation_id="conv-uuid-123", agent_id="agent",
149
161
  input="Why is the auth middleware returning 401?",
150
162
  output="The token validation is checking the wrong issuer claim...",
151
- seed="conv-uuid-123:agent:Why is the auth middleware returning 401?",
152
- index_for_search=True)
163
+ seed="conv-uuid-123:agent:Why is the auth middleware returning 401?")
153
164
  ```
154
165
 
155
166
  ---
@@ -157,7 +168,7 @@ conversation_add_message(scope="write", conversation_id="conv-uuid-123", agent_i
157
168
  ### conversation_get
158
169
 
159
170
  ```
160
- conversation_get(scope="read", conversation_id="conv-uuid-123", agent_id="agent",
171
+ conversation_get(conversation_id="conv-uuid-123", agent_id="agent",
161
172
  include_messages=True, limit=50)
162
173
  ```
163
174
 
@@ -165,8 +176,12 @@ conversation_get(scope="read", conversation_id="conv-uuid-123", agent_id="agent"
165
176
 
166
177
  ### conversation_list
167
178
 
179
+ Target the datapack by `datapack_id` (UUID). It's optional — omit it to use the
180
+ pinned/default datapack, or pass the pinned `datapack_id`. Use `datapack_list`
181
+ to look up the id.
182
+
168
183
  ```
169
- conversation_list(scope="read", agent_id="agent", limit=20)
184
+ conversation_list(datapack_id="<datapack-uuid>", agent_id="agent", limit=20)
170
185
  ```
171
186
 
172
187
  ---
@@ -174,7 +189,7 @@ conversation_list(scope="read", agent_id="agent", limit=20)
174
189
  ### conversation_update
175
190
 
176
191
  ```
177
- conversation_update(scope="write", conversation_id="conv-uuid-123", agent_id="agent",
192
+ conversation_update(conversation_id="conv-uuid-123", agent_id="agent",
178
193
  title="Resolved: Auth middleware issuer mismatch")
179
194
  ```
180
195
 
@@ -182,10 +197,10 @@ conversation_update(scope="write", conversation_id="conv-uuid-123", agent_id="ag
182
197
 
183
198
  ### conversation_delete
184
199
 
185
- **Destructive. Requires admin scope.**
200
+ **Destructive.**
186
201
 
187
202
  ```
188
- conversation_delete(scope="admin", conversation_id="conv-uuid-123", agent_id="agent")
203
+ conversation_delete(conversation_id="conv-uuid-123", agent_id="agent")
189
204
  ```
190
205
 
191
206
  ---
@@ -202,7 +217,6 @@ See `tools-rag-workflow.md` for the decision table.
202
217
 
203
218
  ```
204
219
  knowledgebase_search(
205
- scope="read",
206
220
  query="natural-language question",
207
221
  agent_id="agent",
208
222
  conversation_id="<uuid from conversation_create>",
@@ -212,7 +226,7 @@ knowledgebase_search(
212
226
 
213
227
  Unlike memory tools, `datapack_id` has no default — you must pass it explicitly.
214
228
 
215
- **Response (empty KB, verified 2026-05-07):**
229
+ **Response (empty KB):**
216
230
  ```json
217
231
  {"results": [], "count": 0}
218
232
  ```
@@ -229,7 +243,6 @@ Populated KBs return results with chunk content and similarity scores. An empty/
229
243
 
230
244
  ```
231
245
  artifact_put(
232
- scope="write",
233
246
  filename="analysis_report.csv",
234
247
  content_type="text/csv",
235
248
  content_base64="<base64-encoded bytes>",
@@ -255,6 +268,7 @@ Save the `content_hash` — it's the retrieval key for `artifact_get`.
255
268
  **Common errors:**
256
269
  - `invalid_base64` — `content_base64` is not valid base64; decode the file before passing it.
257
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.
258
272
 
259
273
  ---
260
274
 
@@ -265,7 +279,6 @@ Save the `content_hash` — it's the retrieval key for `artifact_get`.
265
279
  **Small files (< 1 MB) — content returned inline:**
266
280
  ```
267
281
  artifact_get(
268
- scope="read",
269
282
  content_hash="a665a45920422f9d417e4867efdc4fb8a5f1f89ea5b8440b1ad4c4c6b8a7e4d3",
270
283
  conversation_id="<uuid from conversation_create>",
271
284
  agent_id="agent"
@@ -309,16 +322,23 @@ For large files use the `local_path` value to read the file with normal file too
309
322
  ### datapack_create / datapack_list / datapack_describe
310
323
 
311
324
  ```
312
- datapack_create(scope="write", name="analytics_prod")
313
- datapack_list(scope="read") # returns datapack_id for each datapack
314
- datapack_describe(scope="read", datapack_id="<uuid>", include_status=True)
325
+ datapack_create(name="analytics_prod")
326
+ datapack_list(conversation_id="<session conversation id>") # returns datapack_id for each datapack
327
+ datapack_describe(datapack_id="<uuid>", include_status=True)
315
328
  ```
316
329
 
317
330
  ### datapack_update / datapack_delete
318
331
 
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.
333
+
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.
335
+
319
336
  ```
320
- datapack_update(scope="write", datapack_id="<uuid>", connection_string="postgresql://...")
321
- datapack_delete(scope="admin", datapack_id="<uuid>") # Irreversible!
337
+ datapack_update(datapack_id="<uuid>", name="renamed-datapack")
338
+ datapack_update(datapack_id="<uuid>", description="new description")
339
+ datapack_update(datapack_id="<uuid>", name="x", description="y")
340
+ datapack_update(datapack_id="<uuid>", conversation_search_opt_out=True)
341
+ datapack_delete(datapack_id="<uuid>") # Irreversible!
322
342
  ```
323
343
 
324
344
  ### Agent and knowledge-base management (NOT MCP — control-plane only)
@@ -326,6 +346,6 @@ datapack_delete(scope="admin", datapack_id="<uuid>") # Irreversible!
326
346
  Agent and KB lifecycle does not ship as MCP tools. If the user asks to create/list/delete agents or KB sources, don't invent a tool call — point them at the control plane:
327
347
 
328
348
  - REST: `POST/GET/DELETE /datapacks/:datapack_id/agents` (agents), `POST/GET/DELETE /datapacks/:datapack_id/knowledge-bases` (KB sources).
329
- - Or the Meko UI at `app.mekodev.com` → Datapacks → agents / knowledge-bases.
349
+ - Or the Meko Cloud UI at `cloud.mekodata.ai` → Datapacks → agents / knowledge-bases.
330
350
 
331
351
  KB ingestion specifically lives in the UI today: Datapack → Actions → **Add Knowledge** (PDF/TXT/MD/JSON/MP4, 5 MB each, 10/batch). Agents querying a populated index use `knowledgebase_search` — see `tools-rag-workflow.md`.
@@ -22,8 +22,8 @@ Datapacks are isolated workspaces — each has its own memory store and knowledg
22
22
  ### Creation
23
23
 
24
24
  ```
25
- datapack_create(scope="write", agent_id="<your agent_id>",
26
- conversation_id="<uuid>", name="sales_analytics")
25
+ datapack_create(name="sales_analytics",
26
+ conversation_id="<uuid>")
27
27
  -- Returns: {"datapack_id": "dp-uuid-123", "datapack_name": "sales_analytics", ...}
28
28
  ```
29
29
 
@@ -37,20 +37,20 @@ If the user asks to set those up mid-session, point them at the control plane ra
37
37
  ### Targeting a specific datapack on subsequent calls
38
38
 
39
39
  ```
40
- memory_search(scope="read", agent_id="<your-agent-id>",
40
+ memory_search(agent_id="<your-agent-id>",
41
41
  conversation_id="<uuid>", query="...", datapack_id="dp-uuid-123")
42
- knowledgebase_search(scope="read", agent_id="<your-agent-id>",
42
+ knowledgebase_search(agent_id="<your-agent-id>",
43
43
  conversation_id="<uuid>", datapack_id="dp-uuid-123", query="...")
44
44
  ```
45
45
 
46
- ### Teardown (requires admin scope)
46
+ ### Teardown
47
47
 
48
48
  Delete child resources first (agents and KB sources via the control plane), then the datapack:
49
49
 
50
50
  ```
51
51
  # Control-plane (REST or UI): DELETE /datapacks/:datapack_id/knowledge-bases
52
52
  # Control-plane (REST or UI): DELETE /datapacks/:datapack_id/agents/sales_agent
53
- datapack_delete(scope="admin", datapack_id="dp-uuid-123") # MCP-exposed, destructive, irreversible
53
+ datapack_delete(datapack_id="dp-uuid-123") # MCP-exposed, destructive, irreversible
54
54
  ```
55
55
 
56
56
  ## Common mistake: forgetting datapack_id on memory tools
@@ -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
@@ -36,7 +60,7 @@ It works **poorly** for:
36
60
 
37
61
  1. **Write a single narrative summary** as a memory — one call, not row-by-row:
38
62
  ```
39
- memory_add(scope="write",
63
+ memory_add(
40
64
  agent_id="<your session agent_id>",
41
65
  conversation_id="<session conversation_id>",
42
66
  text="Customer Complaints dataset has fields: Complaint ID (int PK), Date Submitted (date), Product (text, e.g. Mortgage/Credit Card), Sub-product (text), Issue (text), Company Response (text), State (text, 2-letter code), ZIP Code (text)")
@@ -46,8 +70,8 @@ It works **poorly** for:
46
70
 
47
71
  Never ingest CSV row-by-row into memory — each row becomes a fragmented fact with lost context.
48
72
 
49
- ## No conversation search
73
+ ## No semantic search over conversation content
50
74
 
51
- `conversation_list` returns conversations by agent, but there is no semantic search across conversation content. To find a specific past exchange, you need to list conversations and inspect them individually with `conversation_get`.
75
+ Semantic (meaning-based) search across stored conversation content is not part of the public tool surface today. To find a past conversation, browse with `conversation_list` (by datapack) and inspect candidates with `conversation_get`.
52
76
 
53
- For finding past knowledge by meaning, use `memory_search` instead — which is why storing key facts via `memory_add` alongside conversations is important.
77
+ For finding past knowledge by meaning, `memory_search` remains the most reliable path — which is why storing key facts via `memory_add` alongside conversations is important.