@fitchmultz/pi-mcp-adapter 8.0.6 → 8.0.8
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 +142 -8
- package/OAUTH.md +13 -16
- package/README.md +8 -8
- package/cli.js +67 -28
- package/dist/abort.js +18 -9
- package/dist/client-operations.js +4 -2
- package/dist/commands.js +77 -43
- package/dist/config.js +194 -105
- package/dist/connection-runtime.d.ts +2 -2
- package/dist/connection-runtime.js +29 -18
- package/dist/consent-manager.d.ts +2 -2
- package/dist/consent-manager.js +5 -2
- package/dist/direct-tools.d.ts +1 -1
- package/dist/direct-tools.js +13 -7
- package/dist/elicitation-handler.d.ts +2 -3
- package/dist/elicitation-handler.js +113 -58
- package/dist/gateway-arguments.d.ts +1 -1
- package/dist/gateway-arguments.js +90 -23
- package/dist/glimpse-ui.js +10 -5
- package/dist/host-html-template.d.ts +3 -1
- package/dist/host-html-template.js +9 -12
- package/dist/index.d.ts +1 -1
- package/dist/index.js +264 -119
- package/dist/init.d.ts +1 -3
- package/dist/init.js +91 -51
- package/dist/legacy-migration.d.ts +1 -1
- package/dist/legacy-migration.js +17 -12
- package/dist/lifecycle.d.ts +3 -3
- package/dist/lifecycle.js +33 -17
- package/dist/logger.d.ts +2 -2
- package/dist/logger.js +4 -2
- package/dist/mcp-auth-flow.js +150 -58
- package/dist/mcp-auth.d.ts +7 -7
- package/dist/mcp-auth.js +189 -138
- package/dist/mcp-callback-server.js +19 -8
- package/dist/mcp-code.js +168 -54
- package/dist/mcp-keyring-helper.cjs +57 -23
- package/dist/mcp-oauth-provider.d.ts +6 -7
- package/dist/mcp-oauth-provider.js +146 -72
- package/dist/mcp-oauth-runtime.js +29 -16
- package/dist/mcp-output-guard.js +193 -65
- package/dist/mcp-output-preview.js +41 -20
- package/dist/mcp-panel.d.ts +9 -9
- package/dist/mcp-panel.js +141 -70
- package/dist/mcp-script-worker.mjs +135 -43
- package/dist/mcp-setup-panel.d.ts +8 -8
- package/dist/mcp-setup-panel.js +130 -44
- package/dist/mcp-status.js +14 -7
- package/dist/mcp-trace.d.ts +10 -5
- package/dist/mcp-trace.js +127 -61
- package/dist/metadata-cache.d.ts +3 -4
- package/dist/metadata-cache.js +83 -43
- package/dist/npx-resolver.js +101 -60
- package/dist/onboarding-state.js +4 -2
- package/dist/plain-result-reader.js +78 -31
- package/dist/prompts.js +36 -20
- package/dist/proxy-modes.js +670 -193
- package/dist/resource-tools.js +30 -9
- package/dist/runtime-owner.js +36 -18
- package/dist/sampling-handler.d.ts +1 -2
- package/dist/sampling-handler.js +41 -21
- package/dist/search-ranking.d.ts +1 -1
- package/dist/search-ranking.js +67 -34
- package/dist/server-manager.d.ts +11 -11
- package/dist/server-manager.js +283 -166
- package/dist/session-recovery.js +113 -61
- package/dist/tool-approval.js +9 -3
- package/dist/tool-loader.js +154 -55
- package/dist/tool-metadata.d.ts +1 -1
- package/dist/tool-metadata.js +51 -23
- package/dist/tool-registrar.js +32 -10
- package/dist/tool-result-renderer.js +58 -33
- package/dist/types.d.ts +2 -2
- package/dist/types.js +39 -18
- package/dist/ui-message-history.js +33 -13
- package/dist/ui-resource-handler.d.ts +3 -3
- package/dist/ui-resource-handler.js +37 -21
- package/dist/ui-server.js +101 -43
- package/dist/ui-session.js +66 -29
- package/dist/ui-stream-types.js +14 -4
- package/dist/ui-tool-visibility.js +12 -6
- package/dist/unix-socket-transport.d.ts +1 -2
- package/dist/unix-socket-transport.js +19 -12
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +60 -35
- package/package.json +28 -2
- package/skills/mcp-scripting/SKILL.md +6 -6
package/dist/mcp-setup-panel.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
2
2
|
import { createPanelKeys } from "./panel-keys.js";
|
|
3
|
-
import { KNOWN_SERVER_PRESETS } from "./config.js";
|
|
3
|
+
import { KNOWN_SERVER_PRESETS, } from "./config.js";
|
|
4
4
|
const DEFAULT_THEME = {
|
|
5
5
|
border: "2",
|
|
6
6
|
title: "36",
|
|
@@ -18,8 +18,9 @@ function fg(code, text) {
|
|
|
18
18
|
return code ? `\x1b[${code}m${text}\x1b[0m` : text;
|
|
19
19
|
}
|
|
20
20
|
function wrapText(text, width) {
|
|
21
|
-
if (width <= 8)
|
|
21
|
+
if (width <= 8) {
|
|
22
22
|
return [text];
|
|
23
|
+
}
|
|
23
24
|
const words = text.split(/\s+/).filter(Boolean);
|
|
24
25
|
const lines = [];
|
|
25
26
|
let current = "";
|
|
@@ -29,12 +30,14 @@ function wrapText(text, width) {
|
|
|
29
30
|
current = candidate;
|
|
30
31
|
continue;
|
|
31
32
|
}
|
|
32
|
-
if (current)
|
|
33
|
+
if (current) {
|
|
33
34
|
lines.push(current);
|
|
35
|
+
}
|
|
34
36
|
current = word;
|
|
35
37
|
}
|
|
36
|
-
if (current)
|
|
38
|
+
if (current) {
|
|
37
39
|
lines.push(current);
|
|
40
|
+
}
|
|
38
41
|
return lines.length > 0 ? lines : [""];
|
|
39
42
|
}
|
|
40
43
|
export class McpSetupPanel {
|
|
@@ -68,8 +71,9 @@ export class McpSetupPanel {
|
|
|
68
71
|
this.resetInactivityTimeout();
|
|
69
72
|
}
|
|
70
73
|
resetInactivityTimeout() {
|
|
71
|
-
if (this.inactivityTimeout)
|
|
74
|
+
if (this.inactivityTimeout) {
|
|
72
75
|
clearTimeout(this.inactivityTimeout);
|
|
76
|
+
}
|
|
73
77
|
this.inactivityTimeout = setTimeout(() => {
|
|
74
78
|
this.cleanup();
|
|
75
79
|
this.done();
|
|
@@ -84,24 +88,61 @@ export class McpSetupPanel {
|
|
|
84
88
|
getActions() {
|
|
85
89
|
const actions = [];
|
|
86
90
|
if (this.screen === "empty") {
|
|
87
|
-
actions.push({
|
|
91
|
+
actions.push({
|
|
92
|
+
id: "run-setup",
|
|
93
|
+
label: "Run setup",
|
|
94
|
+
description: "Inspect detected configs, adopt imports, and scaffold a minimal `.mcp.json`.",
|
|
95
|
+
});
|
|
88
96
|
}
|
|
89
97
|
if (this.discovery.imports.length > 0) {
|
|
90
|
-
actions.push({
|
|
98
|
+
actions.push({
|
|
99
|
+
id: "adopt-imports",
|
|
100
|
+
label: "Adopt detected compatibility imports",
|
|
101
|
+
description: `Choose which host-specific MCP configs Pi should import into its own override file. ${this.discovery.imports.length} source${this.discovery.imports.length === 1 ? "" : "s"} found.`,
|
|
102
|
+
});
|
|
91
103
|
}
|
|
92
|
-
actions.push({
|
|
104
|
+
actions.push({
|
|
105
|
+
id: "view-example",
|
|
106
|
+
label: "View example `.mcp.json`",
|
|
107
|
+
description: "Preview a working shared MCP config you can paste or adapt.",
|
|
108
|
+
});
|
|
93
109
|
if (!this.discovery.sources.some((source) => source.id === "shared-project" && source.exists)) {
|
|
94
|
-
actions.push({
|
|
110
|
+
actions.push({
|
|
111
|
+
id: "scaffold-project",
|
|
112
|
+
label: "Scaffold project `.mcp.json`",
|
|
113
|
+
description: "Write a minimal project config using the standard shared MCP file path, then reload Pi.",
|
|
114
|
+
});
|
|
95
115
|
}
|
|
96
|
-
actions.push({
|
|
116
|
+
actions.push({
|
|
117
|
+
id: "show-precedence",
|
|
118
|
+
label: "Explain config precedence",
|
|
119
|
+
description: "Show the read order and where Pi writes compatibility settings.",
|
|
120
|
+
});
|
|
97
121
|
if (this.getDetectedPaths().length > 0) {
|
|
98
|
-
actions.push({
|
|
122
|
+
actions.push({
|
|
123
|
+
id: "open-paths",
|
|
124
|
+
label: "Open detected config paths",
|
|
125
|
+
description: "Browse the actual config files that Pi discovered on this machine.",
|
|
126
|
+
});
|
|
99
127
|
}
|
|
100
128
|
for (const preset of KNOWN_SERVER_PRESETS) {
|
|
101
|
-
actions.push({
|
|
129
|
+
actions.push({
|
|
130
|
+
id: "add-known-server",
|
|
131
|
+
label: preset.name,
|
|
132
|
+
description: preset.summary,
|
|
133
|
+
preset,
|
|
134
|
+
});
|
|
102
135
|
}
|
|
103
|
-
if (!this.discovery.repoPrompt.configured &&
|
|
104
|
-
|
|
136
|
+
if (!this.discovery.repoPrompt.configured &&
|
|
137
|
+
this.discovery.repoPrompt.executablePath &&
|
|
138
|
+
this.discovery.repoPrompt.targetPath &&
|
|
139
|
+
this.discovery.repoPrompt.entry &&
|
|
140
|
+
this.discovery.repoPrompt.serverName) {
|
|
141
|
+
actions.push({
|
|
142
|
+
id: "add-repoprompt",
|
|
143
|
+
label: "Add RepoPrompt to shared MCP config",
|
|
144
|
+
description: "Write a standard MCP entry for RepoPrompt to the recommended shared target, then reload MCP in-session.",
|
|
145
|
+
});
|
|
105
146
|
}
|
|
106
147
|
actions.push({ id: "close", label: "Close", description: "Exit the onboarding flow." });
|
|
107
148
|
return actions;
|
|
@@ -119,8 +160,9 @@ export class McpSetupPanel {
|
|
|
119
160
|
}
|
|
120
161
|
handleInput(data) {
|
|
121
162
|
this.resetInactivityTimeout();
|
|
122
|
-
if (!this.busy)
|
|
163
|
+
if (!this.busy) {
|
|
123
164
|
this.notice = null;
|
|
165
|
+
}
|
|
124
166
|
if (matchesKey(data, "ctrl+c")) {
|
|
125
167
|
this.cleanup();
|
|
126
168
|
this.done();
|
|
@@ -136,8 +178,9 @@ export class McpSetupPanel {
|
|
|
136
178
|
this.done();
|
|
137
179
|
return;
|
|
138
180
|
}
|
|
139
|
-
if (this.busy)
|
|
181
|
+
if (this.busy) {
|
|
140
182
|
return;
|
|
183
|
+
}
|
|
141
184
|
if (this.screen === "imports") {
|
|
142
185
|
this.handleImportsInput(data);
|
|
143
186
|
return;
|
|
@@ -159,8 +202,9 @@ export class McpSetupPanel {
|
|
|
159
202
|
}
|
|
160
203
|
if (this.keys.selectConfirm(data)) {
|
|
161
204
|
const selected = this.getSelectedAction();
|
|
162
|
-
if (selected)
|
|
205
|
+
if (selected) {
|
|
163
206
|
void this.runAction(selected);
|
|
207
|
+
}
|
|
164
208
|
}
|
|
165
209
|
}
|
|
166
210
|
handleImportsInput(data) {
|
|
@@ -177,8 +221,9 @@ export class McpSetupPanel {
|
|
|
177
221
|
}
|
|
178
222
|
if (matchesKey(data, "space")) {
|
|
179
223
|
const current = imports[this.importCursor];
|
|
180
|
-
if (!current)
|
|
224
|
+
if (!current) {
|
|
181
225
|
return;
|
|
226
|
+
}
|
|
182
227
|
if (this.selectedImports.has(current.kind)) {
|
|
183
228
|
this.selectedImports.delete(current.kind);
|
|
184
229
|
}
|
|
@@ -206,8 +251,9 @@ export class McpSetupPanel {
|
|
|
206
251
|
}
|
|
207
252
|
if (this.keys.selectConfirm(data)) {
|
|
208
253
|
const selected = paths[this.pathCursor];
|
|
209
|
-
if (!selected)
|
|
254
|
+
if (!selected) {
|
|
210
255
|
return;
|
|
256
|
+
}
|
|
211
257
|
void this.runBusy(async () => {
|
|
212
258
|
await this.callbacks.openPath(selected);
|
|
213
259
|
this.notice = { text: `Opened ${selected}`, tone: "success" };
|
|
@@ -237,7 +283,10 @@ export class McpSetupPanel {
|
|
|
237
283
|
await this.runBusy(async () => {
|
|
238
284
|
const result = await this.callbacks.scaffoldProjectConfig();
|
|
239
285
|
this.callbacks.markSetupCompleted();
|
|
240
|
-
this.notice = {
|
|
286
|
+
this.notice = {
|
|
287
|
+
text: `Wrote starter config to ${result.path}. Pi will reload after this panel closes.`,
|
|
288
|
+
tone: "success",
|
|
289
|
+
};
|
|
241
290
|
});
|
|
242
291
|
return;
|
|
243
292
|
}
|
|
@@ -245,7 +294,10 @@ export class McpSetupPanel {
|
|
|
245
294
|
await this.runBusy(async () => {
|
|
246
295
|
const result = await this.callbacks.addRepoPrompt();
|
|
247
296
|
this.callbacks.markSetupCompleted();
|
|
248
|
-
this.notice = {
|
|
297
|
+
this.notice = {
|
|
298
|
+
text: `Added ${result.serverName} to ${result.path}. Pi will reload after this panel closes.`,
|
|
299
|
+
tone: "success",
|
|
300
|
+
};
|
|
249
301
|
});
|
|
250
302
|
return;
|
|
251
303
|
}
|
|
@@ -254,7 +306,10 @@ export class McpSetupPanel {
|
|
|
254
306
|
await this.runBusy(async () => {
|
|
255
307
|
const result = await this.callbacks.addKnownServer(preset);
|
|
256
308
|
this.callbacks.markSetupCompleted();
|
|
257
|
-
this.notice = {
|
|
309
|
+
this.notice = {
|
|
310
|
+
text: `Added ${result.serverName} to ${result.path}. Pi will reload after this panel closes.`,
|
|
311
|
+
tone: "success",
|
|
312
|
+
};
|
|
258
313
|
});
|
|
259
314
|
return;
|
|
260
315
|
}
|
|
@@ -263,11 +318,16 @@ export class McpSetupPanel {
|
|
|
263
318
|
this.done();
|
|
264
319
|
return;
|
|
265
320
|
}
|
|
266
|
-
this.notice = {
|
|
321
|
+
this.notice = {
|
|
322
|
+
text: "Review the details below. Press Enter on an action with a side effect to apply it.",
|
|
323
|
+
tone: "muted",
|
|
324
|
+
};
|
|
267
325
|
this.tui.requestRender();
|
|
268
326
|
}
|
|
269
327
|
async applySelectedImports() {
|
|
270
|
-
const selected = this.discovery.imports
|
|
328
|
+
const selected = this.discovery.imports
|
|
329
|
+
.filter((entry) => this.selectedImports.has(entry.kind))
|
|
330
|
+
.map((entry) => entry.kind);
|
|
271
331
|
if (selected.length === 0) {
|
|
272
332
|
this.notice = { text: "Select at least one compatibility import first.", tone: "warning" };
|
|
273
333
|
this.tui.requestRender();
|
|
@@ -276,9 +336,13 @@ export class McpSetupPanel {
|
|
|
276
336
|
await this.runBusy(async () => {
|
|
277
337
|
const result = await this.callbacks.adoptImports(selected);
|
|
278
338
|
this.callbacks.markSetupCompleted();
|
|
279
|
-
this.notice =
|
|
280
|
-
|
|
281
|
-
|
|
339
|
+
this.notice =
|
|
340
|
+
result.added.length > 0
|
|
341
|
+
? {
|
|
342
|
+
text: `Added ${result.added.join(", ")} to ${result.path}. Pi will reload after this panel closes.`,
|
|
343
|
+
tone: "success",
|
|
344
|
+
}
|
|
345
|
+
: { text: `No changes needed in ${result.path}.`, tone: "muted" };
|
|
282
346
|
this.screen = this.discovery.hasAnyConfig ? "setup" : "empty";
|
|
283
347
|
this.actionCursor = 0;
|
|
284
348
|
});
|
|
@@ -317,7 +381,11 @@ export class McpSetupPanel {
|
|
|
317
381
|
}
|
|
318
382
|
lines.push(this.padLine("", innerW));
|
|
319
383
|
if (this.notice) {
|
|
320
|
-
const tone = this.notice.tone === "success"
|
|
384
|
+
const tone = this.notice.tone === "success"
|
|
385
|
+
? this.t.success
|
|
386
|
+
: this.notice.tone === "warning"
|
|
387
|
+
? this.t.warning
|
|
388
|
+
: this.t.hint;
|
|
321
389
|
for (const line of wrapText(this.notice.text, contentW)) {
|
|
322
390
|
lines.push(this.padLine(fg(tone, line), innerW));
|
|
323
391
|
}
|
|
@@ -348,9 +416,11 @@ export class McpSetupPanel {
|
|
|
348
416
|
}
|
|
349
417
|
for (let index = start; index < end; index++) {
|
|
350
418
|
const action = actions[index];
|
|
351
|
-
if (!action)
|
|
419
|
+
if (!action) {
|
|
352
420
|
continue;
|
|
353
|
-
|
|
421
|
+
}
|
|
422
|
+
if (action.id === "add-known-server" &&
|
|
423
|
+
(index === start || actions[index - 1]?.id !== "add-known-server")) {
|
|
354
424
|
lines.push(this.padLine(fg(this.t.title, "Add a known server"), innerW));
|
|
355
425
|
}
|
|
356
426
|
const selected = index === this.actionCursor;
|
|
@@ -361,12 +431,14 @@ export class McpSetupPanel {
|
|
|
361
431
|
lines.push(this.padLine(fg(this.t.muted, `… ${actions.length - end} more below`), innerW));
|
|
362
432
|
}
|
|
363
433
|
lines.push(this.padLine("", innerW));
|
|
364
|
-
const preview = this.previewOrError(width => this.getActionPreview(this.getSelectedAction(), width), innerW);
|
|
434
|
+
const preview = this.previewOrError((width) => this.getActionPreview(this.getSelectedAction(), width), innerW);
|
|
365
435
|
for (const line of preview) {
|
|
366
436
|
lines.push(this.padLine(line, innerW));
|
|
367
437
|
}
|
|
368
438
|
lines.push(this.padLine("", innerW));
|
|
369
|
-
const hint = compact
|
|
439
|
+
const hint = compact
|
|
440
|
+
? "Enter select · Esc back"
|
|
441
|
+
: "Enter selects, Esc goes back, Ctrl+C closes.";
|
|
370
442
|
lines.push(this.padLine(fg(this.t.muted, hint), innerW));
|
|
371
443
|
return lines;
|
|
372
444
|
}
|
|
@@ -376,15 +448,18 @@ export class McpSetupPanel {
|
|
|
376
448
|
lines.push(this.padLine("", innerW));
|
|
377
449
|
for (let index = 0; index < this.discovery.imports.length; index++) {
|
|
378
450
|
const entry = this.discovery.imports[index];
|
|
379
|
-
if (!entry)
|
|
451
|
+
if (!entry) {
|
|
380
452
|
continue;
|
|
453
|
+
}
|
|
381
454
|
const selected = this.selectedImports.has(entry.kind) ? "[x]" : "[ ]";
|
|
382
455
|
const cursor = index === this.importCursor ? fg(this.t.selected, "›") : " ";
|
|
383
456
|
lines.push(this.padLine(`${cursor} ${selected} ${entry.kind} ${entry.path}`, innerW));
|
|
384
457
|
}
|
|
385
458
|
lines.push(this.padLine("", innerW));
|
|
386
|
-
const selected = this.discovery.imports
|
|
387
|
-
|
|
459
|
+
const selected = this.discovery.imports
|
|
460
|
+
.filter((entry) => this.selectedImports.has(entry.kind))
|
|
461
|
+
.map((entry) => entry.kind);
|
|
462
|
+
for (const line of this.previewOrError((width) => this.formatWritePreview("Compatibility import write preview", this.callbacks.previewImports(selected), [], width), innerW)) {
|
|
388
463
|
lines.push(this.padLine(line, innerW));
|
|
389
464
|
}
|
|
390
465
|
return lines;
|
|
@@ -397,8 +472,9 @@ export class McpSetupPanel {
|
|
|
397
472
|
for (let index = 0; index < paths.length; index++) {
|
|
398
473
|
const cursor = index === this.pathCursor ? fg(this.t.selected, "›") : " ";
|
|
399
474
|
const path = paths[index];
|
|
400
|
-
if (path !== undefined)
|
|
475
|
+
if (path !== undefined) {
|
|
401
476
|
lines.push(this.padLine(`${cursor} ${path}`, innerW));
|
|
477
|
+
}
|
|
402
478
|
}
|
|
403
479
|
return lines;
|
|
404
480
|
}
|
|
@@ -408,7 +484,8 @@ export class McpSetupPanel {
|
|
|
408
484
|
? "No MCP servers are active right now."
|
|
409
485
|
: "No MCP config is active yet.");
|
|
410
486
|
}
|
|
411
|
-
if (this.discovery.totalServerCount === 0 &&
|
|
487
|
+
if (this.discovery.totalServerCount === 0 &&
|
|
488
|
+
(this.discovery.imports.length > 0 || Boolean(this.discovery.repoPrompt.executablePath))) {
|
|
412
489
|
return fg(this.t.warning, "Pi found MCP-related setup options, but none are active in Pi yet.");
|
|
413
490
|
}
|
|
414
491
|
const shared = this.discovery.sources.filter((source) => source.kind === "shared" && source.serverCount > 0).length;
|
|
@@ -431,8 +508,9 @@ export class McpSetupPanel {
|
|
|
431
508
|
return `Shared MCP files are preferred. Pi-owned files are only for compatibility imports and adapter-specific overrides.${hostNote}${conflictNote}`;
|
|
432
509
|
}
|
|
433
510
|
visibleActionRange(total) {
|
|
434
|
-
if (total <= COMPACT_ACTION_ROWS)
|
|
511
|
+
if (total <= COMPACT_ACTION_ROWS) {
|
|
435
512
|
return { start: 0, end: total };
|
|
513
|
+
}
|
|
436
514
|
const half = Math.floor(COMPACT_ACTION_ROWS / 2);
|
|
437
515
|
const start = Math.min(Math.max(0, this.actionCursor - half), Math.max(0, total - COMPACT_ACTION_ROWS));
|
|
438
516
|
return { start, end: Math.min(total, start + COMPACT_ACTION_ROWS) };
|
|
@@ -450,7 +528,9 @@ export class McpSetupPanel {
|
|
|
450
528
|
"Run setup to adopt host-specific imports, inspect detected paths, and scaffold a minimal `.mcp.json` if needed.",
|
|
451
529
|
], previewW);
|
|
452
530
|
case "adopt-imports":
|
|
453
|
-
return this.formatWritePreview("Compatibility import write preview", this.callbacks.previewImports(this.discovery.imports
|
|
531
|
+
return this.formatWritePreview("Compatibility import write preview", this.callbacks.previewImports(this.discovery.imports
|
|
532
|
+
.filter((entry) => this.selectedImports.has(entry.kind))
|
|
533
|
+
.map((entry) => entry.kind)), [
|
|
454
534
|
`Detected imports: ${this.discovery.imports.map((entry) => `${entry.kind} (${entry.serverCount} servers)`).join(", ")}`,
|
|
455
535
|
"Selected imports are written into the Pi agent dir config as Pi-owned compatibility state.",
|
|
456
536
|
], previewW);
|
|
@@ -479,8 +559,10 @@ export class McpSetupPanel {
|
|
|
479
559
|
"5. .mcp.json",
|
|
480
560
|
"6. .pi/fitch-mcp-adapter/mcp.json",
|
|
481
561
|
`Host discovery: ${this.discovery.hostConfigDiscovery}. Conflicts reported: ${this.discovery.conflicts.length}.`,
|
|
482
|
-
...this.discovery.conflicts
|
|
483
|
-
|
|
562
|
+
...this.discovery.conflicts
|
|
563
|
+
.slice(0, 8)
|
|
564
|
+
.map((conflict) => `${conflict.serverName}: ${conflict.sources.map((source) => source.path).join(" -> ")} (winner: ${conflict.winner.path})`),
|
|
565
|
+
"Pi writes compatibility imports and adapter-only overrides to Pi-owned files.",
|
|
484
566
|
], previewW);
|
|
485
567
|
case "open-paths":
|
|
486
568
|
return this.formatPreview(this.getDetectedPaths().length > 0
|
|
@@ -500,8 +582,9 @@ export class McpSetupPanel {
|
|
|
500
582
|
}
|
|
501
583
|
case "add-known-server": {
|
|
502
584
|
const preset = action.preset;
|
|
503
|
-
if (!preset)
|
|
585
|
+
if (!preset) {
|
|
504
586
|
return this.formatPreview(["Known server preset is unavailable."], previewW);
|
|
587
|
+
}
|
|
505
588
|
return this.formatWritePreview(`${preset.name} write preview`, this.callbacks.previewKnownServer(preset), [preset.summary], previewW);
|
|
506
589
|
}
|
|
507
590
|
case "scaffold-project":
|
|
@@ -535,10 +618,13 @@ export class McpSetupPanel {
|
|
|
535
618
|
for (const line of intro) {
|
|
536
619
|
lines.push(...wrapText(line, width));
|
|
537
620
|
}
|
|
538
|
-
if (intro.length > 0)
|
|
621
|
+
if (intro.length > 0) {
|
|
539
622
|
lines.push("");
|
|
623
|
+
}
|
|
540
624
|
lines.push(...wrapText(`${title}: ${preview.path}`, width));
|
|
541
|
-
lines.push(...wrapText(preview.existed
|
|
625
|
+
lines.push(...wrapText(preview.existed
|
|
626
|
+
? "Existing file detected. Showing exact before/after diff."
|
|
627
|
+
: "New file will be created. Showing exact content diff.", width));
|
|
542
628
|
lines.push("");
|
|
543
629
|
const diffLines = preview.diffText.split("\n");
|
|
544
630
|
const maxLines = 18;
|
package/dist/mcp-status.js
CHANGED
|
@@ -2,11 +2,13 @@ import { MCP_STATUS_EVENT, MCP_STATUS_SNAPSHOT_VERSION, } from "./types.js";
|
|
|
2
2
|
const FAILURE_BACKOFF_MS = 60 * 1000;
|
|
3
3
|
function getActiveFailureAgeSeconds(state, serverName) {
|
|
4
4
|
const failedAt = state.failureTracker.get(serverName);
|
|
5
|
-
if (!failedAt)
|
|
5
|
+
if (!failedAt) {
|
|
6
6
|
return undefined;
|
|
7
|
+
}
|
|
7
8
|
const ageMs = Date.now() - failedAt;
|
|
8
|
-
if (ageMs > FAILURE_BACKOFF_MS)
|
|
9
|
+
if (ageMs > FAILURE_BACKOFF_MS) {
|
|
9
10
|
return undefined;
|
|
11
|
+
}
|
|
10
12
|
return Math.round(ageMs / 1000);
|
|
11
13
|
}
|
|
12
14
|
/** Build a sanitized snapshot without connecting or querying any MCP server. */
|
|
@@ -21,10 +23,12 @@ export function createMcpStatusSnapshot(state) {
|
|
|
21
23
|
const disabled = definition?.disabled === true;
|
|
22
24
|
const connection = disabled ? undefined : state.manager.getConnection(name);
|
|
23
25
|
const metadata = disabled ? undefined : state.toolMetadata.get(name);
|
|
24
|
-
const toolCount = metadata?.filter(tool => !tool.resourceUri).length ??
|
|
26
|
+
const toolCount = metadata?.filter((tool) => !tool.resourceUri).length ??
|
|
27
|
+
(connection?.status === "connected" ? connection.tools.length : 0);
|
|
25
28
|
const resourceCount = disabled
|
|
26
29
|
? undefined
|
|
27
|
-
: state.resourceCounts?.get(name) ??
|
|
30
|
+
: (state.resourceCounts?.get(name) ??
|
|
31
|
+
(connection?.status === "connected" ? connection.resources.length : undefined));
|
|
28
32
|
const failedAgoSeconds = disabled ? undefined : getActiveFailureAgeSeconds(state, name);
|
|
29
33
|
let status = "not-connected";
|
|
30
34
|
if (disabled) {
|
|
@@ -45,8 +49,9 @@ export function createMcpStatusSnapshot(state) {
|
|
|
45
49
|
status = "cached";
|
|
46
50
|
}
|
|
47
51
|
totalTools += disabled ? 0 : toolCount;
|
|
48
|
-
if (!disabled && resourceCount !== undefined)
|
|
52
|
+
if (!disabled && resourceCount !== undefined) {
|
|
49
53
|
totalResources += resourceCount;
|
|
54
|
+
}
|
|
50
55
|
servers.push({
|
|
51
56
|
name,
|
|
52
57
|
status,
|
|
@@ -68,8 +73,9 @@ export function createMcpStatusSnapshot(state) {
|
|
|
68
73
|
}
|
|
69
74
|
export function publishMcpStatusSnapshot(state, snapshot) {
|
|
70
75
|
const events = state.statusEvents;
|
|
71
|
-
if (!events)
|
|
76
|
+
if (!events) {
|
|
72
77
|
return;
|
|
78
|
+
}
|
|
73
79
|
try {
|
|
74
80
|
events.emit(MCP_STATUS_EVENT, snapshot ?? createMcpStatusSnapshot(state));
|
|
75
81
|
}
|
|
@@ -78,8 +84,9 @@ export function publishMcpStatusSnapshot(state, snapshot) {
|
|
|
78
84
|
}
|
|
79
85
|
}
|
|
80
86
|
export function publishMcpStatusShutdown(events) {
|
|
81
|
-
if (!events)
|
|
87
|
+
if (!events) {
|
|
82
88
|
return;
|
|
89
|
+
}
|
|
83
90
|
try {
|
|
84
91
|
events.emit(MCP_STATUS_EVENT, {
|
|
85
92
|
version: MCP_STATUS_SNAPSHOT_VERSION,
|
package/dist/mcp-trace.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { Transport } from "@modelcontextprotocol/client";
|
|
2
|
-
import type { JSONRPCMessage } from "@modelcontextprotocol/client";
|
|
1
|
+
import type { Transport, JSONRPCMessage } from "@modelcontextprotocol/client";
|
|
3
2
|
export declare const MCP_TRACE_SCHEMA_VERSION = 1;
|
|
4
3
|
export declare const DEFAULT_MCP_TRACE_MAX_BYTES: number;
|
|
5
4
|
export declare const DEFAULT_MCP_TRACE_MAX_EVENTS = 10000;
|
|
@@ -47,10 +46,16 @@ export interface McpTraceWriterOptions {
|
|
|
47
46
|
}
|
|
48
47
|
/** Redact strings before they can become durable trace metadata. */
|
|
49
48
|
export declare function redactTraceText(value: string, maxLength?: number): string;
|
|
50
|
-
export
|
|
49
|
+
export interface McpTraceEventRequest {
|
|
50
|
+
direction: McpTraceDirection;
|
|
51
|
+
server: string;
|
|
52
|
+
transport: McpTraceTransport;
|
|
53
|
+
message: JSONRPCMessage;
|
|
54
|
+
status: "sent" | "received" | "error";
|
|
51
55
|
relatedRequestId?: unknown;
|
|
52
56
|
durationMs?: number;
|
|
53
|
-
}
|
|
57
|
+
}
|
|
58
|
+
export declare function createMcpTraceEvent(request: McpTraceEventRequest): McpTraceEvent;
|
|
54
59
|
export declare class McpTraceWriter {
|
|
55
60
|
private readonly maxBytes;
|
|
56
61
|
private readonly maxEvents;
|
|
@@ -77,7 +82,7 @@ export declare class McpTraceWriter {
|
|
|
77
82
|
}
|
|
78
83
|
export declare function createMcpTraceWriter(sessionCwd: string | undefined, settings?: McpTraceSettings, randomSuffix?: string): McpTraceWriter;
|
|
79
84
|
export interface McpTraceObserver {
|
|
80
|
-
record(event: McpTraceEvent)
|
|
85
|
+
record: (event: McpTraceEvent) => void;
|
|
81
86
|
}
|
|
82
87
|
export declare function isMcpTraceEnabled(definition: {
|
|
83
88
|
trace?: boolean;
|