@fitchmultz/pi-mcp-adapter 6.0.0 → 7.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.
Files changed (111) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/OAUTH.md +1 -1
  3. package/README.md +27 -18
  4. package/dist/app-bridge.bundle.js +14 -14
  5. package/dist/config.js +41 -16
  6. package/dist/direct-tools.js +1 -1
  7. package/dist/gateway-arguments.d.ts +1 -1
  8. package/dist/index.js +38 -59
  9. package/dist/lifecycle.d.ts +2 -2
  10. package/dist/lifecycle.js +2 -2
  11. package/dist/mcp-auth-flow.js +2 -2
  12. package/dist/mcp-auth.d.ts +1 -1
  13. package/dist/mcp-auth.js +3 -3
  14. package/dist/mcp-code.d.ts +6 -6
  15. package/dist/mcp-code.js +11 -10
  16. package/dist/mcp-oauth-provider.d.ts +5 -5
  17. package/dist/mcp-oauth-provider.js +5 -5
  18. package/dist/mcp-output-guard.d.ts +1 -1
  19. package/dist/mcp-output-guard.js +1 -1
  20. package/dist/mcp-panel.d.ts +2 -2
  21. package/dist/mcp-panel.js +2 -2
  22. package/dist/mcp-setup-panel.d.ts +5 -4
  23. package/dist/mcp-setup-panel.js +15 -7
  24. package/dist/mcp-trace.d.ts +1 -1
  25. package/dist/mcp-trace.js +1 -1
  26. package/dist/npx-resolver.js +8 -4
  27. package/dist/proxy-modes.d.ts +2 -2
  28. package/dist/proxy-modes.js +20 -19
  29. package/dist/sampling-handler.js +1 -0
  30. package/dist/search-ranking.js +6 -2
  31. package/dist/server-manager.d.ts +2 -2
  32. package/dist/server-manager.js +44 -27
  33. package/dist/session-recovery.d.ts +7 -4
  34. package/dist/session-recovery.js +76 -10
  35. package/dist/tool-loader.d.ts +7 -2
  36. package/dist/tool-loader.js +56 -5
  37. package/dist/tool-metadata.d.ts +43 -43
  38. package/dist/tool-result-renderer.d.ts +3 -3
  39. package/dist/tool-result-renderer.js +3 -3
  40. package/dist/ui-resource-handler.d.ts +2 -2
  41. package/dist/ui-resource-handler.js +2 -2
  42. package/dist/ui-server.js +5 -4
  43. package/dist/ui-stream-types.d.ts +8 -8
  44. package/dist/unix-socket-transport.d.ts +1 -1
  45. package/dist/unix-socket-transport.js +1 -1
  46. package/dist/utils.d.ts +1 -0
  47. package/dist/utils.js +14 -0
  48. package/package.json +34 -98
  49. package/skills/mcp-scripting/SKILL.md +2 -0
  50. package/abort.ts +0 -34
  51. package/agent-dir.ts +0 -24
  52. package/app-bridge.bundle.js +0 -109
  53. package/banner.png +0 -0
  54. package/checkpoint.ts +0 -55
  55. package/commands.ts +0 -622
  56. package/config.ts +0 -1204
  57. package/consent-manager.ts +0 -25
  58. package/direct-tools.ts +0 -75
  59. package/elicitation-handler.ts +0 -349
  60. package/error-signal.ts +0 -21
  61. package/gateway-arguments.ts +0 -73
  62. package/glimpse-ui.ts +0 -80
  63. package/host-html-template.ts +0 -456
  64. package/index.ts +0 -767
  65. package/init.ts +0 -613
  66. package/legacy-migration.ts +0 -47
  67. package/lifecycle.ts +0 -165
  68. package/logger.ts +0 -127
  69. package/mcp-auth-flow.ts +0 -975
  70. package/mcp-auth.ts +0 -793
  71. package/mcp-callback-server.ts +0 -450
  72. package/mcp-code.ts +0 -412
  73. package/mcp-keyring-helper.cjs +0 -89
  74. package/mcp-oauth-provider.ts +0 -774
  75. package/mcp-output-guard.ts +0 -530
  76. package/mcp-panel.ts +0 -907
  77. package/mcp-script-worker.mjs +0 -131
  78. package/mcp-setup-panel.ts +0 -666
  79. package/mcp-status.ts +0 -110
  80. package/mcp-trace.ts +0 -295
  81. package/metadata-cache.ts +0 -271
  82. package/npx-resolver.ts +0 -488
  83. package/onboarding-state.ts +0 -58
  84. package/panel-keys.ts +0 -37
  85. package/prompts.ts +0 -337
  86. package/proxy-modes.ts +0 -1109
  87. package/resource-tools.ts +0 -52
  88. package/runtime-owner.ts +0 -123
  89. package/sampling-handler.ts +0 -276
  90. package/scripts/build-app-bridge.mjs +0 -15
  91. package/scripts/build.mjs +0 -132
  92. package/scripts/prepare.mjs +0 -103
  93. package/search-ranking.ts +0 -132
  94. package/server-manager.ts +0 -1320
  95. package/session-recovery.ts +0 -316
  96. package/state.ts +0 -64
  97. package/tool-approval.ts +0 -78
  98. package/tool-loader.ts +0 -153
  99. package/tool-metadata.ts +0 -240
  100. package/tool-registrar.ts +0 -74
  101. package/tool-result-renderer.ts +0 -294
  102. package/tsconfig.build.json +0 -13
  103. package/tsconfig.json +0 -16
  104. package/types.ts +0 -785
  105. package/ui-resource-handler.ts +0 -249
  106. package/ui-server.ts +0 -808
  107. package/ui-session.ts +0 -568
  108. package/ui-stream-types.ts +0 -89
  109. package/ui-tool-visibility.ts +0 -25
  110. package/unix-socket-transport.ts +0 -85
  111. package/utils.ts +0 -307
@@ -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
- }