@modootoday/pmcp 0.1.2 → 0.1.3
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSkillServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NTQWFY45.js";
|
|
4
4
|
|
|
5
5
|
// src/stdio.ts
|
|
6
6
|
import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
@@ -30,4 +30,4 @@ export {
|
|
|
30
30
|
serve,
|
|
31
31
|
main
|
|
32
32
|
};
|
|
33
|
-
//# sourceMappingURL=chunk-
|
|
33
|
+
//# sourceMappingURL=chunk-3SOVLFDB.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
normaliseIntent
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NTQWFY45.js";
|
|
4
4
|
|
|
5
5
|
// src/cache.ts
|
|
6
6
|
async function openDatabase(path) {
|
|
@@ -131,4 +131,4 @@ export {
|
|
|
131
131
|
DEFAULT_INTENT_CACHE_LIMIT,
|
|
132
132
|
openIntentCache
|
|
133
133
|
};
|
|
134
|
-
//# sourceMappingURL=chunk-
|
|
134
|
+
//# sourceMappingURL=chunk-BP45RDLT.js.map
|
|
@@ -338,7 +338,7 @@ function registerSkillTools(server, tools) {
|
|
|
338
338
|
return server;
|
|
339
339
|
}
|
|
340
340
|
function createSkillServer(options) {
|
|
341
|
-
const server = new McpServer({ name: SERVER_NAME, version: "0.1.
|
|
341
|
+
const server = new McpServer({ name: SERVER_NAME, version: "0.1.3" });
|
|
342
342
|
return registerSkillTools(server, createSkillTools(options));
|
|
343
343
|
}
|
|
344
344
|
|
|
@@ -360,4 +360,4 @@ export {
|
|
|
360
360
|
registerSkillTools,
|
|
361
361
|
createSkillServer
|
|
362
362
|
};
|
|
363
|
-
//# sourceMappingURL=chunk-
|
|
363
|
+
//# sourceMappingURL=chunk-NTQWFY45.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
openDatabase
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BP45RDLT.js";
|
|
5
5
|
import {
|
|
6
6
|
serve
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-3SOVLFDB.js";
|
|
8
8
|
import {
|
|
9
9
|
readCatalog
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NTQWFY45.js";
|
|
11
11
|
|
|
12
12
|
// src/cli/command.ts
|
|
13
13
|
var ArgumentError = class extends Error {
|
|
@@ -510,14 +510,14 @@ async function discover(issuer, fetcher2) {
|
|
|
510
510
|
}
|
|
511
511
|
return body;
|
|
512
512
|
}
|
|
513
|
-
async function startDevice(metadata,
|
|
513
|
+
async function startDevice(metadata, request2, fetcher2, now = Date.now) {
|
|
514
514
|
const res = await fetcher2(metadata.device_authorization_endpoint, {
|
|
515
515
|
method: "POST",
|
|
516
516
|
headers: FORM_HEADERS,
|
|
517
517
|
body: form({
|
|
518
|
-
client_id:
|
|
519
|
-
resource:
|
|
520
|
-
scope:
|
|
518
|
+
client_id: request2.clientId,
|
|
519
|
+
resource: request2.resource,
|
|
520
|
+
scope: request2.scope
|
|
521
521
|
})
|
|
522
522
|
});
|
|
523
523
|
const body = await res.json();
|
|
@@ -544,14 +544,14 @@ async function startDevice(metadata, request, fetcher2, now = Date.now) {
|
|
|
544
544
|
expiresAt: now() + (Number.isFinite(expires) ? expires : 600) * 1e3
|
|
545
545
|
};
|
|
546
546
|
}
|
|
547
|
-
async function pollOnce(metadata,
|
|
547
|
+
async function pollOnce(metadata, request2, fetcher2, now = Date.now) {
|
|
548
548
|
const res = await fetcher2(metadata.token_endpoint, {
|
|
549
549
|
method: "POST",
|
|
550
550
|
headers: FORM_HEADERS,
|
|
551
551
|
body: form({
|
|
552
552
|
grant_type: DEVICE_GRANT,
|
|
553
|
-
device_code:
|
|
554
|
-
client_id:
|
|
553
|
+
device_code: request2.deviceCode,
|
|
554
|
+
client_id: request2.clientId
|
|
555
555
|
})
|
|
556
556
|
});
|
|
557
557
|
const body = await res.json();
|
|
@@ -565,7 +565,7 @@ async function pollOnce(metadata, request, fetcher2, now = Date.now) {
|
|
|
565
565
|
return {
|
|
566
566
|
kind: "granted",
|
|
567
567
|
session: {
|
|
568
|
-
issuer:
|
|
568
|
+
issuer: request2.issuer,
|
|
569
569
|
accessToken: token,
|
|
570
570
|
...typeof refresh === "string" ? { refreshToken: refresh } : {},
|
|
571
571
|
...Number.isFinite(expiresIn) ? { expiresAt: now() + expiresIn * 1e3 } : {},
|
|
@@ -786,6 +786,28 @@ var whoamiCommand = {
|
|
|
786
786
|
}
|
|
787
787
|
};
|
|
788
788
|
|
|
789
|
+
// src/commands/standing.ts
|
|
790
|
+
function sayStanding(context, line) {
|
|
791
|
+
if (!line) return;
|
|
792
|
+
if (line.status === "recalled" && line.recall) {
|
|
793
|
+
context.ui.warn(
|
|
794
|
+
"recalled",
|
|
795
|
+
`${line.recall.severity} advisory against the versions this line covers`
|
|
796
|
+
);
|
|
797
|
+
context.ui.line(` ${line.recall.summary}`);
|
|
798
|
+
context.ui.line(` ${line.recall.advisoryUrl}`);
|
|
799
|
+
context.ui.line(
|
|
800
|
+
line.recall.reverifyAt ? ` the fix is in ${line.recall.reverifyAt}; move there and this skill still applies` : " no release in this line is unaffected; move to a newer major"
|
|
801
|
+
);
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
if (line.status === "frozen") {
|
|
805
|
+
context.ui.line(
|
|
806
|
+
` written for ${String(line.major)}.x, which is no longer revised; the date above is where it stopped`
|
|
807
|
+
);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
789
811
|
// src/installed.ts
|
|
790
812
|
import { readFileSync as readFileSync2 } from "fs";
|
|
791
813
|
import { dirname, join as join2, resolve } from "path";
|
|
@@ -1035,8 +1057,17 @@ function planInstall(options) {
|
|
|
1035
1057
|
if (installed && semver.gt(installed.version, entry2.delivery.version))
|
|
1036
1058
|
throw new Error("catalog would downgrade an installed skill package");
|
|
1037
1059
|
return !installed || installed.version !== entry2.delivery.version;
|
|
1038
|
-
}).
|
|
1039
|
-
|
|
1060
|
+
}).sort(
|
|
1061
|
+
(a, b) => a.delivery.packageName.localeCompare(b.delivery.packageName)
|
|
1062
|
+
);
|
|
1063
|
+
const recalled = changes.filter((entry2) => entry2.line?.status === "recalled").map((entry2) => ({
|
|
1064
|
+
packageName: entry2.delivery.packageName,
|
|
1065
|
+
line: entry2.line
|
|
1066
|
+
}));
|
|
1067
|
+
const deliveries = changes.map((entry2) => entry2.delivery);
|
|
1068
|
+
const specs = deliveries.map(
|
|
1069
|
+
(entry2) => `${entry2.packageName}@${entry2.version}`
|
|
1070
|
+
);
|
|
1040
1071
|
let args;
|
|
1041
1072
|
if (context.manager === "npm") {
|
|
1042
1073
|
args = [
|
|
@@ -1058,7 +1089,8 @@ function planInstall(options) {
|
|
|
1058
1089
|
return {
|
|
1059
1090
|
catalogRevision: catalog.revision,
|
|
1060
1091
|
context,
|
|
1061
|
-
changes,
|
|
1092
|
+
changes: deliveries,
|
|
1093
|
+
recalled,
|
|
1062
1094
|
command: {
|
|
1063
1095
|
executable: context.manager,
|
|
1064
1096
|
args,
|
|
@@ -1071,9 +1103,62 @@ function planInstall(options) {
|
|
|
1071
1103
|
import { resolve as resolve3 } from "path";
|
|
1072
1104
|
|
|
1073
1105
|
// src/remote/catalog.ts
|
|
1074
|
-
import { readFileSync as
|
|
1106
|
+
import { readFileSync as readFileSync5, statSync } from "fs";
|
|
1075
1107
|
import semver2 from "semver";
|
|
1076
1108
|
import { z } from "zod";
|
|
1109
|
+
|
|
1110
|
+
// src/remote/catalog-cache.ts
|
|
1111
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, renameSync, writeFileSync } from "fs";
|
|
1112
|
+
import { join as join4 } from "path";
|
|
1113
|
+
var MAX_CACHE_BYTES = 8 * 1024 * 1024;
|
|
1114
|
+
function memoryCatalogCache() {
|
|
1115
|
+
const held = /* @__PURE__ */ new Map();
|
|
1116
|
+
return {
|
|
1117
|
+
read: (origin) => held.get(origin) ?? null,
|
|
1118
|
+
write: (origin, entry2) => {
|
|
1119
|
+
held.set(origin, entry2);
|
|
1120
|
+
}
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
function fileCatalogCache(dir) {
|
|
1124
|
+
const path = join4(dir, "catalog-cache.json");
|
|
1125
|
+
return {
|
|
1126
|
+
read(origin) {
|
|
1127
|
+
try {
|
|
1128
|
+
const raw = readFileSync4(path, "utf8");
|
|
1129
|
+
if (raw.length > MAX_CACHE_BYTES) return null;
|
|
1130
|
+
const held = JSON.parse(raw);
|
|
1131
|
+
if (typeof held !== "object" || held === null) return null;
|
|
1132
|
+
const record = held;
|
|
1133
|
+
if (record["origin"] !== origin) return null;
|
|
1134
|
+
const etag = record["etag"];
|
|
1135
|
+
const body = record["body"];
|
|
1136
|
+
if (typeof etag !== "string" || typeof body !== "string") return null;
|
|
1137
|
+
return { etag, body };
|
|
1138
|
+
} catch {
|
|
1139
|
+
return null;
|
|
1140
|
+
}
|
|
1141
|
+
},
|
|
1142
|
+
write(origin, entry2) {
|
|
1143
|
+
try {
|
|
1144
|
+
if (entry2.body.length > MAX_CACHE_BYTES) return;
|
|
1145
|
+
mkdirSync2(dir, { recursive: true });
|
|
1146
|
+
const temporary = `${path}.${String(process.pid)}`;
|
|
1147
|
+
writeFileSync(
|
|
1148
|
+
temporary,
|
|
1149
|
+
`${JSON.stringify({ origin, etag: entry2.etag, body: entry2.body })}
|
|
1150
|
+
`,
|
|
1151
|
+
{ mode: 384 }
|
|
1152
|
+
);
|
|
1153
|
+
renameSync(temporary, path);
|
|
1154
|
+
} catch {
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
// src/remote/catalog.ts
|
|
1077
1162
|
var npmName = z.string().max(214).regex(/^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/u);
|
|
1078
1163
|
var version = z.string().refine(
|
|
1079
1164
|
(value) => semver2.valid(value) !== null && semver2.valid(value) === value.split("+")[0]
|
|
@@ -1110,6 +1195,20 @@ var entry = z.object({
|
|
|
1110
1195
|
headings: z.array(z.string().min(1)),
|
|
1111
1196
|
example: z.string().min(1)
|
|
1112
1197
|
}).optional(),
|
|
1198
|
+
// Where this line stands: which major of the target it is written for, and
|
|
1199
|
+
// whether it is the current one, an older one nobody is revising, or one an
|
|
1200
|
+
// advisory has reached. Optional for the same reason as the preview -- a
|
|
1201
|
+
// client that demands it rejects a catalog published before it existed.
|
|
1202
|
+
line: z.object({
|
|
1203
|
+
major: z.number().int().nonnegative(),
|
|
1204
|
+
status: z.enum(["active", "frozen", "recalled"]),
|
|
1205
|
+
recall: z.object({
|
|
1206
|
+
advisoryUrl: z.string().url(),
|
|
1207
|
+
severity: z.enum(["high", "critical"]),
|
|
1208
|
+
summary: z.string().min(1),
|
|
1209
|
+
reverifyAt: version.optional()
|
|
1210
|
+
}).optional()
|
|
1211
|
+
}).optional(),
|
|
1113
1212
|
targets: z.array(target).min(1)
|
|
1114
1213
|
});
|
|
1115
1214
|
var responseSchema = z.object({
|
|
@@ -1149,18 +1248,39 @@ function readCatalogFile(path) {
|
|
|
1149
1248
|
const stat = statSync(path);
|
|
1150
1249
|
if (!stat.isFile() || stat.size > MAX_CATALOG_BYTES)
|
|
1151
1250
|
throw new Error("catalog file exceeds the supported size");
|
|
1152
|
-
const bytes =
|
|
1251
|
+
const bytes = readFileSync5(path);
|
|
1153
1252
|
if (bytes.byteLength > MAX_CATALOG_BYTES)
|
|
1154
1253
|
throw new Error("catalog file exceeds the supported size");
|
|
1155
1254
|
return parseCatalog(JSON.parse(bytes.toString("utf8")));
|
|
1156
1255
|
}
|
|
1157
|
-
async function fetchCatalog(origin, fetcher2 = fetch) {
|
|
1256
|
+
async function fetchCatalog(origin, fetcher2 = fetch, cache = memoryCatalogCache()) {
|
|
1257
|
+
const held = cache.read(origin);
|
|
1258
|
+
if (held) {
|
|
1259
|
+
try {
|
|
1260
|
+
return await request(origin, fetcher2, held, cache);
|
|
1261
|
+
} catch (error) {
|
|
1262
|
+
if (!(error instanceof StaleCacheError)) throw error;
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
return await request(origin, fetcher2, null, cache);
|
|
1266
|
+
}
|
|
1267
|
+
var StaleCacheError = class extends Error {
|
|
1268
|
+
};
|
|
1269
|
+
async function request(origin, fetcher2, held, cache) {
|
|
1158
1270
|
const response = await fetcher2(catalogEndpoint(origin), {
|
|
1159
1271
|
method: "GET",
|
|
1160
|
-
headers: { accept: "application/json" },
|
|
1272
|
+
headers: held ? { accept: "application/json", "if-none-match": held.etag } : { accept: "application/json" },
|
|
1161
1273
|
redirect: "error",
|
|
1162
1274
|
signal: AbortSignal.timeout(15e3)
|
|
1163
1275
|
});
|
|
1276
|
+
if (response.status === 304) {
|
|
1277
|
+
if (!held) throw new Error("catalog answered 304 to an unconditional read");
|
|
1278
|
+
try {
|
|
1279
|
+
return parseCatalog(JSON.parse(held.body));
|
|
1280
|
+
} catch {
|
|
1281
|
+
throw new StaleCacheError("the held catalog no longer parses");
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1164
1284
|
if (!response.ok)
|
|
1165
1285
|
throw new Error(`catalog request failed (${response.status})`);
|
|
1166
1286
|
if (!response.headers.get("content-type")?.toLowerCase().startsWith("application/json")) {
|
|
@@ -1189,7 +1309,12 @@ async function fetchCatalog(origin, fetcher2 = fetch) {
|
|
|
1189
1309
|
bytes.set(chunk, offset);
|
|
1190
1310
|
offset += chunk.byteLength;
|
|
1191
1311
|
}
|
|
1192
|
-
|
|
1312
|
+
const text = new TextDecoder().decode(bytes);
|
|
1313
|
+
const catalog = parseCatalog(JSON.parse(text));
|
|
1314
|
+
const tag = response.headers.get("etag");
|
|
1315
|
+
if (tag !== null && tag !== "")
|
|
1316
|
+
cache.write(origin, { etag: tag, body: text });
|
|
1317
|
+
return catalog;
|
|
1193
1318
|
}
|
|
1194
1319
|
|
|
1195
1320
|
// src/commands/remote-options.ts
|
|
@@ -1220,7 +1345,7 @@ async function remoteCatalog(context) {
|
|
|
1220
1345
|
throw new Error("choose --catalog or --api, not both");
|
|
1221
1346
|
return readCatalogFile(resolve3(context.cwd, file));
|
|
1222
1347
|
}
|
|
1223
|
-
return fetchCatalog(apiOrigin(context));
|
|
1348
|
+
return fetchCatalog(apiOrigin(context), fetch, fileCatalogCache(globalDir()));
|
|
1224
1349
|
}
|
|
1225
1350
|
|
|
1226
1351
|
// src/commands/available.ts
|
|
@@ -1255,6 +1380,7 @@ var availableCommand = {
|
|
|
1255
1380
|
if (headings.length > 0) {
|
|
1256
1381
|
context.ui.line(` ${headings.join(" \xB7 ")}`);
|
|
1257
1382
|
}
|
|
1383
|
+
sayStanding(context, match.entry.line);
|
|
1258
1384
|
}
|
|
1259
1385
|
context.ui.info(`${matches.length} matching skills`, catalog.revision);
|
|
1260
1386
|
if (matches.length > 0) {
|
|
@@ -1298,6 +1424,9 @@ var previewCommand = {
|
|
|
1298
1424
|
summary: entry2.summary,
|
|
1299
1425
|
package: `${entry2.delivery.packageName}@${entry2.delivery.version}`,
|
|
1300
1426
|
evidence: entry2.evidence,
|
|
1427
|
+
// A script deciding on our behalf needs the recall as much as a
|
|
1428
|
+
// person does, and more so: it will not read the prose.
|
|
1429
|
+
line: entry2.line,
|
|
1301
1430
|
targets: entry2.targets,
|
|
1302
1431
|
preview: entry2.preview
|
|
1303
1432
|
},
|
|
@@ -1320,6 +1449,7 @@ ${entry2.summary}
|
|
|
1320
1449
|
|
|
1321
1450
|
`
|
|
1322
1451
|
);
|
|
1452
|
+
sayStanding(context, entry2.line);
|
|
1323
1453
|
if (!entry2.preview) {
|
|
1324
1454
|
context.ui.data(
|
|
1325
1455
|
"This entry was published before previews were recorded, so there is no sample to show.\n"
|
|
@@ -1437,8 +1567,8 @@ function applyInstallPlan(plan, runner = packageManagerRunner) {
|
|
|
1437
1567
|
|
|
1438
1568
|
// src/install/verify-content.ts
|
|
1439
1569
|
import { createHash as createHash2 } from "crypto";
|
|
1440
|
-
import { readdirSync, readFileSync as
|
|
1441
|
-
import { join as
|
|
1570
|
+
import { readdirSync, readFileSync as readFileSync6, statSync as statSync2 } from "fs";
|
|
1571
|
+
import { join as join5, relative as relative2, resolve as resolve4, sep as sep2 } from "path";
|
|
1442
1572
|
var SKILL = "SKILL.md";
|
|
1443
1573
|
var SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", ".cache"]);
|
|
1444
1574
|
function skillFiles(root) {
|
|
@@ -1452,7 +1582,7 @@ function skillFiles(root) {
|
|
|
1452
1582
|
}
|
|
1453
1583
|
for (const name of entries) {
|
|
1454
1584
|
if (SKIP.has(name)) continue;
|
|
1455
|
-
const path =
|
|
1585
|
+
const path = join5(dir, name);
|
|
1456
1586
|
let stats;
|
|
1457
1587
|
try {
|
|
1458
1588
|
stats = statSync2(path);
|
|
@@ -1463,7 +1593,7 @@ function skillFiles(root) {
|
|
|
1463
1593
|
else if (name === SKILL)
|
|
1464
1594
|
found.set(
|
|
1465
1595
|
relative2(root, path).split(sep2).join("/"),
|
|
1466
|
-
|
|
1596
|
+
readFileSync6(path, "utf8")
|
|
1467
1597
|
);
|
|
1468
1598
|
}
|
|
1469
1599
|
};
|
|
@@ -1492,9 +1622,9 @@ function verifyInstalledContent(project, packageName2, expected) {
|
|
|
1492
1622
|
}
|
|
1493
1623
|
|
|
1494
1624
|
// src/remote/distribution.ts
|
|
1495
|
-
import { chmodSync as chmodSync2, mkdtempSync, rmSync as rmSync2, writeFileSync } from "fs";
|
|
1625
|
+
import { chmodSync as chmodSync2, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
1496
1626
|
import { tmpdir } from "os";
|
|
1497
|
-
import { join as
|
|
1627
|
+
import { join as join6 } from "path";
|
|
1498
1628
|
function api(origin, path) {
|
|
1499
1629
|
const base = new URL(catalogEndpoint(origin));
|
|
1500
1630
|
base.pathname = path;
|
|
@@ -1520,23 +1650,43 @@ function credential(value) {
|
|
|
1520
1650
|
}
|
|
1521
1651
|
var REFUSALS = {
|
|
1522
1652
|
401: "sign in again before installing skills",
|
|
1523
|
-
402: "
|
|
1653
|
+
402: "a subscription is needed to install these skills",
|
|
1524
1654
|
403: "sign in again to approve skill downloads"
|
|
1525
1655
|
};
|
|
1526
|
-
|
|
1656
|
+
function helpUrl(body) {
|
|
1657
|
+
const error = body["error"];
|
|
1658
|
+
if (!error || typeof error !== "object") return void 0;
|
|
1659
|
+
const help = error["help"];
|
|
1660
|
+
if (!help || typeof help !== "object") return void 0;
|
|
1661
|
+
const url = help["subscribeUrl"];
|
|
1662
|
+
if (typeof url !== "string") return void 0;
|
|
1663
|
+
const parsed = URL.parse(url);
|
|
1664
|
+
if (!parsed || parsed.protocol !== "https:") return void 0;
|
|
1665
|
+
return parsed.host === "pmcp.build" ? parsed.href : void 0;
|
|
1666
|
+
}
|
|
1667
|
+
async function refusal(response, fallback, subjects = []) {
|
|
1527
1668
|
let requestId;
|
|
1669
|
+
let where;
|
|
1528
1670
|
try {
|
|
1529
1671
|
const body = await response.json();
|
|
1530
1672
|
const value = body && typeof body === "object" && !Array.isArray(body) ? body : {};
|
|
1531
1673
|
if (typeof value["requestId"] === "string" && value["requestId"] !== "") {
|
|
1532
1674
|
requestId = value["requestId"];
|
|
1533
1675
|
}
|
|
1676
|
+
where = helpUrl(value);
|
|
1534
1677
|
} catch {
|
|
1535
1678
|
}
|
|
1536
1679
|
const said = REFUSALS[response.status] ?? `${fallback} (${response.status})`;
|
|
1537
|
-
|
|
1680
|
+
const named = subjects.length > 0 ? `${said}: ${subjects.join(", ")}` : said;
|
|
1681
|
+
return new Error(
|
|
1682
|
+
[
|
|
1683
|
+
named,
|
|
1684
|
+
where ? `subscribe at ${where}` : "",
|
|
1685
|
+
requestId ? `[request ${requestId}]` : ""
|
|
1686
|
+
].filter((part) => part !== "").join("\n ")
|
|
1687
|
+
);
|
|
1538
1688
|
}
|
|
1539
|
-
async function issueDistributionCredential(accessToken, origin = DEFAULT_API_ORIGIN, fetcher2 = fetch) {
|
|
1689
|
+
async function issueDistributionCredential(accessToken, origin = DEFAULT_API_ORIGIN, fetcher2 = fetch, subjects = []) {
|
|
1540
1690
|
const response = await fetcher2(api(origin, "/v1/distribution/credentials"), {
|
|
1541
1691
|
method: "POST",
|
|
1542
1692
|
redirect: "error",
|
|
@@ -1547,7 +1697,11 @@ async function issueDistributionCredential(accessToken, origin = DEFAULT_API_ORI
|
|
|
1547
1697
|
}
|
|
1548
1698
|
});
|
|
1549
1699
|
if (!response.ok)
|
|
1550
|
-
throw await refusal(
|
|
1700
|
+
throw await refusal(
|
|
1701
|
+
response,
|
|
1702
|
+
"distribution credential request failed",
|
|
1703
|
+
subjects
|
|
1704
|
+
);
|
|
1551
1705
|
return credential(await response.json());
|
|
1552
1706
|
}
|
|
1553
1707
|
async function verifyRegistryIntegrity(entries, value, fetcher2 = fetch) {
|
|
@@ -1610,12 +1764,12 @@ async function revokeDistributionCredential(accessToken, id, origin = DEFAULT_AP
|
|
|
1610
1764
|
}
|
|
1611
1765
|
}
|
|
1612
1766
|
function temporaryRegistryConfig(value) {
|
|
1613
|
-
const directory = mkdtempSync(
|
|
1767
|
+
const directory = mkdtempSync(join6(tmpdir(), "pmcp-registry-"));
|
|
1614
1768
|
chmodSync2(directory, 448);
|
|
1615
|
-
const path =
|
|
1769
|
+
const path = join6(directory, ".npmrc");
|
|
1616
1770
|
const registry = new URL(value.registry);
|
|
1617
1771
|
const auth = `//${registry.host}${registry.pathname}:_authToken=${value.token}`;
|
|
1618
|
-
|
|
1772
|
+
writeFileSync2(path, `${value.scope}:registry=${registry.href}
|
|
1619
1773
|
${auth}
|
|
1620
1774
|
`, {
|
|
1621
1775
|
mode: 384
|
|
@@ -1684,6 +1838,16 @@ async function manage(context, sync) {
|
|
|
1684
1838
|
context.ui.line(
|
|
1685
1839
|
` ${plan.command.executable} ${plan.command.args.join(" ")}`
|
|
1686
1840
|
);
|
|
1841
|
+
for (const entry2 of plan.recalled) {
|
|
1842
|
+
context.ui.warn(
|
|
1843
|
+
"recalled",
|
|
1844
|
+
`${entry2.packageName} is written for versions a ${entry2.line.recall?.severity ?? "high"} advisory covers`
|
|
1845
|
+
);
|
|
1846
|
+
if (entry2.line.recall) {
|
|
1847
|
+
context.ui.line(` ${entry2.line.recall.summary}`);
|
|
1848
|
+
context.ui.line(` ${entry2.line.recall.advisoryUrl}`);
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1687
1851
|
}
|
|
1688
1852
|
if (!dryRun && plan.changes.length === 0) {
|
|
1689
1853
|
const drifted = mismatched(
|
|
@@ -1737,7 +1901,9 @@ async function manage(context, sync) {
|
|
|
1737
1901
|
const origin = apiOrigin(context);
|
|
1738
1902
|
const credential2 = await issueDistributionCredential(
|
|
1739
1903
|
session.accessToken,
|
|
1740
|
-
origin
|
|
1904
|
+
origin,
|
|
1905
|
+
fetch,
|
|
1906
|
+
plan.changes.map((entry2) => entry2.packageName)
|
|
1741
1907
|
);
|
|
1742
1908
|
const registry = temporaryRegistryConfig(credential2);
|
|
1743
1909
|
let revoked = false;
|
|
@@ -1876,7 +2042,7 @@ function dispatch(argv, options = {}) {
|
|
|
1876
2042
|
}
|
|
1877
2043
|
return run(command, rest, { ui, env, cwd });
|
|
1878
2044
|
}
|
|
1879
|
-
var VERSION = "0.1.
|
|
2045
|
+
var VERSION = "0.1.3";
|
|
1880
2046
|
async function run(command, argv, context) {
|
|
1881
2047
|
try {
|
|
1882
2048
|
return await command.run({
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_INTENT_CACHE_LIMIT,
|
|
3
3
|
openIntentCache
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-BP45RDLT.js";
|
|
5
5
|
import {
|
|
6
6
|
DEFAULT_FIND_LIMIT,
|
|
7
7
|
MAX_SKILL_DEPTH,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
readFrontmatter,
|
|
20
20
|
registerSkillTools,
|
|
21
21
|
withoutBody
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-NTQWFY45.js";
|
|
23
23
|
export {
|
|
24
24
|
DEFAULT_FIND_LIMIT,
|
|
25
25
|
DEFAULT_INTENT_CACHE_LIMIT,
|
package/dist/stdio.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@modootoday/pmcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "Elastic-2.0",
|
|
5
5
|
"author": "modootoday",
|
|
6
6
|
"description": "An MCP server that finds the skills your installed packages already ship. Reads SKILL.md out of node_modules by shape rather than by path, so it sees the skills, .agent, .claude, .gemini and .codex conventions alike, and keeps session startup flat as the number of installed skills grows.",
|
|
@@ -61,7 +61,8 @@
|
|
|
61
61
|
"test": "vitest run",
|
|
62
62
|
"clean": "rimraf dist",
|
|
63
63
|
"catalog:refresh": "node scripts/refresh-catalog.mjs",
|
|
64
|
-
"
|
|
64
|
+
"observations:refresh": "node scripts/refresh-observations.mjs",
|
|
65
|
+
"site:build": "node scripts/build-catalog-pages.mjs && node scripts/build-observation-pages.mjs && node scripts/build-sitemap.mjs",
|
|
65
66
|
"site:deployed": "node scripts/check-deployed.mjs",
|
|
66
67
|
"prepack": "npm run build && npm run typecheck && npm test",
|
|
67
68
|
"format": "prettier --write .",
|