pi-mcp-extension 1.10.0 → 1.10.2
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/README.md +1 -0
- package/package.json +2 -2
- package/src/config.ts +1 -74
- package/src/jsonc.ts +95 -0
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/pi-mcp-extension)
|
|
4
4
|
[](https://github.com/irahardianto/pi-mcp-extension/blob/main/LICENSE)
|
|
5
5
|
[](https://scorecard.dev/viewer/?uri=github.com/irahardianto/pi-mcp-extension)
|
|
6
|
+
[](https://www.bestpractices.dev/projects/15659)
|
|
6
7
|
|
|
7
8
|
**Connect [Pi](https://pi.dev) to any MCP server.** Supabase, DeepSource, Playwright, Context7, filesystem, databases — if it speaks [MCP](https://modelcontextprotocol.io), Pi can use it.
|
|
8
9
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-mcp-extension",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.2",
|
|
4
4
|
"description": "MCP (Model Context Protocol) client extension for the Pi coding agent — connect Pi to any MCP server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
37
|
-
"zod": "^4.6.
|
|
37
|
+
"zod": "^4.6.7"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-ai": "*",
|
package/src/config.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { join } from "node:path";
|
|
|
16
16
|
import { z } from "zod";
|
|
17
17
|
import { callbackServerConfigFromRedirectUrl } from "./callback-server.js";
|
|
18
18
|
import { McpError } from "./errors.js";
|
|
19
|
+
import { stripJsonComments } from "./jsonc.js";
|
|
19
20
|
|
|
20
21
|
// ─── Zod Schemas ──────────────────────────────────────────────────────────────
|
|
21
22
|
|
|
@@ -227,80 +228,6 @@ export interface LoadConfigOptions {
|
|
|
227
228
|
|
|
228
229
|
// ─── Loader ───────────────────────────────────────────────────────────────────
|
|
229
230
|
|
|
230
|
-
/**
|
|
231
|
-
* Strip `//` line comments and `/* ... *\/` block comments outside of double-quoted
|
|
232
|
-
* JSON strings in a single character-by-character pass.
|
|
233
|
-
*
|
|
234
|
-
* Preserves `\n` and `\r` characters so line numbers in `JSON.parse` error messages
|
|
235
|
-
* remain accurate. Unterminated `/*` block comments are left intact so `JSON.parse`
|
|
236
|
-
* fails with a syntax error rather than silently truncating the document.
|
|
237
|
-
*/
|
|
238
|
-
export function stripJsonComments(text: string): string {
|
|
239
|
-
let out = "";
|
|
240
|
-
let inString = false;
|
|
241
|
-
let i = 0;
|
|
242
|
-
|
|
243
|
-
while (i < text.length) {
|
|
244
|
-
const ch = text[i]!;
|
|
245
|
-
|
|
246
|
-
if (inString) {
|
|
247
|
-
if (ch === "\\") {
|
|
248
|
-
out += ch;
|
|
249
|
-
if (i + 1 < text.length) {
|
|
250
|
-
out += text[i + 1]!;
|
|
251
|
-
i += 2;
|
|
252
|
-
} else {
|
|
253
|
-
i += 1;
|
|
254
|
-
}
|
|
255
|
-
continue;
|
|
256
|
-
}
|
|
257
|
-
if (ch === '"') {
|
|
258
|
-
inString = false;
|
|
259
|
-
}
|
|
260
|
-
out += ch;
|
|
261
|
-
i += 1;
|
|
262
|
-
continue;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
if (ch === '"') {
|
|
266
|
-
inString = true;
|
|
267
|
-
out += ch;
|
|
268
|
-
i += 1;
|
|
269
|
-
continue;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (ch === "/" && text[i + 1] === "/") {
|
|
273
|
-
i += 2;
|
|
274
|
-
while (i < text.length && text[i] !== "\n") {
|
|
275
|
-
if (text[i] === "\r" && text[i + 1] === "\n") break;
|
|
276
|
-
i += 1;
|
|
277
|
-
}
|
|
278
|
-
continue;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
if (ch === "/" && text[i + 1] === "*") {
|
|
282
|
-
const closeIdx = text.indexOf("*/", i + 2);
|
|
283
|
-
if (closeIdx === -1) {
|
|
284
|
-
// WHY: Leave unterminated block comments intact so JSON.parse fails with a
|
|
285
|
-
// SyntaxError rather than silently truncating the rest of the file.
|
|
286
|
-
out += text.slice(i);
|
|
287
|
-
break;
|
|
288
|
-
}
|
|
289
|
-
for (let j = i; j < closeIdx + 2; j += 1) {
|
|
290
|
-
const commentCh = text[j]!;
|
|
291
|
-
out += commentCh === "\n" || commentCh === "\r" ? commentCh : " ";
|
|
292
|
-
}
|
|
293
|
-
i = closeIdx + 2;
|
|
294
|
-
continue;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
out += ch;
|
|
298
|
-
i += 1;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return out;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
231
|
async function readJsonFile(path: string): Promise<unknown> {
|
|
305
232
|
let text: string;
|
|
306
233
|
try {
|
package/src/jsonc.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure JSON-with-comments (JSONC) text utilities. This module has no `src/`
|
|
3
|
+
* dependencies of its own and is safe for `scripts/` and `tests/` to import: it
|
|
4
|
+
* does not load `zod`, the MCP error types, or the OAuth/callback modules, so
|
|
5
|
+
* non-runtime consumers stay free of runtime MCP imports.
|
|
6
|
+
*
|
|
7
|
+
* The only behaviour this module performs is `stripJsonComments` — a single-pass
|
|
8
|
+
* character scan that removes `//` line comments and `/* ... *\/` block comments
|
|
9
|
+
* while leaving the rest of the document byte-equivalent. Comments inside
|
|
10
|
+
* double-quoted strings are preserved verbatim, so a JSON value such as
|
|
11
|
+
* `"https://example.com/foo"` is never accidentally truncated. Trailing commas
|
|
12
|
+
* (the other common JSONC extension) are **not** handled here — none of the
|
|
13
|
+
* files this helper feeds today uses them, and an explicit `JSON.parse` failure
|
|
14
|
+
* on a misplaced comma is a more honest signal than silent acceptance.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Strip `//` line comments and `/* ... *\/` block comments outside of double-quoted
|
|
19
|
+
* JSON strings in a single character-by-character pass.
|
|
20
|
+
*
|
|
21
|
+
* Preserves `\n` and `\r` characters so line numbers in `JSON.parse` error messages
|
|
22
|
+
* remain accurate. Unterminated `/*` block comments are left intact so `JSON.parse`
|
|
23
|
+
* fails with a syntax error rather than silently truncating the document.
|
|
24
|
+
*
|
|
25
|
+
* WHY: this module exists so `scripts/ruleset-audit.ts` and `tests/repo-policy.test.ts`
|
|
26
|
+
* can read `.github/rulesets/*.json` with the same JSONC tolerance the runtime uses
|
|
27
|
+
* for `mcp.json`. A future maintainer can add `// WHY: …` style comments to the
|
|
28
|
+
* ruleset files (mirroring the convention used throughout `src/`) without breaking the
|
|
29
|
+
* ruleset audit or policy tests.
|
|
30
|
+
*/
|
|
31
|
+
export function stripJsonComments(text: string): string {
|
|
32
|
+
let out = "";
|
|
33
|
+
let inString = false;
|
|
34
|
+
let i = 0;
|
|
35
|
+
|
|
36
|
+
while (i < text.length) {
|
|
37
|
+
const ch = text[i]!;
|
|
38
|
+
|
|
39
|
+
if (inString) {
|
|
40
|
+
if (ch === "\\") {
|
|
41
|
+
out += ch;
|
|
42
|
+
if (i + 1 < text.length) {
|
|
43
|
+
out += text[i + 1]!;
|
|
44
|
+
i += 2;
|
|
45
|
+
} else {
|
|
46
|
+
i += 1;
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (ch === '"') {
|
|
51
|
+
inString = false;
|
|
52
|
+
}
|
|
53
|
+
out += ch;
|
|
54
|
+
i += 1;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (ch === '"') {
|
|
59
|
+
inString = true;
|
|
60
|
+
out += ch;
|
|
61
|
+
i += 1;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (ch === "/" && text[i + 1] === "/") {
|
|
66
|
+
i += 2;
|
|
67
|
+
while (i < text.length && text[i] !== "\n") {
|
|
68
|
+
if (text[i] === "\r" && text[i + 1] === "\n") break;
|
|
69
|
+
i += 1;
|
|
70
|
+
}
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (ch === "/" && text[i + 1] === "*") {
|
|
75
|
+
const closeIdx = text.indexOf("*/", i + 2);
|
|
76
|
+
if (closeIdx === -1) {
|
|
77
|
+
// WHY: Leave unterminated block comments intact so JSON.parse fails with a
|
|
78
|
+
// SyntaxError rather than silently truncating the rest of the file.
|
|
79
|
+
out += text.slice(i);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
for (let j = i; j < closeIdx + 2; j += 1) {
|
|
83
|
+
const commentCh = text[j]!;
|
|
84
|
+
out += commentCh === "\n" || commentCh === "\r" ? commentCh : " ";
|
|
85
|
+
}
|
|
86
|
+
i = closeIdx + 2;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
out += ch;
|
|
91
|
+
i += 1;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return out;
|
|
95
|
+
}
|