@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
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Meko Setup Installer
2
2
 
3
- A zero-dependency Node.js CLI that configures [Meko MCP Server](https://mekodata.netlify.app/) for Claude Code, Claude Desktop, and Cursor in one command. It registers MCP server settings, configures hook/runtime environment where supported, installs skills support, and validates the setup.
3
+ A zero-dependency Node.js CLI that configures [Meko MCP Server](https://mekodata.netlify.app/) for Claude Code, Claude Desktop, Cursor, and OpenAI Codex (CLI + Desktop App) in one command. It registers MCP server settings, configures hook/runtime environment where supported, installs skills support, and validates the setup.
4
4
 
5
5
  Reduces manual setup to a single command.
6
6
 
@@ -18,7 +18,7 @@ The installer is path-agnostic — the three forms below are equivalent. Pick th
18
18
  | Repo clone, from repo root | `node installer/bin/create-meko-setup.mjs [options]` |
19
19
  | Repo clone, from `installer/` | `node bin/create-meko-setup.mjs [options]` |
20
20
 
21
- Claude Desktop install (issue [#7](https://github.com/amiramm/meko-mcp-server/issues/7)) still requires a repo clone — the `.skill` packaging script isn't bundled. All other clients work from the npm tarball without a checkout.
21
+ Claude Desktop has two install paths: a one-click `.mcpb` Desktop Extension downloaded from GitHub Releases, and the scripted installer here (run via `npx` or from a clone) — only the latter also installs the agent skill bundle. See [Claude Desktop install](#claude-desktop-install) below for the full comparison.
22
22
 
23
23
  **Interactive (recommended for first-time users):**
24
24
 
@@ -40,19 +40,57 @@ npx @yugabytedb/meko-mcp --local --yes
40
40
  npx @yugabytedb/meko-mcp --client cursor --local --scope project --yes
41
41
  ```
42
42
 
43
- **Claude Desktop install (local, from a repo clone):**
43
+ **Claude Desktop install:**
44
44
 
45
- Claude Desktop supports two install paths — pick one per machine:
45
+ Claude Desktop has two install paths — pick based on whether you want the agent skill (the behavioral guide that teaches the agent *when* to call Meko tools, like proactive `memory_add`):
46
46
 
47
- **Option A — Desktop Extension (`.mcpb`), one-click.** Download `meko-<version>.mcpb` from the [GitHub Releases page](https://github.com/amiramm/meko-mcp-server/releases) and drag it onto **Claude Desktop > Settings > Extensions > Install from file**. You'll be prompted for your Meko MCP URL and API key in the Settings UI, and that's it. Best for non-technical users. See [`mcpb/README.md`](../mcpb/README.md) for what's in the bundle. Prerequisite: Node 18+ on PATH (the bundle launches `npx mcp-remote` under the hood).
47
+ | | Option A: `.mcpb` Desktop Extension | Option B: `create-meko-setup` installer |
48
+ |---|---|---|
49
+ | Installs MCP server | Yes | Yes |
50
+ | Installs the agent skill (behavioral guide) | **No** | **Yes** |
51
+ | Repo clone needed | No | No (works via `npx`); clones also work |
52
+ | Best for | Non-technical users; quickest path to a working MCP connection | Anyone who wants the skill that teaches the agent *when* to call Meko tools |
53
+ | Auto-capture of conversations/memories | No (see [issue #8](https://github.com/amiramm/meko-mcp-server/issues/8)) | Skill-driven only — the agent is prompted to call `memory_add` proactively, but it's not as reliable as Claude Code hooks |
54
+
55
+ You can also combine both: install via `.mcpb` for the MCP wiring, then run Option B to add the skill bundle. If you re-run the Option B installer on top of an `.mcpb` install, it detects the existing entry and prompts before overwriting `mcpServers.meko`.
56
+
57
+ **Option A — Desktop Extension (`.mcpb`), one-click:**
58
+
59
+ 1. Download `meko-<version>.mcpb` from the [GitHub Releases page](https://github.com/yugabyte/meko-mcp-server/releases) (e.g. `meko-1.1.0.mcpb`).
60
+ 2. Open **Claude Desktop > Settings > Extensions > Install from file** and select the file (or drag the file onto that pane).
61
+ 3. When prompted, paste your Meko MCP URL and API key.
62
+ 4. Quit and relaunch Claude Desktop.
63
+ 5. Verify in chat: *"Is Claude configured with an MCP Server for Meko?"*
64
+
65
+ Prerequisite: Node 18+ on `PATH` (the bundle launches `npx mcp-remote` under the hood). See [`mcpb/README.md`](../mcpb/README.md) for what's in the bundle.
48
66
 
49
- **Option B — `create-meko-setup` installer.** Use this when you want a scripted / repeatable install, or when you need the `.skill` bundle built at the same time:
67
+ **Option B — `create-meko-setup` installer:**
68
+
69
+ Run via `npx` (no clone needed) — pick the form that matches the table at the top of this section. From a repo clone:
50
70
 
51
71
  ```bash
52
72
  node installer/bin/create-meko-setup.mjs --client claude-desktop --local --yes
53
73
  ```
54
74
 
55
- Builds a `.skill` bundle at `skills/meko-mcp-tools-desktop.skill`. Drag it onto Claude Desktop (or import via Settings > Extensions) once and restart the app. The installer also merges `mcpServers.meko` into `claude_desktop_config.json`. If it detects that Meko was previously installed via the `.mcpb` path (Option A), it flags the entry and prompts before overwriting so you don't end up with two conflicting configs.
75
+ Or via npm without a clone:
76
+
77
+ ```bash
78
+ npx @yugabytedb/meko-mcp --client claude-desktop --local --yes
79
+ ```
80
+
81
+ This does two things:
82
+
83
+ 1. Merges `mcpServers.meko` into `claude_desktop_config.json` (backed up to `.bak`).
84
+ 2. Builds the `meko-mcp-tools-desktop.skill` bundle and prints its absolute path. The location depends on how you invoked the installer — under the npm package's asset root for `npx`, or under `skills/` in your clone.
85
+
86
+ Then, **once per machine**:
87
+
88
+ 1. Open the path that the installer printed (look for the `Built Meko skill bundle: ...` log line).
89
+ 2. Drag `meko-mcp-tools-desktop.skill` onto the Claude Desktop window — or import it via **Settings > Extensions > Install from file**.
90
+ 3. Quit and relaunch Claude Desktop.
91
+ 4. Verify the skill loaded: ask *"Which Meko skills do you have available?"* — the agent should mention `meko-mcp-tools-desktop`.
92
+
93
+ Re-run the installer to refresh the bundle when skill content updates; you'll need to re-drag the rebuilt `.skill` to pick up changes.
56
94
 
57
95
  **Install on multiple clients at once:**
58
96
 
@@ -82,10 +120,18 @@ The installer performs up to 5 steps (some are skippable via flags):
82
120
  | Step | Action | Command / File Modified |
83
121
  |------|--------|------------------------|
84
122
  | 1 | Register MCP server | `claude mcp add meko <url> --transport http --scope user` (with `-H "Authorization: Bearer <key>"` for cloud) |
85
- | 2 | Set hook environment vars | Writes `MEKO_MCP_URL` and `MEKO_API_KEY` into `~/.claude/settings.json` under the `env` key |
123
+ | 2 | Set hook environment vars | Writes `MEKO_MCP_URL` and `MEKO_API_KEY` into `~/.claude/settings.json` under the `env` key. Also prunes any stale Meko hook entries in `settings.json.hooks` that point at a prior install path (e.g. a previous `npx` cache or homebrew-global copy) so only the current install's hooks fire. |
86
124
  | 3 | Register plugin marketplace | `claude plugin marketplace add yugabyte/meko-mcp-server --scope user` |
87
125
  | 4 | Install skills plugin | `claude plugin install meko-agent-skills --scope user` |
88
- | 5 | Validate setup | Config check via `claude mcp list`, MCP `initialize` handshake, `tools/list` verification |
126
+ | 5 | Validate setup | Config check via `claude mcp list`, MCP `initialize` handshake, `tools/list` verification, and a canary `datapack_list` call |
127
+
128
+ ### Post-install validation (canary)
129
+
130
+ Step 5 includes a **canary call** that invokes the read-only `datapack_list` tool and asserts the response is a non-empty JSON array of datapack records. This proves the part of the stack that connectivity + `tools/list` don't cover: the API token authenticated as a real Meko identity, the tenant resolver found an account for it, and datapack routing wired up the user's actual workspace. A successful `tools/list` only proves the server speaks MCP — it says nothing about whether a Meko tool call would actually find the user's data.
131
+
132
+ The canary used to do a `memory_add` → `memory_get_by_id` → `memory_delete_by_id` round-trip, but mem0's LLM fact-extractor is non-deterministic for synthetic test text — for the same input it sometimes returned `results: []` (no facts extracted) while still adding graph relations, which the installer reported as "no memory id" and surfaced as a validation failure even when the server was healthy. `datapack_list` is a single SQL read with no LLM in the path and returns deterministically.
133
+
134
+ `--no-canary` skips the canary entirely. The `initialize` and `tools/list` checks still run. Use this when you've already proved the round-trip in a prior step (CI, pre-flight smoke).
89
135
 
90
136
  **Files modified (depends on `--client`):**
91
137
 
@@ -100,6 +146,15 @@ The installer performs up to 5 steps (some are skippable via flags):
100
146
  - MCP config: `~/.cursor/mcp.json` or `.cursor/mcp.json`
101
147
  - Hooks config: `~/.cursor/hooks.json` or `.cursor/hooks.json` (native mode)
102
148
  - Skills path: `~/.cursor/skills` or `.cursor/skills`
149
+ - **OpenAI Codex (CLI + Desktop App)** — one install configures both surfaces (they share `~/.codex/`).
150
+ - MCP config: `~/.codex/config.toml` (TOML; `[mcp_servers.<name>]` block).
151
+ - Skills path: `~/.agents/skills/meko-mcp-tools/` (the shared agent-skills convention).
152
+ - System prompt: `~/.codex/AGENTS.md` (a Meko-managed sentinel block is upserted; user content outside the fence is preserved).
153
+ - **Cloud auth (MCP server)**: Codex's TOML stores `bearer_token_env_var = "MEKO_API_KEY"` rather than the key itself. You must export `MEKO_API_KEY` in your shell before launching Codex. The installer offers (interactively, never with `--yes`) to append the export line to your shell rc (`~/.zshrc` / `~/.bashrc` / `~/.config/fish/config.fish`). On macOS, when the desktop app is detected and an API key is supplied, the installer runs `launchctl setenv MEKO_API_KEY ...` so Codex.app launched from Finder/Dock can authenticate in the current login session.
154
+ - **No project scope**: Codex has no per-project config. `--scope project --client codex` warns and degrades to user scope.
155
+ - **Auto-capture hooks**: when Codex hooks are available, the installer writes Meko lifecycle hooks to `~/.codex/hooks.json` and prunes stale Meko hook entries from deleted install paths. Memory persistence still also works via the model proactively calling `memory_search` / `memory_add` (the AGENTS.md block prompts this).
156
+ - **API key storage** (security note): Codex's hooks.json schema rejects a top-level `env` block and provides no per-command env field. The installer writes `MEKO_MCP_URL` and (when supplied) `MEKO_API_KEY` to `~/.codex/meko-env.sh` at mode 0600 (user read/write only); each hook's `command` field sources that file before invoking bash, e.g. `. '/Users/you/.codex/meko-env.sh' && bash '/.../session-start.sh'`. The key never appears in process arguments, so `ps -ef` from another user can't lift it while a hook is running. Trust boundary is the same as `~/.aws/credentials` or `~/.netrc` — file-system permissions on the user's home directory. If your threat model precludes even that, install for the local Meko URL (no API key prompt), or skip hook installation by deleting the Meko entries from `~/.codex/hooks.json` and removing `~/.codex/meko-env.sh` after install.
157
+ - **Restart Codex.app** after install so it picks up the new MCP server registration.
103
158
 
104
159
  ## CLI Reference
105
160
 
@@ -110,15 +165,16 @@ Usage:
110
165
 
111
166
  | Flag | Description | Default |
112
167
  |------|-------------|---------|
113
- | `--client <list>` | Target client(s): one or more of `claude-code`, `claude-desktop`, `cursor`. Comma-separated, or `all` | `claude-code` |
168
+ | `--client <list>` | Target client(s): one or more of `claude-code`, `claude-desktop`, `cursor`, `codex`. Comma-separated, or `all`. `codex` covers both the OpenAI Codex CLI and the Codex Desktop App (they share `~/.codex/config.toml`). | `claude-code` |
114
169
  | `--url <url>` | MCP server URL (from app.mekodev.com > Datapacks > Connect) | _(interactive prompt)_ |
115
- | `--api-key <key>` | API key for Cloud Meko authentication | _(interactive prompt or `$MEKO_API_KEY` env)_ |
170
+ | `--api-key <key>` | API key for Cloud Meko authentication. If a Cloud `--url` is supplied without this flag, the installer falls back to `$MEKO_API_KEY`, then to an interactive prompt on a TTY. Only fails hard when running under `--yes` or with no TTY attached. | _(interactive prompt or `$MEKO_API_KEY` env)_ |
116
171
  | `--local` | Use local Meko at `http://localhost:8000/mcp` (no API key needed) | `false` |
117
172
  | `--scope <scope>` | Config scope: `user` or `project` (`claude-desktop` uses user scope config) | `user` |
118
173
  | `--name <name>` | MCP server name in config | `meko` |
119
- | `--cursor-hook-mode <mode>` | Cursor hook strategy: `native`, `claude-compat`, `hybrid` | `hybrid` |
174
+ | `--cursor-hook-mode <mode>` | Cursor hook strategy: `native` or `claude-compat` | `native` |
120
175
  | `--skip-skills` | Skip plugin marketplace and skills installation (steps 3-4) | `false` |
121
176
  | `--skip-validation` | Skip post-install validation (step 5) | `false` |
177
+ | `--no-canary` | Skip the canary `datapack_list` call. Basic connectivity + tools/list still run. | `false` |
122
178
  | `--dry-run` | Show what would be done without making changes | `false` |
123
179
  | `--uninstall` | Remove Meko MCP server, skills, env vars, and marketplace entry | `false` |
124
180
  | `--verbose` | Show detailed output (API keys are always redacted) | `false` |
@@ -149,9 +205,9 @@ After installing Meko, `--migrate` seeds your new datapack with the conversation
149
205
  |---|---|---|
150
206
  | Claude Code transcripts | `~/.claude/projects/<slug>/<uuid>.jsonl` | One Meko conversation (one Langfuse trace) per session; one paired user↔assistant turn per message pair. |
151
207
  | Cursor transcripts | `~/.cursor/projects/<name>/agent-transcripts/<uuid>/*.jsonl` | Same — one conversation per session, one paired turn per user↔assistant round. |
152
- | User-scope CLAUDE.md | `~/.claude/CLAUDE.md` | One memory per top-level `# ` section (agent = `claude-code:user`). |
153
- | Project-scope CLAUDE.md | `<projectCwd>/.claude/CLAUDE.md` | One memory per top-level `# ` section (agent = `claude-code:<slug>`). |
154
- | Indexed project memories | `~/.claude/projects/<slug>/memory/*.md` | One memory per file; YAML frontmatter (`name`, `description`, `type`) is preserved in metadata. |
208
+ | User-scope CLAUDE.md | `~/.claude/CLAUDE.md` | One memory per top-level `# ` section (`agent_id = "meko_agent"` — the cross-project common bucket — with `metadata.scope = "user"`). |
209
+ | Project-scope CLAUDE.md | `<projectCwd>/.claude/CLAUDE.md` | One memory per top-level `# ` section (`agent_id = "claude_code:<repo-basename>"`, `metadata.scope = "project"`, `metadata.cwd = <project path>`). |
210
+ | Indexed project memories | `~/.claude/projects/<slug>/memory/*.md` | One memory per file (`agent_id = "claude_code:<repo-basename>"`); YAML frontmatter (`name`, `description`, `type`) is preserved in metadata. |
155
211
 
156
212
  Project `cwd` is derived by reading the `cwd` field from a real session file in each slug directory — never by reverse-slugging the directory name, which loses `.` and `-` in component names.
157
213
 
@@ -227,7 +283,7 @@ status: running (pending → running → done | failed | stopped)
227
283
  scope: user
228
284
  started: 2026-04-29T00:09:12.673Z
229
285
  finished: (in progress)
230
- current: claude-code:-Users-.../meko-test / a2f6a1d6-... (<adapter>:<source-session> / <message-id>)
286
+ current: agent / a2f6a1d6-... (agent_id / source-session-uuid)
231
287
  sessions: 76 / 111 (processed / discovered)
232
288
  messages: 674
233
289
  memory pairs: 674 (memory_add from Mem0 extractor)
@@ -260,31 +316,35 @@ memory errs: 0 (failed memory_add calls; re-run with --force to
260
316
 
261
317
  - Per-run logs: `~/.meko/migrate/<run-id>/log.ndjson` (one JSON object per line). `tail -f | jq .` is a reasonable debug loop.
262
318
  - Per-run progress snapshot: `~/.meko/migrate/<run-id>/progress.json` (what `--migrate-status` reads).
263
- - Durable state: `~/.meko/migrate/state.json` tracks per-session checkpoints (`conversationId`, `messagesSent`, `lastUuid`, `status`) and per-memory content hashes. A re-run skips sessions marked `done` and memories whose body hash is unchanged. A partial session resumes from `lastUuid + 1`.
319
+ - Durable state: `~/.meko/migrate/state/<datapack-key>.json` tracks per-session checkpoints (`conversationId`, `messagesSent`, `lastUuid`, `status`) and per-memory content hashes, **scoped per destination datapack**. A re-run skips sessions marked `done` and memories whose body hash is unchanged. A partial session resumes from `lastUuid + 1`.
320
+ - **Per-datapack scoping**: the datapack key is the UUID segment of the MCP URL (`https://<uuid>.mcp.mekodev.com/mcp` → `<uuid>`), or a stable 16-char sha256 prefix for non-UUID URLs (e.g. `http://localhost:8000/mcp`). Switching datapacks produces completely independent state — migrating into a fresh datapack never falsely treats sessions as already-done just because an earlier run populated a different one. `--migrate-status` prints the `datapack:` key of the latest run so you can tell at a glance which state it belongs to.
321
+ - Back-compat for the legacy layout: migrations created before this change wrote to a single `~/.meko/migrate/state.json`. On the first run after upgrading, if `state/` is empty and `state.json` exists, the installer asks (or, under `--yes` / CI, silently accepts) "treat the legacy state as belonging to the current datapack" and copies `state.json` → `state/<current-key>.json`. The legacy file is kept on disk in case you roll back the installer.
264
322
  - Server-side dedup: `conversation_add_message` gets a deterministic `seed = sha256(agentId + ":" + sessionUuid + ":" + messageUuid)` so partial-run overlap doesn't create duplicate messages.
265
- - `--force` wipes resume state and re-issues every MCP call (useful for testing or after a server-side wipe).
323
+ - `--force` wipes the **current datapack's** resume state and re-issues every MCP call for it. Other datapacks' state files are untouched. If you only want to re-migrate into a new datapack, just point `--url` at the new one — no `--force` needed.
266
324
 
267
325
  ### What does NOT get migrated (v1)
268
326
 
269
327
  - Slash-command skills, hooks, and `.claude/settings.json` — those remain in Claude Code's own config; Meko has no equivalent tool.
270
328
  - Knowledge-base documents — would need an S3 upload path and `knowledgebase_trigger_index_creation` wiring.
271
- - Transcripts from other coding agents (Aider, Continue.dev, Windsurf, Codex CLI). Claude Code + Cursor only.
329
+ - Transcripts from other coding agents (Aider, Continue.dev, Windsurf, Codex). Claude Code + Cursor only.
272
330
  - `user_id` is left null on every call (the server fills it from the API key). Multi-user routing is a follow-up.
273
331
 
274
332
  ## Client Compatibility Matrix
275
333
 
276
- | Capability | Claude Code | Claude Desktop | Cursor |
277
- |---|---|---|---|
278
- | One-command install | Yes | Yes | Yes |
279
- | MCP server registration | via `claude mcp add` | via `claude_desktop_config.json` merge using `mcp-remote` stdio bridge | via `.cursor/mcp.json` merge |
280
- | Backup before config write | `.bak` on `~/.claude/settings.json` | `.bak` on `claude_desktop_config.json` | `.bak` on Cursor config |
281
- | Automatic conversation capture | Yes (hooks) | **No** — see [issue #8](https://github.com/amiramm/meko-mcp-server/issues/8) | Yes (hybrid hook mode) |
282
- | Automatic memory persistence | Yes (hooks + skill) | Skill only (proactive `memory_add`) | Yes (hooks + skill) |
283
- | Skill install | Plugin marketplace (automatic) | `.skill` bundle auto-built, user drags into app | Copy into `.cursor/skills` |
284
- | Uninstall | Full automatic | MCP entry removed; skill must be removed manually from app | MCP + hooks + skills cleaned up |
285
- | `agent_id` used by skill | `claude_code` | `claude_desktop` | `claude_code` |
286
- | Transport | HTTP only | HTTP (or stdio via hand-edited config) | HTTP only |
287
- | Deferred to a follow-up | — | `.mcpb` Desktop Extension packaging — see [issue #7](https://github.com/amiramm/meko-mcp-server/issues/7) | — |
334
+ | Capability | Claude Code | Claude Desktop | Cursor | Codex (CLI + App) |
335
+ |---|---|---|---|---|
336
+ | One-command install | Yes | Yes | Yes | Yes |
337
+ | MCP server registration | via `claude mcp add` | via `claude_desktop_config.json` merge using `mcp-remote` stdio bridge | via `.cursor/mcp.json` merge | via `codex mcp add` (CLI) or direct TOML write (App-only) |
338
+ | Backup before config write | `.bak` on `~/.claude/settings.json` | `.bak` on `claude_desktop_config.json` | `.bak` on Cursor config | `.bak` on `~/.codex/config.toml` and `~/.codex/AGENTS.md` |
339
+ | Automatic conversation capture | Yes (hooks) | **No** — see [issue #8](https://github.com/amiramm/meko-mcp-server/issues/8) | Yes (native hooks) | Yes (hooks via `~/.codex/hooks.json`) |
340
+ | Automatic memory persistence | Yes (hooks + skill) | Skill only (proactive `memory_add`) | Yes (hooks + skill) | Yes (hooks + skill + AGENTS.md) |
341
+ | Skill install | Plugin marketplace (automatic) | `.skill` bundle auto-built, user drags into app | Copy into `.cursor/skills` | Copy into `~/.agents/skills/meko-mcp-tools/` |
342
+ | Uninstall | Full automatic | MCP entry removed; skill must be removed manually from app | MCP + hooks + skills cleaned up | MCP entry, skill dir, and AGENTS.md block all cleaned up |
343
+ | `agent_id` used by skill | `claude_code:<repo>` per project (via SessionStart hook); cross-project facts go to `meko_agent` | `claude_desktop` | `cursor:<repo>` per project (via Cursor hook); cross-project facts go to `meko_agent` | `claude_code:<repo>` per project (capture.js still classifies non-cursor hooks as the `claude_code` client; native `codex:<repo>` derivation is a follow-up); cross-project facts go to `meko_agent` |
344
+ | Transport | HTTP only | HTTP (or stdio via hand-edited config) | HTTP only | HTTP (Codex's `bearer_token_env_var` model) |
345
+ | Auth model | inline `Authorization: Bearer ...` header | inline header via `mcp-remote` | inline header | MCP server: env-var name reference (`MEKO_API_KEY` exported in shell or via `launchctl setenv`). Hooks: key written to `~/.codex/meko-env.sh` at mode 0600; each hook command sources the file before bash (no env block in Codex's hooks schema; see [Security](#security)). |
346
+ | Project scope | Yes (`--scope project`) | No | Yes (`--scope project`) | No (warns and degrades to user scope) |
347
+ | Deferred to a follow-up | — | `.mcpb` Desktop Extension packaging — see [issue #7](https://github.com/amiramm/meko-mcp-server/issues/7) | — | Native `codex:<repo>` agent_id classification in capture.js |
288
348
 
289
349
  ## Cloud vs Local
290
350
 
@@ -302,10 +362,19 @@ The installer auto-detects cloud vs local based on the URL: any URL containing `
302
362
 
303
363
  ## Security
304
364
 
305
- **Where credentials are stored:**
365
+ **Where credentials are stored** (per client; all files inherit standard user-only filesystem permissions):
306
366
 
307
- - **API key header** -- stored in `~/.claude.json` (MCP server config, managed by `claude mcp add`). Readable only by the current user.
308
- - **`MEKO_API_KEY` env var** -- written to `~/.claude/settings.json` so lifecycle hooks can authenticate with the MCP server. This file has standard user-only filesystem permissions.
367
+ - **Claude Code**
368
+ - API key header — stored in `~/.claude.json` (MCP server config, managed by `claude mcp add`).
369
+ - `MEKO_API_KEY` env var — written to `~/.claude/settings.json` under `env` so lifecycle hooks can authenticate with the MCP server.
370
+ - **Claude Desktop**
371
+ - `MEKO_API_KEY` env var — written to `claude_desktop_config.json` under `mcpServers.<name>.env`. The header itself uses `${MEKO_API_KEY}` interpolation in `args`, so the key value lives only in the `env` block.
372
+ - **Cursor**
373
+ - API key header — stored in `~/.cursor/mcp.json` (or `.cursor/mcp.json` for project scope) under `mcpServers.<name>.headers.Authorization`.
374
+ - `MEKO_API_KEY` env var — written to `~/.cursor/hooks.json` (native hook mode) and/or `~/.claude/settings.json` (claude-compat hook mode) under `env` so lifecycle hooks can authenticate.
375
+ - **OpenAI Codex (CLI + Desktop App)**
376
+ - MCP-server bearer reference — `~/.codex/config.toml` stores `bearer_token_env_var = "MEKO_API_KEY"`, **not** the key itself. The runtime env (shell rc or `launchctl setenv`) supplies the value.
377
+ - Hook commands — Codex's `~/.codex/hooks.json` schema rejects a top-level `env` block and provides no per-command env field, so the installer writes `MEKO_API_KEY` to `~/.codex/meko-env.sh` at **mode 0600** (user read/write only). Each Meko hook's `command` field sources that file before invoking bash, so the key never appears in process arguments — `ps -ef` from another user can't lift it while the hook runs. Same trust boundary as `~/.aws/credentials` or `~/.netrc` (file-system permissions on the user's home directory). To opt out: install for the local Meko URL (no key prompt), or skip Codex hook installation by deleting the Meko entries from `~/.codex/hooks.json` and removing `~/.codex/meko-env.sh` after install.
309
378
 
310
379
  **How credentials are protected:**
311
380
 
@@ -313,11 +382,103 @@ The installer auto-detects cloud vs local based on the URL: any URL containing `
313
382
  - `--dry-run` mode redacts the key in displayed commands (shown as `<set>`).
314
383
  - The API key is never logged to stdout or stderr during normal operation.
315
384
  - Interactive mode uses masked input (echoes `*` characters) when prompting for the API key.
316
- - The `MEKO_API_KEY` env var fallback means the key does not need to appear in shell history -- set it in your shell profile or CI secrets.
385
+ - The `MEKO_API_KEY` env var fallback means the key does not need to appear in shell history — set it in your shell profile or CI secrets.
386
+ - During Codex installs, the installer emits a `warn`-level log line confirming where the API key has been written.
317
387
 
318
388
  **Backups:**
319
389
 
320
- Before modifying `~/.claude/settings.json`, the installer creates a `.bak` copy at `~/.claude/settings.json.bak`. The merge is additive: existing keys are preserved unless explicitly overridden.
390
+ Before modifying any config file the installer touches, it creates a `.bak` copy alongside the original (e.g. `~/.claude/settings.json.bak`, `~/.codex/config.toml.bak`, `~/.codex/AGENTS.md.bak`). The merge is additive: existing keys are preserved unless explicitly overridden.
391
+
392
+ ## Upgrading
393
+
394
+ There is no separate upgrade command — re-running the installer is the upgrade mechanism. The steps below cover the canonical paths and what to expect.
395
+
396
+ ### Upgrading via `npx` (recommended)
397
+
398
+ ```bash
399
+ npx @yugabytedb/meko-mcp@latest
400
+ ```
401
+
402
+ The `@latest` tag is load-bearing. `npx` aggressively caches the installer tarball based on semver resolution, so plain `npx @yugabytedb/meko-mcp` can silently re-run a stale cached copy and appear to do nothing. `@latest` forces a registry lookup and pulls the newest published version. This applies to every `npx @yugabytedb/meko-mcp ...` example earlier in this README — append `@latest` whenever you intend to upgrade rather than re-run the same version.
403
+
404
+ ### Upgrading a globally-installed copy
405
+
406
+ If you installed via `npm install -g @yugabytedb/meko-mcp`, the `npx` path above will not touch the global copy. Update the global package first, then re-run:
407
+
408
+ ```bash
409
+ npm update -g @yugabytedb/meko-mcp
410
+ create-meko-setup
411
+ ```
412
+
413
+ ### What a re-run actually does
414
+
415
+ Re-running the installer is idempotent but not inert. A re-run:
416
+
417
+ - Overwrites the `env` block in `~/.claude/settings.json` (with a `.bak` backup — see the Security section above for backup semantics and locations).
418
+ - Prunes stale Meko hook entries in `settings.json.hooks` that reference a prior install path (e.g., a frozen `capture.js` from an old `npx` cache or homebrew-global copy). The current install's hook entries — whether they come from the plugin (`${CLAUDE_PLUGIN_ROOT}/...`) or an absolute path matching the current `hooks-handlers/` root — are preserved. Non-Meko hooks in the same arrays are untouched.
419
+ - Rewrites the Cursor skill directory and hooks config if `--client cursor` is targeted.
420
+ - Auto-updates the skills plugin if it's already installed (via `claude plugin update meko-agent-skills@meko-agent-skills`), otherwise installs it. See "Updating the skills plugin" below.
421
+ - Rebuilds the Claude Desktop `.skill` bundle if `--client claude-desktop` is targeted. You must re-drag the rebuilt bundle into Claude Desktop to pick up the new skill content.
422
+
423
+ ### Updating the skills plugin (Claude Code)
424
+
425
+ The `meko-agent-skills` plugin is distributed via the Claude Code plugin marketplace and versions independently of the installer npm package. Re-running the installer now picks up the latest skill definitions automatically: it probes `claude plugin list` and, when the plugin is already present, calls
426
+
427
+ ```bash
428
+ claude plugin update meko-agent-skills@meko-agent-skills --scope <scope>
429
+ ```
430
+
431
+ using the qualified `plugin@marketplace` form required by Claude Code CLI 2.1.x. Older CLIs that don't know `plugin update` fall back to an uninstall-then-install dance to achieve the same refresh. You can still run the update manually if you want to bypass the installer:
432
+
433
+ ```bash
434
+ claude plugin update meko-agent-skills@meko-agent-skills
435
+ ```
436
+
437
+ #### Inside an active Claude Code session
438
+
439
+ If you're already in a session and want to pull the latest skill content without exiting:
440
+
441
+ ```
442
+ /plugin marketplace update meko-agent-skills
443
+ /reload-plugins
444
+ ```
445
+
446
+ The first command refetches the marketplace's source and rebuilds the plugin cache; the second activates the new content without restarting. Run `/doctor` afterward to confirm there are no plugin load errors.
447
+
448
+ #### Enabling auto-update so future skill changes land automatically
449
+
450
+ Auto-update is **per-marketplace and disabled by default for third-party marketplaces** (only Anthropic-official marketplaces auto-update out of the box). To opt in:
451
+
452
+ 1. Open the in-session `/plugin` command, switch to the **Marketplaces** tab, select `meko-agent-skills`, and toggle **Enable auto-update**.
453
+ 2. Or set it directly in your settings file (`~/.claude/settings.json` for user scope, or a project's `.claude/settings.json`):
454
+
455
+ ```json
456
+ {
457
+ "extraKnownMarketplaces": {
458
+ "meko-agent-skills": {
459
+ "autoUpdate": true
460
+ }
461
+ }
462
+ }
463
+ ```
464
+
465
+ Once enabled, Claude Code refreshes the marketplace and pulls the latest plugin version on each session start. There's no global "auto-update everything" switch — opt in per marketplace.
466
+
467
+ ### Checking your installed version
468
+
469
+ ```bash
470
+ create-meko-setup --version
471
+ ```
472
+
473
+ ### Rollback
474
+
475
+ If an upgrade breaks something, restore the `.bak` backups the installer wrote before its changes:
476
+
477
+ ```bash
478
+ cp ~/.claude/settings.json.bak ~/.claude/settings.json
479
+ ```
480
+
481
+ See the Security section above for the full list of backup locations across Claude Code, Claude Desktop, and Cursor.
321
482
 
322
483
  ## Troubleshooting
323
484
 
@@ -342,14 +503,25 @@ Connection refused. Is the MCP server running?
342
503
  For local Meko, ensure `docker compose up -d` has started the stack.
343
504
  ```
344
505
 
345
- For local setups, confirm the stack is running and the MCP endpoint is accessible:
506
+ For local setups, confirm the stack is running and the MCP endpoint is accessible. Note that the `Accept` header **must** advertise both `application/json` and `text/event-stream` per the MCP Streamable HTTP spec — sending only one yields HTTP 406:
346
507
 
347
508
  ```bash
348
509
  curl -s http://localhost:8000/mcp -X POST \
349
510
  -H "Content-Type: application/json" \
511
+ -H "Accept: application/json, text/event-stream" \
350
512
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}'
351
513
  ```
352
514
 
515
+ For cloud, swap the URL and add `-H "Authorization: Bearer $MEKO_API_KEY"`.
516
+
517
+ ### HTTP 406 Not Acceptable
518
+
519
+ ```
520
+ Server returned HTTP 406: ... "Client must accept both application/json and text/event-stream"
521
+ ```
522
+
523
+ The MCP server is enforcing strict Streamable HTTP compliance: clients must advertise both content types in their `Accept` header. The installer does this automatically; if you see this error, you're likely on an older installer release. Upgrade with `npx @yugabytedb/meko-mcp@latest`.
524
+
353
525
  ### Authentication failure (401 / 403)
354
526
 
355
527
  ```
@@ -358,6 +530,8 @@ Server returned 401. Verify your API key is correct and has not expired.
358
530
 
359
531
  - Confirm the API key at app.mekodev.com > Datapacks > Connect.
360
532
  - If using `$MEKO_API_KEY` env var, ensure it is exported in the current shell.
533
+ - Confirm the key environment matches the URL: PATs minted on `app.mekodev.com` only validate against `mcp.mekodev.com`; PATs minted on `cloud.mekodata.ai` only validate against `mcp.mekodata.ai`.
534
+ - The installer normalizes API keys (trims surrounding whitespace and a single matching pair of quotes) so a paste with a trailing newline or a literal `"…"` from a `.env` file is fine — but your raw shell variable might still be contaminated. Echo it (`echo "[$MEKO_API_KEY]"`) and check the brackets bracket the key tightly with no extra characters.
361
535
  - Re-run the installer interactively to re-enter the key.
362
536
 
363
537
  ### Plugin marketplace already registered
@@ -384,10 +558,10 @@ cp ~/.claude/settings.json.bak ~/.claude/settings.json
384
558
  ### Missing core tools
385
559
 
386
560
  ```
387
- Missing core tools: memory_search, conversation_create. Found 0 tool(s) total.
561
+ Missing core tools: memory_search, memory_get_by_id, conversation_create. Found 0 tool(s) total.
388
562
  ```
389
563
 
390
- The MCP server responded but does not expose the expected tools (`memory_search`, `conversation_create`, `db_summarize_database`). This usually means a server version mismatch. Update the MCP server or check which datapack is connected.
564
+ The MCP server responded but does not expose the expected tools (`memory_search`, `memory_get_by_id`, `conversation_create`, `db_summarize_database`). This usually means a server version mismatch. Update the MCP server or check which datapack is connected. `memory_get_by_id` is used by the canary round-trip for direct-row verification (see [Post-install validation](#post-install-validation-canary-round-trip) above), so an older server that exposes `memory_search` but not `memory_get_by_id` will fail the canary check.
391
565
 
392
566
  ### DNS lookup failed
393
567
 
@@ -490,17 +664,27 @@ installer/
490
664
  create-meko-setup.mjs # CLI entry point (arg parsing, orchestration)
491
665
  lib/
492
666
  installer.mjs # Shared multi-client orchestration
493
- clients/ # Per-client adapters (claude-code/desktop/cursor)
494
- claude-code.mjs # Backward-compatible Claude wrapper
667
+ clients/ # Per-client adapters (claude-code/desktop/cursor), aliases, common helpers
495
668
  config.mjs # Safe JSON read/merge/write + path helpers
496
669
  detect.mjs # Claude CLI and existing config detection
497
670
  logger.mjs # ANSI-colored console output (respects NO_COLOR)
498
671
  prompt.mjs # Interactive readline prompts (choice, text, secret, yes/no)
499
- validate.mjs # Post-install validation (config, connectivity, tools)
672
+ validate.mjs # Post-install validation (config, connectivity, tools, canary)
673
+ migrate.mjs # Migrate subcommand orchestration + per-datapack state
674
+ migrate/
675
+ id.mjs # datapackKeyFromUrl + agent-id / seed helpers
676
+ orchestrator.mjs, daemon.mjs, state.mjs, progress.mjs, lockfile.mjs, logger.mjs
677
+ claude-parser.mjs, mcp-client.mjs, adapters/
678
+ scripts/
679
+ bundle-assets.mjs # prepack: copy skill/hook assets into the npm tarball
680
+ prepublish-smoke.sh # Pre-publish smoke harness (run before `npm publish`)
500
681
  test/
501
682
  config.test.mjs # Unit tests for JSON merge/read/write
502
- clients.test.mjs # Unit tests for cursor adapter behavior
503
- validate.test.mjs # Unit tests for validation logic
683
+ clients.test.mjs # Unit tests for cursor/claude-code/desktop adapters
684
+ validate.test.mjs # Unit tests for validation logic (including the canary round-trip)
685
+ migrate.test.mjs # Unit tests for migrator + datapackKeyFromUrl helper
686
+ migrate-integration.test.mjs # Integration tests for migrator scoping + legacy state back-compat
687
+ prepublish-smoke.test.mjs # Piped-stdin smoke tests, gated by SMOKE_HARNESS=1
504
688
  installer.test.mjs # Integration tests for full install flow
505
689
  fixtures/ # Mock settings files for tests
506
690
  ```
@@ -524,12 +708,26 @@ npm run test:integration
524
708
  export MEKO_TEST_CLOUD_URL=https://<your-mcp>.mekodev.com/mcp
525
709
  export MEKO_TEST_API_KEY=<your-cloud-api-key>
526
710
  npm run test:integration:cloud
711
+
712
+ # Pre-publish smoke harness: npm pack → install tarball into a throwaway
713
+ # $HOME → exercise the installed CLI (`--version`, `--help`, `--dry-run`)
714
+ # via both the raw node entry and the `node_modules/.bin/meko-mcp` symlink
715
+ # that `npx` resolves through. Gated piped-stdin tests in
716
+ # `test/prepublish-smoke.test.mjs` (SMOKE_HARNESS=1) are run by the harness.
717
+ npm run smoke
527
718
  ```
528
719
 
529
720
  The cloud round-trip tests point the installer at a throw-away `$HOME` via
530
721
  `spawnSync`, so the developer's real `~/.claude/settings.json` is never
531
722
  modified. They skip cleanly when either env var is unset.
532
723
 
724
+ The pre-publish smoke harness is the last gate before `npm publish`. See
725
+ [`RELEASING.md`](../RELEASING.md) at the repo root for the full release
726
+ procedure (version bump → smoke harness → manual TTY checklist → tag → CI
727
+ publish workflows). A CI workflow at `.github/workflows/prepublish-smoke.yml`
728
+ runs the harness on Ubuntu and macOS for every push to a `release/*`
729
+ branch.
730
+
533
731
  ### Design Principles
534
732
 
535
733
  - **Zero external dependencies** -- Node.js built-ins only (`fs`, `path`, `readline`, `child_process`, `url`, `http`, `https`, `os`, `node:test`, `node:assert`), matching the pattern of `capture.js`.
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Cursor native beforeSubmitPrompt hook. It only reads local cache populated by
4
+ # cursor-session-start.sh; it never performs Meko network calls.
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
+
8
+ load_cursor_hook_env() {
9
+ if [ -n "${MEKO_MCP_URL:-}" ]; then
10
+ return
11
+ fi
12
+ eval "$(node -e '
13
+ const fs = require("fs");
14
+ const path = require("path");
15
+ function shellQuote(value) {
16
+ return "'"'"'" + String(value).replace(/'"'"'/g, "'"'"'\\'"'"''"'"'") + "'"'"'";
17
+ }
18
+ const candidates = [
19
+ path.join(process.cwd(), ".cursor", "hooks.json"),
20
+ path.join(process.env.HOME || "", ".cursor", "hooks.json"),
21
+ ];
22
+ for (const file of candidates) {
23
+ try {
24
+ const cfg = JSON.parse(fs.readFileSync(file, "utf8"));
25
+ const env = cfg && cfg.env && typeof cfg.env === "object" ? cfg.env : {};
26
+ const out = [];
27
+ for (const key of ["MEKO_MCP_URL", "MEKO_API_KEY"]) {
28
+ if (typeof env[key] === "string" && env[key]) {
29
+ out.push(`export ${key}=${shellQuote(env[key])}`);
30
+ }
31
+ }
32
+ if (out.length) {
33
+ process.stdout.write(out.join("\n"));
34
+ break;
35
+ }
36
+ } catch {}
37
+ }
38
+ ')"
39
+ }
40
+
41
+ load_cursor_hook_env
42
+ HOOK_INPUT="$(cat)"
43
+
44
+ printf '%s' "$HOOK_INPUT" | MEKO_HOOK_CLIENT=cursor node "$SCRIPT_DIR/lib/capture.js" before-submit-prompt
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Cursor native SessionStart hook. Cursor only documents context injection from
4
+ # SessionStart, so this wrapper returns the Meko context synchronously.
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
+
8
+ load_cursor_hook_env() {
9
+ if [ -n "${MEKO_MCP_URL:-}" ]; then
10
+ return
11
+ fi
12
+ eval "$(node -e '
13
+ const fs = require("fs");
14
+ const path = require("path");
15
+ function shellQuote(value) {
16
+ return "'"'"'" + String(value).replace(/'"'"'/g, "'"'"'\\'"'"''"'"'") + "'"'"'";
17
+ }
18
+ const candidates = [
19
+ path.join(process.cwd(), ".cursor", "hooks.json"),
20
+ path.join(process.env.HOME || "", ".cursor", "hooks.json"),
21
+ ];
22
+ for (const file of candidates) {
23
+ try {
24
+ const cfg = JSON.parse(fs.readFileSync(file, "utf8"));
25
+ const env = cfg && cfg.env && typeof cfg.env === "object" ? cfg.env : {};
26
+ const out = [];
27
+ for (const key of ["MEKO_MCP_URL", "MEKO_API_KEY"]) {
28
+ if (typeof env[key] === "string" && env[key]) {
29
+ out.push(`export ${key}=${shellQuote(env[key])}`);
30
+ }
31
+ }
32
+ if (out.length) {
33
+ process.stdout.write(out.join("\n"));
34
+ break;
35
+ }
36
+ } catch {}
37
+ }
38
+ ')"
39
+ }
40
+
41
+ load_cursor_hook_env
42
+ MEKO_HOOK_CLIENT=cursor node "$SCRIPT_DIR/lib/capture.js" session-start