@modootoday/pmcp 0.1.1 → 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.
package/README.md CHANGED
@@ -7,7 +7,7 @@ Find and use package skills without loading every document into your agent's con
7
7
  ## Install
8
8
 
9
9
  ```sh
10
- npm install --save-dev pmcp
10
+ npm install --save-dev @modootoday/pmcp
11
11
  ```
12
12
 
13
13
  Register it with an MCP host:
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createSkillServer
3
- } from "./chunk-OPCK6D2H.js";
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-DKZ2DN6U.js.map
33
+ //# sourceMappingURL=chunk-3SOVLFDB.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  normaliseIntent
3
- } from "./chunk-OPCK6D2H.js";
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-EXPHIDIV.js.map
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.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-OPCK6D2H.js.map
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-EXPHIDIV.js";
4
+ } from "./chunk-BP45RDLT.js";
5
5
  import {
6
6
  serve
7
- } from "./chunk-DKZ2DN6U.js";
7
+ } from "./chunk-3SOVLFDB.js";
8
8
  import {
9
9
  readCatalog
10
- } from "./chunk-OPCK6D2H.js";
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, request, fetcher2, now = Date.now) {
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: request.clientId,
519
- resource: request.resource,
520
- scope: request.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, request, fetcher2, now = Date.now) {
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: request.deviceCode,
554
- client_id: request.clientId
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: request.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
- }).map((entry2) => entry2.delivery).sort((a, b) => a.packageName.localeCompare(b.packageName));
1039
- const specs = changes.map((entry2) => `${entry2.packageName}@${entry2.version}`);
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 readFileSync4, statSync } from "fs";
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 = readFileSync4(path);
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
- return parseCatalog(JSON.parse(new TextDecoder().decode(bytes)));
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 readFileSync5, statSync as statSync2 } from "fs";
1441
- import { join as join4, relative as relative2, resolve as resolve4, sep as sep2 } from "path";
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 = join4(dir, name);
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
- readFileSync5(path, "utf8")
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 join5 } from "path";
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: "your subscription does not include skill downloads",
1653
+ 402: "a subscription is needed to install these skills",
1524
1654
  403: "sign in again to approve skill downloads"
1525
1655
  };
1526
- async function refusal(response, fallback) {
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
- return new Error(requestId ? `${said} [request ${requestId}]` : said);
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(response, "distribution credential request failed");
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(join5(tmpdir(), "pmcp-registry-"));
1767
+ const directory = mkdtempSync(join6(tmpdir(), "pmcp-registry-"));
1614
1768
  chmodSync2(directory, 448);
1615
- const path = join5(directory, ".npmrc");
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
- writeFileSync(path, `${value.scope}:registry=${registry.href}
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.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-EXPHIDIV.js";
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-OPCK6D2H.js";
22
+ } from "./chunk-NTQWFY45.js";
23
23
  export {
24
24
  DEFAULT_FIND_LIMIT,
25
25
  DEFAULT_INTENT_CACHE_LIMIT,
package/dist/stdio.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  main,
4
4
  resolveRoots,
5
5
  serve
6
- } from "./chunk-DKZ2DN6U.js";
7
- import "./chunk-OPCK6D2H.js";
6
+ } from "./chunk-3SOVLFDB.js";
7
+ import "./chunk-NTQWFY45.js";
8
8
  export {
9
9
  main,
10
10
  resolveRoots,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modootoday/pmcp",
3
- "version": "0.1.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
- "site:build": "node scripts/build-catalog-pages.mjs",
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 .",
@@ -23,7 +23,7 @@ need a server in front of them. This exists for the skills you did not write.
23
23
  ## Install and wire
24
24
 
25
25
  ```sh
26
- npm install --save-dev pmcp
26
+ npm install --save-dev @modootoday/pmcp
27
27
  ```
28
28
 
29
29
  For a host that spawns MCP servers over stdio: