@debugai/mcp 2.4.0 → 2.4.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/README.md +33 -3
- package/dist/memorySection.d.ts +39 -0
- package/dist/memorySection.js +62 -0
- package/dist/tools/debugError.js +7 -52
- package/dist/tools/reportOutcome.js +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -133,6 +133,8 @@ call report_outcome so the project's error memory stays accurate.
|
|
|
133
133
|
|
|
134
134
|
You do not need this package. The [DebugAI extension](https://marketplace.visualstudio.com/items?itemName=debugai.debugai) registers the MCP server automatically (VS Code 1.101+) and adds one-click fix apply, proactive scan, and codebase indexing on top. It is on [Open VSX](https://open-vsx.org/extension/debugai/debugai) too, for Cursor, Windsurf, and VSCodium.
|
|
135
135
|
|
|
136
|
+
The two servers are the same protocol surface and are kept in step by a test that reads both copies as text, because a comment saying "keep these in sync" has failed here before. From extension 2.8.1 the bundled server also does local source resolution, which this package has had since 2.2.0. Until then, an agent on the bundled server that pasted a traceback into a workspace nobody had indexed still got "Insufficient context for specific fix" at 20% confidence, which is the exact answer this feature exists to remove.
|
|
137
|
+
|
|
136
138
|
## Manual setup
|
|
137
139
|
|
|
138
140
|
`setup` covers this, and `install --client=<id>` covers the case where a client is installed somewhere unusual. If you would still rather edit the file yourself, the entry is the same everywhere:
|
|
@@ -197,6 +199,7 @@ Then run `npx -y @debugai/mcp login` once to store your key. If you would rather
|
|
|
197
199
|
- Simple errors route to a fast model. Ugly cross-file ones route to a stronger one on paid tiers. The `Model:` badge in each response tells you which one answered.
|
|
198
200
|
- Analyses run on DebugAI's servers. The error text, any snippet you pass, and — since 2.2 — the project source files the stack trace names are sent there, and Claude (Anthropic) does the analysis. The response lists every file that was read. Scope and limits are spelled out under [`debug_error`](#it-reads-the-source-the-trace-names-22). Privacy policy: [debugai.io/privacy](https://debugai.io/privacy?src=npm).
|
|
199
201
|
- Errors are remembered per project so a repeat hit starts from a fix that was already confirmed. The project identity is a hash of your repo root path; the path itself is never sent.
|
|
202
|
+
- The VS Code extension reads the project's `requirements.txt`, `pyproject.toml` and `package.json` and the interpreter the editor has selected, which is what lets it tell "not installed" apart from "installed under a different interpreter". This server sends none of that, so on a missing-module error you get the general answer and the check to run, not a verdict. You have a shell and it does not, so the honest division is that you run the check. Reporting those facts back through this server is planned.
|
|
200
203
|
|
|
201
204
|
## Troubleshooting
|
|
202
205
|
|
|
@@ -211,9 +214,36 @@ Run `npx -y @debugai/mcp doctor` first. It checks your Node version, whether a k
|
|
|
211
214
|
|
|
212
215
|
**Note on updates**: the analysis runs on DebugAI's servers, so improvements to
|
|
213
216
|
error parsing, retrieval and root-cause quality reach you without upgrading this
|
|
214
|
-
package.
|
|
215
|
-
|
|
216
|
-
|
|
217
|
+
package. Client releases are only for things that change on your machine.
|
|
218
|
+
|
|
219
|
+
Recent server-side work, all of it live for agents already:
|
|
220
|
+
|
|
221
|
+
- `ModuleNotFoundError` no longer opens with an install command. A read of every
|
|
222
|
+
one we had answered found five of eight rejected by the agent that received
|
|
223
|
+
them, for three different causes needing three different fixes: the package
|
|
224
|
+
was installed under another interpreter, the name was a local file, or the
|
|
225
|
+
import line was malformed. Rank 1 is now the check that tells those apart.
|
|
226
|
+
- A Python `SyntaxError` is no longer diagnosed as a JavaScript one, and the
|
|
227
|
+
framework is read from the error text rather than from what the repository
|
|
228
|
+
contains.
|
|
229
|
+
- Operating-system errors (`Access is denied.`, `No space left on device`) are
|
|
230
|
+
recognised as errors. Thirty were probed and twenty-eight had been refused.
|
|
231
|
+
- Credentials in the text you send are replaced before anything is stored or
|
|
232
|
+
reaches a model.
|
|
233
|
+
- pytest, unittest, jest, vitest and mocha output yields real file paths, so a
|
|
234
|
+
failing test gets cross-file context instead of none.
|
|
235
|
+
|
|
236
|
+
**2.4.0**: `report_outcome` gains `unused`. An agent that solved the problem its
|
|
237
|
+
own way had to report `failed`, which marks a fix as tried and beaten when
|
|
238
|
+
nothing of ours was ever run. Both tool surfaces, the npm server and the one
|
|
239
|
+
bundled in the VS Code extension, now take the same fields.
|
|
240
|
+
|
|
241
|
+
**2.3.0**: agents get the same four memory states the editor panel does.
|
|
242
|
+
`debug_error` had two branches, and a fix that had been tried and kept failing
|
|
243
|
+
read identically to one nobody had tried. To an agent those are the same
|
|
244
|
+
sentence, so the natural next move is to propose the fix that already did not
|
|
245
|
+
work. The four states now match the panel: confirmed and verified, confirmed,
|
|
246
|
+
unproven, and anti-pattern.
|
|
217
247
|
|
|
218
248
|
**2.2.0**: two things that were advertised but not delivered.
|
|
219
249
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What this project already knows about this exact error.
|
|
3
|
+
*
|
|
4
|
+
* ## Why it is its own module
|
|
5
|
+
*
|
|
6
|
+
* This section was the headline of npm 2.4.0 and **never reached the bundled
|
|
7
|
+
* server** — the zero-config one VS Code registers automatically, with no
|
|
8
|
+
* install and no config, and therefore the copy an agent is most likely to be
|
|
9
|
+
* on. For weeks the most-used MCP server advertised memory in its own
|
|
10
|
+
* instructions and never printed a word of it. That is the third time a
|
|
11
|
+
* decision duplicated across this boundary has drifted in the same direction.
|
|
12
|
+
*
|
|
13
|
+
* Inlined in two `debugError.ts` files it drifted silently, because
|
|
14
|
+
* `drift.test.ts` pinned tool SIGNATURES and the signatures were identical.
|
|
15
|
+
* As a module it is byte-comparable, and that comparison now ships as a test.
|
|
16
|
+
*
|
|
17
|
+
* Mirror: apps/extension/src/mcp/memorySection.ts
|
|
18
|
+
* The two are identical below this header. Change one, change the other, on
|
|
19
|
+
* the same commit (Rule 15b).
|
|
20
|
+
*/
|
|
21
|
+
/** The fields the engine sends about a remembered error. Every one optional:
|
|
22
|
+
* an older engine sends none, and absence must read as "nothing remembered"
|
|
23
|
+
* rather than as "nothing happened". */
|
|
24
|
+
export interface MemoryFields {
|
|
25
|
+
memory_hit?: boolean;
|
|
26
|
+
memory_times_seen?: number;
|
|
27
|
+
memory_fix_confirmed?: boolean;
|
|
28
|
+
memory_fix_state?: string;
|
|
29
|
+
memory_verified_count?: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The "Seen before" section, or null when there is nothing remembered.
|
|
33
|
+
*
|
|
34
|
+
* Returns null rather than an empty string so a caller cannot push a blank
|
|
35
|
+
* heading into the response and leave an agent reading "## Seen before"
|
|
36
|
+
* followed by nothing, which is worse than no section: it looks like a lookup
|
|
37
|
+
* that ran and found the error is new.
|
|
38
|
+
*/
|
|
39
|
+
export declare function memorySection(result: MemoryFields | null | undefined): string | null;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The "Seen before" section, or null when there is nothing remembered.
|
|
3
|
+
*
|
|
4
|
+
* Returns null rather than an empty string so a caller cannot push a blank
|
|
5
|
+
* heading into the response and leave an agent reading "## Seen before"
|
|
6
|
+
* followed by nothing, which is worse than no section: it looks like a lookup
|
|
7
|
+
* that ran and found the error is new.
|
|
8
|
+
*/
|
|
9
|
+
export function memorySection(result) {
|
|
10
|
+
if (!result?.memory_hit) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const seen = typeof result.memory_times_seen === 'number'
|
|
14
|
+
? `${result.memory_times_seen}x before in this project`
|
|
15
|
+
: 'before in this project';
|
|
16
|
+
// Four states, not two. Until 2026-08-21 this said "a fix was confirmed
|
|
17
|
+
// working" on the strength of somebody clicking Apply, and a fix that had
|
|
18
|
+
// been tried and FAILED was indistinguishable from one nobody had ever
|
|
19
|
+
// tried — both fell into the else branch and read "no fix has been confirmed
|
|
20
|
+
// yet". An agent reading that will happily re-propose the fix that already
|
|
21
|
+
// did not work, which is the loop this exists to break.
|
|
22
|
+
//
|
|
23
|
+
// memory_fix_state is what the engine sends now. When it is absent (older
|
|
24
|
+
// engine) the boolean still decides, exactly as before.
|
|
25
|
+
const state = typeof result.memory_fix_state === 'string'
|
|
26
|
+
? result.memory_fix_state
|
|
27
|
+
: (result.memory_fix_confirmed ? 'confirmed' : 'none');
|
|
28
|
+
const verified = typeof result.memory_verified_count === 'number'
|
|
29
|
+
? result.memory_verified_count
|
|
30
|
+
: 0;
|
|
31
|
+
let body;
|
|
32
|
+
if (state === 'confirmed' && verified > 0) {
|
|
33
|
+
body =
|
|
34
|
+
`This error has been seen ${seen}. A fix for it was VERIFIED BY ` +
|
|
35
|
+
`OBSERVATION ${verified}x: a live session watched the error stop ` +
|
|
36
|
+
`after that fix was applied. It led the analysis above.`;
|
|
37
|
+
}
|
|
38
|
+
else if (state === 'confirmed') {
|
|
39
|
+
body =
|
|
40
|
+
`This error has been seen ${seen}. A fix for it was applied and ` +
|
|
41
|
+
`accepted by a developer, though nothing has observed it working. ` +
|
|
42
|
+
`It led the analysis above. Treat it as a strong lead, not proof.`;
|
|
43
|
+
}
|
|
44
|
+
else if (state === 'unproven') {
|
|
45
|
+
body =
|
|
46
|
+
`This error has been seen ${seen}. A fix was applied for it and ` +
|
|
47
|
+
`THE ERROR HAS RECURRED ONCE SINCE, so that fix is unproven. The ` +
|
|
48
|
+
`analysis above was told not to lead with it.`;
|
|
49
|
+
}
|
|
50
|
+
else if (state === 'anti_pattern') {
|
|
51
|
+
body =
|
|
52
|
+
`This error has been seen ${seen}. A fix was applied for it and ` +
|
|
53
|
+
`THE ERROR KEPT HAPPENING. That fix did not work and the analysis ` +
|
|
54
|
+
`above was told not to propose it again. If you are about to ` +
|
|
55
|
+
`suggest something equivalent, the cause is somewhere it does not ` +
|
|
56
|
+
`touch.`;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
body = `This error has been seen ${seen}. No fix has been confirmed for it yet.`;
|
|
60
|
+
}
|
|
61
|
+
return `\n## Seen before\n${body}`;
|
|
62
|
+
}
|
package/dist/tools/debugError.js
CHANGED
|
@@ -3,6 +3,7 @@ import { callDebugBackend } from '../backend.js';
|
|
|
3
3
|
import { mapBackendErrorToToolResult } from '../errors.js';
|
|
4
4
|
import { resolveAuth } from './authGate.js';
|
|
5
5
|
import { getProjectId, getProjectRoot } from '../project.js';
|
|
6
|
+
import { memorySection } from '../memorySection.js';
|
|
6
7
|
import { resolveSourceContext } from '../sourceContext.js';
|
|
7
8
|
// Tri-state verification labeling (docs/plan-v2-contract-phase1.md §1).
|
|
8
9
|
// The null case is rendered ON PURPOSE: a confidence number nothing checked
|
|
@@ -121,58 +122,12 @@ export function registerDebugError(server, config) {
|
|
|
121
122
|
// Memory first, above the badges: "this project has hit this exact
|
|
122
123
|
// error before, and a fix was confirmed" is the one thing here the
|
|
123
124
|
// agent cannot derive from the code in front of it, so it should not
|
|
124
|
-
// be buried in a metadata footer.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
// confirmed working" on the strength of somebody clicking Apply,
|
|
131
|
-
// and a fix that had been tried and FAILED was indistinguishable
|
|
132
|
-
// from one nobody had ever tried — both fell into the else branch
|
|
133
|
-
// and read "no fix has been confirmed yet". An agent reading that
|
|
134
|
-
// will happily re-propose the fix that already did not work, which
|
|
135
|
-
// is the loop this whole change exists to break.
|
|
136
|
-
//
|
|
137
|
-
// memory_fix_state is what the engine sends now. When it is absent
|
|
138
|
-
// (older engine) the boolean still decides, exactly as before.
|
|
139
|
-
const state = typeof result.memory_fix_state === 'string'
|
|
140
|
-
? result.memory_fix_state
|
|
141
|
-
: (result.memory_fix_confirmed ? 'confirmed' : 'none');
|
|
142
|
-
const verified = typeof result.memory_verified_count === 'number'
|
|
143
|
-
? result.memory_verified_count
|
|
144
|
-
: 0;
|
|
145
|
-
let memoryBody;
|
|
146
|
-
if (state === 'confirmed' && verified > 0) {
|
|
147
|
-
memoryBody =
|
|
148
|
-
`This error has been seen ${seen}. A fix for it was VERIFIED BY ` +
|
|
149
|
-
`OBSERVATION ${verified}x: a live session watched the error stop ` +
|
|
150
|
-
`after that fix was applied. It led the analysis above.`;
|
|
151
|
-
}
|
|
152
|
-
else if (state === 'confirmed') {
|
|
153
|
-
memoryBody =
|
|
154
|
-
`This error has been seen ${seen}. A fix for it was applied and ` +
|
|
155
|
-
`accepted by a developer, though nothing has observed it working. ` +
|
|
156
|
-
`It led the analysis above. Treat it as a strong lead, not proof.`;
|
|
157
|
-
}
|
|
158
|
-
else if (state === 'unproven') {
|
|
159
|
-
memoryBody =
|
|
160
|
-
`This error has been seen ${seen}. A fix was applied for it and ` +
|
|
161
|
-
`THE ERROR HAS RECURRED ONCE SINCE, so that fix is unproven. The ` +
|
|
162
|
-
`analysis above was told not to lead with it.`;
|
|
163
|
-
}
|
|
164
|
-
else if (state === 'anti_pattern') {
|
|
165
|
-
memoryBody =
|
|
166
|
-
`This error has been seen ${seen}. A fix was applied for it and ` +
|
|
167
|
-
`THE ERROR KEPT HAPPENING. That fix did not work and the analysis ` +
|
|
168
|
-
`above was told not to propose it again. If you are about to ` +
|
|
169
|
-
`suggest something equivalent, the cause is somewhere it does not ` +
|
|
170
|
-
`touch.`;
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
memoryBody = `This error has been seen ${seen}. No fix has been confirmed for it yet.`;
|
|
174
|
-
}
|
|
175
|
-
sections.push(`\n## Seen before\n${memoryBody}`);
|
|
125
|
+
// be buried in a metadata footer. The wording lives in
|
|
126
|
+
// ../memorySection.ts, byte-identical with the bundled server, because
|
|
127
|
+
// inlined here it drifted out of that copy entirely.
|
|
128
|
+
const memory = memorySection(result);
|
|
129
|
+
if (memory) {
|
|
130
|
+
sections.push(memory);
|
|
176
131
|
}
|
|
177
132
|
const badges = [];
|
|
178
133
|
// Named, not counted. "Read 2 files" is unverifiable; "read src/api.ts,
|
|
@@ -41,7 +41,7 @@ import { resolveAuth } from './authGate.js';
|
|
|
41
41
|
export function registerReportOutcome(server, config) {
|
|
42
42
|
server.registerTool('report_outcome', {
|
|
43
43
|
title: 'Report Fix Outcome',
|
|
44
|
-
description: 'Report what happened after DebugAI answered
|
|
44
|
+
description: 'Report what happened after DebugAI answered, including when you did not use its fix. ' +
|
|
45
45
|
'Call this ONCE per debug_error response, passing the debug_log_id from it. ' +
|
|
46
46
|
'If you solved the problem another way, say so with result "unused" and put the real ' +
|
|
47
47
|
'fix in actualFix: a case DebugAI got wrong is worth more to it than one it got right. ' +
|
|
@@ -58,8 +58,8 @@ export function registerReportOutcome(server, config) {
|
|
|
58
58
|
.describe('"worked" = you applied a DebugAI fix and the error stopped. ' +
|
|
59
59
|
'"failed" = you applied one and it did not help (or made things worse). ' +
|
|
60
60
|
'"unused" = you did not apply any of them and resolved it another way. ' +
|
|
61
|
-
'Use "unused" rather than "failed" when nothing of ours was actually run
|
|
62
|
-
'
|
|
61
|
+
'Use "unused" rather than "failed" when nothing of ours was actually run. ' +
|
|
62
|
+
'They are different facts and reporting the wrong one buries a fix nobody tried.'),
|
|
63
63
|
fixRank: z
|
|
64
64
|
.number()
|
|
65
65
|
.int()
|
|
@@ -77,7 +77,7 @@ export function registerReportOutcome(server, config) {
|
|
|
77
77
|
.max(4000)
|
|
78
78
|
.optional()
|
|
79
79
|
.describe('What actually resolved the error, when it was not the fix DebugAI suggested. ' +
|
|
80
|
-
'Free text. Say what the real cause turned out to be and what you changed
|
|
80
|
+
'Free text. Say what the real cause turned out to be and what you changed, ' +
|
|
81
81
|
'especially if the cause was in a different layer than the answer addressed ' +
|
|
82
82
|
'(the shell, the runtime version, the environment, a missing package).'),
|
|
83
83
|
toolFeedback: z
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@debugai/mcp",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
4
|
"mcpName": "io.github.1shizaan/debugai-mcp",
|
|
5
5
|
"description": "DebugAI MCP server. One command sets it up in Claude Desktop, Claude Code, Cursor, Zed, Windsurf, Cline or any MCP client: browser sign-in, no key pasting, no config editing.",
|
|
6
6
|
"license": "MIT",
|