@0x1f320.sh/why-did-you-render-mcp 1.0.0-dev.13 → 1.0.0-dev.14

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.
@@ -206,25 +206,34 @@ function buildOptions(opts) {
206
206
  });
207
207
  pendingBatch = null;
208
208
  }
209
- return { notifier(info) {
210
- const report = {
211
- displayName: info.displayName,
212
- reason: sanitizeReason(info.reason),
213
- hookName: info.hookName
214
- };
215
- if (pendingBatch && pendingBatch.commitId === commitId) pendingBatch.reports.push(report);
216
- else {
217
- if (pendingBatch) flushBatch();
218
- pendingBatch = {
219
- commitId,
220
- reports: [report]
209
+ return {
210
+ registerComponents(components) {
211
+ send({
212
+ type: "register",
213
+ projectId,
214
+ components
215
+ });
216
+ },
217
+ notifier(info) {
218
+ const report = {
219
+ displayName: info.displayName,
220
+ reason: sanitizeReason(info.reason),
221
+ hookName: info.hookName
221
222
  };
223
+ if (pendingBatch && pendingBatch.commitId === commitId) pendingBatch.reports.push(report);
224
+ else {
225
+ if (pendingBatch) flushBatch();
226
+ pendingBatch = {
227
+ commitId,
228
+ reports: [report]
229
+ };
230
+ }
231
+ if (!flushScheduled) {
232
+ flushScheduled = true;
233
+ queueMicrotask(flushBatch);
234
+ }
222
235
  }
223
- if (!flushScheduled) {
224
- flushScheduled = true;
225
- queueMicrotask(flushBatch);
226
- }
227
- } };
236
+ };
228
237
  }
229
238
  //#endregion
230
239
  exports.buildOptions = buildOptions;
@@ -7,6 +7,7 @@ interface ClientOptions {
7
7
  projectId?: string;
8
8
  }
9
9
  declare function buildOptions(opts?: ClientOptions): {
10
+ registerComponents(components: string[]): void;
10
11
  notifier(info: UpdateInfo): void;
11
12
  };
12
13
  //#endregion
@@ -7,6 +7,7 @@ interface ClientOptions {
7
7
  projectId?: string;
8
8
  }
9
9
  declare function buildOptions(opts?: ClientOptions): {
10
+ registerComponents(components: string[]): void;
10
11
  notifier(info: UpdateInfo): void;
11
12
  };
12
13
  //#endregion
@@ -205,25 +205,34 @@ function buildOptions(opts) {
205
205
  });
206
206
  pendingBatch = null;
207
207
  }
208
- return { notifier(info) {
209
- const report = {
210
- displayName: info.displayName,
211
- reason: sanitizeReason(info.reason),
212
- hookName: info.hookName
213
- };
214
- if (pendingBatch && pendingBatch.commitId === commitId) pendingBatch.reports.push(report);
215
- else {
216
- if (pendingBatch) flushBatch();
217
- pendingBatch = {
218
- commitId,
219
- reports: [report]
208
+ return {
209
+ registerComponents(components) {
210
+ send({
211
+ type: "register",
212
+ projectId,
213
+ components
214
+ });
215
+ },
216
+ notifier(info) {
217
+ const report = {
218
+ displayName: info.displayName,
219
+ reason: sanitizeReason(info.reason),
220
+ hookName: info.hookName
220
221
  };
222
+ if (pendingBatch && pendingBatch.commitId === commitId) pendingBatch.reports.push(report);
223
+ else {
224
+ if (pendingBatch) flushBatch();
225
+ pendingBatch = {
226
+ commitId,
227
+ reports: [report]
228
+ };
229
+ }
230
+ if (!flushScheduled) {
231
+ flushScheduled = true;
232
+ queueMicrotask(flushBatch);
233
+ }
221
234
  }
222
- if (!flushScheduled) {
223
- flushScheduled = true;
224
- queueMicrotask(flushBatch);
225
- }
226
- } };
235
+ };
227
236
  }
228
237
  //#endregion
229
238
  export { buildOptions };
@@ -130,6 +130,7 @@ var RenderStore = class {
130
130
  timers = /* @__PURE__ */ new Map();
131
131
  dicts = /* @__PURE__ */ new Map();
132
132
  bufferMeta = /* @__PURE__ */ new Map();
133
+ trackedComponents = /* @__PURE__ */ new Map();
133
134
  constructor(dir) {
134
135
  this.dir = dir ?? join(homedir(), ".wdyr-mcp", "renders");
135
136
  mkdirSync(this.dir, { recursive: true });
@@ -288,6 +289,21 @@ var RenderStore = class {
288
289
  }
289
290
  return summary;
290
291
  }
292
+ setTrackedComponents(components, projectId) {
293
+ this.trackedComponents.set(projectId, components);
294
+ }
295
+ getTrackedComponents(projectId) {
296
+ const result = {};
297
+ const projects = projectId ? [projectId] : this.getProjects();
298
+ for (const proj of projects) {
299
+ const observed = [...new Set(this.getAllRenders(proj).map((r) => r.displayName))];
300
+ result[proj] = {
301
+ registered: this.trackedComponents.get(proj) ?? [],
302
+ observed
303
+ };
304
+ }
305
+ return result;
306
+ }
291
307
  bufferKey(projectId, commitId) {
292
308
  return `${projectId}\0${commitId ?? NOCOMMIT}`;
293
309
  }
@@ -355,7 +371,7 @@ function textResult(text) {
355
371
  }
356
372
  //#endregion
357
373
  //#region src/server/tools/clear-renders.ts
358
- function register$5(server) {
374
+ function register$6(server) {
359
375
  server.registerTool("clear_renders", {
360
376
  title: "Clear Renders",
361
377
  description: "Clears collected render data. If multiple projects are active and no project is specified, the tool will ask you to disambiguate.",
@@ -369,7 +385,7 @@ function register$5(server) {
369
385
  }
370
386
  //#endregion
371
387
  //#region src/server/tools/get-commits.ts
372
- function register$4(server) {
388
+ function register$5(server) {
373
389
  server.registerTool("get_commits", {
374
390
  title: "Get Commits",
375
391
  description: "Returns a list of React commit IDs that have recorded render data for a project. Use these IDs with get_renders_by_commit to inspect individual commits.",
@@ -384,7 +400,7 @@ function register$4(server) {
384
400
  }
385
401
  //#endregion
386
402
  //#region src/server/tools/get-projects.ts
387
- function register$3(server) {
403
+ function register$4(server) {
388
404
  server.registerTool("get_projects", {
389
405
  title: "Get Projects",
390
406
  description: "Returns a list of project identifiers (browser origin URLs) that have recorded render data.",
@@ -397,7 +413,7 @@ function register$3(server) {
397
413
  }
398
414
  //#endregion
399
415
  //#region src/server/tools/get-render-summary.ts
400
- function register$2(server) {
416
+ function register$3(server) {
401
417
  server.registerTool("get_render_summary", {
402
418
  title: "Get Render Summary",
403
419
  description: "Returns a summary of re-renders grouped by component name with counts. Use groupBy: 'commit' to get per-commit breakdowns instead of a single aggregate. If multiple projects are active and no project is specified, the tool will ask you to disambiguate.",
@@ -440,7 +456,7 @@ function commitSummary(projectId) {
440
456
  }
441
457
  //#endregion
442
458
  //#region src/server/tools/get-renders-by-commit.ts
443
- function register$1(server) {
459
+ function register$2(server) {
444
460
  server.registerTool("get_renders_by_commit", {
445
461
  title: "Get Renders by Commit",
446
462
  description: "Returns all re-renders for a specific React commit ID. Use get_commits first to discover available commit IDs.",
@@ -460,7 +476,7 @@ function register$1(server) {
460
476
  }
461
477
  //#endregion
462
478
  //#region src/server/tools/get-renders.ts
463
- function register(server) {
479
+ function register$1(server) {
464
480
  server.registerTool("get_renders", {
465
481
  title: "Get Renders",
466
482
  description: "Returns all re-renders collected from the browser. If multiple projects are active and no project is specified, the tool will ask you to disambiguate by asking the user for their dev server URL.",
@@ -477,14 +493,43 @@ function register(server) {
477
493
  });
478
494
  }
479
495
  //#endregion
496
+ //#region src/server/tools/get-tracked-components.ts
497
+ function register(server) {
498
+ server.registerTool("get_tracked_components", {
499
+ title: "Get Tracked Components",
500
+ description: "Returns the list of components being tracked by why-did-you-render. Shows both explicitly registered components (sent by the client) and components observed in render data. If multiple projects are active and no project is specified, the tool will ask you to disambiguate.",
501
+ inputSchema: { project: z.string().optional().describe("Project identifier (the browser's origin URL, e.g. http://localhost:3000). Omit to auto-detect.") }
502
+ }, async ({ project }) => {
503
+ const resolved = resolveProject(project);
504
+ if (resolved.error) return textResult(resolved.error);
505
+ const tracked = store.getTrackedComponents(resolved.projectId);
506
+ if (Object.keys(tracked).length === 0) return textResult("No tracked components found. Make sure the browser is connected and triggering re-renders.");
507
+ const lines = [];
508
+ for (const [proj, { registered, observed }] of Object.entries(tracked)) {
509
+ lines.push(`[${proj}]`);
510
+ if (registered.length > 0) {
511
+ lines.push(" Registered:");
512
+ for (const name of registered) lines.push(` - ${name}`);
513
+ }
514
+ if (observed.length > 0) {
515
+ lines.push(" Observed in renders:");
516
+ for (const name of observed) lines.push(` - ${name}`);
517
+ }
518
+ if (registered.length === 0 && observed.length === 0) lines.push(" No components tracked yet.");
519
+ }
520
+ return textResult(lines.join("\n"));
521
+ });
522
+ }
523
+ //#endregion
480
524
  //#region src/server/tools/index.ts
481
525
  function registerTools(server) {
482
- register(server);
483
- register$2(server);
484
- register$4(server);
485
526
  register$1(server);
486
527
  register$3(server);
487
528
  register$5(server);
529
+ register$2(server);
530
+ register$4(server);
531
+ register(server);
532
+ register$6(server);
488
533
  }
489
534
  //#endregion
490
535
  //#region src/server/liveness.ts
@@ -563,6 +608,7 @@ function createWsServer(port) {
563
608
  heartbeat.setProjectId(ws, projectId);
564
609
  if (msg.type === "render") store.addRender(msg.payload, projectId, msg.commitId);
565
610
  else if (msg.type === "render-batch") for (const report of msg.payload) store.addRender(report, projectId, msg.commitId);
611
+ else if (msg.type === "register") store.setTrackedComponents(msg.components, projectId);
566
612
  } catch {
567
613
  console.error("[wdyr-mcp] invalid message received");
568
614
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0x1f320.sh/why-did-you-render-mcp",
3
- "version": "1.0.0-dev.13",
3
+ "version": "1.0.0-dev.14",
4
4
  "type": "module",
5
5
  "description": "MCP server that collects why-did-you-render data from browser and exposes it to coding agents",
6
6
  "license": "MIT",