@4da/mcp-server 6.0.0 → 6.0.2
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 +82 -0
- package/README.md +12 -9
- package/dist/db.d.ts +17 -57
- package/dist/db.js +71 -292
- package/dist/index.js +11 -3
- package/dist/setup.d.ts +76 -3
- package/dist/setup.js +313 -130
- package/dist/tool-dispatch.d.ts +2 -0
- package/dist/tool-dispatch.js +21 -1
- package/dist/types.d.ts +0 -135
- package/package.json +15 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,87 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 6.0.2 — 2026-10-04
|
|
4
|
+
|
|
5
|
+
### `--setup` writes the files editors actually read
|
|
6
|
+
|
|
7
|
+
Three of the four editors `--setup` reported as configured were configured in
|
|
8
|
+
files those editors never read, so nothing happened:
|
|
9
|
+
|
|
10
|
+
| Editor | Before | Now |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| VS Code | `~/.vscode/mcp.json` | the user profile's `mcp.json`: `%APPDATA%\Code\User\` (Windows), `~/Library/Application Support/Code/User/` (macOS), `$XDG_CONFIG_HOME/Code/User/` (Linux, default `~/.config`), key `servers`, `"type": "stdio"` |
|
|
13
|
+
| Windsurf | `~/.windsurf/mcp.json` | `~/.codeium/windsurf/mcp_config.json`, key `mcpServers` |
|
|
14
|
+
| Claude Code | `mcpServers` in the project's `.claude/settings.json` (or, outside a project, rewrote `~/.claude.json`) | prints `claude mcp add --scope user 4da -- npx @4da/mcp-server`; `~/.claude.json` is never edited |
|
|
15
|
+
|
|
16
|
+
Added: VS Code Insiders, Claude Desktop (`claude_desktop_config.json`) and
|
|
17
|
+
Devin Desktop / Devin CLI (`~/.config/devin/mcp_config.json`,
|
|
18
|
+
`%APPDATA%\devin\` on Windows), Windsurf's successor. Cursor
|
|
19
|
+
(`~/.cursor/mcp.json`) was already right.
|
|
20
|
+
|
|
21
|
+
- **A config file setup cannot parse is left untouched.** It used to be read
|
|
22
|
+
as `{}`, so a VS Code `mcp.json` with a comment or a trailing comma (both
|
|
23
|
+
legal there) was replaced by our entry alone, deleting every other server.
|
|
24
|
+
Files are now parsed as JSONC and edited in place with `jsonc-parser`
|
|
25
|
+
(Microsoft's, the parser VS Code uses; no dependencies of its own), which
|
|
26
|
+
keeps comments, formatting, other servers and other keys. A file that does
|
|
27
|
+
not parse is reported with the entry to add by hand.
|
|
28
|
+
- An existing `4da` entry is updated, not duplicated, and keeps its other
|
|
29
|
+
fields (`env`); an identical one is left alone, so a second run writes
|
|
30
|
+
nothing.
|
|
31
|
+
- Every modified file is backed up first (`<file>.bak`; an earlier backup is
|
|
32
|
+
never overwritten) and replaced atomically (temp file, then rename).
|
|
33
|
+
- `--setup --dry-run` wrote anyway when run through `npx @4da/mcp-server`
|
|
34
|
+
(only the `4da-mcp-setup` entry honoured the flag). It now writes nothing on
|
|
35
|
+
either, and prints each file and the exact entry it would add.
|
|
36
|
+
|
|
37
|
+
### Clearer answers when the database cannot help
|
|
38
|
+
|
|
39
|
+
- A desktop-only tool (`get_relevant_content`, `get_actionable_signals`,
|
|
40
|
+
`knowledge_gaps`, `record_feedback`, `developer_dna`) called without the
|
|
41
|
+
desktop app's database answered `[]`, which reads as "nothing relevant". It
|
|
42
|
+
now carries a `desktop_app_note` saying it needs the app.
|
|
43
|
+
- A database file that is damaged or not SQLite answered every call with
|
|
44
|
+
SQLite's bare "file is not a database". The message now names the file and
|
|
45
|
+
what to do, and never advises deleting it (`--doctor`'s integrity check used
|
|
46
|
+
to say "Try deleting data/4da.db"). The handle a failed open left behind is
|
|
47
|
+
closed, so on Windows the file can be moved aside while the server runs.
|
|
48
|
+
- The database lookup no longer checks `data/4da.db` two directories above the
|
|
49
|
+
server's own files, a leftover from when the server was a folder of the app
|
|
50
|
+
repository; installed, it pointed into `node_modules/@4da/`.
|
|
51
|
+
|
|
52
|
+
- Dependencies: `@modelcontextprotocol/server` ^2.2.0, `hono` ^4.13.12; dev: `@types/node` ^26.6.3, `vitest` ^5.0.3 (#2).
|
|
53
|
+
|
|
54
|
+
## 6.0.1 — 2026-10-04
|
|
55
|
+
|
|
56
|
+
### The server has its own repository
|
|
57
|
+
|
|
58
|
+
`@4da/mcp-server` now lives at
|
|
59
|
+
[github.com/4DA-Systems/4da-mcp-server](https://github.com/4DA-Systems/4da-mcp-server),
|
|
60
|
+
with its full history, instead of a folder of the 4DA desktop app's monorepo.
|
|
61
|
+
Issues, releases and the Claude Code plugin marketplace move with it:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
claude plugin marketplace add 4DA-Systems/4da-mcp-server
|
|
65
|
+
claude plugin install 4da@4da
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The package, its name in the MCP Registry (`io.github.4DA-Systems/4da-mcp-server`)
|
|
69
|
+
and every tool are unchanged.
|
|
70
|
+
|
|
71
|
+
- **Published with provenance.** Releases are built and published from this
|
|
72
|
+
repository's `release.yml` through npm trusted publishing, so each version
|
|
73
|
+
carries a SLSA provenance attestation tying it to the commit it was built from.
|
|
74
|
+
- **App-schema contract.** The server reads the desktop app's database, which
|
|
75
|
+
is now maintained in a different repository. `pnpm run contract` checks every
|
|
76
|
+
statement the server issues, and every column it probes for, against the
|
|
77
|
+
schema the app's migrations produce (`contract/app-schema.sql`, generated in
|
|
78
|
+
the app's CI). The app's CI runs the same check before a migration merges.
|
|
79
|
+
- **Removed dead code.** `explainRelevance`, `getSourceItem`,
|
|
80
|
+
`recordAgentFeedback` and `getAgentFeedbackStats` had no callers since their
|
|
81
|
+
tools were removed; the standalone schema no longer creates the unused
|
|
82
|
+
`agent_feedback` table.
|
|
83
|
+
- The Claude Code plugin pins the exact server version it was released with.
|
|
84
|
+
|
|
3
85
|
## 6.0.0 — 2026-10-02
|
|
4
86
|
|
|
5
87
|
### New: `upgrade_impact`
|
package/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@4da/mcp-server)
|
|
4
4
|
[](LICENSE)
|
|
5
|
-
[](https://nodejs.org/)
|
|
6
|
+
[](https://github.com/4DA-Systems/4da-mcp-server/actions/workflows/ci.yml)
|
|
7
7
|
|
|
8
8
|
**Upgrade intelligence for AI coding agents.** Before your agent bumps a dependency it learns what changes between the version you run and the one you want, which of your files that touches, and which vulnerabilities the move fixes, from your own lockfiles, on your machine. Plus vulnerability scanning at osv-scanner parity, ranked upgrade plans and decision memory. Zero config, no account.
|
|
9
9
|
|
|
@@ -38,16 +38,16 @@ claude mcp add 4da -- npx @4da/mcp-server
|
|
|
38
38
|
**As a Claude Code plugin** (the MCP server plus a hook):
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
claude plugin marketplace add 4DA-Systems/
|
|
41
|
+
claude plugin marketplace add 4DA-Systems/4da-mcp-server
|
|
42
42
|
claude plugin install 4da@4da
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
The hook: when your agent edits a dependency's version in `package.json`, `Cargo.toml`, `pyproject.toml`, `requirements.txt` or `go.mod`, it is told which packages moved and given the exact `dependency_check` and `upgrade_impact` calls to make before it installs and builds. The hook is plain Node, contacts nothing, and stays silent for every other edit.
|
|
46
46
|
|
|
47
47
|
<details>
|
|
48
|
-
<summary><b>Cursor / Windsurf</b></summary>
|
|
48
|
+
<summary><b>Cursor / Windsurf / Devin Desktop</b></summary>
|
|
49
49
|
|
|
50
|
-
Add to `~/.cursor/mcp.json`
|
|
50
|
+
Add to `~/.cursor/mcp.json` (Cursor), `~/.codeium/windsurf/mcp_config.json` (Windsurf), or `~/.config/devin/mcp_config.json` (Devin Desktop and Devin CLI; `%APPDATA%devinmcp_config.json` on Windows):
|
|
51
51
|
```json
|
|
52
52
|
{
|
|
53
53
|
"mcpServers": {
|
|
@@ -63,7 +63,7 @@ Add to `~/.cursor/mcp.json` or `~/.windsurf/mcp.json`:
|
|
|
63
63
|
<details>
|
|
64
64
|
<summary><b>VS Code (Copilot)</b></summary>
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
Run **MCP: Open User Configuration** and add the entry, or edit the file directly: `%APPDATA%CodeUsermcp.json` (Windows), `~/Library/Application Support/Code/User/mcp.json` (macOS), `~/.config/Code/User/mcp.json` (Linux). VS Code uses `servers`, not `mcpServers`:
|
|
67
67
|
```json
|
|
68
68
|
{
|
|
69
69
|
"servers": {
|
|
@@ -97,8 +97,11 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
97
97
|
<summary><b>Auto-setup</b> (detects all installed editors)</summary>
|
|
98
98
|
|
|
99
99
|
```bash
|
|
100
|
+
npx @4da/mcp-server --setup --dry-run # show each file and entry, write nothing
|
|
100
101
|
npx @4da/mcp-server --setup
|
|
101
102
|
```
|
|
103
|
+
|
|
104
|
+
Writes Cursor, VS Code (and Insiders), Windsurf, Devin Desktop and Claude Desktop configs it finds, merging into what is there: other servers, settings and comments are kept, a backup (`.bak`) is written first, and a file it cannot parse is left untouched with the entry to add by hand. For Claude Code it prints the `claude mcp add` command instead of editing `~/.claude.json`.
|
|
102
105
|
</details>
|
|
103
106
|
|
|
104
107
|
Then ask your AI: **"What changes if I upgrade X to Y?"**, **"Scan for vulnerabilities"** or **"What should I upgrade first?"**
|
|
@@ -268,11 +271,11 @@ Any tool that supports [MCP](https://modelcontextprotocol.io): Claude Code, Clau
|
|
|
268
271
|
## Build from Source
|
|
269
272
|
|
|
270
273
|
```bash
|
|
271
|
-
git clone https://github.com/4DA-Systems/
|
|
272
|
-
cd
|
|
274
|
+
git clone https://github.com/4DA-Systems/4da-mcp-server.git
|
|
275
|
+
cd 4da-mcp-server
|
|
273
276
|
pnpm install
|
|
274
277
|
pnpm build
|
|
275
|
-
pnpm test #
|
|
278
|
+
pnpm test # offline
|
|
276
279
|
```
|
|
277
280
|
|
|
278
281
|
## License
|
package/dist/db.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import type BetterSqlite3 from "better-sqlite3";
|
|
8
8
|
/** Null when better-sqlite3 can open a database here; otherwise why not, with the fix. */
|
|
9
9
|
export declare function nativeBindingProblem(): string | null;
|
|
10
|
-
import type {
|
|
10
|
+
import type { RelevantItem, UserContext, FeedbackAction, FeedbackResult } from "./types.js";
|
|
11
11
|
import type { ProjectScanResult } from "./project-scanner.js";
|
|
12
12
|
/**
|
|
13
13
|
* Where the deployed desktop app keeps its database, mirroring
|
|
@@ -30,6 +30,20 @@ export declare function desktopAppDbPaths(platform?: NodeJS.Platform, env?: Node
|
|
|
30
30
|
* in, so agent memory and decisions did not follow the user between projects.
|
|
31
31
|
*/
|
|
32
32
|
export declare function standaloneDbPath(): string;
|
|
33
|
+
/**
|
|
34
|
+
* Whether an error says the database file itself is unreadable: not SQLite at
|
|
35
|
+
* all, or damaged. better-sqlite3 reports these as SQLITE_NOTADB ("file is not
|
|
36
|
+
* a database") and SQLITE_CORRUPT ("database disk image is malformed").
|
|
37
|
+
*/
|
|
38
|
+
export declare function isUnreadableDbError(error: unknown): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* What to tell the user about an unreadable database. Every tool call used to
|
|
41
|
+
* answer with the bare SQLite text ("file is not a database"), with no way
|
|
42
|
+
* out. Nothing is deleted or moved automatically: the desktop app's database
|
|
43
|
+
* can be the user's whole corpus, and the standalone one holds their recorded
|
|
44
|
+
* decisions and agent memory.
|
|
45
|
+
*/
|
|
46
|
+
export declare function unreadableDbMessage(absolutePath: string, error: unknown): string;
|
|
33
47
|
export interface DatabaseValidationResult {
|
|
34
48
|
valid: boolean;
|
|
35
49
|
error?: string;
|
|
@@ -98,6 +112,8 @@ export declare const DEPENDENCY_GROUP_QUERY = "SELECT DISTINCT package_name, lan
|
|
|
98
112
|
export declare class FourDADatabase {
|
|
99
113
|
private db;
|
|
100
114
|
private _isStandalone;
|
|
115
|
+
/** Absolute path of the open database file. */
|
|
116
|
+
readonly dbPath: string;
|
|
101
117
|
constructor(dbPath?: string);
|
|
102
118
|
/**
|
|
103
119
|
* Whether this database was freshly created in standalone mode
|
|
@@ -193,10 +209,6 @@ export declare class FourDADatabase {
|
|
|
193
209
|
* Fallback: TypeScript keyword scoring for standalone mode (no Rust pipeline).
|
|
194
210
|
*/
|
|
195
211
|
private getRelevantContentFallback;
|
|
196
|
-
/**
|
|
197
|
-
* Get a single source item by ID and type
|
|
198
|
-
*/
|
|
199
|
-
getSourceItem(itemId: number, sourceType: string): SourceItem | null;
|
|
200
212
|
/**
|
|
201
213
|
* Look up persisted necessity scores for an item (written by Rust analysis pipeline).
|
|
202
214
|
* Returns defaults (0.0/null) if no necessity data exists yet.
|
|
@@ -206,10 +218,6 @@ export declare class FourDADatabase {
|
|
|
206
218
|
* Get the user's context (what 4DA knows about them)
|
|
207
219
|
*/
|
|
208
220
|
getUserContext(includeAce?: boolean, includeLearned?: boolean): UserContext;
|
|
209
|
-
/**
|
|
210
|
-
* Explain why an item was considered relevant
|
|
211
|
-
*/
|
|
212
|
-
explainRelevance(itemId: number, sourceType: string): RelevanceExplanation | null;
|
|
213
221
|
/**
|
|
214
222
|
* Record user feedback on an item
|
|
215
223
|
*/
|
|
@@ -221,54 +229,6 @@ export declare class FourDADatabase {
|
|
|
221
229
|
* so against the desktop database this is a no-op.
|
|
222
230
|
*/
|
|
223
231
|
private ensureFeedbackTable;
|
|
224
|
-
/**
|
|
225
|
-
* Ensure the agent_feedback table exists.
|
|
226
|
-
* Called on first use so existing databases (created before this feature)
|
|
227
|
-
* get the table added without requiring a migration.
|
|
228
|
-
*/
|
|
229
|
-
private ensureAgentFeedbackTable;
|
|
230
|
-
/**
|
|
231
|
-
* Record agent feedback on recommended content items
|
|
232
|
-
*/
|
|
233
|
-
recordAgentFeedback(itemIds: string[], outcome: string, context?: string, sessionTask?: string): {
|
|
234
|
-
success: boolean;
|
|
235
|
-
message: string;
|
|
236
|
-
recorded_count: number;
|
|
237
|
-
};
|
|
238
|
-
/**
|
|
239
|
-
* Get agent feedback statistics for the given period
|
|
240
|
-
*/
|
|
241
|
-
getAgentFeedbackStats(days?: number): {
|
|
242
|
-
period_days: number;
|
|
243
|
-
outcomes: {
|
|
244
|
-
used: number;
|
|
245
|
-
rejected: number;
|
|
246
|
-
partially_used: number;
|
|
247
|
-
total: number;
|
|
248
|
-
};
|
|
249
|
-
by_source: Array<{
|
|
250
|
-
source_type: string;
|
|
251
|
-
used: number;
|
|
252
|
-
rejected: number;
|
|
253
|
-
partially_used: number;
|
|
254
|
-
total: number;
|
|
255
|
-
usefulness_rate: number;
|
|
256
|
-
}>;
|
|
257
|
-
top_used_items: Array<{
|
|
258
|
-
item_id: string;
|
|
259
|
-
title: string | null;
|
|
260
|
-
source_type: string | null;
|
|
261
|
-
used_count: number;
|
|
262
|
-
rejected_count: number;
|
|
263
|
-
}>;
|
|
264
|
-
recent_feedback: Array<{
|
|
265
|
-
item_id: string;
|
|
266
|
-
outcome: string;
|
|
267
|
-
context: string | null;
|
|
268
|
-
session_task: string | null;
|
|
269
|
-
recorded_at: string;
|
|
270
|
-
}>;
|
|
271
|
-
};
|
|
272
232
|
/**
|
|
273
233
|
* Compute relevance score for an item based on user context
|
|
274
234
|
*/
|