@humain/terminal 0.0.14 → 0.0.15
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 +7 -0
- package/dist/bundle/chunks/{chunk-6TW5AYGH.js → chunk-QMTWJZBT.js} +251 -39
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +30 -9
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/CHANGELOG.md +27 -0
- package/dist/humain/mcp-adapter/vendor/README.md +13 -13
- package/dist/humain/mcp-adapter/vendor/commands.ts +58 -21
- package/dist/humain/mcp-adapter/vendor/config.ts +18 -4
- package/dist/humain/mcp-adapter/vendor/direct-tools.ts +26 -6
- package/dist/humain/mcp-adapter/vendor/dist/config.d.ts +4 -0
- package/dist/humain/mcp-adapter/vendor/dist/config.js +13 -4
- package/dist/humain/mcp-adapter/vendor/dist/config.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/dist/types.d.ts +11 -3
- package/dist/humain/mcp-adapter/vendor/dist/types.js.map +1 -1
- package/dist/humain/mcp-adapter/vendor/error-signal.ts +15 -4
- package/dist/humain/mcp-adapter/vendor/errors.ts +141 -0
- package/dist/humain/mcp-adapter/vendor/host-html-template.ts +58 -5
- package/dist/humain/mcp-adapter/vendor/index.bundle.mjs +1017 -160
- package/dist/humain/mcp-adapter/vendor/index.ts +2 -3
- package/dist/humain/mcp-adapter/vendor/init.ts +5 -0
- package/dist/humain/mcp-adapter/vendor/mcp-panel.ts +30 -9
- package/dist/humain/mcp-adapter/vendor/mcp-setup-panel.ts +66 -28
- package/dist/humain/mcp-adapter/vendor/mcp-status.ts +2 -0
- package/dist/humain/mcp-adapter/vendor/package.json +3 -2
- package/dist/humain/mcp-adapter/vendor/proxy-modes.ts +66 -13
- package/dist/humain/mcp-adapter/vendor/sandbox-proxy-template.ts +217 -0
- package/dist/humain/mcp-adapter/vendor/server-manager.ts +337 -6
- package/dist/humain/mcp-adapter/vendor/skills/mcp-scripting/SKILL.md +1 -0
- package/dist/humain/mcp-adapter/vendor/types.ts +18 -3
- package/dist/humain/mcp-adapter/vendor/ui-resource-handler.ts +18 -2
- package/dist/humain/mcp-adapter/vendor/ui-server.ts +179 -54
- package/dist/humain/mcp-adapter/vendor/ui-session.ts +28 -8
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/src/humain/mcp-adapter/UPSTREAM.md +1 -1
- package/src/humain/mcp-adapter/upstream.json +4 -4
- package/src/humain/mcp-adapter/vendor/CHANGELOG.md +27 -0
|
@@ -32,9 +32,9 @@ The adapter reads standard MCP files automatically. No extra setup needed if you
|
|
|
32
32
|
|
|
33
33
|
| You already have... | What happens |
|
|
34
34
|
|---------------------|--------------|
|
|
35
|
-
| `.mcp.json` or `~/.config/mcp/mcp.json` | Pi uses it immediately. The first time you open `/mcp`, you'll see a short heads-up explaining which file Pi detected and that Pi only writes adapter-specific overrides to its own files. |
|
|
35
|
+
| `.mcp.json` or `~/.config/mcp/mcp.json` | Pi uses it immediately. Use `.mcp.json` for project/team sharing and `~/.config/mcp/mcp.json` for all projects. The first time you open `/mcp`, you'll see a short heads-up explaining which file Pi detected and that Pi only writes adapter-specific overrides to its own files. |
|
|
36
36
|
| Host-specific configs (Cursor, Claude Code, Codex, etc.) but no standard MCP files | Run `/mcp setup` to adopt those host configs into Pi. The setup flow shows exactly what it found, lets you pick which ones to import, and previews the exact file changes before writing. |
|
|
37
|
-
| Nothing configured yet | Run `/mcp setup
|
|
37
|
+
| Nothing configured yet | Run `/mcp setup`, choose project `.mcp.json` or global `~/.config/mcp/mcp.json`, then scaffold a minimal config, add a curated known server, quick-add RepoPrompt, or inspect what the adapter discovered on your machine. |
|
|
38
38
|
|
|
39
39
|
If you prefer the terminal, you can also run `pi-mcp-adapter init` after install to scan for host-specific configs and add missing compatibility imports to the Pi agent dir (`~/.pi/agent/mcp.json` by default, or `$PI_CODING_AGENT_DIR/mcp.json` when set).
|
|
40
40
|
|
|
@@ -53,16 +53,16 @@ Preferred project config: `.mcp.json`
|
|
|
53
53
|
}
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
Preferred user-global shared config: `~/.config/mcp/mcp.json
|
|
56
|
+
Preferred user-global shared config: `~/.config/mcp/mcp.json` (for all projects). Pi also reads the tool-agnostic global paths `~/.agents/mcp.json` and `~/.agents/mcp/mcp.json` as compatibility inputs.
|
|
57
57
|
|
|
58
|
-
Pi
|
|
58
|
+
Pi-owned files are not additional normal setup choices. They hold Pi-specific settings, compatibility imports, and adapter-only overrides:
|
|
59
59
|
|
|
60
60
|
- `<Pi agent dir>/mcp.json` — Pi global override (`~/.pi/agent/mcp.json` by default)
|
|
61
61
|
- `.pi/mcp.json` — Pi project override
|
|
62
62
|
|
|
63
|
-
Host-specific configs are detected and shown by `/mcp setup` and `pi-mcp-adapter init`, but they are not loaded automatically. The normal `/mcp` panel does not scan host-specific files when `settings.hostConfigDiscovery` is `"off"`. To explicitly opt in to host-config fallback discovery, set `settings.hostConfigDiscovery` to `"on"` or run `pi-mcp-adapter init --discover-host-configs`. The default is `"off"`; `"prompt"` is available for integrations that want detection without activation. Host configs are lower precedence than every shared and Pi-owned source, and `/mcp setup` continues to offer explicit import adoption. Discovery reports source paths, provenance, and same-name conflicts; it never writes to external host files or silently launches commands from them.
|
|
63
|
+
Host-specific configs are detected and shown by `/mcp setup` and `pi-mcp-adapter init`, but they are compatibility inputs rather than normal setup paths and are not loaded automatically. The normal `/mcp` panel does not scan host-specific files when `settings.hostConfigDiscovery` is `"off"`. To explicitly opt in to host-config fallback discovery, set `settings.hostConfigDiscovery` to `"on"` or run `pi-mcp-adapter init --discover-host-configs`. The default is `"off"`; `"prompt"` is available for integrations that want detection without activation. Host configs are lower precedence than every shared and Pi-owned source, and `/mcp setup` continues to offer explicit import adoption. Discovery reports source paths, provenance, and same-name conflicts; it never writes to external host files or silently launches commands from them.
|
|
64
64
|
|
|
65
|
-
Precedence is:
|
|
65
|
+
Precedence is (later entries win):
|
|
66
66
|
|
|
67
67
|
1. `~/.config/mcp/mcp.json`
|
|
68
68
|
2. `~/.agents/mcp.json`
|
|
@@ -302,7 +302,7 @@ Use `"auto"` to probe for MCP 2026-07-28 and conservatively fall back to the cla
|
|
|
302
302
|
|
|
303
303
|
Use `"2026-07-28"` to pin that revision. Pinning has no legacy or SSE fallback and fails if the server does not offer the requested version.
|
|
304
304
|
|
|
305
|
-
The stable SDK handles era-specific request envelopes, result decoding, list-changed subscriptions, cancellation, and multi-round-trip sampling/elicitation. The adapter keeps strict OAuth issuer validation in every mode. Adapter-level roots support, standard MCP logging presentation, and configuration/UI for protocol cache hints are not yet implemented.
|
|
305
|
+
The stable SDK handles era-specific request envelopes, result decoding, list-changed subscriptions, cancellation, and multi-round-trip sampling/elicitation. The SDK's embedded-input progress callback does not expose the originating tool or resource identity, so the adapter cannot maintain a durable per-tool waiting status row; interactive sessions keep the existing input dialog visible, and proxy calls show request progress when UI is available. The adapter keeps strict OAuth issuer validation in every mode. Adapter-level roots support, standard MCP logging presentation, and configuration/UI for protocol cache hints are not yet implemented.
|
|
306
306
|
|
|
307
307
|
For pre-registered browser OAuth clients, set `oauth.redirectUri` to the exact callback registered with the provider, for example `"http://localhost:3118/callback"`. Dynamic clients normally omit it and use a lazy OS-assigned localhost callback port. A configured `https://` callback runs in manual mode because the adapter cannot receive a callback on another host. After authorization, copy the full callback URL from the browser address bar and paste it into `/mcp-auth` or `mcp({ action: "auth-complete", ... })`.
|
|
308
308
|
|
|
@@ -412,7 +412,7 @@ When any enabled server uses `eager` or `keep-alive`, initialization also starts
|
|
|
412
412
|
| `strictDirectToolArguments` | Validate direct-tool inputs against their advertised schemas and recover one JSON string layer for object and array properties (default: false). |
|
|
413
413
|
| `directToolResultDetails` | Direct-tool result details: `"lean"` (default) or `"bounded"` to retain the guarded raw MCP result. |
|
|
414
414
|
| `warnOnLargeDirectTools` | Show the advisory when 75 or more direct tools resolve (default: `true`). Set to `false` to suppress only this advisory. |
|
|
415
|
-
| `freezeDirectTools` | Keep direct-tool registration stable after the initial sync so
|
|
415
|
+
| `freezeDirectTools` | Keep direct-tool registration stable after the initial sync so metadata updates and explicit reconnects do not rebuild the system prompt. Proxy/search/cache metadata still refreshes. Default: false. |
|
|
416
416
|
| `scriptMode` | Register the MCP-only `mcpScript` plain-JavaScript tool (default: true). Set to `false` to hide it. |
|
|
417
417
|
| `disableProxyTool` | Hide the `mcp` proxy tool once configured direct tools are fully available from cache. |
|
|
418
418
|
| `autoAuth` | Auto-run OAuth on `connect`/tool calls when a server needs auth, then retry once (default: false). |
|
|
@@ -484,7 +484,7 @@ Set `"outputGuard": false` — or the env kill switch `MCP_OUTPUT_GUARD=0` — t
|
|
|
484
484
|
|
|
485
485
|
For multi-call MCP work, write ordinary JavaScript: discover, inspect, call, loop, filter, chain, or fan out, then return one result. Run that code with the default-on `mcpScript` tool. For a single MCP call, search, describe, status check, or auth action, use `mcp` instead. Set `settings.scriptMode` to `false` to hide the scripting tool.
|
|
486
486
|
|
|
487
|
-
The bundled `mcp-scripting` skill is a separate Pi package resource. To
|
|
487
|
+
The bundled `mcp-scripting` skill is a separate Pi package resource and is manual-only by default, so its description is not added to the model's automatic skill context. Use `/skill:mcp-scripting` when you want its detailed workflow. To remove the manual skill command as well while keeping the adapter extension and `mcpScript` tool installed, replace the package entry in Pi settings with the object form and disable package skills:
|
|
488
488
|
|
|
489
489
|
```json
|
|
490
490
|
{
|
|
@@ -624,13 +624,13 @@ Models sometimes encode an object or array argument as a JSON string. Set `setti
|
|
|
624
624
|
|
|
625
625
|
Set `settings.directToolResultDetails` to `"bounded"` when an extension needs structured MCP result fields in Pi's direct-tool result details. The same output guard limits apply. Small leading structured fields stay available, while large fields receive bounded summaries and the complete guarded result follows the output guard's spill-file policy. The default `"lean"` mode keeps the existing server and tool metadata only.
|
|
626
626
|
|
|
627
|
-
If prompt-cache stability matters more than
|
|
627
|
+
If prompt-cache stability matters more than direct-tool hot-loading, set `settings.freezeDirectTools` to `true`. The initial direct-tool sync still runs, but later metadata updates and explicit reconnects keep the registered tool surface unchanged while proxy/search/cache metadata refreshes normally.
|
|
628
628
|
|
|
629
629
|
When you change direct-tool toggles in `/mcp`, the extension updates direct tool registration in the current session. Broader setup writes from `/mcp setup` still use Pi's normal reload flow because they can add or restructure MCP config files.
|
|
630
630
|
|
|
631
|
-
**Interactive configuration:** Run `/mcp` to open an interactive panel showing all servers with connection status, tools, and direct/proxy toggles. You can reconnect servers
|
|
631
|
+
**Interactive configuration:** Run `/mcp` to open an interactive panel showing all servers with connection status, tools, and direct/proxy toggles. You can reconnect servers, toggle tools between direct and proxy, and enable or disable servers (`ctrl+d`) from the same overlay. For OAuth, press Enter on a server that needs auth or `ctrl+a` on any OAuth server. The Save action defaults to `ctrl+s` and can be remapped with the `mcp.panel.save` keybinding.
|
|
632
632
|
|
|
633
|
-
**Guided first-run setup:** Run `/mcp setup` to inspect detected shared MCP files, adopt compatibility imports from other hosts, open discovered config paths, preview exact before/after file diffs for writes, scaffold a minimal
|
|
633
|
+
**Guided first-run setup:** Run `/mcp setup` to choose the normal write target for new shared servers — project `.mcp.json` or global `~/.config/mcp/mcp.json` — inspect detected shared MCP files, adopt compatibility imports from other hosts, open discovered config paths, preview exact before/after file diffs for writes, scaffold a minimal selected config, add a curated known server (DeepWiki, Context7, Notion, GitHub, or Chrome DevTools), or quick-add RepoPrompt into a standard/shared MCP file.
|
|
634
634
|
|
|
635
635
|
**Subagent integration:** If you use the subagent extension, agents can request direct MCP tools in their frontmatter with `mcp:server-name` syntax. See the subagent README for details.
|
|
636
636
|
|
|
@@ -712,7 +712,7 @@ Supported compatibility imports: `cursor`, `claude-code`, `claude-desktop`, `ope
|
|
|
712
712
|
|
|
713
713
|
### Project Config
|
|
714
714
|
|
|
715
|
-
Prefer `.mcp.json` for project-local shared MCP config. Use `.pi/mcp.json` only when you need a Pi-specific project override. Project files override both user-global shared MCP config and Pi global overrides.
|
|
715
|
+
Prefer `.mcp.json` for project-local shared MCP config and `~/.config/mcp/mcp.json` for user-global shared MCP config. Use `.pi/mcp.json` only when you need a Pi-specific project override. Project files override both user-global shared MCP config and Pi global overrides.
|
|
716
716
|
|
|
717
717
|
## Usage
|
|
718
718
|
|
|
@@ -4,17 +4,19 @@ import type { McpExtensionState } from "./state.ts";
|
|
|
4
4
|
import { isServerDisabled, type McpAuthResult, type McpConfig, type McpPanelCallbacks, type McpPanelResult, type ImportKind } from "./types.ts";
|
|
5
5
|
import {
|
|
6
6
|
ensureCompatibilityImports,
|
|
7
|
+
getSharedConfigPath,
|
|
7
8
|
getMcpDiscoverySummary,
|
|
8
9
|
getMcpStandardConfigSummary,
|
|
9
|
-
getProjectConfigPath,
|
|
10
10
|
type KnownServerPreset,
|
|
11
|
+
type SharedConfigTarget,
|
|
11
12
|
getServerProvenance,
|
|
12
13
|
previewCompatibilityImports,
|
|
13
14
|
previewSharedServerEntry,
|
|
14
|
-
|
|
15
|
+
previewStarterSharedConfig,
|
|
15
16
|
writeDirectToolsConfig,
|
|
17
|
+
writeProjectServerDisabledOverride,
|
|
16
18
|
writeSharedServerEntry,
|
|
17
|
-
|
|
19
|
+
writeStarterSharedConfig,
|
|
18
20
|
} from "./config.ts";
|
|
19
21
|
import { markKeepAliveAfterConnect, notifyToolMetadataUpdated, updateMetadataCache, updateStatusBar, getFailureAgeSeconds, getFailureMessage, clearFailure, recordFailure } from "./init.ts";
|
|
20
22
|
import { isServerInActiveFailureBackoff } from "./failure-backoff.ts";
|
|
@@ -48,6 +50,13 @@ export async function showStatus(state: McpExtensionState, ctx: ExtensionContext
|
|
|
48
50
|
if (!ctx.hasUI) return;
|
|
49
51
|
|
|
50
52
|
const lines: string[] = ["MCP Server Status:", ""];
|
|
53
|
+
if (!state.programmaticConfig) {
|
|
54
|
+
lines.push(
|
|
55
|
+
"Shared MCP config: .mcp.json for this project/team or ~/.config/mcp/mcp.json for all projects.",
|
|
56
|
+
"Pi-owned files hold compatibility imports and adapter-specific overrides.",
|
|
57
|
+
"",
|
|
58
|
+
);
|
|
59
|
+
}
|
|
51
60
|
|
|
52
61
|
for (const name of Object.keys(state.config.mcpServers)) {
|
|
53
62
|
const definition = state.config.mcpServers[name];
|
|
@@ -59,12 +68,22 @@ export async function showStatus(state: McpExtensionState, ctx: ExtensionContext
|
|
|
59
68
|
const metadata = state.toolMetadata.get(name);
|
|
60
69
|
const toolCount = metadata?.length ?? 0;
|
|
61
70
|
const failedAgo = getFailureAgeSeconds(state, name);
|
|
62
|
-
let status = "not
|
|
71
|
+
let status = "not listening (disconnected)";
|
|
63
72
|
let statusIcon = "○";
|
|
64
73
|
let failed = false;
|
|
65
74
|
|
|
66
75
|
if (connection?.status === "connected") {
|
|
67
|
-
status = "
|
|
76
|
+
status = connection.listenState === "active"
|
|
77
|
+
? connection.listenCatalogStale
|
|
78
|
+
? "connected; listen active; catalog may be stale"
|
|
79
|
+
: "connected; listen active"
|
|
80
|
+
: connection.listenState === "dropped"
|
|
81
|
+
? "connected; catalog may be stale — will reconcile on next keep-alive or tool use"
|
|
82
|
+
: connection.listenState === "re-establishing"
|
|
83
|
+
? "connected; re-establishing listen"
|
|
84
|
+
: connection.listenState === "legacy"
|
|
85
|
+
? "connected; legacy notification path"
|
|
86
|
+
: "connected; not listening for catalog updates";
|
|
68
87
|
statusIcon = "✓";
|
|
69
88
|
} else if (connection?.status === "needs-auth") {
|
|
70
89
|
status = "needs auth";
|
|
@@ -75,16 +94,20 @@ export async function showStatus(state: McpExtensionState, ctx: ExtensionContext
|
|
|
75
94
|
statusIcon = "✗";
|
|
76
95
|
failed = true;
|
|
77
96
|
} else if (metadata !== undefined) {
|
|
78
|
-
status = "cached";
|
|
97
|
+
status = "cached; not listening (disconnected)";
|
|
79
98
|
}
|
|
80
99
|
|
|
81
|
-
const toolSuffix = failed ? "" : ` (${toolCount} tools${status
|
|
100
|
+
const toolSuffix = failed ? "" : ` (${toolCount} tools${status.startsWith("cached") ? ", cached" : ""})`;
|
|
82
101
|
lines.push(`${statusIcon} ${name}: ${status}${toolSuffix}`);
|
|
83
102
|
}
|
|
84
103
|
|
|
104
|
+
if (state.config.settings?.freezeDirectTools === true) {
|
|
105
|
+
lines.push("", "Direct tools frozen; active registrations may differ from current metadata.");
|
|
106
|
+
}
|
|
107
|
+
|
|
85
108
|
if (Object.keys(state.config.mcpServers).length === 0) {
|
|
86
109
|
lines.push("No MCP servers configured");
|
|
87
|
-
lines.push("Run /mcp setup to
|
|
110
|
+
lines.push("Run /mcp setup to add a server to .mcp.json or ~/.config/mcp/mcp.json");
|
|
88
111
|
}
|
|
89
112
|
|
|
90
113
|
ctx.ui.notify(lines.join("\n"), "info");
|
|
@@ -450,16 +473,18 @@ export interface PanelFlowResult {
|
|
|
450
473
|
function buildSharedConfigNoticeLines(configOverridePath: string | undefined, cwd: string): { lines: string[]; fingerprint: string | null } {
|
|
451
474
|
const discovery = getMcpStandardConfigSummary(configOverridePath, cwd);
|
|
452
475
|
const onboardingState = loadOnboardingState();
|
|
453
|
-
|
|
476
|
+
const sharedSources = discovery.sources.filter((source) =>
|
|
477
|
+
(source.id === "shared-project" || source.id === "shared-global") && source.serverCount > 0,
|
|
478
|
+
);
|
|
479
|
+
if (sharedSources.length === 0 || onboardingState.sharedConfigHintShown) {
|
|
454
480
|
return { lines: [], fingerprint: null };
|
|
455
481
|
}
|
|
456
482
|
|
|
457
|
-
const sharedSources = discovery.sources.filter((source) => source.kind === "shared" && source.serverCount > 0);
|
|
458
483
|
const sourceList = sharedSources.map((source) => source.path).join(", ");
|
|
459
484
|
return {
|
|
460
485
|
lines: [
|
|
461
486
|
`Using standard MCP config from ${sourceList}.`,
|
|
462
|
-
"Pi only writes compatibility imports and adapter-specific overrides into Pi-owned files when needed.",
|
|
487
|
+
"Use .mcp.json for project/team config or ~/.config/mcp/mcp.json for all projects. Pi only writes compatibility imports and adapter-specific overrides into Pi-owned files when needed.",
|
|
463
488
|
],
|
|
464
489
|
fingerprint: discovery.fingerprint,
|
|
465
490
|
};
|
|
@@ -490,34 +515,34 @@ export async function openMcpSetup(
|
|
|
490
515
|
|
|
491
516
|
const callbacks = {
|
|
492
517
|
previewImports: (imports: ImportKind[]) => previewCompatibilityImports(imports, configOverridePath),
|
|
493
|
-
|
|
494
|
-
previewRepoPrompt: () => {
|
|
518
|
+
previewStarterConfig: (target: SharedConfigTarget) => previewStarterSharedConfig(target, ctx.cwd),
|
|
519
|
+
previewRepoPrompt: (target: SharedConfigTarget) => {
|
|
495
520
|
const repoPrompt = getMcpDiscoverySummary(configOverridePath, ctx.cwd, options).repoPrompt;
|
|
496
521
|
if (!repoPrompt.entry || !repoPrompt.targetPath || !repoPrompt.serverName) return null;
|
|
497
|
-
return previewSharedServerEntry(
|
|
522
|
+
return previewSharedServerEntry(getSharedConfigPath(target, ctx.cwd), repoPrompt.serverName, repoPrompt.entry);
|
|
498
523
|
},
|
|
499
|
-
previewKnownServer: (preset: KnownServerPreset) => previewSharedServerEntry(
|
|
524
|
+
previewKnownServer: (preset: KnownServerPreset, target: SharedConfigTarget) => previewSharedServerEntry(getSharedConfigPath(target, ctx.cwd), preset.id, preset.entry),
|
|
500
525
|
adoptImports: async (imports: ImportKind[]) => {
|
|
501
526
|
const result = ensureCompatibilityImports(imports, configOverridePath);
|
|
502
527
|
if (result.added.length > 0) configChanged = true;
|
|
503
528
|
return result;
|
|
504
529
|
},
|
|
505
|
-
|
|
506
|
-
const path =
|
|
530
|
+
scaffoldConfig: async (target: SharedConfigTarget) => {
|
|
531
|
+
const path = writeStarterSharedConfig(target, ctx.cwd);
|
|
507
532
|
configChanged = true;
|
|
508
533
|
return { path };
|
|
509
534
|
},
|
|
510
|
-
addRepoPrompt: async () => {
|
|
535
|
+
addRepoPrompt: async (target: SharedConfigTarget) => {
|
|
511
536
|
const repoPrompt = getMcpDiscoverySummary(configOverridePath, ctx.cwd, options).repoPrompt;
|
|
512
537
|
if (!repoPrompt.entry || !repoPrompt.targetPath || !repoPrompt.serverName) {
|
|
513
538
|
throw new Error("RepoPrompt is not available to add from this setup screen.");
|
|
514
539
|
}
|
|
515
|
-
const path = writeSharedServerEntry(
|
|
540
|
+
const path = writeSharedServerEntry(getSharedConfigPath(target, ctx.cwd), repoPrompt.serverName, repoPrompt.entry);
|
|
516
541
|
configChanged = true;
|
|
517
542
|
return { path, serverName: repoPrompt.serverName };
|
|
518
543
|
},
|
|
519
|
-
addKnownServer: async (preset: KnownServerPreset) => {
|
|
520
|
-
const path = writeSharedServerEntry(
|
|
544
|
+
addKnownServer: async (preset: KnownServerPreset, target: SharedConfigTarget) => {
|
|
545
|
+
const path = writeSharedServerEntry(getSharedConfigPath(target, ctx.cwd), preset.id, preset.entry);
|
|
521
546
|
configChanged = true;
|
|
522
547
|
return { path, serverName: preset.name };
|
|
523
548
|
},
|
|
@@ -648,6 +673,18 @@ export async function openMcpPanel(
|
|
|
648
673
|
(tui, _theme, keybindings, done) => {
|
|
649
674
|
return createMcpPanel(config, cache, provenanceMap, callbacks, tui, (result: McpPanelResult) => {
|
|
650
675
|
void (async () => {
|
|
676
|
+
if (!result.cancelled && result.disabledChanges.size > 0) {
|
|
677
|
+
for (const [serverName, disabled] of result.disabledChanges) {
|
|
678
|
+
try {
|
|
679
|
+
const override = writeProjectServerDisabledOverride(configPath, ctx.cwd, serverName, disabled);
|
|
680
|
+
if (override.changed) {
|
|
681
|
+
configChanged = true;
|
|
682
|
+
}
|
|
683
|
+
} catch (error) {
|
|
684
|
+
ctx.ui.notify(`Failed to ${disabled ? "disable" : "enable"} server "${serverName}": ${error instanceof Error ? error.message : String(error)}`, "error");
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
651
688
|
if (!result.cancelled && result.changes.size > 0) {
|
|
652
689
|
writeDirectToolsConfig(result.changes, provenanceMap, config);
|
|
653
690
|
await onDirectToolsConfigChanged?.(result.changes);
|
|
@@ -175,6 +175,8 @@ export interface ConfigWritePreview {
|
|
|
175
175
|
diffText: string;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
+
export type SharedConfigTarget = "project" | "global";
|
|
179
|
+
|
|
178
180
|
export function getPiGlobalConfigPath(overridePath?: string): string {
|
|
179
181
|
return overridePath ? resolve(overridePath) : getAgentPath("mcp.json");
|
|
180
182
|
}
|
|
@@ -191,6 +193,10 @@ export function getProjectPiConfigPath(cwd = process.cwd()): string {
|
|
|
191
193
|
return resolve(cwd, getConfigDirName(), PROJECT_PI_CONFIG_NAME);
|
|
192
194
|
}
|
|
193
195
|
|
|
196
|
+
export function getSharedConfigPath(target: SharedConfigTarget, cwd = process.cwd()): string {
|
|
197
|
+
return target === "project" ? getProjectConfigPath(cwd) : getGenericGlobalConfigPath();
|
|
198
|
+
}
|
|
199
|
+
|
|
194
200
|
export function getConfigDiscoveryPaths(overridePath?: string, cwd = process.cwd()): ConfigDiscoveryPath[] {
|
|
195
201
|
return getConfigSources(overridePath, cwd).map((source) => ({
|
|
196
202
|
label: source.label,
|
|
@@ -1159,19 +1165,27 @@ export function buildStarterProjectConfig(): McpConfig {
|
|
|
1159
1165
|
};
|
|
1160
1166
|
}
|
|
1161
1167
|
|
|
1162
|
-
export function
|
|
1163
|
-
const targetPath =
|
|
1168
|
+
export function previewStarterSharedConfig(target: SharedConfigTarget, cwd = process.cwd()): ConfigWritePreview {
|
|
1169
|
+
const targetPath = getSharedConfigPath(target, cwd);
|
|
1164
1170
|
const nextRaw = { mcpServers: buildStarterProjectConfig().mcpServers };
|
|
1165
1171
|
return buildConfigWritePreview(targetPath, nextRaw);
|
|
1166
1172
|
}
|
|
1167
1173
|
|
|
1168
|
-
export function
|
|
1169
|
-
const targetPath =
|
|
1174
|
+
export function writeStarterSharedConfig(target: SharedConfigTarget, cwd = process.cwd()): string {
|
|
1175
|
+
const targetPath = getSharedConfigPath(target, cwd);
|
|
1170
1176
|
const raw = { mcpServers: buildStarterProjectConfig().mcpServers };
|
|
1171
1177
|
writeRawConfigObject(targetPath, raw);
|
|
1172
1178
|
return targetPath;
|
|
1173
1179
|
}
|
|
1174
1180
|
|
|
1181
|
+
export function previewStarterProjectConfig(cwd = process.cwd()): ConfigWritePreview {
|
|
1182
|
+
return previewStarterSharedConfig("project", cwd);
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
export function writeStarterProjectConfig(cwd = process.cwd()): string {
|
|
1186
|
+
return writeStarterSharedConfig("project", cwd);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1175
1189
|
export function previewSharedServerEntry(filePath: string, serverName: string, entry: ServerEntry): ConfigWritePreview {
|
|
1176
1190
|
const raw = readRawConfigObject(filePath);
|
|
1177
1191
|
const nextRaw = { ...raw };
|
|
@@ -20,6 +20,7 @@ import { SessionRecoveryAuthRequiredError, withSessionRecovery } from "./session
|
|
|
20
20
|
import { combineAbortSignals, isAbortError } from "./runtime-owner.ts";
|
|
21
21
|
import { ensureToolCallApproved } from "./tool-approval.ts";
|
|
22
22
|
import { Check, Errors } from "typebox/value";
|
|
23
|
+
import { getInputRequiredNeedsUiDetails } from "./errors.ts";
|
|
23
24
|
|
|
24
25
|
type ClientCallToolResult = Awaited<ReturnType<Client["callTool"]>>;
|
|
25
26
|
type ClientReadResourceResult = Awaited<ReturnType<Client["readResource"]>>;
|
|
@@ -486,7 +487,13 @@ export function createDirectToolExecutor(
|
|
|
486
487
|
onNeedsAuth: recoverAuthConnection,
|
|
487
488
|
},
|
|
488
489
|
spec.serverName,
|
|
489
|
-
(conn) =>
|
|
490
|
+
async (conn) => {
|
|
491
|
+
const refreshRead = await state.manager.prepareResourceUse?.(spec.serverName, spec.resourceUri!, conn);
|
|
492
|
+
return conn.client.readResource(
|
|
493
|
+
{ uri: spec.resourceUri! },
|
|
494
|
+
refreshRead ? { ...requestOptions, cacheMode: "refresh" } : requestOptions,
|
|
495
|
+
);
|
|
496
|
+
},
|
|
490
497
|
);
|
|
491
498
|
const content = transformMcpResourceContents(result.contents ?? [], state.owner?.signal);
|
|
492
499
|
const guarded = await guardMcpOutput(content.length > 0 ? content : [{ type: "text" as const, text: "(empty resource)" }], {
|
|
@@ -520,11 +527,14 @@ export function createDirectToolExecutor(
|
|
|
520
527
|
onNeedsAuth: recoverAuthConnection,
|
|
521
528
|
},
|
|
522
529
|
spec.serverName,
|
|
523
|
-
(conn) =>
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
530
|
+
async (conn) => {
|
|
531
|
+
await state.manager.ensureListen?.(spec.serverName, conn);
|
|
532
|
+
return abortable(conn.client.callTool({
|
|
533
|
+
name: spec.originalName,
|
|
534
|
+
arguments: normalizedParams,
|
|
535
|
+
_meta: uiSession?.requestMeta,
|
|
536
|
+
}, requestOptions), ownedSignal);
|
|
537
|
+
},
|
|
528
538
|
);
|
|
529
539
|
uiSession?.sendToolResult(result as unknown as import("@modelcontextprotocol/client").CallToolResult);
|
|
530
540
|
|
|
@@ -596,6 +606,16 @@ export function createDirectToolExecutor(
|
|
|
596
606
|
details: { error: "url_elicitation_required", server: spec.serverName, action },
|
|
597
607
|
};
|
|
598
608
|
}
|
|
609
|
+
const inputRequired = getInputRequiredNeedsUiDetails(error, spec.resourceUri
|
|
610
|
+
? { server: spec.serverName, resourceUri: spec.resourceUri }
|
|
611
|
+
: { server: spec.serverName, tool: spec.originalName });
|
|
612
|
+
if (inputRequired) {
|
|
613
|
+
uiSession?.sendToolCancelled(inputRequired.message);
|
|
614
|
+
return {
|
|
615
|
+
content: [{ type: "text" as const, text: inputRequired.message }],
|
|
616
|
+
details: { ...inputRequired },
|
|
617
|
+
};
|
|
618
|
+
}
|
|
599
619
|
const message = error instanceof Error ? error.message : String(error);
|
|
600
620
|
const aborted = isAbortError(error, ownedSignal);
|
|
601
621
|
if (!aborted) {
|
|
@@ -85,10 +85,12 @@ export interface ConfigWritePreview {
|
|
|
85
85
|
afterText: string;
|
|
86
86
|
diffText: string;
|
|
87
87
|
}
|
|
88
|
+
export type SharedConfigTarget = "project" | "global";
|
|
88
89
|
export declare function getPiGlobalConfigPath(overridePath?: string): string;
|
|
89
90
|
export declare function getGenericGlobalConfigPath(): string;
|
|
90
91
|
export declare function getProjectConfigPath(cwd?: string): string;
|
|
91
92
|
export declare function getProjectPiConfigPath(cwd?: string): string;
|
|
93
|
+
export declare function getSharedConfigPath(target: SharedConfigTarget, cwd?: string): string;
|
|
92
94
|
export declare function getConfigDiscoveryPaths(overridePath?: string, cwd?: string): ConfigDiscoveryPath[];
|
|
93
95
|
export declare function findAvailableImportConfigs(cwd?: string): DiscoveredImportConfig[];
|
|
94
96
|
export declare function getMcpStandardConfigSummary(overridePath?: string, cwd?: string): McpStandardConfigSummary;
|
|
@@ -113,6 +115,8 @@ export declare function ensureCompatibilityImports(importKinds: ImportKind[], ov
|
|
|
113
115
|
added: ImportKind[];
|
|
114
116
|
};
|
|
115
117
|
export declare function buildStarterProjectConfig(): McpConfig;
|
|
118
|
+
export declare function previewStarterSharedConfig(target: SharedConfigTarget, cwd?: string): ConfigWritePreview;
|
|
119
|
+
export declare function writeStarterSharedConfig(target: SharedConfigTarget, cwd?: string): string;
|
|
116
120
|
export declare function previewStarterProjectConfig(cwd?: string): ConfigWritePreview;
|
|
117
121
|
export declare function writeStarterProjectConfig(cwd?: string): string;
|
|
118
122
|
export declare function previewSharedServerEntry(filePath: string, serverName: string, entry: ServerEntry): ConfigWritePreview;
|
|
@@ -93,6 +93,9 @@ export function getProjectConfigPath(cwd = process.cwd()) {
|
|
|
93
93
|
export function getProjectPiConfigPath(cwd = process.cwd()) {
|
|
94
94
|
return resolve(cwd, getConfigDirName(), PROJECT_PI_CONFIG_NAME);
|
|
95
95
|
}
|
|
96
|
+
export function getSharedConfigPath(target, cwd = process.cwd()) {
|
|
97
|
+
return target === "project" ? getProjectConfigPath(cwd) : getGenericGlobalConfigPath();
|
|
98
|
+
}
|
|
96
99
|
export function getConfigDiscoveryPaths(overridePath, cwd = process.cwd()) {
|
|
97
100
|
return getConfigSources(overridePath, cwd).map((source) => ({
|
|
98
101
|
label: source.label,
|
|
@@ -976,17 +979,23 @@ export function buildStarterProjectConfig() {
|
|
|
976
979
|
mcpServers: {},
|
|
977
980
|
};
|
|
978
981
|
}
|
|
979
|
-
export function
|
|
980
|
-
const targetPath =
|
|
982
|
+
export function previewStarterSharedConfig(target, cwd = process.cwd()) {
|
|
983
|
+
const targetPath = getSharedConfigPath(target, cwd);
|
|
981
984
|
const nextRaw = { mcpServers: buildStarterProjectConfig().mcpServers };
|
|
982
985
|
return buildConfigWritePreview(targetPath, nextRaw);
|
|
983
986
|
}
|
|
984
|
-
export function
|
|
985
|
-
const targetPath =
|
|
987
|
+
export function writeStarterSharedConfig(target, cwd = process.cwd()) {
|
|
988
|
+
const targetPath = getSharedConfigPath(target, cwd);
|
|
986
989
|
const raw = { mcpServers: buildStarterProjectConfig().mcpServers };
|
|
987
990
|
writeRawConfigObject(targetPath, raw);
|
|
988
991
|
return targetPath;
|
|
989
992
|
}
|
|
993
|
+
export function previewStarterProjectConfig(cwd = process.cwd()) {
|
|
994
|
+
return previewStarterSharedConfig("project", cwd);
|
|
995
|
+
}
|
|
996
|
+
export function writeStarterProjectConfig(cwd = process.cwd()) {
|
|
997
|
+
return writeStarterSharedConfig("project", cwd);
|
|
998
|
+
}
|
|
990
999
|
export function previewSharedServerEntry(filePath, serverName, entry) {
|
|
991
1000
|
const raw = readRawConfigObject(filePath);
|
|
992
1001
|
const nextRaw = { ...raw };
|