@debugai/mcp 2.4.1 → 2.4.3

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 CHANGED
@@ -233,6 +233,16 @@ Recent server-side work, all of it live for agents already:
233
233
  - pytest, unittest, jest, vitest and mocha output yields real file paths, so a
234
234
  failing test gets cross-file context instead of none.
235
235
 
236
+ **2.4.2**: the bundled server prints the memory it advertises. This package and
237
+ the copy bundled in the VS Code extension are the same server, and only this one
238
+ was rendering the recurrence count and confirmed fix that both of them promise an
239
+ agent at connect time. The section is now one module both copies call, so there
240
+ is nothing left to keep in step by hand.
241
+
242
+ **2.4.1**: two tool descriptions repaired. An em-dash strip had cut both of them
243
+ mid-sentence, which matters more here than it reads: a tool description is the
244
+ only thing an agent sees before deciding whether to call this server at all.
245
+
236
246
  **2.4.0**: `report_outcome` gains `unused`. An agent that solved the problem its
237
247
  own way had to report `failed`, which marks a fix as tried and beaten when
238
248
  nothing of ours was ever run. Both tool surfaces, the npm server and the one
@@ -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
+ }
@@ -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
- if (result.memory_hit) {
126
- const seen = typeof result.memory_times_seen === 'number'
127
- ? `${result.memory_times_seen}x before in this project`
128
- : 'before in this project';
129
- // Four states, not two. Until 2026-08-21 this said "a fix was
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 including when you did not use its fix. ' +
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. ' +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@debugai/mcp",
3
- "version": "2.4.1",
3
+ "version": "2.4.3",
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",