@yugabytedb/meko-mcp 1.0.8 → 1.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 (51) hide show
  1. package/README.md +242 -44
  2. package/assets/hooks-handlers/before-submit-prompt.sh +44 -0
  3. package/assets/hooks-handlers/cursor-session-start.sh +42 -0
  4. package/assets/hooks-handlers/lib/capture.js +457 -107
  5. package/assets/hooks-handlers/lib/package.json +1 -0
  6. package/assets/hooks-handlers/test_single_conversation.sh +1 -1
  7. package/assets/scripts/package-desktop-skill.sh +36 -0
  8. package/assets/skills/meko-mcp-tools/SKILL.md +167 -53
  9. package/assets/skills/meko-mcp-tools/references/_sections.md +1 -1
  10. package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +84 -22
  11. package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +89 -56
  12. package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +15 -7
  13. package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +17 -9
  14. package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +94 -5
  15. package/assets/skills/meko-mcp-tools/references/tools-overview.md +52 -37
  16. package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +108 -37
  17. package/assets/skills/meko-mcp-tools/references/tools-scope-permissions.md +6 -10
  18. package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +30 -18
  19. package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +55 -69
  20. package/assets/skills/meko-mcp-tools-desktop/SKILL.md +251 -0
  21. package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +150 -0
  22. package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +24 -0
  23. package/assets/skills/meko-mcp-tools-desktop/references/tools-agent-id-conventions.md +99 -0
  24. package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +406 -0
  25. package/assets/skills/meko-mcp-tools-desktop/references/tools-known-limitations.md +69 -0
  26. package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +217 -0
  27. package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +112 -0
  28. package/assets/skills/meko-mcp-tools-desktop/references/tools-rag-workflow.md +134 -0
  29. package/assets/skills/meko-mcp-tools-desktop/references/tools-scope-permissions.md +75 -0
  30. package/assets/skills/meko-mcp-tools-desktop/references/tools-troubleshooting.md +155 -0
  31. package/bin/create-meko-setup.mjs +151 -22
  32. package/lib/clients/claude-code.mjs +378 -68
  33. package/lib/clients/claude-desktop.mjs +45 -8
  34. package/lib/clients/codex.mjs +1209 -0
  35. package/lib/clients/common.mjs +223 -1
  36. package/lib/clients/cursor.mjs +118 -13
  37. package/lib/clients/index.mjs +2 -0
  38. package/lib/config.mjs +56 -0
  39. package/lib/detect.mjs +52 -44
  40. package/lib/installer.mjs +11 -4
  41. package/lib/mcp-transport.mjs +61 -2
  42. package/lib/migrate/adapters/memory-md.mjs +13 -6
  43. package/lib/migrate/datapack.mjs +167 -0
  44. package/lib/migrate/id.mjs +127 -9
  45. package/lib/migrate/orchestrator.mjs +68 -10
  46. package/lib/migrate.mjs +346 -3
  47. package/lib/prompt.mjs +22 -4
  48. package/lib/validate.mjs +313 -9
  49. package/lib/version-check.mjs +178 -0
  50. package/package.json +2 -1
  51. package/scripts/bundle-assets.mjs +8 -0
@@ -0,0 +1,217 @@
1
+ # When to Use Memory Tools vs Conversation Tools
2
+
3
+ **WRONG:** `memory_add(text="User asked about pricing. I explained tiers. User chose Pro.")` — mem0 extracts facts, discarding conversational structure, turn ordering, and reasoning traces.
4
+
5
+ ## Use `memory_add` when storing:
6
+
7
+ - A **fact**: "User prefers dark mode"
8
+ - A **preference**: "Customer budget is $50k"
9
+ - An **entity relationship**: "Alice works at Acme Corp"
10
+
11
+ Memory is backed by pgvector (semantic search) and Apache AGE (entity-relationship graph). It retrieves relevant facts by meaning, not by conversation order.
12
+
13
+ ```
14
+ memory_add(scope="write", agent_id="support_bot",
15
+ text="Customer Alice (alice@acme.com) prefers email, has Pro plan.", user_id="alice_123")
16
+
17
+ memory_search(scope="read", query="What plan does Alice have?", agent_id="support_bot")
18
+ ```
19
+
20
+ ## Use `conversation_create` + `conversation_add_message` when storing:
21
+
22
+ - A **full dialog exchange** with input/output pairs
23
+ - A **chain-of-thought** reasoning trace alongside the response
24
+ - A **multi-turn chat** where turn order matters
25
+
26
+ Conversations are backed by Langfuse sessions and traces. They preserve full structure: who said what, in what order, with what reasoning.
27
+
28
+ ```
29
+ conversation_create(scope="write", agent_id="support_bot", user_id="alice_123", title="Pricing discussion")
30
+ -- Returns: {"id": "conv-uuid-here"}
31
+
32
+ conversation_add_message(scope="write", conversation_id="conv-uuid-here", agent_id="support_bot",
33
+ input="What are your pricing tiers?",
34
+ output="We offer Starter ($10/mo), Pro ($50/mo), and Enterprise (custom).",
35
+ reasoning="Retrieved pricing page data. No special discounts apply.")
36
+ ```
37
+
38
+ ## Decision Matrix
39
+
40
+ | Signal | Tool |
41
+ |--------|------|
42
+ | "remember that...", "note that...", "keep in mind..." | `memory_add` |
43
+ | "store this conversation", "save this chat" | `conversation_create` + `conversation_add_message` |
44
+ | "what do you know about X?", "recall..." | `memory_search` |
45
+ | "show me our past conversation about..." | `conversation_list` + `conversation_get` |
46
+ | "the user prefers...", "their budget is..." | `memory_add` |
47
+ | "save my query and your response" | `conversation_add_message` |
48
+
49
+ ## Verbatim Content Rules for conversation_add_message
50
+
51
+ **WRONG:** Summarizing or rephrasing content before storing:
52
+ ```
53
+ conversation_add_message(...,
54
+ input="User inquired about database performance", -- rephrased
55
+ output="I provided optimization suggestions", -- summarized
56
+ reasoning="Analyzed the query and suggested improvements" -- condensed
57
+ )
58
+ ```
59
+
60
+ All three fields — `input`, `output`, and `reasoning` — must contain the **exact, verbatim text**. Never summarize, rephrase, editorialize, or condense any field:
61
+
62
+ - **`input`**: The user's exact prompt, word for word
63
+ - **`output`**: The assistant's complete response, word for word — including code blocks, formatting, and all detail
64
+ - **`reasoning`**: The full chain-of-thought or internal reasoning trace, unedited
65
+
66
+ The purpose of conversation storage is to create a faithful, replayable record. A rephrased summary loses the original wording, tone, and detail — making the stored conversation useless for review, debugging, or audit.
67
+
68
+ ## Personal memory vs. team-shared knowledge — the three read paths
69
+
70
+ Agents on Cloud Meko have three distinct read surfaces. Pick the right one for the question.
71
+
72
+ | Read path | What it returns | How to call |
73
+ |---|---|---|
74
+ | Your own desktop memories | Memories you wrote under this `agent_id`, filtered by `(datapack_id, user_id, agent_id)` | `memory_search(agent_id="claude_desktop", query="...", ...)` |
75
+ | Cross-project common bucket | Memories any agent (including this one) wrote with `agent_id="meko_agent"` — the empty-default bucket for genuinely cross-project facts | `memory_search(agent_id="meko_agent", query="...", ...)` |
76
+ | Team's shared knowledge | Promoted memories + uploaded documents, visible to every member of the datapack | `knowledgebase_search(agent_id="<anything>", datapack_id="<datapack UUID>", query="...")` — `agent_id` is ignored |
77
+
78
+ For a true fan-out across other clients' buckets (e.g. also see what was written from `claude_code:some-repo` or `cursor:foo`), call `memory_search` once per agent_id — there's no single-call shortcut. Empty string is rewritten to `meko_agent` server-side; it does not drop the filter.
79
+
80
+ ### How content gets into each surface
81
+
82
+ - **Personal memories** — written by `memory_add`. Scoped per-user and per-agent from the moment of write. Only the writer sees them via MCP reads.
83
+ - **Team-shared Shared Knowledge** — arrives two ways:
84
+ 1. The **user** (never the agent) promotes a personal memory to Knowledge via the Cloud UI's Learnings tab. That copies the row into the shared `knowledge_base` table with the `user_id` stripped, making it team-wide. Originating `agent_id` is preserved in metadata for provenance.
85
+ 2. The user uploads a file via Datapack → Actions → **Add Knowledge** in the Cloud UI. PDF/TXT/MD/JSON/MP4 up to 5MB each.
86
+
87
+ Both show up in `knowledgebase_search`, tagged `metadata_filters.source: "memory"` vs other values so the agent can distinguish provenance in responses.
88
+
89
+ **No MCP tool promotes to Shared Knowledge.** The agent can flag memories it thinks are worth promoting and suggest the user do it from the UI — but the action is user-initiated.
90
+
91
+ ### When the user asks "what do you know about X?"
92
+
93
+ A full sweep is three calls (budget for it — each is 2-6 seconds):
94
+
95
+ ```
96
+ memory_search(agent_id="claude_desktop", query="X", conversation_id=..., ...)
97
+ memory_search(agent_id="meko_agent", query="X", conversation_id=..., ...) # cross-project common bucket
98
+ knowledgebase_search(agent_id="<anything>", datapack_id="<uuid>", query="X", conversation_id=..., ...)
99
+ ```
100
+
101
+ When you answer, be explicit about scope so the user knows why something is or isn't there:
102
+
103
+ - "I found this in your own desktop memories…"
104
+ - "I found this in your common cross-project bucket (something you or another agent wrote under `meko_agent`)…"
105
+ - "I found this in your team's Shared Knowledge — someone (you or a teammate) promoted it earlier…"
106
+ - "I couldn't find anything in your personal memories. You might want to check the Cloud UI's Memory Summary tab for a cross-agent view."
107
+
108
+ For a true fan-out across other clients' buckets (e.g. also see what was written from `claude_code:some-repo` or `cursor:foo`), call `memory_search` once per known agent_id — empty string just resolves to `meko_agent`, not a fan-out.
109
+
110
+ ## Memory limitations for structured data
111
+
112
+ **WRONG:** Using `memory_add` to ingest CSV rows, data dictionaries, or tabular schemas — Mem0 extracts individual facts and may drop columns, rows, or structural relationships.
113
+
114
+ On Cloud Meko today the `db_run_write_query` path isn't available (returns `{"error": "not_available"}`), so there's no MCP-side "just put it in a database table" option. Workarounds:
115
+
116
+ 1. **Write a single narrative summary** as a memory: `"The Customer Complaints dataset has fields: Complaint ID (int), Date Submitted (date), Product (text), Sub-product (text), Issue (text)..."` — one call, not row-by-row.
117
+ 2. **Suggest the user upload the file** via the Cloud UI's Add Knowledge flow if it's a document (CSV files aren't in the supported list — PDF/TXT/MD/JSON/MP4 are; for CSV, convert to MD or JSON first).
118
+ 3. **Never ingest CSV row-by-row** into memory — each row becomes a fragmented fact with lost context.
119
+
120
+ ## Proactive Memory Storage
121
+
122
+ Don't wait for the user to say "remember this." Store context proactively when you detect:
123
+
124
+ - **Personal info** → `memory_add`: "User is VP of Product, prefers concise responses"
125
+ - **Team conventions** → `memory_add`: "Team uses Python for backend, Go for infrastructure"
126
+ - **Domain knowledge** → `memory_add`: "Meko traces are decision traces that capture how and why decisions were made"
127
+ - **Corrections** → `memory_add`: "User corrected: always use 'resilience' instead of 'high availability'"
128
+
129
+ Use `memory_search` at the start of sessions to recall what you already know before asking the user to repeat themselves.
130
+
131
+ ## Using Both Together
132
+
133
+ A common pattern: store the full conversation (preserves structure) AND extract key facts with `memory_add` (enables semantic search later).
134
+
135
+ ## Key Retrieval Difference
136
+
137
+ - `memory_search`: **semantic similarity** across all memories via pgvector. Returns relevant facts regardless of when stored.
138
+ - `conversation_get`: **ordered list of message turns** for a specific conversation. No semantic search. Requires `conversation_id`.
139
+
140
+ ## Automatic Conversation Capture
141
+
142
+ The Meko plugin captures conversations automatically via three mechanisms:
143
+
144
+ 1. **Periodic checkpoint (~10 min)** — Agent-driven via CronCreate, uses `conversation_add_message` MCP tool directly
145
+ 2. **PreCompact hook** — Shell script that fires before Claude Code's auto-compaction, captures via MCP JSON-RPC
146
+ 3. **SessionEnd hook** — Shell script that fires at session termination, captures final exchanges
147
+
148
+ ### What gets captured
149
+
150
+ The full transcript including:
151
+ - **User prompts** — verbatim text (the `input` field)
152
+ - **Assistant responses** — all text blocks (the `output` field)
153
+ - **Tool calls** — tool name + input parameters (the `reasoning` field)
154
+ - **Tool results** — output from tool executions (appended to `reasoning`)
155
+
156
+ This is more than just text — tool calls and results are critical context for session replay, cross-agent sharing, and compaction.
157
+
158
+ ### Seed-based deduplication
159
+
160
+ Each message's seed is `<conversation_id>:<user_message_uuid>`. All three capture mechanisms generate the same seed for the same exchange, producing the same deterministic trace ID via `sha256(seed)[:16].hex()`. This means duplicate writes from overlapping captures are idempotent.
161
+
162
+ ### When to manually store conversations
163
+
164
+ Automatic capture handles the raw exchange. You should still manually use `conversation_create` + `conversation_add_message` when:
165
+ - The user explicitly asks to "save this conversation"
166
+ - You want to add curated `reasoning` traces beyond raw tool calls
167
+ - You want to store a selected subset of the conversation with a descriptive title
168
+
169
+ ### Watermark coordination
170
+
171
+ A shared watermark file at `~/.claude/meko-capture/<session-id>.watermark.json` tracks what has been saved. Both hooks and the agent's periodic checkpoint use this to avoid reprocessing already-captured exchanges.
172
+
173
+ ## Observability: conversation_id IS the Langfuse trace ID
174
+
175
+ This is the feature agents tend to miss. Verified live 2026-05-07 in the Meko UI's Observe hub.
176
+
177
+ - `conversation_create` returns a `conversation_id` (e.g. `d71fc8b61a7f45d585eea9a6436e0c3f`).
178
+ - That ID is also the **Langfuse trace_id** for the conversation. Not a separate trace — literally the same identifier.
179
+ - Every subsequent MCP tool call made while passing that `conversation_id` becomes a **span under that trace**, named after the tool: `Memory Add (Meko MCP)`, `Memory Search (Meko MCP)`, `Knowledgebase Search (Meko MCP)`, `Conversation Add Message (Meko MCP)`, etc.
180
+ - Child spans reveal internals. Observed structure:
181
+ - `memory_add`: `Memory Add (Meko MCP)` → `Create a new memory in Mem0` → `Bulk Payload Update (yugabytedb / vector)` → `Execute Query (yugabytedb / vector)`
182
+ - `memory_search`: `Memory Search (Meko MCP)` → `Search for memories based on a query in Mem0` (Retriever)
183
+ - `conversation_add_message`: `Conversation Add Message (Meko MCP)` → `Conversation Message Added` span → `Reasoning` generation (the `reasoning` field is stored as a Langfuse *generation*-typed span, not a plain text field)
184
+ - `knowledgebase_search`: `Knowledgebase Search (Meko MCP)` → multiple `Execute Query (yugabytedb)` child spans
185
+ - Trace tags include `agent:<agent_id>` and the Meko org UUID. Both are searchable/filterable in Langfuse.
186
+ - Each datapack has its own Langfuse project — traces for a tool call land in the project for whichever `datapack_id` was on the call (or the default datapack if omitted).
187
+
188
+ ### Finding a trace in the UI
189
+
190
+ Two navigation paths, both verified in the Meko UI:
191
+
192
+ 1. **Datapack → Conversations tab** — every row has an **Open in Observe** button that deep-links to the trace with `session=<conversation_id>` pre-filled. Fastest when you know which conversation to inspect.
193
+ 2. **Observe hub** — browse all traces across a datapack. URL shape: `/observe-hub?project=<langfuse_project_id>&session=<conversation_id>`.
194
+
195
+ The Conversations-tab row preview shows the first user turn verbatim, plus the agent_id tag, message count, and started-at timestamp. If you want a conversation to be recognizable in the UI, call `conversation_add_message` with a clean first-turn `input` early in the session.
196
+
197
+ ### Observed latencies on prod (2026-05-07)
198
+
199
+ From real traces, not the docstring happy path:
200
+
201
+ | Tool | Latency per call |
202
+ |---|---|
203
+ | `memory_add` | 12-21 seconds (calls OpenAI for extraction, then writes to vector + graph) |
204
+ | `memory_search` | 1.8-5.9 seconds |
205
+ | `knowledgebase_search` | 0.6 seconds (empty index; will grow with index size) |
206
+ | `conversation_add_message` | 0.11 seconds (fire-and-forget; queued to Langfuse) |
207
+
208
+ `memory_add` is the expensive one. If you're capturing a long conversation, batch through `conversation_add_message` (cheap, queued) and let the server-side Mem0 extractor handle the heavy lifting on its own schedule, rather than firing `memory_add(messages=...)` per turn.
209
+
210
+ ### Proactive diagnostic pattern
211
+
212
+ If a user reports "my memory_add didn't seem to save", open the Observe hub for their datapack, filter on their `conversation_id`, and look at the span tree. You will see either:
213
+
214
+ - A `Memory Add (Meko MCP)` span with `Create a new memory in Mem0` child → the call reached Mem0. The fact extractor may have returned `"results": []` (common on short or non-fact-shaped text; not a bug, but lossy).
215
+ - No span at all → the call never reached the server. Likely a transport / auth / `conversation_id` mismatch issue.
216
+
217
+ The mem0 extractor is lossy — it extracts atomic facts and graph triples, and may drop prose that doesn't look fact-shaped to it. Observed 2026-05-07: 2 of 5 `memory_add` calls returned `"results": []` and only the graph side landed. When preserving authoritative text matters, store it via `conversation_add_message` (verbatim in `input`/`output`/`reasoning`) — the conversation path preserves text without LLM re-extraction.
@@ -0,0 +1,112 @@
1
+ # Complete Tool Catalog and Decision Tree
2
+
3
+ **26 tools on cloud Meko** (verified against `https://mcp.mekodata.ai/mcp` on 2026-05-07). Earlier counts of 25 or 31 in other docs are stale. Grouped: Memory (8), Conversation (6), Knowledge Base (4), Datapack (5), Database (3).
4
+
5
+ ## Cloud Free-Tier gating at a glance
6
+
7
+ Some tools return `{"error": "not_available", "detail": "..."}` on cloud Free Tier. This is a server-side tier block — don't retry.
8
+
9
+ - **Gated on Free Tier**: `db_summarize_database`, `db_run_read_only_query`, `db_run_write_query`, `knowledgebase_trigger_index_creation`, `knowledgebase_add_source_to_index`, `knowledgebase_check_index_status`
10
+ - **Works on Free Tier**: all memory tools, all conversation tools, `knowledgebase_search`, all datapack tools, `flush_pending_memory_candidates`
11
+
12
+ ## Quick health check before using tools
13
+
14
+ Before starting a session, verify that the Meko MCP tools are working:
15
+
16
+ 1. `memory_search(scope="read", query="test", agent_id="<your-session-agent-id>", conversation_id="<session-conversation-id>")` — Confirms memory subsystem is up. Use the `agent_id` and `conversation_id` from the SessionStart `additionalContext`. May fail with "connection already closed" — see `tools-troubleshooting.md`.
17
+ 2. `datapack_list(scope="read")` — Confirms Meko API connectivity
18
+ 3. `db_summarize_database(scope="read")` — *Optional, paid-tier only.* On free-tier datapacks this returns `{"error": "not_available"}`. The old "use this for `agent_id` discovery" protocol is retired — use your client's bucket (`claude_desktop` for Claude Desktop) or `meko_agent` for the common bucket.
19
+
20
+ ## Decision tree: which tool do I need?
21
+
22
+ ```
23
+ User wants to...
24
+ ├── Query or explore the database?
25
+ │ ├── See what tables exist? ---------> db_summarize_database (read)
26
+ │ ├── Run a SELECT / read query? -----> db_run_read_only_query (read)
27
+ │ └── INSERT / UPDATE / DELETE? -------> db_run_write_query (write)
28
+ ├── Query or build a knowledge base (RAG)?
29
+ │ ├── Search chunks in an existing KB? -> knowledgebase_search (read) — WORKS on cloud today
30
+ │ ├── Create a new index from sources? -> knowledgebase_trigger_index_creation (write) — Free-Tier gated, self-hosted only
31
+ │ ├── Add source to existing index? ---> knowledgebase_add_source_to_index (write) — Free-Tier gated
32
+ │ └── Check build progress? -----------> knowledgebase_check_index_status (read) — Free-Tier gated
33
+ ├── Store or recall information?
34
+ │ ├── Store a fact/preference/entity? -----------> memory_add (write)
35
+ │ ├── Store a full conversation (multi-turn)? ---> conversation_create + conversation_add_message (write)
36
+ │ ├── Search past knowledge? --------------------> memory_search (read)
37
+ │ └── Retrieve a past conversation? -------------> conversation_get (read)
38
+ └── Manage datapacks?
39
+ └── CRUD datapack? -> datapack_create/list/describe/update/delete
40
+ ```
41
+
42
+ Agent / knowledge-base lifecycle is managed **outside** the MCP surface — typically in the Meko control-plane UI — and is not exposed as tools here.
43
+
44
+ ## Database Tools (3)
45
+
46
+ | Tool | Scope | Purpose |
47
+ |------|-------|---------|
48
+ | `db_summarize_database(scope, schema="public", datapack_id=None)` | read | List tables with column schemas and row counts |
49
+ | `db_run_read_only_query(scope, query, datapack_id=None)` | read | Run SELECT, returns JSON. Uses `BEGIN READ ONLY` + `ROLLBACK` |
50
+ | `db_run_write_query(scope, query, datapack_id=None)` | write | Execute INSERT/UPDATE/DELETE/CREATE TABLE. Guardrail-validated. Auto-committed |
51
+
52
+ ## RAG / Knowledge Base Tools (4)
53
+
54
+ | Tool | Scope | Purpose |
55
+ |------|-------|---------|
56
+ | `knowledgebase_search(scope, query, agent_id, conversation_id, datapack_id, limit=10)` | read | Semantic search across KB chunks. `datapack_id` is REQUIRED (no default). Works on cloud today. |
57
+ | `knowledgebase_trigger_index_creation(scope, conversation_id, source_uris, index_name, ai_provider="OPENAI", embedding_model="text-embedding-3-large", embedding_dimensions=1536, chunk_size=1024, chunk_overlap=256, datapack_id=None)` | write | Register sources + init vector index + trigger build. **S3-only worker + no user creds; Free-Tier gated on cloud.** See `tools-rag-workflow.md`. |
58
+ | `knowledgebase_add_source_to_index(scope, conversation_id, index_name, source_uri, chunk_size=1024, chunk_overlap=256, datapack_id=None)` | write | Add a new source (URI, not id) to an existing index. Free-Tier gated on cloud. |
59
+ | `knowledgebase_check_index_status(scope, conversation_id, index_name, datapack_id=None)` | read | Check build progress via `dist_rag.vector_index_pipeline_details`. Free-Tier gated on cloud. |
60
+
61
+ ## Memory Tools (8)
62
+
63
+ | Tool | Scope | Purpose |
64
+ |------|-------|---------|
65
+ | `memory_add(scope, text, agent_id, conversation_id, user_id=None, app_id=None, run_id=None, metadata=None, messages=None, datapack_id=None)` | write | Store fact/preference/entity as long-term memory |
66
+ | `memory_search(scope, query, agent_id, conversation_id="", user_id=None, limit=10, datapack_id=None)` | read | Semantic search across memories + graph relations. `conversation_id` optional (omit or pass `""` for cross-conversation discovery). |
67
+ | `memory_get_by_id(scope, memory_id, agent_id, conversation_id, datapack_id=None)` | read | Direct pgvector row lookup by UUID. Preferred over `memory_search` for exact-id verification. |
68
+ | `memory_get_all(scope, agent_id, conversation_id, user_id=None, app_id=None, run_id=None, datapack_id=None)` | read | List all memories for agent |
69
+ | `memory_update(scope, memory_id, text, agent_id, conversation_id, datapack_id=None)` | write | Overwrite memory text |
70
+ | `memory_delete_by_id(scope, memory_id, agent_id, conversation_id, datapack_id=None)` | write | Delete a single memory |
71
+ | `memory_delete_all(scope, agent_id, conversation_id, user_id=None, app_id=None, run_id=None, datapack_id=None)` | admin | Delete all memories for agent (destructive) |
72
+ | `flush_pending_memory_candidates(scope, agent_id)` | read | Desktop-skill helper: returns an instruction payload telling the agent to scan recent user turns and `memory_add` unsaved facts. No server-side DB write. |
73
+
74
+ ## Conversation Tools (6)
75
+
76
+ | Tool | Scope | Purpose |
77
+ |------|-------|---------|
78
+ | `conversation_create(scope, agent_id, user_id=None, app_id=None, run_id=None, title=None, metadata=None, session_id="")` | write | Create conversation container (Langfuse session) |
79
+ | `conversation_add_message(scope, conversation_id, agent_id, input, output=None, reasoning=None, metadata=None, seed=None, trace_id="")` | write | Add a message turn (Langfuse trace) |
80
+ | `conversation_get(scope, conversation_id, agent_id, include_messages=False, limit=100, offset=0)` | read | Retrieve conversation, optionally with messages |
81
+ | `conversation_list(scope, agent_id, conversation_id="", user_id=None, limit=20, offset=0)` | read | List conversations for agent. `conversation_id` optional (omit for browse). |
82
+ | `conversation_update(scope, conversation_id, agent_id, title=None, metadata=None)` | write | Update title or metadata |
83
+ | `conversation_delete(scope, conversation_id, agent_id)` | admin | Delete entire conversation (destructive) |
84
+
85
+ ## Datapack Management Tools (5)
86
+
87
+ | Tool | Scope | Purpose |
88
+ |------|-------|---------|
89
+ | `datapack_create(scope, name)` | write | Create new datapack |
90
+ | `datapack_list(scope)` | read | List all datapacks |
91
+ | `datapack_describe(scope, name, include_status=False)` | read | Describe datapack |
92
+ | `datapack_update(scope, name, connection_string)` | write | Update connection string |
93
+ | `datapack_delete(scope, name)` | admin | Delete datapack (irreversible) |
94
+
95
+ ## Platform capabilities NOT exposed via MCP
96
+
97
+ Some things the Meko platform can do are not wired into the MCP tool surface today. If a user asks about them, do not invent MCP tool calls — point them at the appropriate control plane instead. Agents attempting these as MCP tools will hit "tool not found".
98
+
99
+ | Capability | Where it lives | How to reach it |
100
+ |---|---|---|
101
+ | Create / list / delete **agents** within a datapack | `yugabyte/meko` API server | REST: `POST/GET/DELETE /datapacks/:name/agents` (`POST/GET/DELETE /agents/:agent` for targeted deletes), or the Meko control-plane UI |
102
+ | Add / list / delete **knowledge-base sources** on a datapack | `yugabyte/meko` API server | REST: `POST/GET/DELETE /datapacks/:name/knowledge-bases`, plus `upload-url`, `upload-complete`, `create`, `status` subroutes. Also available in the Meko UI. |
103
+ | Langfuse project-key generation | `yugabyte/meko` API server | REST: `POST /datapacks/:name/langfuse/project-keys` |
104
+ | Account / billing / tier management | Meko UI only | Not available via MCP or public REST |
105
+
106
+ The MCP-exposed `datapack_create` / `datapack_list` / `datapack_describe` / `datapack_update` / `datapack_delete` tools above are a deliberate subset — the common CRUD that an agent reasonably needs mid-conversation. Anything involving agent or KB lifecycle is control-plane territory.
107
+
108
+ For knowledge-base content on cloud today, the canonical path is **UI upload**: Datapack → Actions → **Add Knowledge** (PDF/TXT/MD/JSON/MP4, 5MB each, 10/batch). `knowledgebase_search` queries the resulting index from MCP. The MCP ingestion tools (`knowledgebase_trigger_index_creation`, `knowledgebase_add_source_to_index`, `knowledgebase_check_index_status`) exist but are Free-Tier gated and rely on an S3-only worker with no user-supplied credentials — see `tools-rag-workflow.md` for the full picture. Tracked upstream as [#89](https://github.com/yugabyte/meko-mcp-server/issues/89) / MEKO-96.
109
+
110
+ ## Common Parameter Patterns
111
+
112
+ Every tool accepts `scope` as the first parameter. All DB, RAG, and memory tools accept optional `datapack_id` to target a specific datapack's database. Memory and conversation tools require `agent_id` for namespace isolation (see `tools-agent-id-conventions.md`).
@@ -0,0 +1,134 @@
1
+ # Knowledge Base / RAG workflow
2
+
3
+ As of 2026-05-07, **knowledge-base ingestion on cloud Meko is a UI-only activity**. The MCP ingestion tools exist but are gated off on cloud and rely on an S3-only worker that has no mechanism to read user-supplied buckets. `knowledgebase_search` is the only KB tool agents can rely on today.
4
+
5
+ This page tells you which tool to reach for, what's usable where, and where the current gaps are tracked.
6
+
7
+ ## Decision table
8
+
9
+ | Situation | Use this | Why |
10
+ |---|---|---|
11
+ | Search an existing KB | `knowledgebase_search` | The one KB tool that works on cloud Free Tier and prod today |
12
+ | Add documents to a KB on cloud | **Meko UI** — Datapack → Actions menu → **Add Knowledge** | File-upload dialog (PDF/TXT/MD/JSON/MP4, 5MB each, 10/batch). The MCP ingestion path is not usable on cloud |
13
+ | Create a new vector index (self-hosted / paid) | `knowledgebase_trigger_index_creation` | Only works when the ingestion worker has IAM access to the S3 bucket you pass |
14
+ | Add a source to an existing index (self-hosted / paid) | `knowledgebase_add_source_to_index` | Same caveat as above |
15
+ | Poll a build (self-hosted / paid) | `knowledgebase_check_index_status` | Gated on cloud Free Tier |
16
+ | Anything that needs KB lifecycle management (list, delete, rename) | **UI** | No MCP tools for KB lifecycle |
17
+
18
+ ## knowledgebase_search — the one you'll actually call
19
+
20
+ ```
21
+ knowledgebase_search(
22
+ scope="read",
23
+ query="natural-language question",
24
+ agent_id="claude_desktop",
25
+ conversation_id="<uuid from conversation_create>",
26
+ datapack_id="<datapack UUID — REQUIRED on this tool>",
27
+ limit=10)
28
+ ```
29
+
30
+ Required: `scope`, `query`, `agent_id`, `conversation_id`, `datapack_id`. Unlike the memory tools, `datapack_id` has no default here — you must pass it explicitly. `agent_id` is **ignored for filtering** on this tool (KB results are team-shared on the datapack), but you still pass it — your session's value is fine.
31
+
32
+ Response shape (verified 2026-05-07 against prod):
33
+ ```
34
+ {"results": [], "count": 0}
35
+ ```
36
+
37
+ On a populated KB each result carries chunk content and similarity scores. On an empty or nonexistent KB you get an empty array and `count: 0` — not an error.
38
+
39
+ ## MCP ingestion tools — what actually happens when you call them
40
+
41
+ This applies to `knowledgebase_trigger_index_creation` and `knowledgebase_add_source_to_index`. Understanding the two-layer architecture is the only way to predict whether a call will succeed.
42
+
43
+ **MCP layer (`src/tools.py`):** takes `source_uris`, splits on `,`, passes each string to `dist_rag.create_source(<uri>)` with **zero validation**. No scheme check, no reachability probe. Returns `"build_triggered"` immediately.
44
+
45
+ **Worker layer (`yugabyte-db/python/ai/rag_agent/rag_pipeline/aws_source_processor.py`):** only handles `s3://` URIs. Any other scheme raises `ValueError("Invalid source URI")` inside the worker — **async, never surfaced to the MCP caller**. The S3 crawler is instantiated with no credentials; it relies on boto3's default chain (env vars, IAM role, `~/.aws/credentials` on the worker host). So the worker can only read buckets its own AWS identity has access to.
46
+
47
+ **Implication:** pointing the MCP tool at a user-owned S3 bucket from cloud will return `"build_triggered"` and silently stall at INIT forever. There is no way for the user to supply AWS credentials through the MCP tool.
48
+
49
+ ## Free-Tier cloud gating (verified 2026-05-07 against `https://mcp.mekodata.ai/mcp`)
50
+
51
+ | Tool | Verbatim response |
52
+ |---|---|
53
+ | `knowledgebase_trigger_index_creation` | `{"error": "not_available", "detail": "Vector index creation is not available on the free tier."}` |
54
+ | `knowledgebase_add_source_to_index` | Same as above |
55
+ | `knowledgebase_check_index_status` | `{"error": "not_available", "detail": "Index status check is not available on the free tier."}` |
56
+ | `knowledgebase_search` | Works: `{"results": [], "count": 0}` |
57
+
58
+ `{"error": "not_available"}` is a server-side tier block. Don't retry.
59
+
60
+ ## UI ingestion (cloud Meko) — what the user sees
61
+
62
+ From `cloud.mekodata.ai`:
63
+
64
+ 1. Open a datapack (`/datapacks/<name>`).
65
+ 2. Click **Actions** → **Add Knowledge**.
66
+ 3. Drag-and-drop or browse for files. Supported: PDF, TXT, MD, JSON, MP4. Per-file limit 5 MB. Up to 10 files per batch.
67
+ 4. The UI handles upload, storage, and index build. The user does not pick a bucket or provide credentials.
68
+ 5. Search results from `knowledgebase_search` become available once indexing completes.
69
+
70
+ If a user asks you "how do I add a document to my knowledge base?", point them at this flow. Do not suggest `knowledgebase_trigger_index_creation` with an S3 URI — on cloud that path does not work.
71
+
72
+ ## Tracked gaps
73
+
74
+ - **Upstream GitHub**: [yugabyte/meko-mcp-server#89](https://github.com/yugabyte/meko-mcp-server/issues/89) — disable or gate KB ingestion tools on cloud until the S3 path works end-to-end; return a clearer error than "not_available"; validate schemes at MCP-call time.
75
+ - **Upstream Jira**: MEKO-96 (same issue, cross-linked).
76
+
77
+ When either lands, the free-tier-gate responses above will change and this page should be revisited.
78
+
79
+ ## Response-shape reference (for agents that need to parse)
80
+
81
+ ### knowledgebase_search
82
+
83
+ Populated KB:
84
+ ```
85
+ {
86
+ "results": [
87
+ {
88
+ "content": "<chunk text>",
89
+ "similarity": 0.87,
90
+ "source_uri": "<original source URI>",
91
+ "document_name": "<file key>",
92
+ ...
93
+ },
94
+ ...
95
+ ],
96
+ "count": <int>
97
+ }
98
+ ```
99
+
100
+ Empty or nonexistent KB: `{"results": [], "count": 0}` (no error).
101
+
102
+ ### knowledgebase_trigger_index_creation (when not gated)
103
+
104
+ Success shape:
105
+ ```
106
+ {
107
+ "source_ids": ["<uuid>", ...],
108
+ "index_id": "<uuid>",
109
+ "index_name": "<name>",
110
+ "status": "build_triggered",
111
+ "message": "N source(s) registered, index '...' initialised, and build triggered."
112
+ }
113
+ ```
114
+
115
+ Do NOT retry this on failure. Each call creates a new index.
116
+
117
+ ### knowledgebase_add_source_to_index (when not gated)
118
+
119
+ The historical `r_index_name` vs `r_index_id` parameter-mismatch bug is fixed on main (`src/tools.py` resolves `index_name → index_id` via `SELECT id FROM dist_rag.vector_indexes WHERE index_name = %s` before calling the dist_rag function). If `index_name` doesn't exist you get `{"error": "index_not_found", "detail": "No vector index found with name '...'"}`.
120
+
121
+ Param is `source_uri` (URI string like `s3://bucket/path/`), **not** `source_id` as older docs may claim.
122
+
123
+ ### knowledgebase_check_index_status (when not gated)
124
+
125
+ Returns `pipeline_details` (per-document status) and `pipeline_stats` (aggregated). Check `completion_rate_percent` in `pipeline_stats` and `document_status` in `pipeline_details`.
126
+
127
+ Stuck at INIT for >5 minutes under self-hosted usually means the worker couldn't reach the bucket — check AWS credentials on the worker host, not the MCP server.
128
+
129
+ ## Prerequisites (self-hosted)
130
+
131
+ - `dist_rag` PostgreSQL extension enabled on the target YugabyteDB database
132
+ - Ingestion workers running (`yugabyte-db/python/ai/rag_agent/`)
133
+ - AWS credentials on the worker host for any S3 bucket you intend to ingest from
134
+ - `datapack_id` passed on every call when targeting a non-default datapack
@@ -0,0 +1,75 @@
1
+ # Scope Permission Hierarchy and Per-Tool Requirements
2
+
3
+ **WRONG:** `db_run_write_query(scope="read", ...)` → PermissionError: requires 'write' or higher.
4
+ **WRONG:** `memory_delete_all(scope="write", ...)` → PermissionError: requires 'admin'.
5
+
6
+ ## Scope Hierarchy
7
+
8
+ ```
9
+ admin (level 2) -- can do everything
10
+ ↓
11
+ write (level 1) -- can read + write, not admin-only
12
+ ↓
13
+ read (level 0) -- can only read
14
+ ```
15
+
16
+ Higher scopes include lower scopes. An unrecognized scope string always fails.
17
+
18
+ ## Per-Tool Requirements
19
+
20
+ ### read scope (11 tools)
21
+
22
+ | Tool | Group |
23
+ |------|-------|
24
+ | `db_summarize_database` | Database |
25
+ | `db_run_read_only_query` | Database |
26
+ | `knowledgebase_check_index_status` | RAG |
27
+ | `memory_search` | Memory |
28
+ | `memory_get_by_id` | Memory |
29
+ | `memory_get_all` | Memory |
30
+ | `flush_pending_memory_candidates` | Memory |
31
+ | `conversation_get` | Conversation |
32
+ | `conversation_list` | Conversation |
33
+ | `datapack_list` | Datapack |
34
+ | `datapack_describe` | Datapack |
35
+
36
+ ### write scope (11 tools)
37
+
38
+ | Tool | Group |
39
+ |------|-------|
40
+ | `db_run_write_query` | Database |
41
+ | `knowledgebase_trigger_index_creation` | RAG |
42
+ | `knowledgebase_add_source_to_index` | RAG |
43
+ | `memory_add` | Memory |
44
+ | `memory_update` | Memory |
45
+ | `memory_delete_by_id` | Memory |
46
+ | `conversation_create` | Conversation |
47
+ | `conversation_add_message` | Conversation |
48
+ | `conversation_update` | Conversation |
49
+ | `datapack_create` | Datapack |
50
+ | `datapack_update` | Datapack |
51
+
52
+ ### admin scope (3 tools — destructive, irreversible)
53
+
54
+ | Tool | Group |
55
+ |------|-------|
56
+ | `memory_delete_all` | Memory |
57
+ | `conversation_delete` | Conversation |
58
+ | `datapack_delete` | Datapack |
59
+
60
+ Agent and knowledge-base lifecycle tools are not MCP-exposed — see "Platform capabilities NOT exposed via MCP" in `tools-overview.md`.
61
+
62
+ ## Best Practices
63
+
64
+ 1. **Use the minimum scope needed.** `scope="read"` for reads documents intent and prevents accidental writes.
65
+ 2. **The scope is a parameter, not an auth token.** When OAuth is enabled, the actual permission check happens against the OAuth token's claims. Both `scope` parameter and OAuth permissions must be satisfied.
66
+
67
+ ## Common Mistakes
68
+
69
+ **WRONG:** `scope="all"` — there is no "all" scope. Valid values are exactly: `"read"`, `"write"`, `"admin"`. Nothing else.
70
+
71
+ Other invalid values that will fail: `"readwrite"`, `"rw"`, `"full"`, `"any"`.
72
+
73
+ The error `Insufficient scope: 'all'. This tool requires 'read' or higher.` means the scope string was not recognized as a valid value. Always use one of the three valid strings.
74
+
75
+ **Default choice:** Start with `scope="read"` unless you specifically need to write or delete.