@bridge-ds/mcp 0.8.0 → 0.8.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.
@@ -596,7 +596,7 @@ var DEFAULT_GOVERNANCE = {
596
596
  owners: { design: [], tech: [] }
597
597
  };
598
598
  var FLAT_TOKEN_KEYS = ["primitives", "brands", "semantic", "base", "density", "components", "contrastChecks"];
599
- var CANONICAL_TOKEN_KEYS = ["root", "include", "exclude", "tiers", "layers"];
599
+ var CANONICAL_TOKEN_KEYS = ["root", "include", "exclude", "tiers", "layers", "usage"];
600
600
  var FLAT_MODE_KEYS = ["brands", "themes", "densities", "defaults"];
601
601
  var AXIS_OF = { brands: "brand", themes: "theme", densities: "density" };
602
602
  var ConfigError = class extends Error {
@@ -684,7 +684,7 @@ function defineConfig(input) {
684
684
  const contrastFile = contrastPath ?? [root === "." ? "" : root, paths.contrastChecks].filter(Boolean).join("/");
685
685
  return {
686
686
  repo: parseRepoInput(input.repo, input.branch),
687
- tokens: { ...paths, include: input.tokens?.include ?? ["**/*.tokens.json"], exclude: input.tokens?.exclude ?? [], tiers, layers },
687
+ tokens: { ...paths, include: input.tokens?.include ?? ["**/*.tokens.json"], exclude: input.tokens?.exclude ?? [], tiers, layers, ...t.usage ? { usage: trimSlashes(t.usage) } : {} },
688
688
  axes,
689
689
  modes,
690
690
  contrast: { path: contrastFile, modes: input.contrast?.modes },
@@ -719,6 +719,7 @@ function defineConfig(input) {
719
719
  products: input.products?.length ? input.products.map((p) => ({ ...p })) : DEFAULT_PRODUCTS.map((p) => ({ ...p })),
720
720
  changes: input.changes === "direct" ? "direct" : DEFAULT_CHANGES_MODE,
721
721
  ...input.storybook?.url ? { storybook: { url: input.storybook.url.trim().replace(/\/+$/, "") } } : {},
722
+ ...input.library?.public === true ? { library: { public: true } } : {},
722
723
  ...input.audit ? { audit: { ...input.audit } } : {},
723
724
  ...input.visualImpact ? { visualImpact: { mode: input.visualImpact.mode === "on-demand" ? "on-demand" : "auto" } } : {},
724
725
  ...input.integrations ? { integrations: { ...input.integrations } } : {},
@@ -763,7 +764,7 @@ function loadConfig(source) {
763
764
  if (!isObj(tokens)) problems.push('"tokens" must be an object');
764
765
  else
765
766
  for (const [k, v] of Object.entries(tokens)) {
766
- if (FLAT_TOKEN_KEYS.includes(k) || k === "root") {
767
+ if (FLAT_TOKEN_KEYS.includes(k) || k === "root" || k === "usage") {
767
768
  if (!isStr(v)) problems.push(`"tokens.${k}" must be a non-empty string`);
768
769
  } else if (k === "include" || k === "exclude") {
769
770
  if (!isStrList(v)) problems.push(`"tokens.${k}" must be a list of globs`);
@@ -849,6 +850,14 @@ function loadConfig(source) {
849
850
  else if (!/^https:\/\/[^\s/]+/.test(sb.url.trim())) problems.push('"storybook.url" must start with https://, for example https://storybook.example.com');
850
851
  else for (const k of Object.keys(sb)) if (k !== "url") problems.push(`"storybook.${k}" is not a known key`);
851
852
  }
853
+ const lib = d.library;
854
+ if (lib !== void 0) {
855
+ if (!isObj(lib)) problems.push('"library" must be an object, for example { "public": true }');
856
+ else {
857
+ if (lib.public !== void 0 && typeof lib.public !== "boolean") problems.push('"library.public" must be true or false');
858
+ for (const k of Object.keys(lib)) if (k !== "public") problems.push(`"library.${k}" is not a known key`);
859
+ }
860
+ }
852
861
  problems.push(...productProblems(d.products));
853
862
  const audit = d.audit;
854
863
  if (audit !== void 0) {
@@ -887,7 +896,7 @@ function toConfigJson(config, schema = "./packages/core/bridge.config.schema.jso
887
896
  $schema: schema,
888
897
  version: 1,
889
898
  ...config.repo ? { repo: config.repo } : {},
890
- tokens: { root: config.tokens.root, include: config.tokens.include, ...config.tokens.exclude.length ? { exclude: config.tokens.exclude } : {}, tiers: config.tokens.tiers, layers: config.tokens.layers.map((l) => l.optional ? l : { files: l.files }) },
899
+ tokens: { root: config.tokens.root, include: config.tokens.include, ...config.tokens.exclude.length ? { exclude: config.tokens.exclude } : {}, tiers: config.tokens.tiers, layers: config.tokens.layers.map((l) => l.optional ? l : { files: l.files }), ...config.tokens.usage ? { usage: config.tokens.usage } : {} },
891
900
  modes: Object.fromEntries(Object.entries(config.axes).map(([k, a]) => [k, a.parity ? a : { values: a.values, default: a.default }])),
892
901
  ...config.contrast ? { contrast: config.contrast.modes ? config.contrast : { path: config.contrast.path } } : {},
893
902
  ...config.components ? { components: Object.fromEntries(Object.entries(config.components).filter(([, v]) => v !== void 0)) } : {},
@@ -900,6 +909,7 @@ function toConfigJson(config, schema = "./packages/core/bridge.config.schema.jso
900
909
  ...config.visualImpact ? { visualImpact: config.visualImpact } : {},
901
910
  changes: changesMode(config),
902
911
  ...config.storybook ? { storybook: config.storybook } : {},
912
+ ...config.library ? { library: config.library } : {},
903
913
  ...config.products && !sameProducts(config.products, DEFAULT_PRODUCTS) ? { products: config.products } : {}
904
914
  };
905
915
  }
@@ -79,7 +79,7 @@ import {
79
79
  validateLayered,
80
80
  variantKeyOf,
81
81
  whoCanShipSentence
82
- } from "./chunk-BHODFN52.js";
82
+ } from "./chunk-DPK46GA2.js";
83
83
 
84
84
  // src/lib.ts
85
85
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -1263,6 +1263,44 @@ function classifyAuth(status, detail, opts = {}) {
1263
1263
  }
1264
1264
  return {};
1265
1265
  }
1266
+ function memoryEtagStore(max = 500) {
1267
+ const map = /* @__PURE__ */ new Map();
1268
+ return {
1269
+ get(key) {
1270
+ const e = map.get(key);
1271
+ if (e) {
1272
+ map.delete(key);
1273
+ map.set(key, e);
1274
+ }
1275
+ return e;
1276
+ },
1277
+ set(key, entry) {
1278
+ map.delete(key);
1279
+ map.set(key, entry);
1280
+ while (map.size > max) map.delete(map.keys().next().value);
1281
+ },
1282
+ clear: () => map.clear()
1283
+ };
1284
+ }
1285
+ var sharedEtags = memoryEtagStore();
1286
+ function tokenFingerprint(token) {
1287
+ if (!token) return "anon";
1288
+ let a = 2166136261;
1289
+ let b = 16777619 ^ token.length;
1290
+ for (let i = 0; i < token.length; i++) {
1291
+ const c = token.charCodeAt(i);
1292
+ a = Math.imul(a ^ c, 16777619) >>> 0;
1293
+ b = Math.imul(b ^ c ^ i & 255, 1540483477) >>> 0;
1294
+ }
1295
+ return a.toString(16).padStart(8, "0") + b.toString(16).padStart(8, "0");
1296
+ }
1297
+ function installationFor(list, owner) {
1298
+ const inst = list.find((i) => i.account?.login?.toLowerCase() === owner.toLowerCase());
1299
+ if (!inst) return { reach: "no" };
1300
+ const selection = inst.repositorySelection ?? inst.repository_selection;
1301
+ return selection === "all" ? { reach: "yes", id: inst.id } : { reach: "check", id: inst.id };
1302
+ }
1303
+ var MAX_PAGES = 10;
1266
1304
  function rateLimitMessage(x) {
1267
1305
  const when = x.resetsAt ? ` It resets at ${x.resetsAt.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}.` : "";
1268
1306
  if (x.withToken) return `GitHub's hourly request limit for this token is used up.${when} Try again after that.`;
@@ -1270,8 +1308,11 @@ function rateLimitMessage(x) {
1270
1308
  return `GitHub's hourly limit for requests without a token (60 an hour) is used up.${when} To keep going now, ${hint}: a token gets 5,000 requests an hour.`;
1271
1309
  }
1272
1310
  var DEFAULT_RETRY = { attempts: 3, baseDelayMs: 600, sleep: (ms) => new Promise((r) => setTimeout(r, ms)) };
1311
+ var hourlyLimitErrors = /* @__PURE__ */ new WeakSet();
1273
1312
  var isTransient = (status, detail) => status === 0 || status >= 500 || status === 429 || status === 403 && /secondary rate limit/i.test(detail);
1274
1313
  var API = "https://api.github.com";
1314
+ var ACCEPT_JSON = "application/vnd.github+json";
1315
+ var ACCEPT_RAW = "application/vnd.github.raw";
1275
1316
  var RAW = "https://raw.githubusercontent.com";
1276
1317
  function parseRepo(repo) {
1277
1318
  const m = /^\s*(?:https?:\/\/github\.com\/|git@github\.com:)?([A-Za-z0-9-]+)\/([A-Za-z0-9._-]+?)(?:\.git)?\/?\s*$/.exec(repo);
@@ -1290,6 +1331,7 @@ function base64ToUtf8(b64) {
1290
1331
  for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
1291
1332
  return new TextDecoder("utf-8").decode(bytes);
1292
1333
  }
1334
+ var copy = (value) => value === null || typeof value !== "object" ? value : typeof structuredClone === "function" ? structuredClone(value) : JSON.parse(JSON.stringify(value));
1293
1335
  var encodeRef = (ref) => ref.split("/").map(encodeURIComponent).join("/");
1294
1336
  var GitHubClient = class _GitHubClient {
1295
1337
  constructor(repo, token, fetchImpl = (url, init) => fetch(url, init), retry = DEFAULT_RETRY, options = {}) {
@@ -1302,6 +1344,8 @@ var GitHubClient = class _GitHubClient {
1302
1344
  this.name = r.name;
1303
1345
  this.api = (options.apiUrl ?? API).replace(/\/$/, "");
1304
1346
  this.protectedBranches = options.protectedBranches ?? DEFAULT_PROTECTED_BRANCHES;
1347
+ this.etags = options.etags === false ? void 0 : options.etags ?? sharedEtags;
1348
+ this.etagScope = options.etagScope ?? tokenFingerprint(token);
1305
1349
  }
1306
1350
  token;
1307
1351
  fetchImpl;
@@ -1312,6 +1356,15 @@ var GitHubClient = class _GitHubClient {
1312
1356
  blobCache = /* @__PURE__ */ new Map();
1313
1357
  api;
1314
1358
  protectedBranches;
1359
+ etags;
1360
+ etagScope;
1361
+ rate;
1362
+ /** What the conditional request cache did for this client. */
1363
+ etagStats = { conditional: 0, notModified: 0, stale: 0 };
1364
+ /** GitHub's rate-limit headers from the last API response, or undefined before any response carried them. */
1365
+ get rateLimit() {
1366
+ return this.rate;
1367
+ }
1315
1368
  /** "owner/name". */
1316
1369
  get fullName() {
1317
1370
  return `${this.owner}/${this.name}`;
@@ -1335,45 +1388,77 @@ var GitHubClient = class _GitHubClient {
1335
1388
  get repoPath() {
1336
1389
  return `/repos/${this.owner}/${this.name}`;
1337
1390
  }
1338
- async request(method, path, body, retryable = method === "GET") {
1391
+ async request(method, path, body, retryable = method === "GET", opts = {}) {
1339
1392
  const attempts = retryable ? Math.max(1, this.retry.attempts) : 1;
1340
1393
  for (let attempt = 1; ; attempt++) {
1341
1394
  try {
1342
- return await this.once(method, path, body);
1395
+ return await this.once(method, path, body, opts);
1343
1396
  } catch (err) {
1344
1397
  const e = err;
1345
- if (attempt >= attempts || !(e instanceof GitHubError) || !isTransient(e.status, e.detail ?? "")) throw err;
1398
+ if (attempt >= attempts || !(e instanceof GitHubError) || hourlyLimitErrors.has(e) || !isTransient(e.status, e.detail ?? "")) throw err;
1346
1399
  await this.retry.sleep(this.retry.baseDelayMs * 2 ** (attempt - 1));
1347
1400
  }
1348
1401
  }
1349
1402
  }
1350
- async once(method, path, body) {
1403
+ noteRateLimit(headers) {
1404
+ const remaining = headers?.get("x-ratelimit-remaining");
1405
+ if (remaining == null) return;
1406
+ const limit = headers?.get("x-ratelimit-limit");
1407
+ const reset = headers?.get("x-ratelimit-reset");
1408
+ this.rate = {
1409
+ limit: limit != null ? Number(limit) : void 0,
1410
+ remaining: Number(remaining),
1411
+ resetsAt: reset ? new Date(Number(reset) * 1e3) : void 0,
1412
+ resource: headers?.get("x-ratelimit-resource") ?? void 0
1413
+ };
1414
+ }
1415
+ async once(method, path, body, opts = {}) {
1416
+ const accept = opts.accept ?? ACCEPT_JSON;
1351
1417
  const headers = {
1352
- Accept: "application/vnd.github+json",
1418
+ Accept: accept,
1353
1419
  "X-GitHub-Api-Version": "2022-11-28"
1354
1420
  };
1355
1421
  if (this.token) headers.Authorization = `Bearer ${this.token}`;
1356
1422
  if (body !== void 0) headers["Content-Type"] = "application/json";
1423
+ const key = method === "GET" && this.etags && opts.etag !== false ? `${this.etagScope} ${accept} ${this.api}${path}` : void 0;
1424
+ const cached = key ? this.etags.get(key) : void 0;
1425
+ if (cached && this.token) {
1426
+ headers["If-None-Match"] = cached.etag;
1427
+ this.etagStats.conditional++;
1428
+ }
1357
1429
  let res;
1358
1430
  try {
1359
1431
  res = await this.fetchImpl(`${this.api}${path}`, { method, headers, ...body !== void 0 ? { body: JSON.stringify(body) } : {} });
1360
1432
  } catch (err) {
1433
+ if (err instanceof GitHubError) throw err;
1361
1434
  throw new GitHubError(0, "Could not reach GitHub. Check your connection, then try again.", err.message);
1362
1435
  }
1436
+ this.noteRateLimit(res.headers);
1437
+ if (res.status === 304 && cached && key && this.token) {
1438
+ this.etagStats.notModified++;
1439
+ this.etags.set(key, { ...cached, at: Date.now() });
1440
+ return copy(cached.body);
1441
+ }
1363
1442
  if (res.status === 204) return void 0;
1364
1443
  if (!res.ok) {
1365
1444
  let detail = "";
1366
1445
  try {
1367
- const data = await res.json();
1368
- detail = [data.message, ...(data.errors ?? []).map((e) => typeof e === "string" ? e : e.message)].filter(Boolean).join(" ");
1446
+ const data2 = await res.json();
1447
+ detail = [data2.message, ...(data2.errors ?? []).map((e) => typeof e === "string" ? e : e.message)].filter(Boolean).join(" ");
1369
1448
  } catch {
1370
1449
  detail = "";
1371
1450
  }
1372
1451
  const remaining = res.headers?.get("x-ratelimit-remaining");
1373
1452
  const reset = res.headers?.get("x-ratelimit-reset");
1374
1453
  if ((res.status === 403 || res.status === 429) && remaining === "0") {
1454
+ if (cached && this.options.serveStaleOnRateLimit) {
1455
+ this.etagStats.stale++;
1456
+ return copy(cached.body);
1457
+ }
1375
1458
  const resetsAt = reset ? new Date(Number(reset) * 1e3) : void 0;
1376
- throw new GitHubError(429, rateLimitMessage({ withToken: Boolean(this.token), resetsAt, tokenHint: this.options.tokenHint }), detail);
1459
+ const limited = new GitHubError(429, rateLimitMessage({ withToken: Boolean(this.token), resetsAt, tokenHint: this.options.tokenHint }), detail);
1460
+ hourlyLimitErrors.add(limited);
1461
+ throw limited;
1377
1462
  }
1378
1463
  const info = classifyAuth(res.status, detail, {
1379
1464
  path,
@@ -1382,7 +1467,24 @@ var GitHubClient = class _GitHubClient {
1382
1467
  });
1383
1468
  throw new GitHubError(res.status, friendlyMessage(res.status, detail, info), detail, info);
1384
1469
  }
1385
- return await res.json();
1470
+ const data = opts.text ? await res.text() : await res.json();
1471
+ const etag = key ? res.headers?.get("etag") : null;
1472
+ if (key && etag) this.etags.set(key, { etag, body: copy(data), at: Date.now() });
1473
+ return data;
1474
+ }
1475
+ /**
1476
+ * Every item of a paged listing (`per_page=100`), at most 10 pages. `pick` takes the items out of one page (the
1477
+ * installation endpoints wrap them in an object with `total_count`).
1478
+ */
1479
+ async paged(path, pick) {
1480
+ const out = [];
1481
+ const sep2 = path.includes("?") ? "&" : "?";
1482
+ for (let page = 1; page <= MAX_PAGES; page++) {
1483
+ const { items, total } = pick(await this.request("GET", `${path}${sep2}per_page=100&page=${page}`));
1484
+ out.push(...items);
1485
+ if (items.length < 100 || total !== void 0 && out.length >= total) break;
1486
+ }
1487
+ return out;
1386
1488
  }
1387
1489
  async getRepo() {
1388
1490
  const r = await this.request(
@@ -1765,6 +1867,14 @@ var GitHubClient = class _GitHubClient {
1765
1867
  */
1766
1868
  async readFile(path, ref) {
1767
1869
  if (this.token) return this.getFileText(path, ref);
1870
+ return this.readRawFile(path, ref);
1871
+ }
1872
+ /**
1873
+ * Text of a file from the raw host (raw.githubusercontent.com), sent without any header so the browser makes a
1874
+ * simple CORS request (no preflight) and nothing counts against the API limit. Works for public repositories only:
1875
+ * a private file answers 404 there, like a missing one. Undefined on 404.
1876
+ */
1877
+ async readRawFile(path, ref) {
1768
1878
  const url = `${(this.options.rawUrl ?? RAW).replace(/\/$/, "")}/${this.owner}/${this.name}/${encodeRef(ref)}/${encodeRef(path)}`;
1769
1879
  let res;
1770
1880
  try {
@@ -1776,6 +1886,76 @@ var GitHubClient = class _GitHubClient {
1776
1886
  if (!res.ok) throw new GitHubError(res.status, friendlyMessage(res.status, ""), `raw ${path}@${ref}`);
1777
1887
  return res.text();
1778
1888
  }
1889
+ /**
1890
+ * Text of a file at a ref through the contents API with the raw media type: the way to read a private file (the raw
1891
+ * host cannot take the token without a preflight). Counts against the API limit; conditional when cached.
1892
+ * Undefined when the file does not exist.
1893
+ */
1894
+ async getRawText(path, ref) {
1895
+ try {
1896
+ return await this.request("GET", `${this.repoPath}/contents/${encodeRef(path)}?ref=${encodeURIComponent(ref)}`, void 0, true, { accept: ACCEPT_RAW, text: true });
1897
+ } catch (err) {
1898
+ if (err instanceof GitHubError && err.status === 404) return void 0;
1899
+ throw err;
1900
+ }
1901
+ }
1902
+ /**
1903
+ * Text of a blob by its sha through the git blobs API with the raw media type: how a signed-in reader loads a file
1904
+ * listed by a tree (the raw host refuses any request that carries a token). A blob sha names its content, so the
1905
+ * answer is cached for the client's life and never revalidated. Undefined on 404.
1906
+ */
1907
+ async getBlobRaw(sha) {
1908
+ const cached = this.blobCache.get(sha);
1909
+ if (cached !== void 0) return cached;
1910
+ try {
1911
+ const text = await this.request("GET", `${this.repoPath}/git/blobs/${encodeURIComponent(sha)}`, void 0, true, { accept: ACCEPT_RAW, text: true, etag: false });
1912
+ this.blobCache.set(sha, text);
1913
+ return text;
1914
+ } catch (err) {
1915
+ if (err instanceof GitHubError && err.status === 404) return void 0;
1916
+ throw err;
1917
+ }
1918
+ }
1919
+ // --- GitHub App installations (user-to-server tokens) ---------------------------------------
1920
+ /**
1921
+ * Installations of the signing-in GitHub App that the signed-in user can reach (GET /user/installations, every
1922
+ * page). Needs a user-to-server token of that same App: a personal or OAuth token is refused (403), and each App
1923
+ * sees only its own installations. GitHub lists only installations on accounts and repositories the user has
1924
+ * explicit permission on: a public repository where the user is not a collaborator is never listed, installed or
1925
+ * not. (GET /repos/{o}/{r}/installation would say, but it needs the App's private key, which Bridge never holds.)
1926
+ */
1927
+ async listUserInstallations() {
1928
+ this.assertToken("Reading where Bridge is installed");
1929
+ const list = await this.paged("/user/installations", (p) => ({ items: p.installations ?? [], total: p.total_count }));
1930
+ return list.map((i) => ({
1931
+ id: i.id,
1932
+ account: i.account?.login ? { login: i.account.login, type: i.account.type ?? "User" } : null,
1933
+ repositorySelection: i.repository_selection ?? "selected",
1934
+ appSlug: i.app_slug
1935
+ }));
1936
+ }
1937
+ /** Repositories of one installation the signed-in user can reach (GET /user/installations/{id}/repositories, every page). */
1938
+ async listInstallationRepos(installationId) {
1939
+ this.assertToken("Reading where Bridge is installed");
1940
+ const list = await this.paged(`/user/installations/${encodeURIComponent(String(installationId))}/repositories`, (p) => ({
1941
+ items: p.repositories ?? [],
1942
+ total: p.total_count
1943
+ }));
1944
+ return list.map((r) => ({ owner: r.owner?.login ?? r.full_name.split("/")[0], name: r.name, fullName: r.full_name, private: Boolean(r.private) }));
1945
+ }
1946
+ /**
1947
+ * The App installation that gives the signed-in user this repository (this client's by default): its id, or null
1948
+ * when the App is not installed there or the user cannot reach it. One call when the installation covers all of
1949
+ * the owner's repositories, two (paged) when it covers selected ones.
1950
+ */
1951
+ async findInstallation(owner = this.owner, repo = this.name) {
1952
+ const found = installationFor(await this.listUserInstallations(), owner);
1953
+ if (found.reach === "no") return null;
1954
+ if (found.reach === "yes") return { id: found.id, selection: "all" };
1955
+ const repos = await this.listInstallationRepos(found.id);
1956
+ const hit = repos.some((r) => r.owner.toLowerCase() === owner.toLowerCase() && r.name.toLowerCase() === repo.toLowerCase());
1957
+ return hit ? { id: found.id, selection: "selected" } : null;
1958
+ }
1779
1959
  /** The repository's default branch. */
1780
1960
  async getDefaultBranch() {
1781
1961
  return (await this.getRepo()).defaultBranch;
@@ -6255,6 +6435,7 @@ function shareMessage(x) {
6255
6435
  // ../core/src/try-in-product.ts
6256
6436
  function tryInProductUrl(preview, pr, screen) {
6257
6437
  const url = new URL(preview);
6438
+ if (url.protocol !== "https:" && url.protocol !== "http:") return "";
6258
6439
  url.pathname = "/";
6259
6440
  url.search = "";
6260
6441
  url.searchParams.set("bridge", String(pr));
@@ -11754,7 +11935,7 @@ async function visualImpact(ctx, a, run2) {
11754
11935
  if (ctx.mode !== "local" || !ctx.root) throw new Error("Visual impact needs a local checkout (start Bridge with --root): it builds Storybook and the app at both refs.");
11755
11936
  if (!ctx.isGit) throw new Error(`${ctx.root} is not a git repository.`);
11756
11937
  const out = a.out ? resolve3(ctx.root, a.out) : join5(ctx.root, "visual-impact");
11757
- const runImpact = run2 ?? (await import("./src-P3GHW467.js")).runImpact;
11938
+ const runImpact = run2 ?? (await import("./src-UNWS2OVM.js")).runImpact;
11758
11939
  const r = await runImpact({
11759
11940
  root: ctx.root,
11760
11941
  base: a.base ?? "main",
@@ -12822,7 +13003,7 @@ async function pushFigmaComponentOp(ctx, a) {
12822
13003
  }
12823
13004
 
12824
13005
  // src/server.ts
12825
- var VERSION = true ? "0.8.0" : "dev";
13006
+ var VERSION = true ? "0.8.2" : "dev";
12826
13007
  var ok = (data) => ({ content: [{ type: "text", text: typeof data === "string" ? data : JSON.stringify(data, null, 2) }] });
12827
13008
  var fail2 = (e) => ({ content: [{ type: "text", text: `Error: ${e.message ?? String(e)}` }], isError: true });
12828
13009
  var run = (fn) => async (a) => {
package/dist/index.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  VERSION,
4
4
  optionsFromArgv,
5
5
  serveStdio
6
- } from "./chunk-VV5HHLLG.js";
7
- import "./chunk-BHODFN52.js";
6
+ } from "./chunk-QCPYJXK4.js";
7
+ import "./chunk-DPK46GA2.js";
8
8
 
9
9
  // src/index.ts
10
10
  var argv = process.argv.slice(2);
package/dist/lib.js CHANGED
@@ -28,12 +28,12 @@ import {
28
28
  serveStdio,
29
29
  studio_exports,
30
30
  suggestions_exports
31
- } from "./chunk-VV5HHLLG.js";
31
+ } from "./chunk-QCPYJXK4.js";
32
32
  import {
33
33
  CONFIG_FILE,
34
34
  loadConfig,
35
35
  toConfigJson
36
- } from "./chunk-BHODFN52.js";
36
+ } from "./chunk-DPK46GA2.js";
37
37
  export {
38
38
  BridgeContext,
39
39
  CONFIG_FILE,
@@ -11,7 +11,7 @@ import {
11
11
  referenceImagePath,
12
12
  selectTokenFiles,
13
13
  showFile
14
- } from "./chunk-BHODFN52.js";
14
+ } from "./chunk-DPK46GA2.js";
15
15
 
16
16
  // ../visual/src/run.ts
17
17
  import { existsSync as existsSync3 } from "node:fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bridge-ds/mcp",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "type": "module",
5
5
  "description": "Bridge MCP server: lets Claude (Claude Code, Claude Desktop or any MCP client) read, check and propose changes to a DTCG design system repo through pull requests.",
6
6
  "license": "MIT",
@@ -54,8 +54,8 @@
54
54
  "build:package": "node ../../scripts/build-packages.mjs mcp"
55
55
  },
56
56
  "dependencies": {
57
- "@bridge-ds/core": "^0.13.0",
58
- "@bridge-ds/visual": "^0.3.7",
57
+ "@bridge-ds/core": "^0.15.0",
58
+ "@bridge-ds/visual": "^0.3.9",
59
59
  "@modelcontextprotocol/sdk": "1.31.0",
60
60
  "typescript": "5.9.3",
61
61
  "zod": "3.25.76"