@debugai/mcp 1.1.0 → 2.1.0

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
@@ -1,112 +1,71 @@
1
1
  # @debugai/mcp
2
2
 
3
- DebugAI as an MCP server. Your agent hands an error to `debug_error` and gets
4
- back the root cause plus up to 3 ranked fixes with code patches. Works in
5
- Claude Desktop, Claude Code, Cursor, Zed, Windsurf, and any other MCP client.
3
+ <p align="center">
4
+ <a href="https://www.npmjs.com/package/@debugai/mcp"><img src="https://img.shields.io/npm/v/@debugai/mcp?color=0A0A0F&label=npm" alt="npm version"></a>
5
+ <img src="https://img.shields.io/badge/node-%3E%3D18-0A0A0F" alt="Node 18+">
6
+ <img src="https://img.shields.io/badge/license-MIT-0A0A0F" alt="MIT license">
7
+ </p>
6
8
 
7
- Until now this server only shipped inside the
8
- [DebugAI VS Code extension](https://marketplace.visualstudio.com/items?itemName=debugai.debugai).
9
- This package is the same server, standalone. No VS Code required.
9
+ Give your coding agent a debugger instead of a grep loop.
10
10
 
11
- ## Setup
12
-
13
- 1. Create a free account at [debugai.io](https://debugai.io) (10 debugs/day, no card).
14
- 2. Copy your API key (`dbg_...`) from [debugai.io/dashboard](https://debugai.io/dashboard).
15
- 3. Add the server to your MCP client (snippets below). Node 18+ required.
11
+ Your agent hands an error to `debug_error` and gets back the root cause, the exact file and line, and up to 3 ranked fixes as ready-to-apply edits. Each fix is labeled with whether a mechanical check actually passed, so the agent knows which ones were checked and which are the model's own estimate.
16
12
 
17
- ### Set the key once for every client (optional)
13
+ Auto-configures Claude Code, Claude Desktop, Cursor, Windsurf, Zed, Gemini CLI, and Cline. Works in any other MCP client with a manual entry. Node 18 or later.
18
14
 
19
- Instead of repeating the key in each client's `env` block, write it to
20
- `~/.debugai/config.json`:
15
+ ## Setup
21
16
 
22
- ```json
23
- { "api_key": "dbg_your_key_here" }
17
+ ```bash
18
+ npx -y @debugai/mcp setup
24
19
  ```
25
20
 
26
- Every MCP client launching `npx -y @debugai/mcp` picks it up you can then
27
- drop the `env` block from the snippets below entirely. An explicit
28
- `DEBUGAI_API_KEY` env var still wins over the file.
21
+ That is the whole thing. It signs you in through your browser (no key to find or copy), writes the config for every MCP client it finds on this machine, then checks that all of it actually works.
29
22
 
30
- ### Claude Code
23
+ Restart the clients it names and your agent has the tools.
31
24
 
32
- ```bash
33
- claude mcp add debugai --env DEBUGAI_API_KEY=dbg_your_key_here -- npx -y @debugai/mcp
34
- ```
35
-
36
- ### Claude Desktop
25
+ Prefer to read first? [debugai.io/start?src=npm](https://debugai.io/start?src=npm) walks the same thing per client.
37
26
 
38
- `claude_desktop_config.json` (Settings, Developer, Edit Config):
27
+ ### What that command does to your machine
39
28
 
40
- ```json
41
- {
42
- "mcpServers": {
43
- "debugai": {
44
- "command": "npx",
45
- "args": ["-y", "@debugai/mcp"],
46
- "env": { "DEBUGAI_API_KEY": "dbg_your_key_here" }
47
- }
48
- }
49
- }
50
- ```
29
+ Worth knowing before you run something that edits your editor config:
51
30
 
52
- ### Cursor
31
+ - Signs you in with a short code you confirm in the browser. Free account, 10 debugs a day, no card.
32
+ - Stores your key in `~/.debugai/config.json` with `0600` permissions. That is the only file that ever holds it.
33
+ - Adds a `debugai` entry to the config of each MCP client it detects. Every file is backed up first (`<file>.debugai-backup-<timestamp>`), every other setting in the file is preserved, and a file it cannot parse is left alone and reported instead. One caveat stated plainly: if your config contains comments, the rewrite drops them, because JSON has nowhere to put them. You get a warning before it happens and the backup still has them.
34
+ - Skips VS Code by default, because the [DebugAI extension](https://marketplace.visualstudio.com/items?itemName=debugai.debugai) already registers this server there and a second entry would show every tool twice. `install --client=vscode` does it anyway if you want the server without the extension.
35
+ - Never writes your key into a client config. Client configs get committed to repos. Keys should not.
53
36
 
54
- `~/.cursor/mcp.json` (or `.cursor/mcp.json` per project):
37
+ Preview it without writing anything:
55
38
 
56
- ```json
57
- {
58
- "mcpServers": {
59
- "debugai": {
60
- "command": "npx",
61
- "args": ["-y", "@debugai/mcp"],
62
- "env": { "DEBUGAI_API_KEY": "dbg_your_key_here" }
63
- }
64
- }
65
- }
39
+ ```bash
40
+ npx -y @debugai/mcp install --dry-run
66
41
  ```
67
42
 
68
- ### Zed
69
-
70
- `settings.json`:
43
+ Undo all of it:
71
44
 
72
- ```json
73
- {
74
- "context_servers": {
75
- "debugai": {
76
- "command": {
77
- "path": "npx",
78
- "args": ["-y", "@debugai/mcp"],
79
- "env": { "DEBUGAI_API_KEY": "dbg_your_key_here" }
80
- }
81
- }
82
- }
83
- }
45
+ ```bash
46
+ npx -y @debugai/mcp uninstall # removes the entry from every client config
47
+ npx -y @debugai/mcp logout # removes the stored key
84
48
  ```
85
49
 
86
- ### Windsurf
50
+ ### Commands
87
51
 
88
- `~/.codeium/windsurf/mcp_config.json`:
52
+ | Command | What it does |
53
+ |---------|--------------|
54
+ | `setup` | `login` then `install`, then verifies. The one you want. |
55
+ | `login` | Browser sign-in. `--key dbg_…` to paste a key instead (CI, air-gapped boxes). `--force` to re-link. |
56
+ | `logout` | Removes the stored key. |
57
+ | `status` | Which key and account are active right now. |
58
+ | `install` | Writes client configs. `--list`, `--client=cursor`, `--all`, `--dry-run`, `--remove`. |
59
+ | `uninstall` | Removes the entry from every client config. |
60
+ | `doctor` | Diagnoses a broken setup: key, API reachability, per-client wiring. |
89
61
 
90
- ```json
91
- {
92
- "mcpServers": {
93
- "debugai": {
94
- "command": "npx",
95
- "args": ["-y", "@debugai/mcp"],
96
- "env": { "DEBUGAI_API_KEY": "dbg_your_key_here" }
97
- }
98
- }
99
- }
100
- ```
62
+ `npx -y @debugai/mcp install --list` prints every supported client, where its config lives on your OS, and whether DebugAI is already in it.
101
63
 
102
- ### VS Code
64
+ ### Signing in from inside a chat
103
65
 
104
- You don't need this package. The
105
- [DebugAI extension](https://marketplace.visualstudio.com/items?itemName=debugai.debugai)
106
- registers the MCP server automatically (VS Code 1.101+) and adds one-click
107
- fix apply, proactive scan, and codebase indexing on top.
66
+ If your agent calls a DebugAI tool before you have signed in, the tool answers with a short code and a URL instead of an error. Confirm it in the browser, tell the agent to try again, and the call goes through. No config editing, and no client restart, because the key is re-read on every call.
108
67
 
109
- ## The tool
68
+ ## The tools
110
69
 
111
70
  ### `debug_error`
112
71
 
@@ -119,10 +78,22 @@ Give it an error, get an analysis.
119
78
  | `codeSnippet` | no | Code around the failing line, if the agent has it. |
120
79
  | `filePath` | no | Path to the file that threw. |
121
80
 
122
- Returns the root cause, up to 3 fixes ranked by confidence (with code
123
- patches), the detected framework, and whether the answer came from cache.
124
- Read-only: it never touches your files. Applying a fix is your agent's
125
- (and your) call.
81
+ Returns the root cause, up to 3 fixes ranked by confidence, the detected framework, and whether the answer came from cache. Since 2.0 each fix also carries, where derivable: `edits` (exact old/new strings your agent's edit tool can apply directly), `unified_diff`, and `verify_with` (a syntax-level check command to run after applying). Read-only: it never touches your files. Applying a fix is your agent's call, and yours.
82
+
83
+ Every fix is labeled with its verification state, and there are three of them, not two: **verified** (a mechanical check passed, currently parse and import classes), **failed check** (confidence capped hard), or **not verified** (the confidence number is the model's own estimate, nothing checked it). We label the third case instead of hiding it.
84
+
85
+ ### `report_outcome`
86
+
87
+ Tell DebugAI whether an applied fix actually worked.
88
+
89
+ | Input | Required | Description |
90
+ |-------|----------|-------------|
91
+ | `debugLogId` | yes | The `debug_log_id` from the `debug_error` response. |
92
+ | `result` | yes | `worked` or `failed`. |
93
+ | `fixRank` | no | Which ranked fix was applied (1-3). |
94
+ | `newError` | no | If it failed: the error you saw after applying. |
95
+
96
+ Confirmed rank-1 fixes are remembered per project, so the next hit on the same error starts from the confirmed fix. Failed-fix follow-ups are the feedback that improves future answers. Agents are asked to call this once per applied fix, through the same pipeline human feedback flows through in the VS Code extension.
126
97
 
127
98
  Example, in Claude Code:
128
99
 
@@ -132,11 +103,66 @@ Example, in Claude Code:
132
103
  > **Root cause:** `db.session` is used after the request context closed.
133
104
  > **Fix 1 (94% confidence):** move the query inside the request handler...
134
105
 
106
+ ### Making your agent reach for it
107
+
108
+ The server tells connecting agents what it is for, but a rule in your project file is the deterministic version. Add this to `CLAUDE.md`, `.cursorrules`, or whatever your agent reads:
109
+
110
+ ```
111
+ On any runtime error, exception, or failing test, call the debugai
112
+ debug_error tool before attempting your own fix. After applying a fix,
113
+ call report_outcome so the project's error memory stays accurate.
114
+ ```
115
+
116
+ ## VS Code
117
+
118
+ 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.
119
+
120
+ ## Manual setup
121
+
122
+ `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:
123
+
124
+ ```json
125
+ {
126
+ "mcpServers": {
127
+ "debugai": {
128
+ "command": "npx",
129
+ "args": ["-y", "@debugai/mcp"]
130
+ }
131
+ }
132
+ }
133
+ ```
134
+
135
+ Where it goes:
136
+
137
+ | Client | File |
138
+ |--------|------|
139
+ | Claude Code | `~/.claude.json` (or `claude mcp add debugai -- npx -y @debugai/mcp`) |
140
+ | Claude Desktop | macOS `~/Library/Application Support/Claude/claude_desktop_config.json`, Windows `%APPDATA%\Claude\claude_desktop_config.json` |
141
+ | Cursor | `~/.cursor/mcp.json` |
142
+ | Windsurf | `~/.codeium/windsurf/mcp_config.json` |
143
+ | Gemini CLI | `~/.gemini/settings.json` |
144
+ | Cline | VS Code globalStorage, `saoudrizwan.claude-dev/settings/cline_mcp_settings.json` |
145
+
146
+ Zed uses a different key and a nested command:
147
+
148
+ ```json
149
+ {
150
+ "context_servers": {
151
+ "debugai": {
152
+ "source": "custom",
153
+ "command": { "path": "npx", "args": ["-y", "@debugai/mcp"] }
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ Then run `npx -y @debugai/mcp login` once to store your key. If you would rather set the key per client, `DEBUGAI_API_KEY` in that client's `env` block still works and still wins over the stored one.
160
+
135
161
  ## Environment variables
136
162
 
137
163
  | Variable | Default | Description |
138
164
  |----------|---------|-------------|
139
- | `DEBUGAI_API_KEY` | (none) | Your API key. Falls back to `api_key` in the config file. |
165
+ | `DEBUGAI_API_KEY` | (none) | Your API key. Overrides `api_key` in the config file. |
140
166
  | `DEBUGAI_API_BASE` | DebugAI production | Override for self-hosted or staging setups. Falls back to `api_base` in the config file. |
141
167
  | `DEBUGAI_TIMEOUT_MS` | `150000` | Per-request deadline. Deep analyses can take 30-90s. |
142
168
  | `DEBUGAI_CONFIG_PATH` | `~/.debugai/config.json` | Alternate config file location. Rarely needed. |
@@ -145,22 +171,23 @@ Example, in Claude Code:
145
171
 
146
172
  - Free tier: 10 debugs/day. Pro ($12/mo): 1,000/mo soft cap, never hard-blocked at it.
147
173
  - When you hit the daily cap the tool says so and stops. It will not silently retry.
148
- - Simple errors route to a fast model; ugly cross-file ones route to a
149
- stronger one on paid tiers. The `Model:` badge in each response tells you
150
- which one answered.
151
- - Analyses run on DebugAI's servers. The error text and any snippet you pass
152
- are sent there. Privacy policy: [debugai.io/privacy](https://debugai.io/privacy).
174
+ - 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.
175
+ - Analyses run on DebugAI's servers. The error text and any snippet you pass are sent there, and Claude (Anthropic) does the analysis. Privacy policy: [debugai.io/privacy](https://debugai.io/privacy?src=npm).
153
176
 
154
177
  ## Troubleshooting
155
178
 
156
- - **"authentication failed"**: key missing or wrong. Check the `env` block in
157
- your client config or `~/.debugai/config.json`, restart the client. Keys
158
- start with `dbg_`.
159
- - **Nothing happens on `npx @debugai/mcp`**: correct. It's a stdio server that
160
- waits for an MCP client to speak first. Run `npx @debugai/mcp --help` to
161
- verify the install.
162
- - **Timeouts**: deep analyses can take up to 90s. If your client has its own
163
- tool timeout, raise it above that.
179
+ Run `npx -y @debugai/mcp doctor` first. It checks your Node version, whether a key is stored and where it came from, whether that key still authenticates against the API, the permissions on the config file, and which detected clients are missing the DebugAI entry. Most answers are in that output.
180
+
181
+ - **"authentication failed"**: the key was rotated or revoked. Run `npx -y @debugai/mcp login --force`.
182
+ - **Tools do not appear in the client**: the client was not restarted, or it reads a different config file. `install --list` shows which file was written.
183
+ - **Nothing happens on `npx @debugai/mcp`**: correct. It is a stdio server waiting for an MCP client to speak first. Use `--help` to verify the install.
184
+ - **Timeouts**: deep analyses can take up to 90s. If your client has its own tool timeout, raise it above that.
185
+
186
+ ## Changelog
187
+
188
+ **2.1.0**: one-command setup. Browser sign-in over a device link (no key pasting), automatic client config writing with backups, `doctor` for diagnosing a broken setup, and in-conversation sign-in when an agent calls a tool before you have an account.
189
+
190
+ **2.0.0**: `report_outcome` tool, ready-to-apply `edits` per fix, and the three-state verification label.
164
191
 
165
192
  ## Development
166
193
 
package/dist/auth.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ export interface AuthProviderOptions {
2
+ apiBase: string;
3
+ env?: NodeJS.ProcessEnv;
4
+ clientLabel?: string;
5
+ /** Injected in tests. */
6
+ now?: () => number;
7
+ fetchImpl?: typeof fetch;
8
+ }
9
+ export type EnsureAuth = {
10
+ ok: true;
11
+ apiKey: string;
12
+ } | {
13
+ ok: false;
14
+ reason: 'link_pending';
15
+ text: string;
16
+ userCode: string;
17
+ verificationUri: string;
18
+ } | {
19
+ ok: false;
20
+ reason: 'link_unavailable';
21
+ text: string;
22
+ };
23
+ export declare class AuthProvider {
24
+ private readonly opts;
25
+ private pending;
26
+ private pendingStartedAt;
27
+ private lastPollAt;
28
+ private readonly env;
29
+ private readonly now;
30
+ constructor(opts: AuthProviderOptions);
31
+ /** Env wins over file, re-read every call — see the header note. */
32
+ currentKey(): string;
33
+ /**
34
+ * Returns a usable key, or the exact words the agent should say to the user.
35
+ * Never throws: a failure to reach the link endpoint degrades to printed
36
+ * instructions, it does not take the tool call down with it.
37
+ */
38
+ ensure(): Promise<EnsureAuth>;
39
+ private pendingResult;
40
+ }
package/dist/auth.js ADDED
@@ -0,0 +1,115 @@
1
+ // Live auth for the running server.
2
+ //
3
+ // Two problems this solves, both of which used to end the funnel:
4
+ //
5
+ // 1. The key used to be read ONCE at process start. A user who fixed their
6
+ // setup while the client was running still got auth errors until they
7
+ // restarted the whole MCP client. Now the key is re-read from env + the
8
+ // config file on every tool call, so `debugai-mcp login` in another
9
+ // terminal takes effect on the next call — no restart, no reconnect.
10
+ //
11
+ // 2. A user with no key at all used to get a dead-end error. Now the server
12
+ // starts a device link itself and hands the agent a short code plus a URL
13
+ // to read out. The human approves in a browser; the agent retries; the
14
+ // second call finds the key and does the real work. Signup happens inside
15
+ // the conversation instead of in a config file the user never opens.
16
+ import { loadFileConfig, writeFileConfig } from './config.js';
17
+ import { DeviceLinkError, pollDeviceLink, startDeviceLink, } from './deviceLink.js';
18
+ /** Minimum gap between in-session polls: one poll per tool call, at most. */
19
+ const MIN_POLL_GAP_MS = 3_000;
20
+ export class AuthProvider {
21
+ opts;
22
+ pending = null;
23
+ pendingStartedAt = 0;
24
+ lastPollAt = 0;
25
+ env;
26
+ now;
27
+ constructor(opts) {
28
+ this.opts = opts;
29
+ this.env = opts.env ?? process.env;
30
+ this.now = opts.now ?? Date.now;
31
+ }
32
+ /** Env wins over file, re-read every call — see the header note. */
33
+ currentKey() {
34
+ const envKey = (this.env.DEBUGAI_API_KEY ?? '').trim();
35
+ if (envKey)
36
+ return envKey;
37
+ return loadFileConfig(this.env, () => { }).apiKey ?? '';
38
+ }
39
+ /**
40
+ * Returns a usable key, or the exact words the agent should say to the user.
41
+ * Never throws: a failure to reach the link endpoint degrades to printed
42
+ * instructions, it does not take the tool call down with it.
43
+ */
44
+ async ensure() {
45
+ const existing = this.currentKey();
46
+ if (existing)
47
+ return { ok: true, apiKey: existing };
48
+ // A link already in flight — poll it once before minting another code, so
49
+ // an agent retrying in a loop doesn't spray fresh codes at the user.
50
+ if (this.pending && this.now() - this.pendingStartedAt < this.pending.expiresIn * 1000) {
51
+ if (this.now() - this.lastPollAt >= MIN_POLL_GAP_MS) {
52
+ this.lastPollAt = this.now();
53
+ try {
54
+ const result = await pollDeviceLink(this.pending.deviceCode, {
55
+ apiBase: this.opts.apiBase,
56
+ fetchImpl: this.opts.fetchImpl,
57
+ });
58
+ if (result.status === 'linked') {
59
+ writeFileConfig({ apiKey: result.apiKey }, this.env);
60
+ this.pending = null;
61
+ return { ok: true, apiKey: result.apiKey };
62
+ }
63
+ if (result.status === 'expired' || result.status === 'denied') {
64
+ this.pending = null; // fall through and mint a fresh code below
65
+ }
66
+ }
67
+ catch {
68
+ // Network hiccup mid-link: keep the pending code, repeat instructions.
69
+ }
70
+ }
71
+ if (this.pending)
72
+ return this.pendingResult(this.pending);
73
+ }
74
+ try {
75
+ const start = await startDeviceLink({
76
+ apiBase: this.opts.apiBase,
77
+ clientLabel: this.opts.clientLabel,
78
+ fetchImpl: this.opts.fetchImpl,
79
+ });
80
+ this.pending = start;
81
+ this.pendingStartedAt = this.now();
82
+ this.lastPollAt = this.now();
83
+ return this.pendingResult(start);
84
+ }
85
+ catch (err) {
86
+ const detail = err instanceof DeviceLinkError ? ` (${err.message})` : '';
87
+ return {
88
+ ok: false,
89
+ reason: 'link_unavailable',
90
+ text: 'DebugAI is not connected to an account yet, and the automatic link could not be ' +
91
+ `started${detail}. Tell the user to run this in a terminal, which signs them in and ` +
92
+ 'stores the key for every MCP client at once:\n\n' +
93
+ ' npx -y @debugai/mcp login\n\n' +
94
+ 'It opens a browser, takes about 20 seconds, and needs no config editing. ' +
95
+ 'Then retry this tool call. No client restart needed.',
96
+ };
97
+ }
98
+ }
99
+ pendingResult(start) {
100
+ return {
101
+ ok: false,
102
+ reason: 'link_pending',
103
+ userCode: start.userCode,
104
+ verificationUri: start.verificationUri,
105
+ text: 'DebugAI is not connected to an account yet. This takes about 20 seconds and needs no ' +
106
+ 'config file editing.\n\n' +
107
+ 'Tell the user, verbatim:\n' +
108
+ ` 1. Open ${start.verificationUriComplete}\n` +
109
+ ` 2. Sign in (free, 10 debugs/day, no card) and confirm the code ${start.userCode}\n\n` +
110
+ 'Then call this tool again with the same arguments. The key is picked up automatically ' +
111
+ 'on the next call. The MCP client does NOT need restarting. ' +
112
+ `The code expires in ${Math.round(start.expiresIn / 60)} minutes.`,
113
+ };
114
+ }
115
+ }
package/dist/backend.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { AuthProvider } from './auth.js';
1
2
  export interface DebugRequest {
2
3
  error_message: string;
3
4
  code_snippet?: string;
@@ -6,6 +7,11 @@ export interface DebugRequest {
6
7
  project_id?: string;
7
8
  framework_hint?: string;
8
9
  }
10
+ export interface DebugEdit {
11
+ file: string;
12
+ old_string: string;
13
+ new_string: string;
14
+ }
9
15
  export interface DebugFix {
10
16
  rank: number;
11
17
  title: string;
@@ -13,6 +19,11 @@ export interface DebugFix {
13
19
  confidence: number;
14
20
  code?: string;
15
21
  line_hint?: string;
22
+ verified?: boolean | null;
23
+ verification_reason?: string;
24
+ edits?: DebugEdit[];
25
+ unified_diff?: string;
26
+ verify_with?: string;
16
27
  }
17
28
  export interface DebugResponse {
18
29
  root_cause: string;
@@ -26,17 +37,43 @@ export interface DebugResponse {
26
37
  pattern_matched?: string;
27
38
  remaining_today?: number;
28
39
  mock?: boolean;
40
+ schema_version?: string;
41
+ debug_log_id?: string | null;
42
+ error_signature?: string;
43
+ session_id?: string;
44
+ memory_hit?: boolean;
45
+ memory_fix_confirmed?: boolean;
46
+ }
47
+ export interface OutcomeRequest {
48
+ debug_log_id: string;
49
+ result: 'worked' | 'failed';
50
+ fix_rank?: number;
51
+ new_error?: string;
52
+ source: 'agent';
53
+ }
54
+ export interface OutcomeResponse {
55
+ success: boolean;
29
56
  }
30
57
  export interface BackendConfig {
58
+ /** Key resolved at process start. Present for direct/test use; live calls prefer `auth`. */
31
59
  apiKey: string;
32
60
  apiBase: string;
33
61
  version: string;
34
62
  /** Whole-request deadline in ms. Claude analysis runs 30-90s; nginx cuts at 120s. */
35
63
  timeoutMs?: number;
64
+ /**
65
+ * Live auth. When set, tools resolve the key through it on every call (so a
66
+ * key added while the client is running works without a restart) and can
67
+ * start a browser sign-in mid-conversation. Absent in unit tests, which pass
68
+ * a fixed apiKey.
69
+ */
70
+ auth?: AuthProvider;
36
71
  }
37
72
  export interface BackendError extends Error {
38
73
  status: number;
39
74
  retryAfterSeconds: number;
40
75
  }
41
76
  export declare const DEFAULT_TIMEOUT_MS = 150000;
77
+ export declare const OUTCOME_TIMEOUT_MS = 15000;
42
78
  export declare function callDebugBackend(req: DebugRequest, config: BackendConfig): Promise<DebugResponse>;
79
+ export declare function callOutcomeBackend(req: OutcomeRequest, config: BackendConfig): Promise<OutcomeResponse>;
package/dist/backend.js CHANGED
@@ -1,21 +1,23 @@
1
1
  export const DEFAULT_TIMEOUT_MS = 150_000;
2
+ // Feedback writes are a fast DB insert, not an LLM call — fail fast so a
3
+ // stuck outcome report never holds an agent hostage for minutes.
4
+ export const OUTCOME_TIMEOUT_MS = 15_000;
2
5
  function makeBackendError(message, status, retryAfterSeconds = 0) {
3
6
  return Object.assign(new Error(message), { status, retryAfterSeconds });
4
7
  }
5
- export async function callDebugBackend(req, config) {
6
- const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
8
+ async function postJson(path, payload, config, timeoutMs) {
7
9
  const controller = new AbortController();
8
10
  const timer = setTimeout(() => controller.abort(), timeoutMs);
9
11
  let res;
10
12
  try {
11
- res = await fetch(`${config.apiBase}/debug`, {
13
+ res = await fetch(`${config.apiBase}${path}`, {
12
14
  method: 'POST',
13
15
  headers: {
14
16
  'content-type': 'application/json',
15
17
  'x-api-key': config.apiKey,
16
18
  'user-agent': `debugai-mcp/${config.version}`,
17
19
  },
18
- body: JSON.stringify(req),
20
+ body: JSON.stringify(payload),
19
21
  signal: controller.signal,
20
22
  });
21
23
  }
@@ -36,3 +38,9 @@ export async function callDebugBackend(req, config) {
36
38
  }
37
39
  return res.json();
38
40
  }
41
+ export async function callDebugBackend(req, config) {
42
+ return postJson('/debug', req, config, config.timeoutMs ?? DEFAULT_TIMEOUT_MS);
43
+ }
44
+ export async function callOutcomeBackend(req, config) {
45
+ return postJson('/user/debug-feedback', req, config, OUTCOME_TIMEOUT_MS);
46
+ }
@@ -0,0 +1,36 @@
1
+ export type ConfigShape = 'mcpServers' | 'context_servers' | 'vscode_servers';
2
+ export interface McpClient {
3
+ id: string;
4
+ label: string;
5
+ shape: ConfigShape;
6
+ /** Absolute path to the config file, or null when this OS isn't supported. */
7
+ configPath: string | null;
8
+ /** Directories that prove the app is installed even before any MCP config exists. */
9
+ probes: string[];
10
+ /** What the user must do after we write the file. */
11
+ afterInstall: string;
12
+ /**
13
+ * True for clients `install` skips unless named explicitly — currently only
14
+ * VS Code, where the DebugAI extension already registers the server and a
15
+ * second manual entry would show the same tools twice.
16
+ */
17
+ optIn?: boolean;
18
+ note?: string;
19
+ }
20
+ export declare function knownClients(env?: NodeJS.ProcessEnv): McpClient[];
21
+ export declare function findClient(id: string, env?: NodeJS.ProcessEnv): McpClient | undefined;
22
+ /** A client counts as present when its config file OR its app directory exists. */
23
+ export declare function isDetected(client: McpClient): boolean;
24
+ export declare function detectedClients(env?: NodeJS.ProcessEnv): McpClient[];
25
+ /**
26
+ * The server entry itself. `npx -y` is deliberate: it self-updates on each
27
+ * launch and needs no global install, which is the only variant that works
28
+ * identically on a laptop, a devcontainer, and CI.
29
+ *
30
+ * No `env` block, ever — the key lives in ~/.debugai/config.json (see
31
+ * config.ts). Client configs get committed to repos; keys should not.
32
+ */
33
+ export declare function serverEntry(client: McpClient): Record<string, unknown>;
34
+ /** Top-level key in that client's config file where servers are listed. */
35
+ export declare function serversKey(shape: ConfigShape): string;
36
+ export declare const SERVER_NAME = "debugai";