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 +23 -0
- package/README.md +19 -5
- package/docs/clients/antigravity.md +52 -0
- package/docs/clients/hermes.md +48 -0
- package/package.json +1 -1
- package/project-memory/embedding.js +23 -8
- package/project-memory/local-embed.js +92 -0
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
|
[](https://www.npmjs.com/package/codex-dev-mcp-suite)
|
|
6
6
|
[](./LICENSE)
|
|
7
7
|
[](https://nodejs.org)
|
|
8
|
+
[](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
|
+
[](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.
|
|
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
|
-
|
|
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 (
|
|
142
|
-
|
|
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
|
+
}
|