codex-dev-mcp-suite 1.7.0 → 1.8.1

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,26 @@
1
+ ## 1.8.0 - 2026-07-22
2
+
3
+ ### Added
4
+ - **Zero-Dependency Local Offline Vector Embedding Engine**:
5
+ - Pure JS 384-dimensional term-frequency hashing vector engine with sublinear $1 + \log(tf)$ scaling and L2 normalization (`project-memory/local-embed.js`).
6
+ - Activated via `MCP_LOCAL_EMBED=true` / `LOCAL_EMBED=true` env flag when no remote embedding API key is available.
7
+ - Sub-millisecond execution, zero network calls, zero external npm dependencies.
8
+ - Full compatibility with existing `cosine(a, b)` and graph ranking in `project-memory`.
9
+ - **Universal Multi-Client Guides**:
10
+ - Hermes Agent setup guide (`docs/clients/hermes.md`).
11
+ - Google Antigravity CLI (AGY CLI) setup guide (`docs/clients/antigravity.md`).
12
+ - Claude Code & Generic MCP setup guides (`docs/clients/claude-code.md`, `docs/clients/generic-mcp.md`).
13
+ - **Test Suite**: 100/100 unit tests passing (100% green across 8 test suites).
14
+
15
+ ## 1.7.0 - 2026-07-22
16
+
17
+ ### Added
18
+ - **Obsidian Vault Parity & MOC Tools**:
19
+ - `memory_moc` Map of Content generator & `.obsidian` vault structure integration.
20
+ - `memory_graph` knowledge graph visualization & backlinks.
21
+ - **Codebase Security Audit Tool (`pack_audit`)**:
22
+ - Detect missing `.gitignore`, exposed secrets/keys (`.env`, `.pem`, `id_rsa`), and overly large files.
23
+
1
24
  ## 1.5.0
2
25
 
3
26
  - add `memory_link` with wiki-link resolution for `[[id]]`, `[[title]]`, `[[project:id]]`, and `[[project:title]]`, plus backlink inspection
package/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
  [![npm downloads](https://img.shields.io/npm/dm/codex-dev-mcp-suite.svg)](https://www.npmjs.com/package/codex-dev-mcp-suite)
6
6
  [![license](https://img.shields.io/npm/l/codex-dev-mcp-suite.svg)](./LICENSE)
7
7
  [![node](https://img.shields.io/node/v/codex-dev-mcp-suite.svg)](https://nodejs.org)
8
+ [![Saweria](https://img.shields.io/badge/Saweria-Dukung%20Proyek-FAAE2B?style=flat&logo=saweria&logoColor=black)](https://saweria.co/sijuling)
8
9
 
9
10
  Published as `codex-dev-mcp-suite` for backward compatibility.
10
11
 
@@ -57,7 +58,7 @@ project-memory-mcp --version
57
58
  project-memory-mcp --doctor # config diagnostics; API keys redacted
58
59
  ```
59
60
 
60
- Other clients (Claude Code, Cursor, Cline, ...): see
61
+ Other clients (Claude Code, Cursor, Hermes Agent, AGY CLI, Cline, ...): see
61
62
  [`docs/clients/`](docs/clients/). Full env reference:
62
63
  [`docs/configuration.md`](docs/configuration.md). Data flow:
63
64
  [`docs/privacy.md`](docs/privacy.md).
@@ -66,20 +67,20 @@ Other clients (Claude Code, Cursor, Cline, ...): see
66
67
 
67
68
  | Server | What it does | Key tools |
68
69
  |---|---|---|
69
- | **project-memory** | Searchable Markdown knowledge vault (Obsidian-style notes + on-demand recall). Notes are also exposed as MCP resources. | `memory_save`, `memory_recall`, `memory_list`, `memory_get`, `memory_delete`, `memory_reindex`, `memory_link`, `memory_global_recall`, `memory_dedup` |
70
+ | **project-memory** | Searchable Markdown knowledge vault (Obsidian-style notes + on-demand recall). Notes are also exposed as MCP resources. | `memory_save`, `memory_recall`, `memory_list`, `memory_get`, `memory_delete`, `memory_reindex`, `memory_link`, `memory_global_recall`, `memory_dedup`, `memory_moc`, `memory_graph` |
70
71
  | **devjournal** | Per-project session timeline + handoff/resume (anti-compaction). | `journal_log`, `journal_handoff`, `journal_resume`, `journal_timeline`, `journal_search`, `journal_clear_handoff` |
71
72
  | **checkpoint** | Git-independent file snapshots for safe experimentation. | `checkpoint_create`, `checkpoint_list`, `checkpoint_diff`, `checkpoint_restore`, `checkpoint_delete` |
72
- | **context-pack** | Token-efficient project briefing (stack, tree, symbols, search). | `pack_overview`, `pack_tree`, `pack_outline`, `pack_search` |
73
+ | **context-pack** | Token-efficient project briefing & security audit (stack, tree, symbols, search, security audit). | `pack_overview`, `pack_tree`, `pack_outline`, `pack_search`, `pack_audit` |
73
74
 
74
75
  ## Recall quality (project-memory & devjournal)
75
76
 
76
77
  Recall auto-selects the best available mode:
77
78
 
78
- 1. **semantic** — if an embeddings endpoint is configured (any OpenAI-compatible `/v1/embeddings`: OpenAI, Ollama, LM Studio, OpenRouter, vLLM, LiteLLM, 9router, ...)
79
+ 1. **semantic** — if an embeddings endpoint is configured (any OpenAI-compatible `/v1/embeddings`: OpenAI, Ollama, LM Studio, OpenRouter, vLLM, LiteLLM, 9router, ...) or local offline embedding (`MCP_LOCAL_EMBED=true`)
79
80
  2. **rerank** — keyword prefilter then an LLM reranker (any OpenAI-compatible chat model)
80
81
  3. **keyword** — always-available offline fallback
81
82
 
82
- All network features degrade gracefully: no endpoint = keyword mode, never an error.
83
+ All network features degrade gracefully: no endpoint = local/keyword mode, never an error.
83
84
  Use the neutral `MCP_*` environment variables for new installs; legacy
84
85
  `NINEROUTER_*` and `LLM_*` variables are still supported. See
85
86
  [`docs/configuration.md`](docs/configuration.md).
@@ -88,6 +89,13 @@ Need hard local-only behavior? Set `MCP_DETERMINISTIC_FALLBACK=true` to disable
88
89
  embeddings/rerank even if model keys are present; results are labeled
89
90
  `[deterministic]`.
90
91
 
92
+ ### New in v1.8.0 & v1.7.0
93
+
94
+ - **Zero-Dependency Local Offline Embeddings (`v1.8.0`)**: Set `MCP_LOCAL_EMBED=true` to enable pure JS 384-d term-frequency hashing vector search when no remote embedding API key is set. Sub-millisecond execution, zero network calls, zero external npm packages.
95
+ - **Codebase Security Audit (`pack_audit` in `v1.7.0`)**: Scan projects for missing `.gitignore`, hardcoded secrets (`.env`, `.pem`, `id_rsa`), and overly large files.
96
+ - **Obsidian Vault Parity (`v1.7.0`)**: `memory_moc` generates Map of Content index files, `memory_graph` maps backlinks & graph links, and bootstrap `.obsidian` vault structure automatically.
97
+ - **Multi-Client Setup Guides**: Native support & setup guides for [Hermes Agent](docs/clients/hermes.md), [Google Antigravity CLI (AGY)](docs/clients/antigravity.md), [Claude Code](docs/clients/claude-code.md), and [Generic MCP hosts](docs/clients/generic-mcp.md).
98
+
91
99
  ## Install
92
100
 
93
101
  Requires Node.js >= 18.
@@ -342,6 +350,12 @@ your machine unless you explicitly configure an external model/API endpoint for
342
350
  rerank or embeddings. See [privacy and data flow](docs/privacy.md). Your
343
351
  personal vault/journal/checkpoints are gitignored.
344
352
 
353
+ ## ☕ Support / Donasi
354
+
355
+ Jika `codex-dev-mcp-suite` bermanfaat untuk produktivitas pengkodean Anda, dukung pengembangan proyek open-source ini melalui Saweria (QRIS, GoPay, DANA, OVO, ShopeePay):
356
+
357
+ [![Saweria](https://img.shields.io/badge/Saweria-Dukung%20Proyek-FAAE2B?style=for-the-badge&logo=saweria&logoColor=black)](https://saweria.co/sijuling)
358
+
345
359
  ## License
346
360
 
347
361
  MIT — see [LICENSE](./LICENSE).
@@ -0,0 +1,52 @@
1
+ # Google Antigravity CLI (AGY CLI) Setup
2
+
3
+ `codex-dev-mcp-suite` connects seamlessly to **Google Antigravity CLI (AGY CLI)** and the AGY SDK agent framework.
4
+
5
+ ## Quick Installation
6
+
7
+ ```bash
8
+ npm install -g codex-dev-mcp-suite
9
+ ```
10
+
11
+ ## AGY Configuration (`mcp.json` / `settings.json`)
12
+
13
+ Add the suite to your AGY CLI settings or project `mcp.json`:
14
+
15
+ ```json
16
+ {
17
+ "mcpServers": {
18
+ "project-memory": {
19
+ "command": "project-memory-mcp",
20
+ "args": [],
21
+ "env": {
22
+ "MEMORY_VAULT_DIR": "~/.local/share/dev-mcp-suite/memories/vault",
23
+ "MCP_LOCAL_EMBED": "true"
24
+ }
25
+ },
26
+ "devjournal": {
27
+ "command": "devjournal-mcp",
28
+ "args": [],
29
+ "env": {
30
+ "JOURNAL_DIR": "~/.local/share/dev-mcp-suite/memories/journal"
31
+ }
32
+ },
33
+ "checkpoint": {
34
+ "command": "checkpoint-mcp",
35
+ "args": [],
36
+ "env": {
37
+ "CHECKPOINT_DIR": "~/.local/share/dev-mcp-suite/memories/checkpoints"
38
+ }
39
+ },
40
+ "context-pack": {
41
+ "command": "context-pack-mcp",
42
+ "args": []
43
+ }
44
+ }
45
+ }
46
+ ```
47
+
48
+ ## Client Compatibility Highlights
49
+
50
+ - **Stdio Isolation**: Zero stdout noise — all logs and diagnostic messages are routed exclusively to `stderr` or MCP log frames.
51
+ - **Offline Vector Engine**: Automatically uses the built-in 384-d term-frequency hashing vector when no remote embedding API key is set (`MCP_LOCAL_EMBED=true`).
52
+ - **Obsidian Graph Compatibility**: Compatible with `.obsidian` vault structure and `[[WikiLinks]]`.
@@ -0,0 +1,48 @@
1
+ # Hermes Agent Setup
2
+
3
+ `codex-dev-mcp-suite` is fully compatible with **Hermes Agent** via the standard Model Context Protocol (MCP) stdio interface.
4
+
5
+ ## Quick Installation
6
+
7
+ Ensure the package is installed globally or accessible via `npx`:
8
+
9
+ ```bash
10
+ npm install -g codex-dev-mcp-suite
11
+ ```
12
+
13
+ ## Hermes Configuration (`~/.hermes/config.yaml`)
14
+
15
+ Add the suite servers to your Hermes `mcp_servers` configuration block in `~/.hermes/config.yaml`:
16
+
17
+ ```yaml
18
+ mcp_servers:
19
+ project-memory:
20
+ command: project-memory-mcp
21
+ args: []
22
+ env:
23
+ MEMORY_VAULT_DIR: "~/.local/share/dev-mcp-suite/memories/vault"
24
+ MCP_LOCAL_EMBED: "true" # Enables zero-dependency local offline vector search
25
+
26
+ devjournal:
27
+ command: devjournal-mcp
28
+ args: []
29
+ env:
30
+ JOURNAL_DIR: "~/.local/share/dev-mcp-suite/memories/journal"
31
+
32
+ checkpoint:
33
+ command: checkpoint-mcp
34
+ args: []
35
+ env:
36
+ CHECKPOINT_DIR: "~/.local/share/dev-mcp-suite/memories/checkpoints"
37
+
38
+ context-pack:
39
+ command: context-pack-mcp
40
+ args: []
41
+ ```
42
+
43
+ ## Features Available to Hermes
44
+
45
+ - **`memory_save` / `memory_recall`**: Persistent cross-session memory with optional local offline 384-d term-frequency hashing vector search (`MCP_LOCAL_EMBED=true`).
46
+ - **`journal_log` / `journal_resume` / `journal_handoff`**: Session log & handoff recovery.
47
+ - **`checkpoint_create` / `checkpoint_diff`**: File checkpoints independent of git.
48
+ - **`pack_overview` / `pack_tree` / `pack_audit`**: Codebase orientation & security risk auditing.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-dev-mcp-suite",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
4
4
  "description": "Four local, file-based MCP servers for solo devs/vibecoders: persistent project memory, session handoff/resume, git-independent file checkpoints, and token-efficient project briefings. Works with any MCP client.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -19,6 +19,7 @@ import http from "http";
19
19
  import https from "https";
20
20
  import { URL } from "url";
21
21
  import { deterministicEnabled } from "./env.js";
22
+ import { generateLocalVectors } from "./local-embed.js";
22
23
 
23
24
  /** Read env at runtime (not module-load time) so tests can override and config is dynamic). */
24
25
  function readEnv() {
@@ -30,6 +31,10 @@ function readEnv() {
30
31
  };
31
32
  }
32
33
 
34
+ export function localEmbedEnabled() {
35
+ return process.env.MCP_LOCAL_EMBED === "true" || process.env.LOCAL_EMBED === "true";
36
+ }
37
+
33
38
  /**
34
39
  * Resolve what retrieval mode memory_recall will use, given current env.
35
40
  * Returns one of: "deterministic" | "semantic" | "keyword".
@@ -38,17 +43,20 @@ function readEnv() {
38
43
  export function recallMode() {
39
44
  if (deterministicEnabled()) return "deterministic";
40
45
  const { key } = readEnv();
41
- return key ? "semantic" : "keyword";
46
+ if (key) return "semantic";
47
+ if (localEmbedEnabled()) return "semantic (local)";
48
+ return "keyword";
42
49
  }
43
50
 
44
51
  export function embeddingConfig() {
45
52
  const { base, key, model } = readEnv();
53
+ const isLocal = !key && localEmbedEnabled();
46
54
  return {
47
- base,
48
- model,
49
- enabled: Boolean(key) && !deterministicEnabled(),
55
+ base: key ? base : (isLocal ? "local-offline" : base),
56
+ model: key ? model : (isLocal ? "local-384d-tf-ngram" : model),
57
+ enabled: Boolean(key || isLocal) && !deterministicEnabled(),
50
58
  deterministic: deterministicEnabled(),
51
- endpoint: isCloudflareURL(base) ? "cloudflare" : "openai-compatible",
59
+ endpoint: key ? (isCloudflareURL(base) ? "cloudflare" : "openai-compatible") : (isLocal ? "local-offline" : "none"),
52
60
  mode: recallMode(),
53
61
  };
54
62
  }
@@ -136,10 +144,17 @@ async function embedCloudflare(inputs) {
136
144
  export async function embed(inputs) {
137
145
  if (deterministicEnabled()) return [];
138
146
  const { base, key } = readEnv();
139
- if (!key) return [];
140
147
  const arr = Array.isArray(inputs) ? inputs : [inputs];
141
- if (isCloudflareURL(base)) return await embedCloudflare(arr);
142
- return await embedOpenAI(arr);
148
+ if (!key) {
149
+ if (localEmbedEnabled()) return generateLocalVectors(arr);
150
+ return [];
151
+ }
152
+ try {
153
+ const res = isCloudflareURL(base) ? await embedCloudflare(arr) : await embedOpenAI(arr);
154
+ if (res && res.length) return res;
155
+ } catch { /* fallback to local if enabled */ }
156
+ if (localEmbedEnabled()) return generateLocalVectors(arr);
157
+ return [];
143
158
  }
144
159
 
145
160
  export async function embedOne(text) {
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Local offline vector embedding engine (384-dimensional term-frequency hashing vector).
3
+ * Zero external dependencies, zero network calls, sub-millisecond execution.
4
+ *
5
+ * Provides a reliable fallback for semantic search when no remote API keys
6
+ * (OpenAI/Cloudflare/Gemini/Ollama) are available.
7
+ */
8
+
9
+ const VECTOR_DIM = 384;
10
+
11
+ /** Simple hash function for N-gram string to integer bucket [0, VECTOR_DIM-1] */
12
+ function hashNgram(ngram) {
13
+ let hash = 5381;
14
+ for (let i = 0; i < ngram.length; i++) {
15
+ hash = ((hash << 5) + hash) + ngram.charCodeAt(i);
16
+ hash = hash & hash; // Convert to 32bit integer
17
+ }
18
+ return Math.abs(hash) % VECTOR_DIM;
19
+ }
20
+
21
+ /**
22
+ * Generate a 384-dimensional L2-normalized vector for a text string.
23
+ * @param {string} text
24
+ * @returns {number[]} Array of 384 float numbers
25
+ */
26
+ export function generateLocalVector(text) {
27
+ if (!text || typeof text !== "string") {
28
+ return new Array(VECTOR_DIM).fill(0);
29
+ }
30
+
31
+ const normalized = text.toLowerCase().trim();
32
+ if (!normalized) {
33
+ return new Array(VECTOR_DIM).fill(0);
34
+ }
35
+
36
+ const vec = new Array(VECTOR_DIM).fill(0);
37
+
38
+ // Extract word tokens and character 3-grams
39
+ const words = normalized.split(/\s+/).filter(Boolean);
40
+
41
+ // 1. Process words (higher weight)
42
+ for (const word of words) {
43
+ const cleanWord = word.replace(/[^a-z0-9]/g, "");
44
+ if (!cleanWord) continue;
45
+
46
+ const idx = hashNgram(cleanWord);
47
+ vec[idx] += 2.0;
48
+
49
+ // 2. Process character 3-grams for fuzzy matching
50
+ if (cleanWord.length >= 3) {
51
+ for (let i = 0; i <= cleanWord.length - 3; i++) {
52
+ const sub = cleanWord.substring(i, i + 3);
53
+ const subIdx = hashNgram(sub);
54
+ vec[subIdx] += 1.0;
55
+ }
56
+ }
57
+ }
58
+
59
+ // 3. Sublinear term-frequency scaling (1 + log(tf))
60
+ for (let i = 0; i < VECTOR_DIM; i++) {
61
+ if (vec[i] > 0) {
62
+ vec[i] = 1 + Math.log(vec[i]);
63
+ }
64
+ }
65
+
66
+ // 4. L2 Normalization (unit length vector)
67
+ let normSq = 0;
68
+ for (let i = 0; i < VECTOR_DIM; i++) {
69
+ normSq += vec[i] * vec[i];
70
+ }
71
+
72
+ if (normSq === 0) {
73
+ return vec;
74
+ }
75
+
76
+ const norm = Math.sqrt(normSq);
77
+ for (let i = 0; i < VECTOR_DIM; i++) {
78
+ vec[i] = vec[i] / norm;
79
+ }
80
+
81
+ return vec;
82
+ }
83
+
84
+ /**
85
+ * Generate vectors for an array of strings.
86
+ * @param {string[]} inputs
87
+ * @returns {number[][]}
88
+ */
89
+ export function generateLocalVectors(inputs) {
90
+ const arr = Array.isArray(inputs) ? inputs : [inputs];
91
+ return arr.map((t) => generateLocalVector(t));
92
+ }