@fitchmultz/pi-mcp-adapter 6.0.0 → 7.0.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/CHANGELOG.md +26 -0
- package/README.md +12 -8
- package/dist/app-bridge.bundle.js +14 -14
- package/dist/config.js +41 -16
- package/dist/gateway-arguments.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lifecycle.d.ts +2 -2
- package/dist/lifecycle.js +2 -2
- package/dist/mcp-auth-flow.js +2 -2
- package/dist/mcp-auth.d.ts +1 -1
- package/dist/mcp-auth.js +3 -3
- package/dist/mcp-code.d.ts +6 -6
- package/dist/mcp-code.js +11 -10
- package/dist/mcp-oauth-provider.d.ts +5 -5
- package/dist/mcp-oauth-provider.js +5 -5
- package/dist/mcp-output-guard.d.ts +1 -1
- package/dist/mcp-panel.d.ts +2 -2
- package/dist/mcp-panel.js +2 -2
- package/dist/mcp-setup-panel.d.ts +5 -4
- package/dist/mcp-setup-panel.js +15 -7
- package/dist/mcp-trace.d.ts +1 -1
- package/dist/mcp-trace.js +1 -1
- package/dist/npx-resolver.js +8 -4
- package/dist/proxy-modes.d.ts +2 -2
- package/dist/proxy-modes.js +9 -9
- package/dist/sampling-handler.js +1 -0
- package/dist/search-ranking.js +6 -2
- package/dist/server-manager.d.ts +2 -2
- package/dist/server-manager.js +44 -27
- package/dist/session-recovery.d.ts +7 -4
- package/dist/session-recovery.js +76 -10
- package/dist/tool-metadata.d.ts +43 -43
- package/dist/tool-result-renderer.d.ts +3 -3
- package/dist/tool-result-renderer.js +3 -3
- package/dist/ui-resource-handler.d.ts +2 -2
- package/dist/ui-resource-handler.js +2 -2
- package/dist/ui-server.js +4 -3
- package/dist/ui-stream-types.d.ts +8 -8
- package/dist/unix-socket-transport.d.ts +1 -1
- package/dist/unix-socket-transport.js +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +14 -0
- package/package.json +34 -98
- package/abort.ts +0 -34
- package/agent-dir.ts +0 -24
- package/app-bridge.bundle.js +0 -109
- package/banner.png +0 -0
- package/checkpoint.ts +0 -55
- package/commands.ts +0 -622
- package/config.ts +0 -1204
- package/consent-manager.ts +0 -25
- package/direct-tools.ts +0 -75
- package/elicitation-handler.ts +0 -349
- package/error-signal.ts +0 -21
- package/gateway-arguments.ts +0 -73
- package/glimpse-ui.ts +0 -80
- package/host-html-template.ts +0 -456
- package/index.ts +0 -767
- package/init.ts +0 -613
- package/legacy-migration.ts +0 -47
- package/lifecycle.ts +0 -165
- package/logger.ts +0 -127
- package/mcp-auth-flow.ts +0 -975
- package/mcp-auth.ts +0 -793
- package/mcp-callback-server.ts +0 -450
- package/mcp-code.ts +0 -412
- package/mcp-keyring-helper.cjs +0 -89
- package/mcp-oauth-provider.ts +0 -774
- package/mcp-output-guard.ts +0 -530
- package/mcp-panel.ts +0 -907
- package/mcp-script-worker.mjs +0 -131
- package/mcp-setup-panel.ts +0 -666
- package/mcp-status.ts +0 -110
- package/mcp-trace.ts +0 -295
- package/metadata-cache.ts +0 -271
- package/npx-resolver.ts +0 -488
- package/onboarding-state.ts +0 -58
- package/panel-keys.ts +0 -37
- package/prompts.ts +0 -337
- package/proxy-modes.ts +0 -1109
- package/resource-tools.ts +0 -52
- package/runtime-owner.ts +0 -123
- package/sampling-handler.ts +0 -276
- package/scripts/build-app-bridge.mjs +0 -15
- package/scripts/build.mjs +0 -132
- package/scripts/prepare.mjs +0 -103
- package/search-ranking.ts +0 -132
- package/server-manager.ts +0 -1320
- package/session-recovery.ts +0 -316
- package/state.ts +0 -64
- package/tool-approval.ts +0 -78
- package/tool-loader.ts +0 -153
- package/tool-metadata.ts +0 -240
- package/tool-registrar.ts +0 -74
- package/tool-result-renderer.ts +0 -294
- package/tsconfig.build.json +0 -13
- package/tsconfig.json +0 -16
- package/types.ts +0 -785
- package/ui-resource-handler.ts +0 -249
- package/ui-server.ts +0 -808
- package/ui-session.ts +0 -568
- package/ui-stream-types.ts +0 -89
- package/ui-tool-visibility.ts +0 -25
- package/unix-socket-transport.ts +0 -85
- package/utils.ts +0 -307
package/scripts/prepare.mjs
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Purpose: Build generated dist output for GitHub/source installs even when Pi invokes npm install --omit=dev.
|
|
4
|
-
* Responsibilities: Detect missing source-build dependencies via the local node_modules tree, install dev
|
|
5
|
-
* dependencies with lifecycle scripts disabled, run the canonical build, then prune the dev tree so installs
|
|
6
|
-
* keep a runtime-only footprint.
|
|
7
|
-
* Scope: Package install lifecycle only; runtime behavior remains owned by scripts/build.mjs.
|
|
8
|
-
* Usage: package.json prepare script.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { execFile as execFileCallback } from "node:child_process";
|
|
12
|
-
import { existsSync } from "node:fs";
|
|
13
|
-
import { join } from "node:path";
|
|
14
|
-
import process from "node:process";
|
|
15
|
-
import { promisify } from "node:util";
|
|
16
|
-
|
|
17
|
-
const execFile = promisify(execFileCallback);
|
|
18
|
-
|
|
19
|
-
// Checked as literal node_modules paths: require.resolve() is unusable here because
|
|
20
|
-
// several @earendil-works packages expose import-only "exports" maps and throw
|
|
21
|
-
// ERR_PACKAGE_PATH_NOT_EXPORTED even when installed.
|
|
22
|
-
const REQUIRED_SOURCE_BUILD_MODULES = [
|
|
23
|
-
"esbuild",
|
|
24
|
-
"typescript",
|
|
25
|
-
"typebox",
|
|
26
|
-
"@earendil-works/pi-ai",
|
|
27
|
-
"@earendil-works/pi-coding-agent",
|
|
28
|
-
"@earendil-works/pi-tui",
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
function hasBuildDependencies() {
|
|
32
|
-
return REQUIRED_SOURCE_BUILD_MODULES.every((moduleName) =>
|
|
33
|
-
existsSync(join(process.cwd(), "node_modules", ...moduleName.split("/"), "package.json")),
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function runNpm(args) {
|
|
38
|
-
const npmExecPath = process.env.npm_execpath;
|
|
39
|
-
if (!npmExecPath) {
|
|
40
|
-
throw new Error(
|
|
41
|
-
`npm_execpath is not set; run "npm ${args.join(" ")}" manually in ${process.cwd()} and retry.`,
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
// No shell: process.execPath runs npm's cli.js directly, which is safe for paths
|
|
45
|
-
// containing spaces on every platform (shell:true concatenates args unescaped).
|
|
46
|
-
await execFile(process.execPath, [npmExecPath, ...args], {
|
|
47
|
-
cwd: process.cwd(),
|
|
48
|
-
maxBuffer: 20 * 1024 * 1024,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function runBuild() {
|
|
53
|
-
const { stderr, stdout } = await execFile(process.execPath, [join(process.cwd(), "scripts", "build.mjs")], {
|
|
54
|
-
cwd: process.cwd(),
|
|
55
|
-
maxBuffer: 20 * 1024 * 1024,
|
|
56
|
-
});
|
|
57
|
-
// Forward build output on success too: install-time diagnostics such as the
|
|
58
|
-
// concurrent-swap race-loss warning are otherwise swallowed.
|
|
59
|
-
if (stdout) process.stdout.write(stdout);
|
|
60
|
-
if (stderr) process.stderr.write(stderr);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async function pruneDevDependencies() {
|
|
64
|
-
await runNpm(["prune", "--omit=dev", "--ignore-scripts"]);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async function pruneQuietly() {
|
|
68
|
-
try {
|
|
69
|
-
await pruneDevDependencies();
|
|
70
|
-
} catch (error) {
|
|
71
|
-
console.warn(`npm prune failed after a failed build: ${error?.message ?? error}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function reportError(error) {
|
|
76
|
-
if (error?.stdout) process.stdout.write(error.stdout);
|
|
77
|
-
if (error?.stderr) process.stderr.write(error.stderr);
|
|
78
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async function main() {
|
|
82
|
-
if (hasBuildDependencies()) {
|
|
83
|
-
await runBuild();
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
await runNpm(["install", "--include=dev", "--ignore-scripts"]);
|
|
87
|
-
try {
|
|
88
|
-
await runBuild();
|
|
89
|
-
} catch (buildError) {
|
|
90
|
-
// Report the build first; cleanup can warn afterward but never mask it.
|
|
91
|
-
reportError(buildError);
|
|
92
|
-
await pruneQuietly();
|
|
93
|
-
process.exitCode = 1;
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
// A prune failure after a successful build still fails the install.
|
|
97
|
-
await pruneDevDependencies();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
main().catch((error) => {
|
|
101
|
-
reportError(error);
|
|
102
|
-
process.exitCode = 1;
|
|
103
|
-
});
|
package/search-ranking.ts
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import MiniSearch, { type SearchOptions } from "minisearch";
|
|
2
|
-
import type { McpExtensionState } from "./state.ts";
|
|
3
|
-
import type { ToolMetadata } from "./types.ts";
|
|
4
|
-
import { getServerPrefix, isServerDisabled, isToolAllowed, resolveToolPrefix } from "./types.ts";
|
|
5
|
-
|
|
6
|
-
export const MAX_PAGE_SIZE = 100;
|
|
7
|
-
export const MAX_TOOL_NAME_LENGTH = 512;
|
|
8
|
-
|
|
9
|
-
export interface RankedToolMatch {
|
|
10
|
-
server: string;
|
|
11
|
-
tool: ToolMetadata;
|
|
12
|
-
score: number;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function normalizeSearchText(value: string): string {
|
|
16
|
-
return value
|
|
17
|
-
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
18
|
-
.replace(/[_./:-]+/g, " ")
|
|
19
|
-
.toLowerCase();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function schemaSearchText(schema: unknown): string {
|
|
23
|
-
if (!schema || typeof schema !== "object") return "";
|
|
24
|
-
if (Array.isArray(schema)) return schema.map(schemaSearchText).join(" ");
|
|
25
|
-
return Object.entries(schema).flatMap(([key, value]) => {
|
|
26
|
-
if ((key === "description" || key === "title" || key === "const") && typeof value === "string") return value;
|
|
27
|
-
if (key === "enum" && Array.isArray(value)) return value.filter(item => typeof item === "string");
|
|
28
|
-
if (key === "properties" && value && typeof value === "object") return [Object.keys(value).join(" "), schemaSearchText(value)];
|
|
29
|
-
return schemaSearchText(value);
|
|
30
|
-
}).join(" ");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
interface SearchDocument {
|
|
34
|
-
id: number;
|
|
35
|
-
server: string;
|
|
36
|
-
tool: ToolMetadata;
|
|
37
|
-
name: string;
|
|
38
|
-
originalName: string;
|
|
39
|
-
description: string;
|
|
40
|
-
schema: string;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const indexes = new WeakMap<McpExtensionState, {
|
|
44
|
-
metadata: Map<string, ToolMetadata[]>;
|
|
45
|
-
index: MiniSearch<SearchDocument>;
|
|
46
|
-
}>();
|
|
47
|
-
|
|
48
|
-
function getIndex(state: McpExtensionState): MiniSearch<SearchDocument> {
|
|
49
|
-
const cached = indexes.get(state);
|
|
50
|
-
// Catalog publishers replace each server's metadata array on discovery/reconnect.
|
|
51
|
-
if (cached && cached.metadata.size === state.toolMetadata.size
|
|
52
|
-
&& [...state.toolMetadata].every(([server, metadata]) => cached.metadata.get(server) === metadata)) {
|
|
53
|
-
return cached.index;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const index = new MiniSearch<SearchDocument>({
|
|
57
|
-
fields: ["name", "originalName", "description", "schema"],
|
|
58
|
-
storeFields: ["server", "tool"],
|
|
59
|
-
searchOptions: { fields: ["name", "description", "schema"], boost: { name: 2, description: 1, schema: 1 }, prefix: true },
|
|
60
|
-
});
|
|
61
|
-
let id = 0;
|
|
62
|
-
for (const [server, tools] of state.toolMetadata) {
|
|
63
|
-
for (const tool of tools) {
|
|
64
|
-
if (tool.resourceUri !== undefined) continue;
|
|
65
|
-
index.add({
|
|
66
|
-
id: id++, server, tool,
|
|
67
|
-
name: normalizeSearchText(tool.name),
|
|
68
|
-
originalName: normalizeSearchText(tool.originalName),
|
|
69
|
-
description: normalizeSearchText([tool.title, tool.description].filter(Boolean).join(" ")),
|
|
70
|
-
schema: normalizeSearchText(schemaSearchText(tool.inputSchema)),
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
indexes.set(state, { metadata: new Map(state.toolMetadata), index });
|
|
75
|
-
return index;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function searchCatalog(state: McpExtensionState, query: string, server?: string, options?: SearchOptions): RankedToolMatch[] {
|
|
79
|
-
return getIndex(state).search(normalizeSearchText(query), {
|
|
80
|
-
...options,
|
|
81
|
-
filter: result => {
|
|
82
|
-
if (server && result.server !== server) return false;
|
|
83
|
-
const definition = state.config.mcpServers[result.server];
|
|
84
|
-
if (!definition || isServerDisabled(definition)) return false;
|
|
85
|
-
const prefix = resolveToolPrefix(definition, state.config.settings?.toolPrefix);
|
|
86
|
-
return isToolAllowed(result.tool.originalName, result.server, prefix, definition.includeTools, definition.excludeTools);
|
|
87
|
-
},
|
|
88
|
-
}).map(({ server, tool, score }) => ({ server, tool, score }))
|
|
89
|
-
.sort((a, b) => b.score - a.score || a.tool.name.localeCompare(b.tool.name));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export function rankToolMatches(state: McpExtensionState, query: string, server?: string): RankedToolMatch[] {
|
|
93
|
-
return searchCatalog(state, query, server);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export function paginate<T>(items: T[], offset: number, limit: number): { items: T[]; total: number; hasMore: boolean; nextOffset: number | null } {
|
|
97
|
-
const safeOffset = Number.isFinite(offset) ? Math.max(0, Math.trunc(offset)) : 0;
|
|
98
|
-
const safeLimit = Number.isFinite(limit) ? Math.min(MAX_PAGE_SIZE, Math.max(1, Math.trunc(limit))) : 1;
|
|
99
|
-
const total = items.length;
|
|
100
|
-
const page = items.slice(safeOffset, safeOffset + safeLimit);
|
|
101
|
-
const nextOffset = safeOffset + page.length;
|
|
102
|
-
return {
|
|
103
|
-
items: page,
|
|
104
|
-
total,
|
|
105
|
-
hasMore: nextOffset < total,
|
|
106
|
-
nextOffset: nextOffset < total ? nextOffset : null,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export function rankSuggestions(state: McpExtensionState, name: string, limit: number, server?: string): string[] {
|
|
111
|
-
if (name.length > MAX_TOOL_NAME_LENGTH) return [];
|
|
112
|
-
|
|
113
|
-
const globalPrefix = state.config.settings?.toolPrefix ?? "server";
|
|
114
|
-
const inferred = server ? undefined : Object.entries(state.config.mcpServers)
|
|
115
|
-
.filter(([, definition]) => !isServerDisabled(definition))
|
|
116
|
-
.map(([candidateServer, definition]) => ({
|
|
117
|
-
server: candidateServer,
|
|
118
|
-
prefix: getServerPrefix(candidateServer, resolveToolPrefix(definition, globalPrefix)),
|
|
119
|
-
}))
|
|
120
|
-
.filter((candidate): candidate is { server: string; prefix: string } =>
|
|
121
|
-
Boolean(candidate.prefix) && name.startsWith(`${candidate.prefix}_`))
|
|
122
|
-
.sort((a, b) => b.prefix.length - a.prefix.length)[0];
|
|
123
|
-
const matchedServer = server ?? inferred?.server;
|
|
124
|
-
const definition = matchedServer ? state.config.mcpServers[matchedServer] : undefined;
|
|
125
|
-
if (matchedServer && (!definition || isServerDisabled(definition))) return [];
|
|
126
|
-
const prefix = inferred?.prefix ?? (matchedServer ? getServerPrefix(matchedServer, resolveToolPrefix(definition, globalPrefix)) : "");
|
|
127
|
-
const query = prefix && name.startsWith(`${prefix}_`) ? name.slice(prefix.length + 1) : name;
|
|
128
|
-
const suggestions = searchCatalog(state, query, matchedServer, {
|
|
129
|
-
fields: [matchedServer ? "originalName" : "name"], combineWith: "AND", fuzzy: 2,
|
|
130
|
-
}).slice(0, limit).map(match => match.tool.name);
|
|
131
|
-
return suggestions.length > 0 || !server ? suggestions : rankSuggestions(state, name, limit);
|
|
132
|
-
}
|