@yugabytedb/meko-mcp 1.2.0 → 2.1.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 (57) hide show
  1. package/README.md +59 -25
  2. package/assets/hooks-handlers/before-submit-prompt.sh +2 -2
  3. package/assets/hooks-handlers/codex-session-end.sh +78 -0
  4. package/assets/hooks-handlers/lib/capture.js +366 -152
  5. package/assets/hooks-handlers/lib/checkpoint-timer.js +67 -13
  6. package/assets/hooks-handlers/session-end.sh +10 -0
  7. package/assets/hooks-handlers/session-start.sh +14 -3
  8. package/assets/hooks-handlers/test_checkpoint_timer.sh +162 -0
  9. package/assets/scripts/meko-statusline.sh +119 -0
  10. package/assets/scripts/package-desktop-skill.sh +64 -30
  11. package/assets/skills/meko-mcp-tools/SKILL.md +84 -86
  12. package/assets/skills/meko-mcp-tools/references/_sections.md +2 -4
  13. package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +29 -25
  14. package/assets/skills/meko-mcp-tools/references/tools-conversation-dedup.md +5 -7
  15. package/assets/skills/meko-mcp-tools/references/tools-conversation-reasoning.md +50 -0
  16. package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +126 -184
  17. package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +31 -37
  18. package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +10 -26
  19. package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +26 -30
  20. package/assets/skills/meko-mcp-tools/references/tools-overview.md +60 -66
  21. package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +28 -93
  22. package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +5 -99
  23. package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +9 -8
  24. package/assets/skills/meko-mcp-tools-desktop/SKILL.md +138 -138
  25. package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +46 -16
  26. package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +2 -2
  27. package/assets/skills/meko-mcp-tools-desktop/references/tools-agent-id-conventions.md +28 -24
  28. package/assets/skills/meko-mcp-tools-desktop/references/tools-conversation-reasoning.md +50 -0
  29. package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +120 -174
  30. package/assets/skills/meko-mcp-tools-desktop/references/tools-known-limitations.md +16 -22
  31. package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +28 -34
  32. package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +60 -66
  33. package/assets/skills/meko-mcp-tools-desktop/references/tools-rag-workflow.md +28 -93
  34. package/assets/skills/meko-mcp-tools-desktop/references/tools-troubleshooting.md +4 -98
  35. package/assets/skills/meko-select-datapack-desktop/SKILL.md +208 -0
  36. package/assets/skills/meko-select-datapack-desktop/references/cookbook.md +121 -0
  37. package/assets/skills/meko-select-datapack-desktop/references/role-display-future.md +41 -0
  38. package/assets/skills/meko-select-datapack-desktop/references/troubleshooting.md +66 -0
  39. package/bin/create-meko-setup.mjs +74 -6
  40. package/lib/clients/claude-code.mjs +137 -6
  41. package/lib/clients/claude-desktop.mjs +51 -12
  42. package/lib/clients/codex.mjs +329 -13
  43. package/lib/clients/common.mjs +43 -1
  44. package/lib/clients/cursor.mjs +82 -21
  45. package/lib/config.mjs +26 -0
  46. package/lib/detect.mjs +7 -2
  47. package/lib/installer.mjs +24 -0
  48. package/lib/mcp-transport.mjs +5 -0
  49. package/lib/prompt.mjs +1 -1
  50. package/lib/url-selection.mjs +55 -0
  51. package/lib/validate.mjs +0 -1
  52. package/package.json +1 -1
  53. package/scripts/bundle-assets.mjs +8 -0
  54. package/assets/skills/meko-mcp-tools/references/tools-db-query-patterns.md +0 -38
  55. package/assets/skills/meko-mcp-tools/references/tools-scope-permissions.md +0 -75
  56. package/assets/skills/meko-mcp-tools/references/tools-write-guardrails.md +0 -30
  57. package/assets/skills/meko-mcp-tools-desktop/references/tools-scope-permissions.md +0 -75
@@ -1,113 +1,23 @@
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`.
6
- >
7
- > **Note on availability on Cloud.** The `db_*` tools and the three KB ingestion tools (`knowledgebase_trigger_index_creation`, `knowledgebase_add_source_to_index`, `knowledgebase_check_index_status`) return `{"error": "not_available"}` on Cloud Meko today. This cookbook keeps their examples for reference but you can't call them from a Cloud client.
8
-
9
- ---
10
-
11
- ## Database Tools
12
-
13
- ### db_summarize_database
14
-
15
- **When to use:** First thing in a session to understand what's in the database. Prefer this over writing your own `information_schema` query.
16
-
17
- ```
18
- db_summarize_database(scope="read", schema="public")
19
- ```
20
-
21
- **Response:**
22
- ```json
23
- [
24
- {
25
- "table_name": "customers",
26
- "schema": [
27
- {"column_name": "id", "data_type": "uuid"},
28
- {"column_name": "name", "data_type": "text"}
29
- ],
30
- "row_count": 1523
31
- }
32
- ]
33
- ```
34
-
35
- **With datapack:**
36
- ```
37
- db_summarize_database(scope="read", schema="public", datapack_id="dp-uuid-123")
38
- ```
39
-
40
- **Common errors:**
41
- - `Insufficient scope: 'all'` — Use `scope="read"`, not `"all"`
42
- - Empty result — The schema may not exist, try `schema="public"`
43
-
44
- ---
45
-
46
- ### db_run_read_only_query
47
-
48
- **When to use:** Any SELECT query. Always add `LIMIT` on exploratory queries.
49
-
50
- ```
51
- db_run_read_only_query(scope="read", query="SELECT id, name FROM customers LIMIT 10")
52
- ```
53
-
54
- **Response:** JSON array of row objects.
55
- ```json
56
- [{"id": "abc-123", "name": "Alice"}, {"id": "def-456", "name": "Bob"}]
57
- ```
58
-
59
- **Best practices:**
60
- - Always use `LIMIT` on unfamiliar tables to avoid flooding context
61
- - Select specific columns rather than `SELECT *` to keep responses small
62
- - For non-public schemas: `SELECT * FROM analytics."monthly_revenue" LIMIT 5`
63
- - Escape single quotes in values: `WHERE name = 'O''Brien'`
64
-
65
- **Common errors:**
66
- - `cannot execute INSERT in a read-only transaction` — Use `db_run_write_query` for writes
67
- - `permission denied for table X` — MCP user lacks access to this table (server-side config issue, not fixable via MCP)
68
- - `connection already closed` — Retry once. If persistent, the DB pool is unhealthy.
69
-
70
- ---
71
-
72
- ### db_run_write_query
73
-
74
- **When to use:** INSERT, UPDATE, DELETE, CREATE TABLE, ALTER TABLE, DROP TABLE, CREATE INDEX.
75
-
76
- ```
77
- db_run_write_query(scope="write", query="INSERT INTO customers (id, name) VALUES ('abc-123', 'Alice')")
78
- ```
79
-
80
- **Response:**
81
- ```json
82
- {"rows_affected": 1}
83
- ```
84
-
85
- **One statement per call.** This is wrong:
86
- ```
87
- db_run_write_query(scope="write", query="CREATE TABLE a (id INT); CREATE TABLE b (id INT);")
88
- ```
89
- Split into two separate calls.
90
-
91
- **Bulk inserts:** Maximum 1000 rows per INSERT VALUES. For more, use `INSERT ... SELECT` or batch into multiple calls.
92
-
93
- **Common errors:**
94
- - `Multi-statement queries not allowed` — Send one statement per call
95
- - `DROP SCHEMA is not allowed` — See `tools-write-guardrails.md` for blocked operations
96
- - `'dict' object has no attribute 'guardrail_config'` — Known server bug in some deployments. Write operations may be unavailable.
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`.
97
6
 
98
7
  ---
99
8
 
100
9
  ## Memory Tools
101
10
 
102
- **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* (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.
103
12
 
104
13
  ### memory_add
105
14
 
106
- **When to use:** Store facts, preferences, user profile info, org conventions, corrections, learnings. Use proactively — don't wait for the user to ask.
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).
107
16
 
108
17
  ```
109
- memory_add(scope="write", agent_id="agent",
110
- text="User Amiram is VP of Product at YugabyteDB. Prefers concise responses.")
18
+ memory_add(agent_id="<your-agent-id>",
19
+ conversation_id="<uuid from conversation_create or the SessionStart hook>",
20
+ text="Remember: deploy scripts must be run from the repo root, never a subdir.")
111
21
  ```
112
22
 
113
23
  **Response:**
@@ -115,16 +25,9 @@ memory_add(scope="write", agent_id="agent",
115
25
  {"results": [{"id": "mem-uuid-123", "memory": "User Amiram is VP of Product at YugabyteDB. Prefers concise responses."}]}
116
26
  ```
117
27
 
118
- **With user scoping:**
119
- ```
120
- memory_add(scope="write", agent_id="agent", user_id="amiram",
121
- text="Prefers Python for backend, Go for infrastructure.")
122
- ```
123
-
124
28
  **What NOT to store via memory_add:**
125
- - CSV rows or tabular data (use `db_run_write_query` instead)
126
29
  - Full conversations (use `conversation_create` + `conversation_add_message`)
127
- - Large documents (use knowledge base ingestion)
30
+ - Large documents (use the UI's Datapack → Actions → Add Knowledge upload flow)
128
31
 
129
32
  **Common errors:**
130
33
  - `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.
@@ -137,9 +40,11 @@ memory_add(scope="write", agent_id="agent", user_id="amiram",
137
40
  **When to use:** Find relevant memories by meaning. Always try this before asking the user to repeat information.
138
41
 
139
42
  ```
140
- memory_search(scope="read", query="What programming language does the team use?", agent_id="agent")
43
+ memory_search(query="What programming language does the team use?", agent_id="agent", conversation_id="<uuid>")
141
44
  ```
142
45
 
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
+
143
48
  **Response:**
144
49
  ```json
145
50
  {"results": [{"id": "mem-uuid-123", "memory": "Team uses Python for backend", "score": 0.89}]}
@@ -147,22 +52,17 @@ memory_search(scope="read", query="What programming language does the team use?"
147
52
 
148
53
  **With limit:**
149
54
  ```
150
- memory_search(scope="read", query="user preferences", agent_id="agent", limit=5)
55
+ memory_search(query="user preferences", agent_id="agent", conversation_id="<uuid>", limit=5)
151
56
  ```
152
57
 
153
58
  ---
154
59
 
155
60
  ### memory_get_all
156
61
 
157
- **When to use:** List everything stored for an agent. Useful at session start to load context.
62
+ **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.
158
63
 
159
64
  ```
160
- memory_get_all(scope="read", agent_id="agent")
161
- ```
162
-
163
- **With user scoping:**
164
- ```
165
- memory_get_all(scope="read", agent_id="agent", user_id="amiram")
65
+ memory_get_all(agent_id="agent", conversation_id="<uuid>")
166
66
  ```
167
67
 
168
68
  ---
@@ -170,7 +70,7 @@ memory_get_all(scope="read", agent_id="agent", user_id="amiram")
170
70
  ### memory_get_by_id
171
71
 
172
72
  ```
173
- memory_get_by_id(scope="read", memory_id="mem-uuid-123", agent_id="agent")
73
+ memory_get_by_id(memory_id="mem-uuid-123", agent_id="agent", conversation_id="<uuid>")
174
74
  ```
175
75
 
176
76
  ---
@@ -180,7 +80,7 @@ memory_get_by_id(scope="read", memory_id="mem-uuid-123", agent_id="agent")
180
80
  **When to use:** Overwrite a specific memory's text. Requires the memory UUID.
181
81
 
182
82
  ```
183
- memory_update(scope="write", memory_id="mem-uuid-123", text="Updated: Team uses Go for all new services", agent_id="agent")
83
+ memory_update(memory_id="mem-uuid-123", text="Updated: Team uses Go for all new services", agent_id="agent", conversation_id="<uuid>")
184
84
  ```
185
85
 
186
86
  ---
@@ -188,21 +88,41 @@ memory_update(scope="write", memory_id="mem-uuid-123", text="Updated: Team uses
188
88
  ### memory_delete_by_id
189
89
 
190
90
  ```
191
- memory_delete_by_id(scope="write", memory_id="mem-uuid-123", agent_id="agent")
91
+ memory_delete_by_id(memory_id="mem-uuid-123", agent_id="agent", conversation_id="<uuid>")
192
92
  ```
193
93
 
194
94
  ---
195
95
 
196
96
  ### memory_delete_all
197
97
 
198
- **Destructive. Requires admin scope.** Deletes all memories for the agent.
98
+ **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.
199
99
 
200
100
  ```
201
- memory_delete_all(scope="admin", agent_id="agent")
101
+ memory_delete_all(agent_id="agent", conversation_id="<uuid>")
202
102
  ```
203
103
 
204
104
  ---
205
105
 
106
+ ### memory_promote
107
+
108
+ **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.
109
+
110
+ ```
111
+ memory_promote(memory_ids=["mem-uuid-123", "mem-uuid-456"],
112
+ agent_id="agent", conversation_id="<uuid from conversation_create>")
113
+ ```
114
+
115
+ **Response:**
116
+ ```json
117
+ {"inserted_ids": ["mem-uuid-123"], "updated_ids": ["mem-uuid-456"], "not_found_ids": []}
118
+ ```
119
+
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.
123
+
124
+ ---
125
+
206
126
  ## Conversation Tools
207
127
 
208
128
  ### conversation_create
@@ -210,7 +130,7 @@ memory_delete_all(scope="admin", agent_id="agent")
210
130
  **When to use:** Start storing a multi-turn exchange. Do this when the session contains valuable dialog worth preserving.
211
131
 
212
132
  ```
213
- conversation_create(scope="write", agent_id="agent", user_id="amiram",
133
+ conversation_create(agent_id="agent",
214
134
  title="Debugging the auth middleware")
215
135
  ```
216
136
 
@@ -225,8 +145,10 @@ conversation_create(scope="write", agent_id="agent", user_id="amiram",
225
145
 
226
146
  **When to use:** Add a user/assistant exchange to an existing conversation. **All fields must be verbatim** — never summarize or rephrase.
227
147
 
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
+
228
150
  ```
229
- conversation_add_message(scope="write", conversation_id="conv-uuid-123", agent_id="agent",
151
+ conversation_add_message(conversation_id="conv-uuid-123", agent_id="agent",
230
152
  input="Why is the auth middleware returning 401?",
231
153
  output="The token validation is checking the wrong issuer claim...",
232
154
  reasoning="Checked the middleware source, found issuer mismatch between config and JWT...")
@@ -234,7 +156,7 @@ conversation_add_message(scope="write", conversation_id="conv-uuid-123", agent_i
234
156
 
235
157
  **With dedup seed (use when client hooks also write to Langfuse):**
236
158
  ```
237
- conversation_add_message(scope="write", conversation_id="conv-uuid-123", agent_id="agent",
159
+ conversation_add_message(conversation_id="conv-uuid-123", agent_id="agent",
238
160
  input="Why is the auth middleware returning 401?",
239
161
  output="The token validation is checking the wrong issuer claim...",
240
162
  seed="conv-uuid-123:agent:Why is the auth middleware returning 401?")
@@ -245,7 +167,7 @@ conversation_add_message(scope="write", conversation_id="conv-uuid-123", agent_i
245
167
  ### conversation_get
246
168
 
247
169
  ```
248
- conversation_get(scope="read", conversation_id="conv-uuid-123", agent_id="agent",
170
+ conversation_get(conversation_id="conv-uuid-123", agent_id="agent",
249
171
  include_messages=True, limit=50)
250
172
  ```
251
173
 
@@ -253,8 +175,12 @@ conversation_get(scope="read", conversation_id="conv-uuid-123", agent_id="agent"
253
175
 
254
176
  ### conversation_list
255
177
 
178
+ Target the datapack by `datapack_id` (UUID). It's optional — omit it to use the
179
+ pinned/default datapack, or pass the pinned `datapack_id`. Use `datapack_list`
180
+ to look up the id.
181
+
256
182
  ```
257
- conversation_list(scope="read", agent_id="agent", limit=20)
183
+ conversation_list(datapack_id="<datapack-uuid>", agent_id="agent", limit=20)
258
184
  ```
259
185
 
260
186
  ---
@@ -262,7 +188,7 @@ conversation_list(scope="read", agent_id="agent", limit=20)
262
188
  ### conversation_update
263
189
 
264
190
  ```
265
- conversation_update(scope="write", conversation_id="conv-uuid-123", agent_id="agent",
191
+ conversation_update(conversation_id="conv-uuid-123", agent_id="agent",
266
192
  title="Resolved: Auth middleware issuer mismatch")
267
193
  ```
268
194
 
@@ -270,19 +196,19 @@ conversation_update(scope="write", conversation_id="conv-uuid-123", agent_id="ag
270
196
 
271
197
  ### conversation_delete
272
198
 
273
- **Destructive. Requires admin scope.**
199
+ **Destructive.**
274
200
 
275
201
  ```
276
- conversation_delete(scope="admin", conversation_id="conv-uuid-123", agent_id="agent")
202
+ conversation_delete(conversation_id="conv-uuid-123", agent_id="agent")
277
203
  ```
278
204
 
279
205
  ---
280
206
 
281
- ## RAG / Knowledge Base Tools
207
+ ## Knowledge Base Tools
282
208
 
283
- **On cloud Meko today, KB ingestion is a UI-only activity.** Users upload files via the datapack's Actions → **Add Knowledge** dialog (PDF/TXT/MD/JSON/MP4, 5MB each, 10/batch). The three ingestion-side MCP tools below are Free-Tier-gated on cloud and brittle even when ungated. `knowledgebase_search` is the one KB tool to reach for.
209
+ **KB ingestion is a UI-only activity.** Users upload files via the datapack's Actions → **Add Knowledge** dialog (PDF/TXT/MD/JSON/MP4, 5MB each, 10/batch). `knowledgebase_search` is the one KB tool exposed via MCP.
284
210
 
285
- See `tools-rag-workflow.md` for the decision table and why.
211
+ See `tools-rag-workflow.md` for the decision table.
286
212
 
287
213
  ### knowledgebase_search
288
214
 
@@ -290,7 +216,6 @@ See `tools-rag-workflow.md` for the decision table and why.
290
216
 
291
217
  ```
292
218
  knowledgebase_search(
293
- scope="read",
294
219
  query="natural-language question",
295
220
  agent_id="agent",
296
221
  conversation_id="<uuid from conversation_create>",
@@ -309,73 +234,84 @@ Populated KBs return results with chunk content and similarity scores. An empty/
309
234
 
310
235
  ---
311
236
 
312
- ### knowledgebase_trigger_index_creation
237
+ ## Artifact Tools
313
238
 
314
- **When to use:** Self-hosted deployments where the ingestion worker has IAM access to the target S3 bucket. **Not available on cloud Free Tier** (returns `{"error": "not_available", "detail": "Vector index creation is not available on the free tier."}`).
239
+ ### artifact_put
240
+
241
+ **When to use:** An agent has generated a file (report, CSV, PDF, code output, image) and wants to persist it in Meko for later retrieval or cross-agent sharing. Files < 1 MB are stored inline in the DB; files ≥ 1 MB go to the datapack's S3 bucket. Idempotent — uploading the same bytes twice returns the same `content_hash`.
315
242
 
316
243
  ```
317
- knowledgebase_trigger_index_creation(
318
- scope="write",
244
+ artifact_put(
245
+ filename="analysis_report.csv",
246
+ content_type="text/csv",
247
+ content_base64="<base64-encoded bytes>",
319
248
  conversation_id="<uuid from conversation_create>",
320
- source_uris="s3://my-bucket/docs/,s3://my-bucket/reports/",
321
- index_name="company_docs")
249
+ agent_id="agent"
250
+ )
322
251
  ```
323
252
 
324
- **Optional parameters:**
325
- - `ai_provider="OPENAI"` (default)
326
- - `embedding_model="text-embedding-3-large"` (default)
327
- - `embedding_dimensions=1536` (default)
328
- - `chunk_size=1024` (default)
329
- - `chunk_overlap=256` (default)
330
- - `datapack_id=None`
331
-
332
- **Success response:**
253
+ **Response:**
333
254
  ```json
334
- {"source_ids": ["<uuid>", ...], "index_id": "<uuid>", "index_name": "company_docs",
335
- "status": "build_triggered", "message": "... registered, index '...' initialised, and build triggered."}
255
+ {
256
+ "artifact_id": "550e8400-e29b-41d4-a716-446655440000",
257
+ "content_hash": "a665a45920422f9d417e4867efdc4fb8a5f1f89ea5b8440b1ad4c4c6b8a7e4d3",
258
+ "filename": "analysis_report.csv",
259
+ "content_type": "text/csv",
260
+ "size_bytes": 4096,
261
+ "stored_in": "db"
262
+ }
336
263
  ```
337
264
 
338
- **Critical caveats:**
339
- - URIs must start with `s3://`. The worker (`aws_source_processor.py:86-117`) rejects any other scheme with `ValueError("Invalid source URI")` — async, not surfaced through the MCP response.
340
- - The worker uses the boto3 default credential chain (env vars, IAM role, `~/.aws/credentials` on the worker host). There is no way for the user to pass AWS credentials through the MCP tool. If the worker's identity can't read the bucket, the build stalls at INIT.
341
- - Each call creates a new index. Do NOT retry on failure — you'll get duplicate indexes.
342
- - Tracked as a gap: [yugabyte/meko-mcp-server#89](https://github.com/yugabyte/meko-mcp-server/issues/89) / MEKO-96.
265
+ Save the `content_hash` — it's the retrieval key for `artifact_get`.
266
+
267
+ **Common errors:**
268
+ - `invalid_base64` — `content_base64` is not valid base64; decode the file before passing it.
269
+ - `artifact_too_large` — file exceeds 5 MiB (default). Set `MEKO_MAX_ARTIFACT_UPLOAD_BYTES` to raise the limit.
343
270
 
344
271
  ---
345
272
 
346
- ### knowledgebase_check_index_status
273
+ ### artifact_get
347
274
 
348
- **When to use:** Poll a self-hosted build for completion. **Not available on cloud Free Tier** (returns `{"error": "not_available"}`).
275
+ **When to use:** Retrieve a file previously uploaded with `artifact_put`.
349
276
 
277
+ **Small files (< 1 MB) — content returned inline:**
350
278
  ```
351
- knowledgebase_check_index_status(
352
- scope="read",
279
+ artifact_get(
280
+ content_hash="a665a45920422f9d417e4867efdc4fb8a5f1f89ea5b8440b1ad4c4c6b8a7e4d3",
353
281
  conversation_id="<uuid from conversation_create>",
354
- index_name="company_docs",
355
- datapack_id=None)
282
+ agent_id="agent"
283
+ )
356
284
  ```
357
285
 
358
- Check `completion_rate_percent` in `pipeline_stats` and `document_status` in `pipeline_details`. If documents stay at `INIT` for >5 minutes, the worker probably can't reach the bucket. Stop polling after 3 consecutive no-progress checks.
359
-
360
- ---
361
-
362
- ### knowledgebase_add_source_to_index
363
-
364
- **When to use:** Grow an existing index with a new source URI (self-hosted / paid). **Not available on cloud Free Tier** (same "Vector index creation is not available" gate as `trigger_index_creation`).
365
-
366
- ```
367
- knowledgebase_add_source_to_index(
368
- scope="write",
369
- conversation_id="<uuid from conversation_create>",
370
- index_name="company_docs",
371
- source_uri="s3://my-bucket/new-docs/")
286
+ **Response (inline):**
287
+ ```json
288
+ {
289
+ "content_hash": "a665a45920422f9d417e4867efdc4fb8...",
290
+ "filename": "analysis_report.csv",
291
+ "content_type": "text/csv",
292
+ "size_bytes": 4096,
293
+ "stored_in": "db",
294
+ "content_base64": "<base64-encoded bytes>"
295
+ }
372
296
  ```
373
297
 
374
- Param is **`source_uri`** (URI string), not `source_id` — older docs had this wrong.
298
+ **Large files (≥ 1 MB) — written to local disk:**
299
+ ```json
300
+ {
301
+ "content_hash": "a665a45920422f9d417e4867efdc4fb8...",
302
+ "filename": "dataset.parquet",
303
+ "content_type": "application/octet-stream",
304
+ "size_bytes": 2097152,
305
+ "stored_in": "s3",
306
+ "local_path": "/Users/you/.meko/artifacts/a665a4.../dataset.parquet"
307
+ }
308
+ ```
375
309
 
376
- The historical `r_index_name` vs `r_index_id` parameter-mismatch bug (reported in 2026-03) is **fixed** on main. The tool now resolves `index_name → index_id` internally via `SELECT id FROM dist_rag.vector_indexes WHERE index_name = %s` before calling the dist_rag function. If the name doesn't exist you get `{"error": "index_not_found", "detail": "No vector index found with name '...'"}`.
310
+ For large files use the `local_path` value to read the file with normal file tools. S3 URLs are never exposed.
377
311
 
378
- Same S3-only / worker-credentials caveats as `trigger_index_creation` apply.
312
+ **Common errors:**
313
+ - `ARTIFACT_NOT_FOUND` — no artifact with that hash in this datapack.
314
+ - `ARTIFACT_EXPIRED` — artifact exists but its free-tier TTL has elapsed (30 days of no access). Pro-tier artifacts never expire.
379
315
 
380
316
  ---
381
317
 
@@ -384,23 +320,29 @@ Same S3-only / worker-credentials caveats as `trigger_index_creation` apply.
384
320
  ### datapack_create / datapack_list / datapack_describe
385
321
 
386
322
  ```
387
- datapack_create(scope="write", name="analytics_prod")
388
- datapack_list(scope="read")
389
- datapack_describe(scope="read", name="analytics_prod", include_status=True)
323
+ datapack_create(name="analytics_prod")
324
+ datapack_list() # returns datapack_id for each datapack
325
+ datapack_describe(datapack_id="<uuid>", include_status=True)
390
326
  ```
391
327
 
392
328
  ### datapack_update / datapack_delete
393
329
 
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.
331
+
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.
333
+
394
334
  ```
395
- datapack_update(scope="write", name="analytics_prod", connection_string="postgresql://...")
396
- datapack_delete(scope="admin", name="analytics_prod") # Irreversible!
335
+ datapack_update(datapack_id="<uuid>", name="renamed-datapack")
336
+ datapack_update(datapack_id="<uuid>", description="new description")
337
+ datapack_update(datapack_id="<uuid>", name="x", description="y")
338
+ datapack_delete(datapack_id="<uuid>") # Irreversible!
397
339
  ```
398
340
 
399
341
  ### Agent and knowledge-base management (NOT MCP — control-plane only)
400
342
 
401
343
  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:
402
344
 
403
- - REST: `POST/GET/DELETE /datapacks/:name/agents` (agents), `POST/GET/DELETE /datapacks/:name/knowledge-bases` (KB sources).
404
- - Or the Meko UI at `app.mekodev.com` → Datapacks → agents / knowledge-bases.
345
+ - REST: `POST/GET/DELETE /datapacks/:datapack_id/agents` (agents), `POST/GET/DELETE /datapacks/:datapack_id/knowledge-bases` (KB sources).
346
+ - Or the Meko Cloud UI at `cloud.mekodata.ai` → Datapacks → agents / knowledge-bases.
405
347
 
406
- To build a RAG index from inside a session (which IS MCP-exposed), use `knowledgebase_trigger_index_creation` / `knowledgebase_add_source_to_index` / `knowledgebase_check_index_status` — those operate on `dist_rag` tables inside the datapack's database.
348
+ 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`.
@@ -1,64 +1,58 @@
1
1
  # Datapack Lifecycle and datapack_id Routing
2
2
 
3
- **WRONG:** Creating a datapack then calling `db_summarize_database(scope="read")` without `datapack_id` — this queries the DEFAULT database, not the datapack.
4
-
5
- ## Always pass datapack_id for datapack-scoped operations
6
-
7
- ```
8
- datapack_create(scope="write", name="analytics_prod")
9
- -- Returns: {"id": "dp-uuid-123", ...}
10
-
11
- db_summarize_database(scope="read", schema="public", datapack_id="dp-uuid-123")
12
- db_run_read_only_query(scope="read", query="SELECT * FROM customers LIMIT 10", datapack_id="dp-uuid-123")
13
- ```
14
-
15
- ## How datapack_id routing works
16
-
17
- 1. When `datapack_id` is **omitted**: uses the default pool from `YUGABYTEDB_URL`
18
- 2. When `datapack_id` is **provided**: resolves connection string via Meko API, creates/reuses a cached pool for that datapack
3
+ Datapacks are isolated workspaces — each has its own memory store and knowledge-base index. Many MCP tools accept an optional `datapack_id` to target a specific workspace; omit it to use the default.
19
4
 
20
5
  ## Which tools accept datapack_id?
21
6
 
22
- All **Database**, **RAG**, and **Memory** tools accept `datapack_id`.
23
-
24
- **Conversation** tools do NOT — they always use Langfuse.
25
- **Datapack management** tools do NOT — they operate on the Meko API itself.
7
+ | Tool group | Accepts `datapack_id`? |
8
+ |---|---|
9
+ | **Memory** (`memory_*`) | Yes — optional, defaults to the caller's default datapack |
10
+ | **Knowledge Base** (`knowledgebase_search`) | Yes — **required** (no default) |
11
+ | **Conversation** (`conversation_*`) | Yes — optional; routes the call's Langfuse trace to that datapack's project (data is Langfuse-stored, not in the datapack DB itself) |
12
+ | **Datapack management** (`datapack_*`) | Yes — `datapack_describe`/`datapack_update`/`datapack_delete` address the datapack by its `datapack_id` (the Meko API routes are `/datapacks/{datapack_id}`); it also routes the call's Langfuse trace to that datapack's project |
26
13
 
27
14
  ## How to obtain a datapack_id
28
15
 
29
- - From `datapack_create` response (`"id"` field)
30
- - From `datapack_list` (each entry has `"id"`)
31
- - From `datapack_describe` response
16
+ - From `datapack_create` response (`"datapack_id"` field; `"datapack_name"` is also returned)
17
+ - From `datapack_list` (each entry has `"datapack_id"` and `"datapack_name"`)
18
+ - From `datapack_describe` response (same field names)
32
19
 
33
20
  ## Datapack lifecycle
34
21
 
35
- ### Creation and setup (MCP)
22
+ ### Creation
36
23
 
37
24
  ```
38
- datapack_create(scope="write", name="sales_analytics")
39
- db_run_write_query(scope="write", query="CREATE TABLE leads (...)", datapack_id="dp-uuid-from-step-1")
25
+ datapack_create(name="sales_analytics",
26
+ conversation_id="<uuid>")
27
+ -- Returns: {"datapack_id": "dp-uuid-123", "datapack_name": "sales_analytics", ...}
40
28
  ```
41
29
 
42
- Provisioning agents and knowledge-base sources on the datapack is **not** MCP-exposed — do that in the Meko control plane (UI at `app.mekodev.com` → Datapacks, or directly via the REST API:
43
- `POST /datapacks/:name/agents`, `POST /datapacks/:name/knowledge-bases`). If the user asks the agent to set those up mid-session, tell them where to go rather than inventing an MCP call that will fail.
30
+ Provisioning agents and knowledge-base sources on a new datapack is **not** MCP-exposed. Use the Meko control plane:
31
+
32
+ - **UI**: `app.mekodata.ai` → Datapacks → select datapack → Agents / Knowledge Bases
33
+ - **REST**: `POST /datapacks/:datapack_id/agents`, `POST /datapacks/:datapack_id/knowledge-bases` (and the Add Knowledge UI for file uploads)
34
+
35
+ If the user asks to set those up mid-session, point them at the control plane rather than inventing an MCP call that will fail.
44
36
 
45
- For RAG indexes inside the datapack's database, use the MCP-exposed RAG tools:
37
+ ### Targeting a specific datapack on subsequent calls
46
38
 
47
39
  ```
48
- knowledgebase_trigger_index_creation(scope="write", source_uris=[...], index_name="leads_docs", datapack_id="dp-uuid-from-step-1")
49
- knowledgebase_check_index_status(scope="read", index_name="leads_docs", datapack_id="dp-uuid-from-step-1")
40
+ memory_search(agent_id="<your-agent-id>",
41
+ conversation_id="<uuid>", query="...", datapack_id="dp-uuid-123")
42
+ knowledgebase_search(agent_id="<your-agent-id>",
43
+ conversation_id="<uuid>", datapack_id="dp-uuid-123", query="...")
50
44
  ```
51
45
 
52
- ### Teardown (requires admin scope)
46
+ ### Teardown
53
47
 
54
48
  Delete child resources first (agents and KB sources via the control plane), then the datapack:
55
49
 
56
50
  ```
57
- # Control-plane (REST or UI): DELETE /datapacks/sales_analytics/knowledge-bases
58
- # Control-plane (REST or UI): DELETE /datapacks/sales_analytics/agents/sales_agent
59
- datapack_delete(scope="admin", name="sales_analytics") # MCP-exposed, destructive
51
+ # Control-plane (REST or UI): DELETE /datapacks/:datapack_id/knowledge-bases
52
+ # Control-plane (REST or UI): DELETE /datapacks/:datapack_id/agents/sales_agent
53
+ datapack_delete(datapack_id="dp-uuid-123") # MCP-exposed, destructive, irreversible
60
54
  ```
61
55
 
62
- ## Common mistake: mixing default and datapack databases
56
+ ## Common mistake: forgetting datapack_id on memory tools
63
57
 
64
- If you created a table with a `datapack_id`, always query it with the same `datapack_id`. Creating in default DB and querying in a datapack (or vice versa) will fail with "table not found".
58
+ Memory writes without `datapack_id` land in the default datapack, not the one you just created. If you `datapack_create` and then `memory_add` without passing the new datapack's id, you'll be searching the wrong store later.