@fitchmultz/pi-mcp-adapter 8.0.5 → 8.0.7
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 +140 -7
- 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.d.ts +3 -3
- package/dist/tool-result-renderer.js +65 -44
- 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 +29 -5
- package/skills/mcp-scripting/SKILL.md +6 -6
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type { JSONRPCMessage } from "@modelcontextprotocol/client";
|
|
1
|
+
import { type Transport, type JSONRPCMessage } from "@modelcontextprotocol/client";
|
|
3
2
|
/** MCP JSONL transport for an explicitly configured Unix-domain socket. */
|
|
4
3
|
export declare class UnixSocketClientTransport implements Transport {
|
|
5
4
|
private socket;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createConnection } from "node:net";
|
|
2
|
-
import { ReadBuffer, serializeMessage } from "@modelcontextprotocol/client";
|
|
2
|
+
import { ReadBuffer, serializeMessage, } from "@modelcontextprotocol/client";
|
|
3
3
|
/** MCP JSONL transport for an explicitly configured Unix-domain socket. */
|
|
4
4
|
export class UnixSocketClientTransport {
|
|
5
5
|
socket;
|
|
@@ -23,13 +23,14 @@ export class UnixSocketClientTransport {
|
|
|
23
23
|
connected = true;
|
|
24
24
|
resolve();
|
|
25
25
|
});
|
|
26
|
-
socket.on("data", chunk => {
|
|
26
|
+
socket.on("data", (chunk) => {
|
|
27
27
|
try {
|
|
28
28
|
this.readBuffer.append(chunk);
|
|
29
29
|
while (true) {
|
|
30
30
|
const message = this.readBuffer.readMessage();
|
|
31
|
-
if (message === null)
|
|
31
|
+
if (message === null) {
|
|
32
32
|
break;
|
|
33
|
+
}
|
|
33
34
|
this.onmessage?.(message);
|
|
34
35
|
}
|
|
35
36
|
}
|
|
@@ -39,14 +40,16 @@ export class UnixSocketClientTransport {
|
|
|
39
40
|
void this.close();
|
|
40
41
|
}
|
|
41
42
|
});
|
|
42
|
-
socket.on("error", error => {
|
|
43
|
-
if (!connected)
|
|
43
|
+
socket.on("error", (error) => {
|
|
44
|
+
if (!connected) {
|
|
44
45
|
reject(error);
|
|
46
|
+
}
|
|
45
47
|
this.onerror?.(error);
|
|
46
48
|
});
|
|
47
49
|
socket.on("close", () => {
|
|
48
|
-
if (this.socket === socket)
|
|
50
|
+
if (this.socket === socket) {
|
|
49
51
|
this.socket = undefined;
|
|
52
|
+
}
|
|
50
53
|
this.readBuffer.clear();
|
|
51
54
|
this.onclose?.();
|
|
52
55
|
});
|
|
@@ -56,9 +59,10 @@ export class UnixSocketClientTransport {
|
|
|
56
59
|
const socket = this.socket;
|
|
57
60
|
this.socket = undefined;
|
|
58
61
|
this.readBuffer.clear();
|
|
59
|
-
if (!socket || socket.destroyed)
|
|
62
|
+
if (!socket || socket.destroyed) {
|
|
60
63
|
return;
|
|
61
|
-
|
|
64
|
+
}
|
|
65
|
+
await new Promise((resolve) => {
|
|
62
66
|
const timeout = setTimeout(() => socket.destroy(), 2_000);
|
|
63
67
|
timeout.unref();
|
|
64
68
|
socket.once("close", () => {
|
|
@@ -70,14 +74,17 @@ export class UnixSocketClientTransport {
|
|
|
70
74
|
}
|
|
71
75
|
async send(message) {
|
|
72
76
|
const socket = this.socket;
|
|
73
|
-
if (!socket || socket.destroyed)
|
|
77
|
+
if (!socket || socket.destroyed) {
|
|
74
78
|
throw new Error("Unix socket is not connected");
|
|
79
|
+
}
|
|
75
80
|
await new Promise((resolve, reject) => {
|
|
76
|
-
socket.write(serializeMessage(message), error => {
|
|
77
|
-
if (error)
|
|
81
|
+
socket.write(serializeMessage(message), (error) => {
|
|
82
|
+
if (error) {
|
|
78
83
|
reject(error);
|
|
79
|
-
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
80
86
|
resolve();
|
|
87
|
+
}
|
|
81
88
|
});
|
|
82
89
|
});
|
|
83
90
|
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
|
2
2
|
import type { McpConfig, ServerEntry } from "./types.ts";
|
|
3
3
|
export declare const ADAPTER_VERSION: string;
|
|
4
4
|
export declare const DEFAULT_MCP_SCRIPT_TIMEOUT_MS = 30000;
|
|
5
|
+
/** Most servers one multi-server pass connects at once. */
|
|
6
|
+
export declare const MAX_CONCURRENT_SERVER_CONNECTS = 10;
|
|
5
7
|
export declare function normalizeRequestTimeoutMs(timeoutMs: number | undefined): number | undefined;
|
|
6
8
|
export declare function openUrl(pi: ExtensionAPI, url: string, browser?: string, signal?: AbortSignal): Promise<void>;
|
|
7
9
|
export declare function openPath(pi: ExtensionAPI, targetPath: string): Promise<void>;
|
package/dist/utils.js
CHANGED
|
@@ -7,8 +7,9 @@ function readAdapterVersion() {
|
|
|
7
7
|
for (const path of ["./package.json", "../package.json"]) {
|
|
8
8
|
try {
|
|
9
9
|
const manifest = JSON.parse(readFileSync(new URL(path, import.meta.url), "utf8"));
|
|
10
|
-
if (manifest.name === "@fitchmultz/pi-mcp-adapter" && typeof manifest.version === "string")
|
|
10
|
+
if (manifest.name === "@fitchmultz/pi-mcp-adapter" && typeof manifest.version === "string") {
|
|
11
11
|
return manifest.version;
|
|
12
|
+
}
|
|
12
13
|
}
|
|
13
14
|
catch { }
|
|
14
15
|
}
|
|
@@ -16,6 +17,8 @@ function readAdapterVersion() {
|
|
|
16
17
|
}
|
|
17
18
|
export const ADAPTER_VERSION = readAdapterVersion();
|
|
18
19
|
export const DEFAULT_MCP_SCRIPT_TIMEOUT_MS = 30_000;
|
|
20
|
+
/** Most servers one multi-server pass connects at once. */
|
|
21
|
+
export const MAX_CONCURRENT_SERVER_CONNECTS = 10;
|
|
19
22
|
export function normalizeRequestTimeoutMs(timeoutMs) {
|
|
20
23
|
return typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0
|
|
21
24
|
? timeoutMs
|
|
@@ -55,13 +58,16 @@ export async function parallelLimit(items, limit, fn) {
|
|
|
55
58
|
async function worker() {
|
|
56
59
|
while (true) {
|
|
57
60
|
const next = iterator.next();
|
|
58
|
-
if (next.done)
|
|
61
|
+
if (next.done) {
|
|
59
62
|
return;
|
|
63
|
+
}
|
|
60
64
|
const [index, item] = next.value;
|
|
61
65
|
results[index] = await fn(item);
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
|
-
const workers = Array(Math.min(limit, items.length))
|
|
68
|
+
const workers = Array(Math.min(limit, items.length))
|
|
69
|
+
.fill(null)
|
|
70
|
+
.map(() => worker());
|
|
65
71
|
await Promise.all(workers);
|
|
66
72
|
return results;
|
|
67
73
|
}
|
|
@@ -82,37 +88,41 @@ function getMissingEnvVars(value) {
|
|
|
82
88
|
return [...missing];
|
|
83
89
|
}
|
|
84
90
|
export function toStringRecord(value) {
|
|
85
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
91
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
86
92
|
return undefined;
|
|
93
|
+
}
|
|
87
94
|
const result = {};
|
|
88
95
|
for (const [key, entry] of Object.entries(value)) {
|
|
89
|
-
if (typeof entry === "string")
|
|
96
|
+
if (typeof entry === "string") {
|
|
90
97
|
result[key] = entry;
|
|
98
|
+
}
|
|
91
99
|
}
|
|
92
100
|
return Object.keys(result).length > 0 ? result : undefined;
|
|
93
101
|
}
|
|
94
102
|
function interpolateSecretExpression(value) {
|
|
95
|
-
if (value.startsWith("!!"))
|
|
103
|
+
if (value.startsWith("!!")) {
|
|
96
104
|
return interpolateEnvVars(value.slice(1));
|
|
105
|
+
}
|
|
97
106
|
return value.startsWith("!") ? value : interpolateEnvVars(value);
|
|
98
107
|
}
|
|
99
108
|
export function interpolateEnvRecord(values) {
|
|
100
|
-
if (!values)
|
|
109
|
+
if (!values) {
|
|
101
110
|
return undefined;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
interpolateSecretExpression(value),
|
|
105
|
-
]));
|
|
111
|
+
}
|
|
112
|
+
return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, interpolateSecretExpression(value)]));
|
|
106
113
|
}
|
|
107
114
|
const COMMAND_SECRET_TIMEOUT_MS = 10_000;
|
|
108
115
|
const COMMAND_SECRET_MAX_OUTPUT_BYTES = 1024 * 1024;
|
|
109
116
|
export function resolveCommandSecret(value, context) {
|
|
110
|
-
if (value === undefined)
|
|
117
|
+
if (value === undefined) {
|
|
111
118
|
return undefined;
|
|
112
|
-
|
|
119
|
+
}
|
|
120
|
+
if (value.startsWith("!!")) {
|
|
113
121
|
return interpolateEnvVars(value.slice(1));
|
|
114
|
-
|
|
122
|
+
}
|
|
123
|
+
if (!value.startsWith("!")) {
|
|
115
124
|
return interpolateEnvVars(value);
|
|
125
|
+
}
|
|
116
126
|
let result;
|
|
117
127
|
try {
|
|
118
128
|
result = spawnSync(value.slice(1), {
|
|
@@ -140,22 +150,22 @@ export function resolveCommandSecret(value, context) {
|
|
|
140
150
|
throw new Error(`Failed to resolve ${context}: command exited with code ${result.status ?? "unknown"}`);
|
|
141
151
|
}
|
|
142
152
|
const resolved = result.stdout.trim();
|
|
143
|
-
if (!resolved)
|
|
153
|
+
if (!resolved) {
|
|
144
154
|
throw new Error(`Failed to resolve ${context}: command returned empty output`);
|
|
155
|
+
}
|
|
145
156
|
return resolved;
|
|
146
157
|
}
|
|
147
158
|
/** Resolve command markers in a configured record without mutating the input. */
|
|
148
159
|
export function resolveCommandSecretsRecord(values, context) {
|
|
149
|
-
if (!values)
|
|
160
|
+
if (!values) {
|
|
150
161
|
return undefined;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
resolveCommandSecret(value, context(key)),
|
|
154
|
-
]));
|
|
162
|
+
}
|
|
163
|
+
return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, resolveCommandSecret(value, context(key))]));
|
|
155
164
|
}
|
|
156
165
|
export function resolveServerUrl(definition) {
|
|
157
|
-
if (definition.url == null)
|
|
166
|
+
if (definition.url == null) {
|
|
158
167
|
return undefined;
|
|
168
|
+
}
|
|
159
169
|
if (typeof definition.url !== "string") {
|
|
160
170
|
throw new Error("MCP server URL must be a string");
|
|
161
171
|
}
|
|
@@ -168,16 +178,20 @@ export function resolveServerUrl(definition) {
|
|
|
168
178
|
new URL(resolved);
|
|
169
179
|
}
|
|
170
180
|
catch (error) {
|
|
171
|
-
throw new Error(`Invalid MCP server URL after environment interpolation: ${resolved}`, {
|
|
181
|
+
throw new Error(`Invalid MCP server URL after environment interpolation: ${resolved}`, {
|
|
182
|
+
cause: error,
|
|
183
|
+
});
|
|
172
184
|
}
|
|
173
185
|
return resolved;
|
|
174
186
|
}
|
|
175
187
|
export function resolveConfigPath(value) {
|
|
176
|
-
if (value === undefined)
|
|
188
|
+
if (value === undefined) {
|
|
177
189
|
return undefined;
|
|
190
|
+
}
|
|
178
191
|
const resolved = interpolateEnvVars(value);
|
|
179
|
-
if (resolved === "~")
|
|
192
|
+
if (resolved === "~") {
|
|
180
193
|
return homedir();
|
|
194
|
+
}
|
|
181
195
|
if (resolved.startsWith("~/") || resolved.startsWith("~\\")) {
|
|
182
196
|
return join(homedir(), resolved.slice(2));
|
|
183
197
|
}
|
|
@@ -203,8 +217,9 @@ export function stripOscSequences(text) {
|
|
|
203
217
|
index += isEscOsc ? 2 : 1;
|
|
204
218
|
while (index < text.length) {
|
|
205
219
|
const code = text.charCodeAt(index++);
|
|
206
|
-
if (code === 0x07 || code === 0x9c)
|
|
220
|
+
if (code === 0x07 || code === 0x9c) {
|
|
207
221
|
break;
|
|
222
|
+
}
|
|
208
223
|
if (code === 0x1b && text[index] === "\\") {
|
|
209
224
|
index++;
|
|
210
225
|
break;
|
|
@@ -224,25 +239,32 @@ export function formatTerminalError(error) {
|
|
|
224
239
|
const messages = [];
|
|
225
240
|
const seen = new Set();
|
|
226
241
|
const collect = (value) => {
|
|
227
|
-
if (seen.has(value))
|
|
242
|
+
if (seen.has(value)) {
|
|
228
243
|
return;
|
|
229
|
-
|
|
244
|
+
}
|
|
245
|
+
if ((typeof value === "object" && value !== null) || typeof value === "function") {
|
|
230
246
|
seen.add(value);
|
|
247
|
+
}
|
|
231
248
|
if (value instanceof AggregateError) {
|
|
232
249
|
const countBefore = messages.length;
|
|
233
|
-
for (const nested of value.errors)
|
|
250
|
+
for (const nested of value.errors) {
|
|
234
251
|
collect(nested);
|
|
235
|
-
|
|
252
|
+
}
|
|
253
|
+
if (value.cause !== undefined) {
|
|
236
254
|
collect(value.cause);
|
|
237
|
-
|
|
255
|
+
}
|
|
256
|
+
if (messages.length === countBefore && value.message) {
|
|
238
257
|
messages.push(value.message);
|
|
258
|
+
}
|
|
239
259
|
return;
|
|
240
260
|
}
|
|
241
261
|
if (value instanceof Error) {
|
|
242
|
-
if (value.message)
|
|
262
|
+
if (value.message) {
|
|
243
263
|
messages.push(value.message);
|
|
244
|
-
|
|
264
|
+
}
|
|
265
|
+
if (value.cause !== undefined) {
|
|
245
266
|
collect(value.cause);
|
|
267
|
+
}
|
|
246
268
|
return;
|
|
247
269
|
}
|
|
248
270
|
messages.push(String(value));
|
|
@@ -251,8 +273,9 @@ export function formatTerminalError(error) {
|
|
|
251
273
|
return sanitizeTerminalText([...new Set(messages)].join(": "));
|
|
252
274
|
}
|
|
253
275
|
export function truncateAtWord(text, target) {
|
|
254
|
-
if (!text || text.length <= target)
|
|
276
|
+
if (!text || text.length <= target) {
|
|
255
277
|
return text;
|
|
278
|
+
}
|
|
256
279
|
const truncated = text.slice(0, target);
|
|
257
280
|
const lastSpace = truncated.lastIndexOf(" ");
|
|
258
281
|
if (lastSpace > target * 0.6) {
|
|
@@ -270,8 +293,9 @@ export function formatAuthRequiredMessage(config, serverName, defaultMessage) {
|
|
|
270
293
|
return template ? template.replaceAll("${server}", serverName) : defaultMessage;
|
|
271
294
|
}
|
|
272
295
|
export function formatMcpStatus(config, message) {
|
|
273
|
-
if (config.settings?.mcpFooterStatus === "off")
|
|
296
|
+
if (config.settings?.mcpFooterStatus === "off") {
|
|
274
297
|
return undefined;
|
|
298
|
+
}
|
|
275
299
|
return `${config.settings?.showStatusIcon === false ? "MCP: " : "🔌 MCP: "}${message}`;
|
|
276
300
|
}
|
|
277
301
|
/**
|
|
@@ -279,8 +303,9 @@ export function formatMcpStatus(config, message) {
|
|
|
279
303
|
*/
|
|
280
304
|
export function extractToolUiStreamMode(toolMeta) {
|
|
281
305
|
const uiMeta = toolMeta?.ui;
|
|
282
|
-
if (!uiMeta || typeof uiMeta !== "object")
|
|
306
|
+
if (!uiMeta || typeof uiMeta !== "object") {
|
|
283
307
|
return undefined;
|
|
308
|
+
}
|
|
284
309
|
const streamMode = uiMeta["pi-mcp-adapter.streamMode"];
|
|
285
310
|
if (streamMode === "eager" || streamMode === "stream-first") {
|
|
286
311
|
return streamMode;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fitchmultz/pi-mcp-adapter",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.7",
|
|
4
4
|
"description": "Token-efficient MCP adapter for the Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -33,10 +33,30 @@
|
|
|
33
33
|
"prepare": "node ./scripts/prepare.mjs",
|
|
34
34
|
"check:compat": "node scripts/compat-host.mjs && npm run build && npm run typecheck && vitest run --exclude __tests__/interactive-visualizer-server.test.ts && npm run test:oauth && node scripts/compat-package-smoke.mjs",
|
|
35
35
|
"typecheck": "node ./scripts/tsc.mjs --noEmit",
|
|
36
|
+
"typecheck:all": "node ./scripts/typecheck-all.mjs",
|
|
36
37
|
"test": "vitest run && npm run test:oauth",
|
|
37
38
|
"test:watch": "vitest",
|
|
38
39
|
"test:oauth": "PI_MCP_ADAPTER_TEST_AUTH_STORE=memory node --test --test-concurrency=1 mcp-auth.test.ts mcp-auth-flow.test.ts mcp-callback-server.test.ts mcp-oauth-provider.test.ts",
|
|
39
|
-
"test:conformance": "bash conformance/run.sh"
|
|
40
|
+
"test:conformance": "bash conformance/run.sh",
|
|
41
|
+
"check:directives": "node scripts/check-directives.mjs",
|
|
42
|
+
"check:policy": "node scripts/check-policy.mjs",
|
|
43
|
+
"lint": "oxlint --deny-warnings .",
|
|
44
|
+
"lint:conformance": "oxlint --deny-warnings conformance",
|
|
45
|
+
"lint:prompts": "oxlint --deny-warnings __tests__/prompts.test.ts __tests__/prompts-sdk-integration.test.ts __tests__/test-state.ts __tests__/test-extension-context.ts",
|
|
46
|
+
"lint:runtime-tests": "oxlint --deny-warnings __tests__/runtime",
|
|
47
|
+
"lint:tracing": "oxlint --deny-warnings mcp-trace.ts",
|
|
48
|
+
"lint:auth-tests": "oxlint --deny-warnings __tests__/auth",
|
|
49
|
+
"lint:discovery-tests": "oxlint --deny-warnings __tests__/discovery __tests__/fixtures/pinned-tools.ts",
|
|
50
|
+
"lint:state-tests": "oxlint --deny-warnings __tests__/state",
|
|
51
|
+
"lint:output-tests": "oxlint --deny-warnings __tests__/output",
|
|
52
|
+
"lint:packaging-tests": "oxlint --deny-warnings __tests__/packaging",
|
|
53
|
+
"lint:quality": "oxlint --deny-warnings scripts/check-directives.mjs scripts/check-policy.mjs scripts/quality-exceptions.mjs __tests__/quality",
|
|
54
|
+
"lint:ui-host-tests": "oxlint --deny-warnings __tests__/ui-host",
|
|
55
|
+
"lint:panel-tests": "oxlint --deny-warnings __tests__/panel",
|
|
56
|
+
"lint:agent": "oxlint --deny-warnings --format=agent .",
|
|
57
|
+
"lint:fix": "oxlint --fix .",
|
|
58
|
+
"format": "oxfmt --write .",
|
|
59
|
+
"format:check": "oxfmt --check ."
|
|
40
60
|
},
|
|
41
61
|
"repository": {
|
|
42
62
|
"type": "git",
|
|
@@ -105,13 +125,17 @@
|
|
|
105
125
|
}
|
|
106
126
|
},
|
|
107
127
|
"devDependencies": {
|
|
108
|
-
"@earendil-works/pi-ai": "1.
|
|
109
|
-
"@earendil-works/pi-coding-agent": "1.
|
|
110
|
-
"@earendil-works/pi-tui": "1.
|
|
128
|
+
"@earendil-works/pi-ai": "1.5.0",
|
|
129
|
+
"@earendil-works/pi-coding-agent": "1.5.0",
|
|
130
|
+
"@earendil-works/pi-tui": "1.5.0",
|
|
111
131
|
"@modelcontextprotocol/server": "2.3.1",
|
|
112
132
|
"@types/cross-spawn": "6.0.6",
|
|
113
133
|
"@types/node": "24.19.1",
|
|
114
134
|
"esbuild": "0.28.2",
|
|
135
|
+
"oxc-parser": "0.156.0",
|
|
136
|
+
"oxfmt": "0.75.0",
|
|
137
|
+
"oxlint": "1.90.0",
|
|
138
|
+
"oxlint-tsgolint": "7.0.2005",
|
|
115
139
|
"typebox": "1.3.27",
|
|
116
140
|
"typescript": "7.0.2",
|
|
117
141
|
"vitest": "5.0.3"
|
|
@@ -66,12 +66,12 @@ return page;
|
|
|
66
66
|
Gateway equivalents require explicit actions:
|
|
67
67
|
|
|
68
68
|
```js
|
|
69
|
-
mcp({ action: "search", query: "search issues", server: "github" })
|
|
70
|
-
mcp({ action: "describe", tool: "github_search_issues" })
|
|
71
|
-
mcp({ action: "call", tool: "github_search_issues", args: { query: "is:open" } })
|
|
72
|
-
mcp({ action: "resources", server: "docs" })
|
|
73
|
-
mcp({ action: "read-resource", server: "docs", uri: "docs://guide" })
|
|
74
|
-
mcp({ action: "read-result", ref: "/returned/result/path", path: "/structuredContent" })
|
|
69
|
+
mcp({ action: "search", query: "search issues", server: "github" });
|
|
70
|
+
mcp({ action: "describe", tool: "github_search_issues" });
|
|
71
|
+
mcp({ action: "call", tool: "github_search_issues", args: { query: "is:open" } });
|
|
72
|
+
mcp({ action: "resources", server: "docs" });
|
|
73
|
+
mcp({ action: "read-resource", server: "docs", uri: "docs://guide" });
|
|
74
|
+
mcp({ action: "read-result", ref: "/returned/result/path", path: "/structuredContent" });
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
Gateway search returns schemas without activating functions; use it when only `mcp` is allowed. New gateway calls use object `args`. Optional v5 mode fields and JSON-string arguments are only a stored-call ingress compatibility path.
|