@ingcreators/annot-mcp 0.1.0 → 0.1.1

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/dist/index.js CHANGED
@@ -1,56 +1,57 @@
1
- import { loadImage as _, createCanvas as B } from "@napi-rs/canvas";
2
- import st from "pixelmatch";
3
- import { readFile as at, writeFile as x } from "node:fs/promises";
1
+ import { SHARED_DEFS as K, BBOX_ANNOTATION_SCHEMA as Z, bboxAnnotationsToSvg as I, BBOX_REDACT_REGION_SCHEMA as Q, createAnnotator as tt } from "@ingcreators/annot-annotator";
2
+ import { BBOX_ANNOTATION_SCHEMA as Ee, BBOX_REDACT_REGION_SCHEMA as xe, arrowBetween as Le, bboxAnnotationsToSvg as Pe, rectForBoundingBox as Ae, textAt as Oe } from "@ingcreators/annot-annotator";
3
+ import { loadImage as T, createCanvas as _ } from "@napi-rs/canvas";
4
+ import et from "pixelmatch";
5
+ import { readFile as rt, writeFile as $ } from "node:fs/promises";
4
6
  import { isAbsolute as w } from "node:path";
5
- import { createAnnotator as ct } from "@ingcreators/annot-annotator";
6
- import { Server as lt } from "@modelcontextprotocol/sdk/server/index.js";
7
- import { ListToolsRequestSchema as ut, CallToolRequestSchema as dt } from "@modelcontextprotocol/sdk/types.js";
8
- import { StdioServerTransport as ft } from "@modelcontextprotocol/sdk/server/stdio.js";
9
- const ht = { width: 1280, height: 800, deviceScaleFactor: 1 }, pt = "load";
10
- async function H(t, e) {
11
- const r = { ...ht, ...e.viewport }, o = e.waitFor ?? pt, n = e.fullPage ?? !1, s = await t.acquire();
12
- let i, a = !1;
7
+ import { Server as ot } from "@modelcontextprotocol/sdk/server/index.js";
8
+ import { ListToolsRequestSchema as nt, CallToolRequestSchema as it } from "@modelcontextprotocol/sdk/types.js";
9
+ import { StdioServerTransport as at } from "@modelcontextprotocol/sdk/server/stdio.js";
10
+ const st = { width: 1280, height: 800, deviceScaleFactor: 1 }, ct = "load";
11
+ async function k(t, e) {
12
+ const r = { ...st, ...e.viewport }, o = e.waitFor ?? ct, i = e.fullPage ?? !1, a = await t.acquire();
13
+ let n, s = !1;
13
14
  const c = () => {
14
- a || (a = !0, t.release());
15
+ s || (s = !0, t.release());
15
16
  };
16
17
  try {
17
- i = await s.newContext({
18
+ n = await a.newContext({
18
19
  viewport: { width: r.width, height: r.height },
19
20
  deviceScaleFactor: r.deviceScaleFactor
20
21
  });
21
- const l = await i.newPage();
22
- await l.goto(e.url, { waitUntil: o });
23
- const u = await l.screenshot({ fullPage: n, type: "png" }), h = new Uint8Array(u.buffer, u.byteOffset, u.byteLength), T = i;
22
+ const u = await n.newPage();
23
+ await u.goto(e.url, { waitUntil: o });
24
+ const l = await u.screenshot({ fullPage: i, type: "png" }), h = new Uint8Array(l.buffer, l.byteOffset, l.byteLength), R = n;
24
25
  return { pngBytes: h, handle: {
25
- page: l,
26
+ page: u,
26
27
  async close() {
27
- if (!a)
28
+ if (!s)
28
29
  try {
29
- await T.close();
30
+ await R.close();
30
31
  } finally {
31
32
  c();
32
33
  }
33
34
  }
34
35
  } };
35
- } catch (l) {
36
- if (i)
36
+ } catch (u) {
37
+ if (n)
37
38
  try {
38
- await i.close();
39
+ await n.close();
39
40
  } catch {
40
41
  }
41
- throw c(), l;
42
+ throw c(), u;
42
43
  }
43
44
  }
44
- const mt = 3e4;
45
- class gt {
45
+ const ut = 3e4;
46
+ class lt {
46
47
  #i;
47
- #s;
48
+ #a;
48
49
  #t;
49
50
  #o;
50
51
  #e = 0;
51
52
  #r;
52
53
  constructor(e, r = {}) {
53
- this.#i = e, this.#s = r.idleTimeoutMs ?? mt;
54
+ this.#i = e, this.#a = r.idleTimeoutMs ?? ut;
54
55
  }
55
56
  /**
56
57
  * Acquire a browser instance. The pool launches lazily on the
@@ -74,7 +75,7 @@ class gt {
74
75
  * instance; otherwise the timer fires and the browser closes.
75
76
  */
76
77
  release() {
77
- this.#e !== 0 && (this.#e -= 1, this.#e === 0 && this.#t && this.#a());
78
+ this.#e !== 0 && (this.#e -= 1, this.#e === 0 && this.#t && this.#s());
78
79
  }
79
80
  /**
80
81
  * Close the pooled browser immediately, regardless of refcount.
@@ -98,23 +99,23 @@ class gt {
98
99
  #n() {
99
100
  this.#r && (clearTimeout(this.#r), this.#r = void 0);
100
101
  }
101
- #a() {
102
+ #s() {
102
103
  this.#n(), this.#r = setTimeout(() => {
103
104
  const e = this.#t;
104
105
  this.#t = void 0, this.#r = void 0, e?.close().catch(() => {
105
106
  });
106
- }, this.#s), this.#r.unref?.();
107
+ }, this.#a), this.#r.unref?.();
107
108
  }
108
109
  }
109
- function yt(t = {}) {
110
- return new gt(
110
+ function dt(t = {}) {
111
+ return new lt(
111
112
  {
112
113
  async launch() {
113
114
  let e;
114
115
  try {
115
116
  ({ chromium: e } = await import("playwright-core"));
116
117
  } catch (r) {
117
- throw new U(
118
+ throw new C(
118
119
  "Failed to load `playwright-core`. Reinstall `@ingcreators/annot-mcp` to restore the dependency.",
119
120
  r
120
121
  );
@@ -122,7 +123,7 @@ function yt(t = {}) {
122
123
  try {
123
124
  return await e.launch({ headless: !0 });
124
125
  } catch (r) {
125
- throw new U(
126
+ throw new C(
126
127
  "Failed to launch Chromium. Run `npx playwright install chromium` to download the runtime, then retry.",
127
128
  r
128
129
  );
@@ -132,7 +133,7 @@ function yt(t = {}) {
132
133
  t
133
134
  );
134
135
  }
135
- class U extends Error {
136
+ class C extends Error {
136
137
  cause;
137
138
  constructor(e, r) {
138
139
  super(e), this.name = "ChromiumUnavailableError", this.cause = r;
@@ -153,7 +154,7 @@ async function f(t, e) {
153
154
  );
154
155
  return r;
155
156
  }
156
- async function wt(t, e) {
157
+ async function ft(t, e) {
157
158
  switch (e.type) {
158
159
  case "rect": {
159
160
  const r = e.bbox ?? await f(t, p(e.locator));
@@ -171,12 +172,12 @@ async function wt(t, e) {
171
172
  return {
172
173
  ...m(e),
173
174
  type: "circle",
174
- center: S(r),
175
+ center: P(r),
175
176
  radius: Math.min(r.width, r.height) / 2
176
177
  };
177
178
  }
178
179
  case "arrow": {
179
- const r = e.from ?? S(await f(t, p(e.fromLocator))), o = e.to ?? S(await f(t, p(e.toLocator)));
180
+ const r = e.from ?? P(await f(t, p(e.fromLocator))), o = e.to ?? P(await f(t, p(e.toLocator)));
180
181
  return {
181
182
  ...m(e),
182
183
  type: "arrow",
@@ -185,7 +186,7 @@ async function wt(t, e) {
185
186
  };
186
187
  }
187
188
  case "text": {
188
- const r = e.at ?? vt(
189
+ const r = e.at ?? mt(
189
190
  await f(t, p(e.locator)),
190
191
  e.fontSize
191
192
  ), o = {
@@ -197,7 +198,7 @@ async function wt(t, e) {
197
198
  return e.fontSize !== void 0 && (o.fontSize = e.fontSize), e.anchor !== void 0 && (o.anchor = e.anchor), o;
198
199
  }
199
200
  case "callout": {
200
- const r = e.at ?? await $t(t, e.atLocator), o = e.targetBbox ?? await f(t, p(e.targetLocator));
201
+ const r = e.at ?? await pt(t, e.atLocator), o = e.targetBbox ?? await f(t, p(e.targetLocator));
201
202
  return {
202
203
  ...m(e),
203
204
  type: "callout",
@@ -210,25 +211,25 @@ async function wt(t, e) {
210
211
  return e;
211
212
  }
212
213
  }
213
- async function bt(t, e) {
214
+ async function ht(t, e) {
214
215
  const r = [];
215
216
  for (const o of e)
216
- r.push(await wt(t, o));
217
+ r.push(await ft(t, o));
217
218
  return r;
218
219
  }
219
- async function $t(t, e) {
220
+ async function pt(t, e) {
220
221
  if (!e)
221
222
  throw new F(
222
223
  "<callout.at>",
223
224
  "callout annotations require either `at` or `atLocator`."
224
225
  );
225
226
  const r = await f(t, e);
226
- return S(r);
227
+ return P(r);
227
228
  }
228
- function S(t) {
229
+ function P(t) {
229
230
  return { x: t.x + t.width / 2, y: t.y + t.height / 2 };
230
231
  }
231
- function vt(t, e) {
232
+ function mt(t, e) {
232
233
  const r = (e ?? 14) + 2;
233
234
  return { x: t.x, y: Math.max(0, t.y - r) };
234
235
  }
@@ -246,186 +247,76 @@ function m(t) {
246
247
  const e = {};
247
248
  return t.intent !== void 0 && (e.intent = t.intent), t.stroke !== void 0 && (e.stroke = t.stroke), t.strokeWidth !== void 0 && (e.strokeWidth = t.strokeWidth), t.fill !== void 0 && (e.fill = t.fill), t.color !== void 0 && (e.color = t.color), e;
248
249
  }
249
- const xt = 4;
250
- function Et(t, e, r) {
251
- const o = new Uint8Array(e * r), n = [];
252
- for (let s = 0; s < r; s++)
253
- for (let i = 0; i < e; i++) {
254
- const a = s * e + i;
255
- if (o[a] || !X(t, a)) continue;
256
- const c = Pt(t, o, i, s, e, r);
257
- c.count >= xt && n.push({
250
+ const gt = 4;
251
+ function yt(t, e, r) {
252
+ const o = new Uint8Array(e * r), i = [];
253
+ for (let a = 0; a < r; a++)
254
+ for (let n = 0; n < e; n++) {
255
+ const s = a * e + n;
256
+ if (o[s] || !G(t, s)) continue;
257
+ const c = wt(t, o, n, a, e, r);
258
+ c.count >= gt && i.push({
258
259
  x: c.minX,
259
260
  y: c.minY,
260
261
  width: c.maxX - c.minX + 1,
261
262
  height: c.maxY - c.minY + 1
262
263
  });
263
264
  }
264
- return n;
265
+ return i;
265
266
  }
266
- function X(t, e) {
267
+ function G(t, e) {
267
268
  return t[e * 4 + 3] > 0;
268
269
  }
269
- function Pt(t, e, r, o, n, s) {
270
- const i = {
270
+ function wt(t, e, r, o, i, a) {
271
+ const n = {
271
272
  count: 0,
272
273
  minX: r,
273
274
  minY: o,
274
275
  maxX: r,
275
276
  maxY: o
276
- }, a = [r, o];
277
- for (; a.length > 0; ) {
278
- const c = a.pop(), l = a.pop();
279
- if (l < 0 || l >= n || c < 0 || c >= s) continue;
280
- const u = c * n + l;
281
- e[u] || X(t, u) && (e[u] = 1, i.count += 1, l < i.minX && (i.minX = l), c < i.minY && (i.minY = c), l > i.maxX && (i.maxX = l), c > i.maxY && (i.maxY = c), a.push(l + 1, c), a.push(l - 1, c), a.push(l, c + 1), a.push(l, c - 1));
277
+ }, s = [r, o];
278
+ for (; s.length > 0; ) {
279
+ const c = s.pop(), u = s.pop();
280
+ if (u < 0 || u >= i || c < 0 || c >= a) continue;
281
+ const l = c * i + u;
282
+ e[l] || G(t, l) && (e[l] = 1, n.count += 1, u < n.minX && (n.minX = u), c < n.minY && (n.minY = c), u > n.maxX && (n.maxX = u), c > n.maxY && (n.maxY = c), s.push(u + 1, c), s.push(u - 1, c), s.push(u, c + 1), s.push(u, c - 1));
282
283
  }
283
- return i;
284
+ return n;
284
285
  }
285
- class Lt extends Error {
286
+ class bt extends Error {
286
287
  constructor(e, r) {
287
288
  super(
288
289
  `Cannot compare screenshots of different dimensions: before is ${e.width}×${e.height}, after is ${r.width}×${r.height}.`
289
290
  ), this.name = "DimensionMismatchError";
290
291
  }
291
292
  }
292
- async function Ot(t, e, r = {}) {
293
- const [o, n] = await Promise.all([
294
- _(Buffer.from(t)),
295
- _(Buffer.from(e))
293
+ async function vt(t, e, r = {}) {
294
+ const [o, i] = await Promise.all([
295
+ T(Buffer.from(t)),
296
+ T(Buffer.from(e))
296
297
  ]);
297
- if (o.width !== n.width || o.height !== n.height)
298
- throw new Lt(
298
+ if (o.width !== i.width || o.height !== i.height)
299
+ throw new bt(
299
300
  { width: o.width, height: o.height },
300
- { width: n.width, height: n.height }
301
+ { width: i.width, height: i.height }
301
302
  );
302
- const { width: s, height: i } = o, a = N(o, s, i), c = N(n, s, i), l = new Uint8Array(s * i * 4), u = st(a, c, l, s, i, {
303
+ const { width: a, height: n } = o, s = N(o, a, n), c = N(i, a, n), u = new Uint8Array(a * n * 4), l = et(s, c, u, a, n, {
303
304
  threshold: r.threshold ?? 0.1,
304
305
  includeAA: !1,
305
306
  diffMask: !0
306
- }), h = Et(l, s, i);
307
- return { mismatchedPixels: u, regions: h, width: s, height: i };
307
+ }), h = yt(u, a, n);
308
+ return { mismatchedPixels: l, regions: h, width: a, height: n };
308
309
  }
309
310
  function N(t, e, r) {
310
- const n = B(e, r).getContext("2d");
311
- n.drawImage(t, 0, 0);
312
- const s = n.getImageData(0, 0, e, r).data;
313
- return new Uint8Array(s.buffer, s.byteOffset, s.byteLength);
311
+ const i = _(e, r).getContext("2d");
312
+ i.drawImage(t, 0, 0);
313
+ const a = i.getImageData(0, 0, e, r).data;
314
+ return new Uint8Array(a.buffer, a.byteOffset, a.byteLength);
314
315
  }
315
- const R = {
316
- BBox: {
317
- type: "object",
318
- required: ["x", "y", "width", "height"],
319
- additionalProperties: !1,
320
- properties: {
321
- x: { type: "number" },
322
- y: { type: "number" },
323
- width: { type: "number", minimum: 0 },
324
- height: { type: "number", minimum: 0 }
325
- }
326
- },
327
- Point: {
328
- type: "object",
329
- required: ["x", "y"],
330
- additionalProperties: !1,
331
- properties: {
332
- x: { type: "number" },
333
- y: { type: "number" }
334
- }
335
- },
336
- Intent: {
337
- type: "string",
338
- enum: ["info", "warning", "error", "success", "neutral"]
339
- },
340
- AnnotationStyle: {
341
- type: "object",
342
- additionalProperties: !1,
343
- properties: {
344
- intent: { $ref: "#/$defs/Intent" },
345
- stroke: { type: "string" },
346
- strokeWidth: { type: "number", minimum: 0 },
347
- fill: { type: "string" },
348
- color: { type: "string" }
349
- }
350
- },
316
+ const O = {
317
+ ...K,
351
318
  Locator: { type: "string", minLength: 1 }
352
- }, St = {
353
- type: "object",
354
- required: ["type", "bbox"],
355
- additionalProperties: !1,
356
- properties: {
357
- type: { const: "rect" },
358
- bbox: { $ref: "#/$defs/BBox" },
359
- intent: { $ref: "#/$defs/Intent" },
360
- stroke: { type: "string" },
361
- strokeWidth: { type: "number", minimum: 0 },
362
- fill: { type: "string" },
363
- color: { type: "string" }
364
- }
365
- }, At = {
366
- type: "object",
367
- required: ["type", "center", "radius"],
368
- additionalProperties: !1,
369
- properties: {
370
- type: { const: "circle" },
371
- center: { $ref: "#/$defs/Point" },
372
- radius: { type: "number", minimum: 0 },
373
- intent: { $ref: "#/$defs/Intent" },
374
- stroke: { type: "string" },
375
- strokeWidth: { type: "number", minimum: 0 },
376
- fill: { type: "string" },
377
- color: { type: "string" }
378
- }
379
- }, Rt = {
380
- type: "object",
381
- required: ["type", "from", "to"],
382
- additionalProperties: !1,
383
- properties: {
384
- type: { const: "arrow" },
385
- from: { $ref: "#/$defs/Point" },
386
- to: { $ref: "#/$defs/Point" },
387
- intent: { $ref: "#/$defs/Intent" },
388
- stroke: { type: "string" },
389
- strokeWidth: { type: "number", minimum: 0 },
390
- color: { type: "string" }
391
- }
392
- }, Tt = {
393
- type: "object",
394
- required: ["type", "at", "content"],
395
- additionalProperties: !1,
396
- properties: {
397
- type: { const: "text" },
398
- at: { $ref: "#/$defs/Point" },
399
- content: { type: "string" },
400
- fontSize: { type: "number", minimum: 0 },
401
- anchor: { type: "string", enum: ["start", "middle", "end"] },
402
- intent: { $ref: "#/$defs/Intent" },
403
- color: { type: "string" }
404
- }
405
- }, kt = {
406
- type: "object",
407
- required: ["type", "at", "targetBbox", "content"],
408
- additionalProperties: !1,
409
- properties: {
410
- type: { const: "callout" },
411
- at: { $ref: "#/$defs/Point" },
412
- targetBbox: { $ref: "#/$defs/BBox" },
413
- content: { type: "string" },
414
- intent: { $ref: "#/$defs/Intent" },
415
- stroke: { type: "string" },
416
- color: { type: "string" }
417
- }
418
- }, z = {
419
- type: "object",
420
- required: ["type", "svgFragment"],
421
- additionalProperties: !1,
422
- properties: {
423
- type: { const: "raw" },
424
- svgFragment: { type: "string" }
425
- }
426
- }, It = {
427
- oneOf: [St, At, Rt, Tt, kt, z]
428
- }, _t = {
319
+ }, $t = {
429
320
  type: "object",
430
321
  required: ["type"],
431
322
  additionalProperties: !1,
@@ -440,7 +331,7 @@ const R = {
440
331
  color: { type: "string" }
441
332
  },
442
333
  anyOf: [{ required: ["bbox"] }, { required: ["locator"] }]
443
- }, Bt = {
334
+ }, Et = {
444
335
  type: "object",
445
336
  required: ["type"],
446
337
  additionalProperties: !1,
@@ -456,7 +347,7 @@ const R = {
456
347
  color: { type: "string" }
457
348
  },
458
349
  anyOf: [{ required: ["center", "radius"] }, { required: ["locator"] }]
459
- }, Ft = {
350
+ }, xt = {
460
351
  type: "object",
461
352
  required: ["type"],
462
353
  additionalProperties: !1,
@@ -475,7 +366,7 @@ const R = {
475
366
  { anyOf: [{ required: ["from"] }, { required: ["fromLocator"] }] },
476
367
  { anyOf: [{ required: ["to"] }, { required: ["toLocator"] }] }
477
368
  ]
478
- }, Ct = {
369
+ }, Lt = {
479
370
  type: "object",
480
371
  required: ["type", "content"],
481
372
  additionalProperties: !1,
@@ -490,7 +381,7 @@ const R = {
490
381
  color: { type: "string" }
491
382
  },
492
383
  anyOf: [{ required: ["at"] }, { required: ["locator"] }]
493
- }, Ut = {
384
+ }, Pt = {
494
385
  type: "object",
495
386
  required: ["type", "content"],
496
387
  additionalProperties: !1,
@@ -509,18 +400,17 @@ const R = {
509
400
  { anyOf: [{ required: ["at"] }, { required: ["atLocator"] }] },
510
401
  { anyOf: [{ required: ["targetBbox"] }, { required: ["targetLocator"] }] }
511
402
  ]
512
- }, Nt = {
513
- oneOf: [_t, Bt, Ft, Ct, Ut, z]
514
- }, qt = {
403
+ }, At = {
515
404
  type: "object",
516
- required: ["bbox"],
405
+ required: ["type", "svgFragment"],
517
406
  additionalProperties: !1,
518
407
  properties: {
519
- bbox: { $ref: "#/$defs/BBox" },
520
- style: { type: "string", enum: ["solid", "mosaic", "blur"] },
521
- color: { type: "string" }
408
+ type: { const: "raw" },
409
+ svgFragment: { type: "string" }
522
410
  }
523
- }, Wt = {
411
+ }, Ot = {
412
+ oneOf: [$t, Et, xt, Lt, Pt, At]
413
+ }, Rt = {
524
414
  type: "object",
525
415
  additionalProperties: !1,
526
416
  properties: {
@@ -530,237 +420,125 @@ const R = {
530
420
  color: { type: "string" }
531
421
  },
532
422
  anyOf: [{ required: ["bbox"] }, { required: ["locator"] }]
533
- };
534
- function Y(t, e = {}) {
535
- const r = e.stroke ?? "red", o = e.strokeWidth ?? 2, n = e.fill ?? "none";
536
- return `<rect x="${t.x}" y="${t.y}" width="${t.width}" height="${t.height}" fill="${v(n)}" stroke="${v(r)}" stroke-width="${o}"/>`;
537
- }
538
- function V(t, e, r = {}) {
539
- const o = r.color ?? "red", n = r.strokeWidth ?? 2, s = `annot-mcp-arrow-${Dt()}`;
540
- return `<defs><marker id="${s}" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto" markerUnits="strokeWidth"><path d="M 0 0 L 10 5 L 0 10 z" fill="${v(o)}"/></marker></defs><line x1="${t.x}" y1="${t.y}" x2="${e.x}" y2="${e.y}" stroke="${v(o)}" stroke-width="${n}" marker-end="url(#${s})"/>`;
541
- }
542
- function J(t, e, r = {}) {
543
- const o = r.color ?? "red", n = r.fontSize ?? 14, s = r.anchor ?? "start";
544
- return `<text x="${t.x}" y="${t.y}" fill="${v(o)}" font-size="${n}" text-anchor="${s}">` + Gt(e) + "</text>";
545
- }
546
- let k = 0;
547
- function Dt() {
548
- return k = k + 1 | 0, k;
549
- }
550
- function v(t) {
551
- return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
552
- }
553
- function Gt(t) {
554
- return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
555
- }
556
- const Mt = {
557
- info: { stroke: "#3b82f6", fill: "rgba(59, 130, 246, 0.12)", text: "#1e40af" },
558
- warning: { stroke: "#f59e0b", fill: "rgba(245, 158, 11, 0.12)", text: "#92400e" },
559
- error: { stroke: "#ef4444", fill: "rgba(239, 68, 68, 0.12)", text: "#991b1b" },
560
- success: { stroke: "#10b981", fill: "rgba(16, 185, 129, 0.12)", text: "#065f46" },
561
- neutral: { stroke: "#6b7280", fill: "rgba(107, 114, 128, 0.12)", text: "#374151" }
562
- }, jt = "error";
563
- function E(t) {
564
- const e = t.intent ?? jt, r = Mt[e];
565
- return {
566
- stroke: t.stroke ?? r.stroke,
567
- fill: t.fill ?? "none",
568
- text: t.color ?? r.text
569
- };
570
- }
571
- function C(t) {
572
- return t.map(Ht).join("");
573
- }
574
- function Ht(t) {
575
- switch (t.type) {
576
- case "rect":
577
- return Xt(t);
578
- case "circle":
579
- return zt(t);
580
- case "arrow":
581
- return Yt(t);
582
- case "text":
583
- return Vt(t);
584
- case "callout":
585
- return Jt(t);
586
- case "raw":
587
- return Kt(t);
588
- }
589
- }
590
- function Xt(t) {
591
- const e = E(t);
592
- return Y(t.bbox, {
593
- stroke: e.stroke,
594
- strokeWidth: t.strokeWidth ?? 2,
595
- fill: e.fill
596
- });
597
- }
598
- function zt(t) {
599
- const e = E(t), r = t.strokeWidth ?? 2;
600
- return `<circle cx="${t.center.x}" cy="${t.center.y}" r="${t.radius}" fill="${W(e.fill)}" stroke="${W(e.stroke)}" stroke-width="${r}"/>`;
601
- }
602
- function Yt(t) {
603
- const e = E(t);
604
- return V(t.from, t.to, {
605
- color: e.stroke,
606
- strokeWidth: t.strokeWidth ?? 2
607
- });
608
- }
609
- function Vt(t) {
610
- const e = E(t);
611
- return J(t.at, t.content, {
612
- color: e.text,
613
- fontSize: t.fontSize ?? 14,
614
- anchor: t.anchor ?? "start"
615
- });
616
- }
617
- function Jt(t) {
618
- const e = E(t), r = t.targetBbox, o = Zt(r, t.at);
619
- return Y(r, {
620
- stroke: e.stroke,
621
- strokeWidth: t.strokeWidth ?? 2,
622
- fill: e.fill
623
- }) + V(t.at, o, {
624
- color: e.stroke,
625
- strokeWidth: 2
626
- }) + J(t.at, t.content, {
627
- color: e.text,
628
- fontSize: 14,
629
- anchor: "start"
630
- });
631
- }
632
- function Kt(t) {
633
- return t.svgFragment;
634
- }
635
- function Zt(t, e) {
636
- const r = q(e.x, t.x, t.x + t.width), o = q(e.y, t.y, t.y + t.height);
637
- return { x: r, y: o };
638
- }
639
- function q(t, e, r) {
640
- return Math.min(Math.max(t, e), r);
641
- }
642
- function W(t) {
643
- return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
644
- }
645
- const D = [137, 80, 78, 71, 13, 10, 26, 10], P = 12, Qt = "IHDR", te = 16, ee = 20, G = 24;
646
- class $ extends Error {
423
+ }, B = [137, 80, 78, 71, 13, 10, 26, 10], E = 12, St = "IHDR", Tt = 16, It = 20, U = 24;
424
+ class v extends Error {
647
425
  constructor(e) {
648
426
  super(e), this.name = "InvalidPngError";
649
427
  }
650
428
  }
651
- function K(t) {
652
- if (t.byteLength < G)
653
- throw new $(
654
- `Expected at least ${G} bytes for a PNG header, got ${t.byteLength}.`
429
+ function M(t) {
430
+ if (t.byteLength < U)
431
+ throw new v(
432
+ `Expected at least ${U} bytes for a PNG header, got ${t.byteLength}.`
655
433
  );
656
- for (let s = 0; s < D.length; s++)
657
- if (t[s] !== D[s])
658
- throw new $(
434
+ for (let a = 0; a < B.length; a++)
435
+ if (t[a] !== B[a])
436
+ throw new v(
659
437
  "Input does not start with the PNG signature (89 50 4E 47 0D 0A 1A 0A). Confirm the input is a PNG — JPEG / WebP / other formats are not supported in v1."
660
438
  );
661
439
  const e = new DataView(t.buffer, t.byteOffset, t.byteLength), r = String.fromCharCode(
662
- t[P],
663
- t[P + 1],
664
- t[P + 2],
665
- t[P + 3]
440
+ t[E],
441
+ t[E + 1],
442
+ t[E + 2],
443
+ t[E + 3]
666
444
  );
667
- if (r !== Qt)
668
- throw new $(
445
+ if (r !== St)
446
+ throw new v(
669
447
  `Expected IHDR chunk after PNG signature, found "${r}". The file may be a corrupt or non-standard PNG.`
670
448
  );
671
- const o = e.getUint32(te, !1), n = e.getUint32(ee, !1);
672
- if (o === 0 || n === 0)
673
- throw new $(`PNG dimensions ${o}×${n} include a zero axis.`);
674
- return { width: o, height: n };
449
+ const o = e.getUint32(Tt, !1), i = e.getUint32(It, !1);
450
+ if (o === 0 || i === 0)
451
+ throw new v(`PNG dimensions ${o}×${i} include a zero axis.`);
452
+ return { width: o, height: i };
675
453
  }
676
454
  class y extends Error {
677
455
  constructor(e) {
678
456
  super(e), this.name = "InvalidImageInputError";
679
457
  }
680
458
  }
681
- const re = "data:", oe = /^data:image\/png;base64,/i;
459
+ const _t = "data:", Ft = /^data:image\/png;base64,/i;
682
460
  async function A(t) {
683
461
  if (typeof t != "string" || t.length === 0)
684
462
  throw new y(
685
463
  "`image` must be a non-empty string (data URL or absolute filesystem path)."
686
464
  );
687
- if (t.startsWith(re))
688
- return ne(t);
465
+ if (t.startsWith(_t))
466
+ return Ct(t);
689
467
  if (!w(t))
690
468
  throw new y(
691
469
  `Filesystem path "${t}" is not absolute. Pass an absolute path so resolution doesn't depend on the MCP server's working directory.`
692
470
  );
693
- return ie(t);
471
+ return Nt(t);
694
472
  }
695
- function ne(t) {
696
- if (!oe.test(t))
473
+ function Ct(t) {
474
+ if (!Ft.test(t))
697
475
  throw new y(
698
476
  "Only `data:image/png;base64,...` URLs are supported. JPEG / WebP / SVG data URLs are not accepted in v1."
699
477
  );
700
- const e = t.slice(t.indexOf(",") + 1), r = se(e), o = Z(r);
478
+ const e = t.slice(t.indexOf(",") + 1), r = Bt(e), o = H(r);
701
479
  return { bytes: r, dataUrl: t, dimensions: o };
702
480
  }
703
- async function ie(t) {
481
+ async function Nt(t) {
704
482
  let e;
705
483
  try {
706
- const n = await at(t);
707
- e = new Uint8Array(n.buffer, n.byteOffset, n.byteLength);
708
- } catch (n) {
709
- const s = n instanceof Error ? n.message : String(n);
710
- throw new y(`Failed to read image at "${t}": ${s}`);
484
+ const i = await rt(t);
485
+ e = new Uint8Array(i.buffer, i.byteOffset, i.byteLength);
486
+ } catch (i) {
487
+ const a = i instanceof Error ? i.message : String(i);
488
+ throw new y(`Failed to read image at "${t}": ${a}`);
711
489
  }
712
- const r = Z(e), o = `data:image/png;base64,${ae(e)}`;
490
+ const r = H(e), o = `data:image/png;base64,${Ut(e)}`;
713
491
  return { bytes: e, dataUrl: o, dimensions: r };
714
492
  }
715
- function Z(t) {
493
+ function H(t) {
716
494
  try {
717
- return K(t);
495
+ return M(t);
718
496
  } catch (e) {
719
- throw e instanceof $ ? new y(e.message) : e;
497
+ throw e instanceof v ? new y(e.message) : e;
720
498
  }
721
499
  }
722
- function se(t) {
500
+ function Bt(t) {
723
501
  const e = Buffer.from(t, "base64");
724
502
  return new Uint8Array(e.buffer, e.byteOffset, e.byteLength);
725
503
  }
726
- function ae(t) {
504
+ function Ut(t) {
727
505
  return Buffer.from(t.buffer, t.byteOffset, t.byteLength).toString("base64");
728
506
  }
729
- const ce = "solid", le = "#000000", M = 16, ue = 12;
730
- async function Q(t, e) {
507
+ const qt = "solid", Dt = "#000000", q = 16, kt = 12;
508
+ async function W(t, e) {
731
509
  if (e.length === 0)
732
510
  return t;
733
- const r = await _(Buffer.from(t)), o = B(r.width, r.height), n = o.getContext("2d");
734
- n.drawImage(r, 0, 0);
735
- for (const i of e) {
736
- if (i.bbox.width <= 0 || i.bbox.height <= 0) continue;
737
- switch (i.style ?? ce) {
511
+ const r = await T(Buffer.from(t)), o = _(r.width, r.height), i = o.getContext("2d");
512
+ i.drawImage(r, 0, 0);
513
+ for (const n of e) {
514
+ if (n.bbox.width <= 0 || n.bbox.height <= 0) continue;
515
+ switch (n.style ?? qt) {
738
516
  case "solid":
739
- de(n, i.bbox, i.color ?? le);
517
+ Gt(i, n.bbox, n.color ?? Dt);
740
518
  break;
741
519
  case "mosaic":
742
- fe(n, r, i.bbox);
520
+ Mt(i, r, n.bbox);
743
521
  break;
744
522
  case "blur":
745
- he(n, r, i.bbox);
523
+ Ht(i, r, n.bbox);
746
524
  break;
747
525
  }
748
526
  }
749
- const s = o.toBuffer("image/png");
750
- return new Uint8Array(s.buffer, s.byteOffset, s.byteLength);
527
+ const a = o.toBuffer("image/png");
528
+ return new Uint8Array(a.buffer, a.byteOffset, a.byteLength);
751
529
  }
752
- function de(t, e, r) {
530
+ function Gt(t, e, r) {
753
531
  t.save(), t.fillStyle = r, t.fillRect(e.x, e.y, e.width, e.height), t.restore();
754
532
  }
755
- function fe(t, e, r) {
756
- const o = Math.max(1, Math.round(r.width / M)), n = Math.max(1, Math.round(r.height / M)), s = B(o, n), i = s.getContext("2d");
757
- i.imageSmoothingEnabled = !1, i.drawImage(e, r.x, r.y, r.width, r.height, 0, 0, o, n), t.save(), t.imageSmoothingEnabled = !1, t.drawImage(s, 0, 0, o, n, r.x, r.y, r.width, r.height), t.restore();
533
+ function Mt(t, e, r) {
534
+ const o = Math.max(1, Math.round(r.width / q)), i = Math.max(1, Math.round(r.height / q)), a = _(o, i), n = a.getContext("2d");
535
+ n.imageSmoothingEnabled = !1, n.drawImage(e, r.x, r.y, r.width, r.height, 0, 0, o, i), t.save(), t.imageSmoothingEnabled = !1, t.drawImage(a, 0, 0, o, i, r.x, r.y, r.width, r.height), t.restore();
758
536
  }
759
- function he(t, e, r) {
760
- t.save(), t.beginPath(), t.rect(r.x, r.y, r.width, r.height), t.clip(), t.filter = `blur(${ue}px)`, t.drawImage(e, 0, 0), t.restore();
537
+ function Ht(t, e, r) {
538
+ t.save(), t.beginPath(), t.rect(r.x, r.y, r.width, r.height), t.clip(), t.filter = `blur(${kt}px)`, t.drawImage(e, 0, 0), t.restore();
761
539
  }
762
- const tt = "annot_annotate_screenshot", pe = {
763
- name: tt,
540
+ const j = "annot_annotate_screenshot", Wt = {
541
+ name: j,
764
542
  description: "Overlay annotations (rectangles, circles, arrows, callouts, text) on a PNG screenshot. Annotation positions are specified as bounding boxes or points; pair with `annot_annotate_url` if you want locator-driven positioning. Returns the annotated PNG inline unless `output` is specified, in which case the PNG is written to that absolute path.",
765
543
  inputSchema: {
766
544
  type: "object",
@@ -782,73 +560,73 @@ const tt = "annot_annotate_screenshot", pe = {
782
560
  }
783
561
  },
784
562
  $defs: {
785
- ...R,
786
- BboxAnnotation: It
563
+ ...O,
564
+ BboxAnnotation: Z
787
565
  }
788
566
  }
789
567
  };
790
- async function me(t, e) {
568
+ async function jt(t, e) {
791
569
  try {
792
- const r = ge(t), o = await A(r.image), n = C(r.annotations), s = e.annotator.toPng({
570
+ const r = Xt(t), o = await A(r.image), i = I(r.annotations), a = e.annotator.toPng({
793
571
  originalDataUrl: o.dataUrl,
794
- annotationsSvg: n,
572
+ annotationsSvg: i,
795
573
  width: o.dimensions.width,
796
574
  height: o.dimensions.height
797
575
  });
798
- return r.output ? (await x(r.output, s), {
576
+ return r.output ? (await $(r.output, a), {
799
577
  content: [
800
578
  {
801
579
  type: "text",
802
- text: `Wrote ${s.byteLength}-byte annotated PNG to ${r.output} (${o.dimensions.width}×${o.dimensions.height}, ${r.annotations.length} annotation${r.annotations.length === 1 ? "" : "s"}).`
580
+ text: `Wrote ${a.byteLength}-byte annotated PNG to ${r.output} (${o.dimensions.width}×${o.dimensions.height}, ${r.annotations.length} annotation${r.annotations.length === 1 ? "" : "s"}).`
803
581
  }
804
582
  ]
805
583
  }) : {
806
584
  content: [
807
585
  {
808
586
  type: "image",
809
- data: we(s),
587
+ data: zt(a),
810
588
  mimeType: "image/png"
811
589
  }
812
590
  ]
813
591
  };
814
592
  } catch (r) {
815
- return ye(r);
593
+ return Yt(r);
816
594
  }
817
595
  }
818
- function ge(t) {
596
+ function Xt(t) {
819
597
  if (typeof t.image != "string")
820
598
  throw new y("`image` is required and must be a string.");
821
599
  if (!Array.isArray(t.annotations))
822
- throw new I("`annotations` is required and must be an array.");
600
+ throw new S("`annotations` is required and must be an array.");
823
601
  const e = t.annotations;
824
602
  let r;
825
603
  if (t.output !== void 0) {
826
604
  if (typeof t.output != "string")
827
- throw new I("`output` must be a string when provided.");
605
+ throw new S("`output` must be a string when provided.");
828
606
  if (!w(t.output))
829
- throw new I(
607
+ throw new S(
830
608
  `\`output\` path "${t.output}" must be absolute so the file lands at a predictable location.`
831
609
  );
832
610
  r = t.output;
833
611
  }
834
612
  return { image: t.image, annotations: e, output: r };
835
613
  }
836
- class I extends Error {
614
+ class S extends Error {
837
615
  constructor(e) {
838
616
  super(e), this.name = "InvalidToolInputError";
839
617
  }
840
618
  }
841
- function ye(t) {
619
+ function Yt(t) {
842
620
  return {
843
621
  content: [{ type: "text", text: t instanceof Error ? `${t.name}: ${t.message}` : `Unknown error: ${String(t)}` }],
844
622
  isError: !0
845
623
  };
846
624
  }
847
- function we(t) {
625
+ function zt(t) {
848
626
  return Buffer.from(t.buffer, t.byteOffset, t.byteLength).toString("base64");
849
627
  }
850
- const et = "annot_annotate_url", be = {
851
- name: et,
628
+ const X = "annot_annotate_url", Vt = {
629
+ name: X,
852
630
  description: 'Open a URL in a headless browser, capture a screenshot, and overlay annotations whose positions are specified as Playwright locator strings (`button:has-text("Submit")`, `[data-testid="email"]`, `role=button[name="Sign in"]`) or bounding boxes. Returns the annotated PNG inline unless `output` is specified.',
853
631
  inputSchema: {
854
632
  type: "object",
@@ -891,8 +669,8 @@ const et = "annot_annotate_url", be = {
891
669
  }
892
670
  },
893
671
  $defs: {
894
- ...R,
895
- LocatorAnnotation: Nt
672
+ ...O,
673
+ LocatorAnnotation: Ot
896
674
  }
897
675
  }
898
676
  };
@@ -901,50 +679,50 @@ class b extends Error {
901
679
  super(e), this.name = "InvalidAnnotateUrlInputError";
902
680
  }
903
681
  }
904
- async function $e(t, e) {
682
+ async function Jt(t, e) {
905
683
  try {
906
- const r = ve(t), o = await H(e.pool, {
684
+ const r = Kt(t), o = await k(e.pool, {
907
685
  url: r.url,
908
686
  viewport: r.viewport,
909
687
  fullPage: r.fullPage,
910
688
  waitFor: r.waitFor
911
689
  });
912
- let n;
690
+ let i;
913
691
  try {
914
- n = await bt(
692
+ i = await ht(
915
693
  o.handle.page,
916
694
  r.annotations
917
695
  );
918
696
  } finally {
919
697
  await o.handle.close();
920
698
  }
921
- const s = K(o.pngBytes), i = C(n), a = e.annotator.toPng({
922
- originalDataUrl: `data:image/png;base64,${j(o.pngBytes)}`,
923
- annotationsSvg: i,
924
- width: s.width,
925
- height: s.height
699
+ const a = M(o.pngBytes), n = I(i), s = e.annotator.toPng({
700
+ originalDataUrl: `data:image/png;base64,${D(o.pngBytes)}`,
701
+ annotationsSvg: n,
702
+ width: a.width,
703
+ height: a.height
926
704
  });
927
- return r.output ? (await x(r.output, a), {
705
+ return r.output ? (await $(r.output, s), {
928
706
  content: [
929
707
  {
930
708
  type: "text",
931
- text: `Wrote ${a.byteLength}-byte annotated PNG to ${r.output} (${s.width}×${s.height}, ${r.annotations.length} annotation${r.annotations.length === 1 ? "" : "s"}, captured from ${r.url}).`
709
+ text: `Wrote ${s.byteLength}-byte annotated PNG to ${r.output} (${a.width}×${a.height}, ${r.annotations.length} annotation${r.annotations.length === 1 ? "" : "s"}, captured from ${r.url}).`
932
710
  }
933
711
  ]
934
712
  }) : {
935
713
  content: [
936
714
  {
937
715
  type: "image",
938
- data: j(a),
716
+ data: D(s),
939
717
  mimeType: "image/png"
940
718
  }
941
719
  ]
942
720
  };
943
721
  } catch (r) {
944
- return xe(r);
722
+ return Zt(r);
945
723
  }
946
724
  }
947
- function ve(t) {
725
+ function Kt(t) {
948
726
  if (typeof t.url != "string" || t.url.length === 0)
949
727
  throw new b("`url` is required and must be a non-empty string.");
950
728
  if (!Array.isArray(t.annotations))
@@ -954,38 +732,38 @@ function ve(t) {
954
732
  if (t.viewport !== void 0) {
955
733
  if (typeof t.viewport != "object" || t.viewport === null)
956
734
  throw new b("`viewport` must be an object when provided.");
957
- const i = t.viewport, a = typeof i.width == "number" ? i.width : 1280, c = typeof i.height == "number" ? i.height : 800, l = typeof i.deviceScaleFactor == "number" ? i.deviceScaleFactor : 1;
958
- r = { width: a, height: c, deviceScaleFactor: l };
735
+ const n = t.viewport, s = typeof n.width == "number" ? n.width : 1280, c = typeof n.height == "number" ? n.height : 800, u = typeof n.deviceScaleFactor == "number" ? n.deviceScaleFactor : 1;
736
+ r = { width: s, height: c, deviceScaleFactor: u };
959
737
  }
960
- const o = t.fullPage === !0, n = t.waitFor === "domcontentloaded" || t.waitFor === "networkidle" ? t.waitFor : "load";
961
- let s;
738
+ const o = t.fullPage === !0, i = t.waitFor === "domcontentloaded" || t.waitFor === "networkidle" ? t.waitFor : "load";
739
+ let a;
962
740
  if (t.output !== void 0) {
963
741
  if (typeof t.output != "string")
964
742
  throw new b("`output` must be a string when provided.");
965
743
  if (!w(t.output))
966
744
  throw new b(`\`output\` path "${t.output}" must be absolute.`);
967
- s = t.output;
745
+ a = t.output;
968
746
  }
969
747
  return {
970
748
  url: t.url,
971
749
  annotations: e,
972
750
  viewport: r,
973
751
  fullPage: o,
974
- waitFor: n,
975
- output: s
752
+ waitFor: i,
753
+ output: a
976
754
  };
977
755
  }
978
- function xe(t) {
756
+ function Zt(t) {
979
757
  return {
980
758
  content: [{ type: "text", text: t instanceof Error ? `${t.name}: ${t.message}` : `Unknown error: ${String(t)}` }],
981
759
  isError: !0
982
760
  };
983
761
  }
984
- function j(t) {
762
+ function D(t) {
985
763
  return Buffer.from(t.buffer, t.byteOffset, t.byteLength).toString("base64");
986
764
  }
987
- const rt = "annot_compare_screenshots", Ee = {
988
- name: rt,
765
+ const Y = "annot_compare_screenshots", Qt = {
766
+ name: Y,
989
767
  description: "Compare two screenshots (must have identical dimensions) and return a PNG of the `after` image with changed regions highlighted as red rectangles. Useful for visual-diff PR review.",
990
768
  inputSchema: {
991
769
  type: "object",
@@ -1016,55 +794,55 @@ const rt = "annot_compare_screenshots", Ee = {
1016
794
  }
1017
795
  }
1018
796
  };
1019
- class L extends Error {
797
+ class x extends Error {
1020
798
  constructor(e) {
1021
799
  super(e), this.name = "InvalidCompareInputError";
1022
800
  }
1023
801
  }
1024
- async function Pe(t, e) {
802
+ async function te(t, e) {
1025
803
  try {
1026
804
  if (typeof t.before != "string")
1027
- throw new L("`before` is required and must be a string.");
805
+ throw new x("`before` is required and must be a string.");
1028
806
  if (typeof t.after != "string")
1029
- throw new L("`after` is required and must be a string.");
807
+ throw new x("`after` is required and must be a string.");
1030
808
  const r = typeof t.threshold == "number" ? t.threshold : 0.1, o = t.includeChangeList === !0;
1031
- let n;
809
+ let i;
1032
810
  if (t.output !== void 0) {
1033
811
  if (typeof t.output != "string")
1034
- throw new L("`output` must be a string when provided.");
812
+ throw new x("`output` must be a string when provided.");
1035
813
  if (!w(t.output))
1036
- throw new L(`\`output\` path "${t.output}" must be absolute.`);
1037
- n = t.output;
814
+ throw new x(`\`output\` path "${t.output}" must be absolute.`);
815
+ i = t.output;
1038
816
  }
1039
- const [s, i] = await Promise.all([
817
+ const [a, n] = await Promise.all([
1040
818
  A(t.before),
1041
819
  A(t.after)
1042
- ]), a = await Ot(s.bytes, i.bytes, { threshold: r }), c = a.regions.map((d) => ({
820
+ ]), s = await vt(a.bytes, n.bytes, { threshold: r }), c = s.regions.map((d) => ({
1043
821
  type: "rect",
1044
822
  bbox: d,
1045
823
  intent: "warning"
1046
- })), l = C(c), u = e.annotator.toPng({
1047
- originalDataUrl: i.dataUrl,
1048
- annotationsSvg: l,
1049
- width: a.width,
1050
- height: a.height
824
+ })), u = I(c), l = e.annotator.toPng({
825
+ originalDataUrl: n.dataUrl,
826
+ annotationsSvg: u,
827
+ width: s.width,
828
+ height: s.height
1051
829
  });
1052
- if (n)
1053
- return await x(n, u), { content: [{ type: "text", text: `Wrote ${u.byteLength}-byte diff-annotated PNG to ${n} (${a.width}×${a.height}, ${a.regions.length} changed region${a.regions.length === 1 ? "" : "s"}, ${a.mismatchedPixels} mismatched pixel${a.mismatchedPixels === 1 ? "" : "s"}).` }] };
830
+ if (i)
831
+ return await $(i, l), { content: [{ type: "text", text: `Wrote ${l.byteLength}-byte diff-annotated PNG to ${i} (${s.width}×${s.height}, ${s.regions.length} changed region${s.regions.length === 1 ? "" : "s"}, ${s.mismatchedPixels} mismatched pixel${s.mismatchedPixels === 1 ? "" : "s"}).` }] };
1054
832
  const h = {
1055
833
  type: "image",
1056
- data: Buffer.from(u.buffer, u.byteOffset, u.byteLength).toString(
834
+ data: Buffer.from(l.buffer, l.byteOffset, l.byteLength).toString(
1057
835
  "base64"
1058
836
  ),
1059
837
  mimeType: "image/png"
1060
838
  };
1061
839
  if (!o)
1062
840
  return { content: [h] };
1063
- const T = `${a.regions.length} changed region${a.regions.length === 1 ? "" : "s"}, ${a.mismatchedPixels} mismatched pixel${a.mismatchedPixels === 1 ? "" : "s"}:
1064
- ` + a.regions.map((d, it) => ` [${it + 1}] x=${d.x} y=${d.y} w=${d.width} h=${d.height}`).join(`
841
+ const R = `${s.regions.length} changed region${s.regions.length === 1 ? "" : "s"}, ${s.mismatchedPixels} mismatched pixel${s.mismatchedPixels === 1 ? "" : "s"}:
842
+ ` + s.regions.map((d, J) => ` [${J + 1}] x=${d.x} y=${d.y} w=${d.width} h=${d.height}`).join(`
1065
843
  `);
1066
844
  return {
1067
- content: [h, { type: "text", text: T }]
845
+ content: [h, { type: "text", text: R }]
1068
846
  };
1069
847
  } catch (r) {
1070
848
  return {
@@ -1073,8 +851,8 @@ async function Pe(t, e) {
1073
851
  };
1074
852
  }
1075
853
  }
1076
- const ot = "annot_redact_screenshot", Le = {
1077
- name: ot,
854
+ const z = "annot_redact_screenshot", ee = {
855
+ name: z,
1078
856
  description: "Destructively burn redactions (solid / mosaic / blur) into a PNG screenshot. The original pixels under each region are irrecoverably replaced. Returns the redacted PNG inline unless `output` is specified.",
1079
857
  inputSchema: {
1080
858
  type: "object",
@@ -1092,37 +870,37 @@ const ot = "annot_redact_screenshot", Le = {
1092
870
  output: { type: "string" }
1093
871
  },
1094
872
  $defs: {
1095
- ...R,
1096
- BboxRedactRegion: qt
873
+ ...O,
874
+ BboxRedactRegion: Q
1097
875
  }
1098
876
  }
1099
877
  };
1100
- class O extends Error {
878
+ class L extends Error {
1101
879
  constructor(e) {
1102
880
  super(e), this.name = "InvalidRedactInputError";
1103
881
  }
1104
882
  }
1105
- async function Oe(t) {
883
+ async function re(t) {
1106
884
  try {
1107
885
  if (typeof t.image != "string")
1108
- throw new O("`image` is required and must be a string.");
886
+ throw new L("`image` is required and must be a string.");
1109
887
  if (!Array.isArray(t.regions))
1110
- throw new O("`regions` is required and must be an array.");
888
+ throw new L("`regions` is required and must be an array.");
1111
889
  const e = t.regions;
1112
890
  let r;
1113
891
  if (t.output !== void 0) {
1114
892
  if (typeof t.output != "string")
1115
- throw new O("`output` must be a string when provided.");
893
+ throw new L("`output` must be a string when provided.");
1116
894
  if (!w(t.output))
1117
- throw new O(`\`output\` path "${t.output}" must be absolute.`);
895
+ throw new L(`\`output\` path "${t.output}" must be absolute.`);
1118
896
  r = t.output;
1119
897
  }
1120
- const o = await A(t.image), n = await Q(o.bytes, e);
1121
- return r ? (await x(r, n), {
898
+ const o = await A(t.image), i = await W(o.bytes, e);
899
+ return r ? (await $(r, i), {
1122
900
  content: [
1123
901
  {
1124
902
  type: "text",
1125
- text: `Wrote ${n.byteLength}-byte redacted PNG to ${r} (${o.dimensions.width}×${o.dimensions.height}, ${e.length} region${e.length === 1 ? "" : "s"}).`
903
+ text: `Wrote ${i.byteLength}-byte redacted PNG to ${r} (${o.dimensions.width}×${o.dimensions.height}, ${e.length} region${e.length === 1 ? "" : "s"}).`
1126
904
  }
1127
905
  ]
1128
906
  }) : {
@@ -1130,9 +908,9 @@ async function Oe(t) {
1130
908
  {
1131
909
  type: "image",
1132
910
  data: Buffer.from(
1133
- n.buffer,
1134
- n.byteOffset,
1135
- n.byteLength
911
+ i.buffer,
912
+ i.byteOffset,
913
+ i.byteLength
1136
914
  ).toString("base64"),
1137
915
  mimeType: "image/png"
1138
916
  }
@@ -1145,8 +923,8 @@ async function Oe(t) {
1145
923
  };
1146
924
  }
1147
925
  }
1148
- const nt = "annot_redact_url", Se = {
1149
- name: nt,
926
+ const V = "annot_redact_url", oe = {
927
+ name: V,
1150
928
  description: "Open a URL in a headless browser, capture a screenshot, and destructively burn redactions over regions identified by locator strings or bboxes. Returns the redacted PNG inline unless `output` is specified.",
1151
929
  inputSchema: {
1152
930
  type: "object",
@@ -1176,8 +954,8 @@ const nt = "annot_redact_url", Se = {
1176
954
  output: { type: "string" }
1177
955
  },
1178
956
  $defs: {
1179
- ...R,
1180
- LocatorRedactRegion: Wt
957
+ ...O,
958
+ LocatorRedactRegion: Rt
1181
959
  }
1182
960
  }
1183
961
  };
@@ -1186,30 +964,30 @@ class g extends Error {
1186
964
  super(e), this.name = "InvalidRedactUrlInputError";
1187
965
  }
1188
966
  }
1189
- async function Ae(t, e) {
967
+ async function ne(t, e) {
1190
968
  try {
1191
- const r = Re(t), o = await H(e.pool, {
969
+ const r = ie(t), o = await k(e.pool, {
1192
970
  url: r.url,
1193
971
  viewport: r.viewport,
1194
972
  fullPage: r.fullPage,
1195
973
  waitFor: r.waitFor
1196
974
  });
1197
- let n;
975
+ let i;
1198
976
  try {
1199
- n = [];
1200
- for (const i of r.regions) {
1201
- const c = { bbox: await Te(o.handle.page, i) };
1202
- i.style !== void 0 && (c.style = i.style), i.color !== void 0 && (c.color = i.color), n.push(c);
977
+ i = [];
978
+ for (const n of r.regions) {
979
+ const c = { bbox: await ae(o.handle.page, n) };
980
+ n.style !== void 0 && (c.style = n.style), n.color !== void 0 && (c.color = n.color), i.push(c);
1203
981
  }
1204
982
  } finally {
1205
983
  await o.handle.close();
1206
984
  }
1207
- const s = await Q(o.pngBytes, n);
1208
- return r.output ? (await x(r.output, s), {
985
+ const a = await W(o.pngBytes, i);
986
+ return r.output ? (await $(r.output, a), {
1209
987
  content: [
1210
988
  {
1211
989
  type: "text",
1212
- text: `Wrote ${s.byteLength}-byte redacted PNG to ${r.output} (${r.regions.length} region${r.regions.length === 1 ? "" : "s"}, captured from ${r.url}).`
990
+ text: `Wrote ${a.byteLength}-byte redacted PNG to ${r.output} (${r.regions.length} region${r.regions.length === 1 ? "" : "s"}, captured from ${r.url}).`
1213
991
  }
1214
992
  ]
1215
993
  }) : {
@@ -1217,9 +995,9 @@ async function Ae(t, e) {
1217
995
  {
1218
996
  type: "image",
1219
997
  data: Buffer.from(
1220
- s.buffer,
1221
- s.byteOffset,
1222
- s.byteLength
998
+ a.buffer,
999
+ a.byteOffset,
1000
+ a.byteLength
1223
1001
  ).toString("base64"),
1224
1002
  mimeType: "image/png"
1225
1003
  }
@@ -1232,7 +1010,7 @@ async function Ae(t, e) {
1232
1010
  };
1233
1011
  }
1234
1012
  }
1235
- function Re(t) {
1013
+ function ie(t) {
1236
1014
  if (typeof t.url != "string" || t.url.length === 0)
1237
1015
  throw new g("`url` is required and must be a non-empty string.");
1238
1016
  if (!Array.isArray(t.regions))
@@ -1242,114 +1020,117 @@ function Re(t) {
1242
1020
  if (t.viewport !== void 0) {
1243
1021
  if (typeof t.viewport != "object" || t.viewport === null)
1244
1022
  throw new g("`viewport` must be an object when provided.");
1245
- const i = t.viewport, a = typeof i.width == "number" ? i.width : 1280, c = typeof i.height == "number" ? i.height : 800, l = typeof i.deviceScaleFactor == "number" ? i.deviceScaleFactor : 1;
1246
- r = { width: a, height: c, deviceScaleFactor: l };
1023
+ const n = t.viewport, s = typeof n.width == "number" ? n.width : 1280, c = typeof n.height == "number" ? n.height : 800, u = typeof n.deviceScaleFactor == "number" ? n.deviceScaleFactor : 1;
1024
+ r = { width: s, height: c, deviceScaleFactor: u };
1247
1025
  }
1248
- const o = t.fullPage === !0, n = t.waitFor === "domcontentloaded" || t.waitFor === "networkidle" ? t.waitFor : "load";
1249
- let s;
1026
+ const o = t.fullPage === !0, i = t.waitFor === "domcontentloaded" || t.waitFor === "networkidle" ? t.waitFor : "load";
1027
+ let a;
1250
1028
  if (t.output !== void 0) {
1251
1029
  if (typeof t.output != "string")
1252
1030
  throw new g("`output` must be a string when provided.");
1253
1031
  if (!w(t.output))
1254
1032
  throw new g(`\`output\` path "${t.output}" must be absolute.`);
1255
- s = t.output;
1033
+ a = t.output;
1256
1034
  }
1257
- return { url: t.url, regions: e, viewport: r, fullPage: o, waitFor: n, output: s };
1035
+ return { url: t.url, regions: e, viewport: r, fullPage: o, waitFor: i, output: a };
1258
1036
  }
1259
- async function Te(t, e) {
1037
+ async function ae(t, e) {
1260
1038
  if (e.bbox !== void 0) return e.bbox;
1261
1039
  if (e.locator !== void 0) return f(t, e.locator);
1262
1040
  throw new g("redact region requires either `bbox` or `locator`.");
1263
1041
  }
1264
- const ke = "annot-mcp", Ie = "0.1.0", _e = [
1265
- pe,
1266
- be,
1267
- Le,
1268
- Se,
1269
- Ee
1042
+ const se = "annot-mcp", ce = "0.1.0", ue = [
1043
+ Wt,
1044
+ Vt,
1045
+ ee,
1046
+ oe,
1047
+ Qt
1270
1048
  ];
1271
- function Be(t = {}) {
1272
- const e = new lt(
1049
+ function le(t = {}) {
1050
+ const e = new ot(
1273
1051
  {
1274
- name: ke,
1275
- version: t.version ?? Ie
1052
+ name: se,
1053
+ version: t.version ?? ce
1276
1054
  },
1277
1055
  {
1278
1056
  capabilities: {
1279
1057
  tools: {}
1280
1058
  }
1281
1059
  }
1282
- ), r = t.annotator ?? ct(t.annotatorOptions ?? {}), o = t.pool ?? yt();
1283
- return e.setRequestHandler(ut, async () => ({ tools: _e })), e.setRequestHandler(dt, async (n) => {
1284
- const { name: s, arguments: i } = n.params;
1285
- let a;
1286
- switch (s) {
1287
- case tt:
1288
- a = await me(i ?? {}, { annotator: r });
1060
+ ), r = t.annotator ?? tt(t.annotatorOptions ?? {}), o = t.pool ?? dt();
1061
+ return e.setRequestHandler(nt, async () => ({ tools: ue })), e.setRequestHandler(it, async (i) => {
1062
+ const { name: a, arguments: n } = i.params;
1063
+ let s;
1064
+ switch (a) {
1065
+ case j:
1066
+ s = await jt(n ?? {}, { annotator: r });
1289
1067
  break;
1290
- case et:
1291
- a = await $e(i ?? {}, { annotator: r, pool: o });
1068
+ case X:
1069
+ s = await Jt(n ?? {}, { annotator: r, pool: o });
1292
1070
  break;
1293
- case ot:
1294
- a = await Oe(i ?? {});
1071
+ case z:
1072
+ s = await re(n ?? {});
1295
1073
  break;
1296
- case nt:
1297
- a = await Ae(i ?? {}, { pool: o });
1074
+ case V:
1075
+ s = await ne(n ?? {}, { pool: o });
1298
1076
  break;
1299
- case rt:
1300
- a = await Pe(i ?? {}, { annotator: r });
1077
+ case Y:
1078
+ s = await te(n ?? {}, { annotator: r });
1301
1079
  break;
1302
1080
  default:
1303
- a = {
1304
- content: [{ type: "text", text: `Unknown tool: ${s}` }],
1081
+ s = {
1082
+ content: [{ type: "text", text: `Unknown tool: ${a}` }],
1305
1083
  isError: !0
1306
1084
  };
1307
1085
  }
1308
- return a;
1086
+ return s;
1309
1087
  }), e;
1310
1088
  }
1311
- async function Me() {
1312
- const t = Be(), e = new ft();
1089
+ async function be() {
1090
+ const t = le(), e = new at();
1313
1091
  await t.connect(e);
1314
1092
  }
1315
1093
  export {
1316
- tt as ANNOTATE_SCREENSHOT_TOOL_NAME,
1317
- et as ANNOTATE_URL_TOOL_NAME,
1318
- It as BBOX_ANNOTATION_SCHEMA,
1319
- qt as BBOX_REDACT_REGION_SCHEMA,
1320
- gt as BrowserPool,
1321
- rt as COMPARE_SCREENSHOTS_TOOL_NAME,
1322
- U as ChromiumUnavailableError,
1323
- Lt as DimensionMismatchError,
1094
+ j as ANNOTATE_SCREENSHOT_TOOL_NAME,
1095
+ X as ANNOTATE_URL_TOOL_NAME,
1096
+ Ee as BBOX_ANNOTATION_SCHEMA,
1097
+ xe as BBOX_REDACT_REGION_SCHEMA,
1098
+ lt as BrowserPool,
1099
+ Y as COMPARE_SCREENSHOTS_TOOL_NAME,
1100
+ C as ChromiumUnavailableError,
1101
+ bt as DimensionMismatchError,
1324
1102
  y as InvalidImageInputError,
1325
- $ as InvalidPngError,
1326
- Nt as LOCATOR_ANNOTATION_SCHEMA,
1327
- Wt as LOCATOR_REDACT_REGION_SCHEMA,
1103
+ v as InvalidPngError,
1104
+ Ot as LOCATOR_ANNOTATION_SCHEMA,
1105
+ Rt as LOCATOR_REDACT_REGION_SCHEMA,
1328
1106
  F as LocatorResolutionError,
1329
- ot as REDACT_SCREENSHOT_TOOL_NAME,
1330
- nt as REDACT_URL_TOOL_NAME,
1331
- R as SHARED_DEFS,
1332
- Et as aggregateDiffRegions,
1333
- pe as annotateScreenshotTool,
1334
- be as annotateUrlTool,
1335
- C as bboxAnnotationsToSvg,
1336
- Q as burnRedactions,
1337
- H as capturePage,
1338
- Ee as compareScreenshotsTool,
1339
- yt as createChromiumPool,
1340
- Be as createServer,
1341
- Ot as diffScreenshots,
1342
- me as handleAnnotateScreenshot,
1343
- $e as handleAnnotateUrl,
1344
- Pe as handleCompareScreenshots,
1345
- Oe as handleRedactScreenshot,
1346
- Ae as handleRedactUrl,
1347
- K as readPngDimensions,
1348
- Le as redactScreenshotTool,
1349
- Se as redactUrlTool,
1107
+ z as REDACT_SCREENSHOT_TOOL_NAME,
1108
+ V as REDACT_URL_TOOL_NAME,
1109
+ O as SHARED_DEFS,
1110
+ yt as aggregateDiffRegions,
1111
+ Wt as annotateScreenshotTool,
1112
+ Vt as annotateUrlTool,
1113
+ Le as arrowBetween,
1114
+ Pe as bboxAnnotationsToSvg,
1115
+ W as burnRedactions,
1116
+ k as capturePage,
1117
+ Qt as compareScreenshotsTool,
1118
+ dt as createChromiumPool,
1119
+ le as createServer,
1120
+ vt as diffScreenshots,
1121
+ jt as handleAnnotateScreenshot,
1122
+ Jt as handleAnnotateUrl,
1123
+ te as handleCompareScreenshots,
1124
+ re as handleRedactScreenshot,
1125
+ ne as handleRedactUrl,
1126
+ M as readPngDimensions,
1127
+ Ae as rectForBoundingBox,
1128
+ ee as redactScreenshotTool,
1129
+ oe as redactUrlTool,
1350
1130
  A as resolveImageInput,
1351
1131
  f as resolveLocator,
1352
- wt as resolveLocatorAnnotation,
1353
- bt as resolveLocatorAnnotations,
1354
- Me as runStdioServer
1132
+ ft as resolveLocatorAnnotation,
1133
+ ht as resolveLocatorAnnotations,
1134
+ be as runStdioServer,
1135
+ Oe as textAt
1355
1136
  };