@xiaou66/vite-plugin-vue-mcp-next 0.0.5 → 0.0.7

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.cjs CHANGED
@@ -54,8 +54,10 @@ var DEFAULT_MASK_HEADERS = [
54
54
  // src/constants.ts
55
55
  var DEFAULT_MCP_PATH = "/__mcp";
56
56
  var DEFAULT_SCREENSHOT_MAX_BYTES = 5 * 1024 * 1024;
57
+ var DEFAULT_SCREENSHOT_SAVE_DIR = ".vite-mcp/screenshot";
57
58
  var MCP_TOOL_NAMES = {
58
59
  listPages: "list_pages",
60
+ reloadPage: "reload_page",
59
61
  getPageState: "get_page_state",
60
62
  getDomTree: "get_dom_tree",
61
63
  queryDom: "query_dom",
@@ -78,7 +80,10 @@ var VIRTUAL_RUNTIME_ID = "virtual:vite-plugin-vue-mcp-next/runtime";
78
80
  var RESOLVED_VIRTUAL_RUNTIME_ID = `\0${VIRTUAL_RUNTIME_ID}`;
79
81
  var VIRTUAL_SCREENSHOT_CONFIG_ID = "virtual:vite-plugin-vue-mcp-next/screenshot-config";
80
82
  var RESOLVED_VIRTUAL_SCREENSHOT_CONFIG_ID = `\0${VIRTUAL_SCREENSHOT_CONFIG_ID}`;
83
+ var VIRTUAL_SNAPDOM_LOADER_ID = "virtual:vite-plugin-vue-mcp-next/snapdom-loader";
84
+ var RESOLVED_VIRTUAL_SNAPDOM_LOADER_ID = `\0${VIRTUAL_SNAPDOM_LOADER_ID}`;
81
85
  var DEFAULT_MCP_CLIENT_SERVER_NAME = "vue-mcp-next";
86
+ var RUNTIME_PAGE_RECONNECTED_EVENT = "vite-plugin-vue-mcp-next:page-reconnected";
82
87
  var DEFAULT_OPTIONS = {
83
88
  mcpPath: DEFAULT_MCP_PATH,
84
89
  host: "localhost",
@@ -119,6 +124,8 @@ var DEFAULT_OPTIONS = {
119
124
  maxRecords: DEFAULT_CONSOLE_MAX_RECORDS
120
125
  },
121
126
  screenshot: {
127
+ type: "path",
128
+ saveDir: DEFAULT_SCREENSHOT_SAVE_DIR,
122
129
  prefer: "auto",
123
130
  maxBytes: DEFAULT_SCREENSHOT_MAX_BYTES,
124
131
  snapdom: {
@@ -648,6 +655,9 @@ function registerNetworkTools(server, ctx) {
648
655
  );
649
656
  }
650
657
 
658
+ // src/mcp/tools/pages.ts
659
+ var import_zod5 = require("zod");
660
+
651
661
  // src/plugin/entryDiscovery.ts
652
662
  var import_node_fs = __toESM(require("fs"), 1);
653
663
  var import_node_path = __toESM(require("path"), 1);
@@ -699,6 +709,118 @@ function registerPageTools(server, ctx, vite) {
699
709
  });
700
710
  }
701
711
  );
712
+ server.registerTool(
713
+ MCP_TOOL_NAMES.reloadPage,
714
+ {
715
+ description: "Reload the selected page. CDP uses ignoreCache; Runtime Hook falls back to normal reload.",
716
+ inputSchema: {
717
+ pageId: import_zod5.z.string().optional(),
718
+ ignoreCache: import_zod5.z.boolean().optional()
719
+ }
720
+ },
721
+ async (input) => {
722
+ if (hasCdpConfig(ctx)) {
723
+ return reloadPageWithCdp(ctx, input.pageId, input.ignoreCache ?? true);
724
+ }
725
+ const target = resolveRuntimeReloadTarget(ctx, input.pageId);
726
+ if (!target.ok) {
727
+ return createToolError(target.error);
728
+ }
729
+ const reconnect = waitForRuntimePageReconnect(ctx);
730
+ ctx.pages.disconnect(target.page.pageId);
731
+ const result = await requestRuntimeData(ctx, (event) => {
732
+ void ctx.rpcServer?.reloadPage({ event });
733
+ });
734
+ if (!isRecord(result) || result.ok === false) {
735
+ reconnect.cancel();
736
+ return createToolResponse(
737
+ isRecord(result) ? result : { ok: false, error: "Invalid runtime reload response" }
738
+ );
739
+ }
740
+ const page = await reconnect.promise;
741
+ return createToolResponse(
742
+ page ? { ...result, reconnected: true, pageId: page.pageId, page } : {
743
+ ...result,
744
+ reconnected: false,
745
+ error: "runtime page reconnect timed out"
746
+ }
747
+ );
748
+ }
749
+ );
750
+ }
751
+ function hasCdpConfig(ctx) {
752
+ return Boolean(ctx.options.cdp.browserUrl || ctx.options.cdp.wsEndpoint);
753
+ }
754
+ function isRecord(value) {
755
+ return typeof value === "object" && value !== null && !Array.isArray(value);
756
+ }
757
+ function resolveRuntimeReloadTarget(ctx, pageId) {
758
+ try {
759
+ const page = resolvePageTarget(ctx, pageId);
760
+ if (page.source !== "runtime") {
761
+ return {
762
+ ok: false,
763
+ error: "Runtime reload requires a runtime page target"
764
+ };
765
+ }
766
+ return { ok: true, page };
767
+ } catch (error) {
768
+ return {
769
+ ok: false,
770
+ error: error instanceof Error ? error.message : String(error)
771
+ };
772
+ }
773
+ }
774
+ function waitForRuntimePageReconnect(ctx) {
775
+ let timeout;
776
+ let cleanup;
777
+ const promise = new Promise((resolve) => {
778
+ timeout = setTimeout(() => {
779
+ cleanup?.();
780
+ resolve(null);
781
+ }, 5e3);
782
+ cleanup = ctx.hooks.hookOnce(RUNTIME_PAGE_RECONNECTED_EVENT, (payload) => {
783
+ if (timeout) {
784
+ clearTimeout(timeout);
785
+ }
786
+ resolve(isPageTarget(payload) ? payload : null);
787
+ });
788
+ });
789
+ return {
790
+ promise,
791
+ cancel() {
792
+ if (timeout) {
793
+ clearTimeout(timeout);
794
+ }
795
+ cleanup?.();
796
+ }
797
+ };
798
+ }
799
+ function isPageTarget(value) {
800
+ if (!isRecord(value)) {
801
+ return false;
802
+ }
803
+ return typeof value.pageId === "string" && (value.source === "runtime" || value.source === "cdp") && typeof value.url === "string" && typeof value.pathname === "string" && typeof value.connected === "boolean";
804
+ }
805
+ async function reloadPageWithCdp(ctx, pageId, ignoreCache) {
806
+ const cdp = await connectCdpForPage(ctx, pageId);
807
+ if (!cdp) {
808
+ return createToolError("CDP target is unavailable for page reload");
809
+ }
810
+ try {
811
+ await cdp.client.Page.enable();
812
+ const loaded = cdp.client.Page.loadEventFired();
813
+ await cdp.client.Page.reload({ ignoreCache });
814
+ await loaded;
815
+ return createToolResponse({
816
+ ok: true,
817
+ source: "cdp",
818
+ ignoreCache,
819
+ pageId
820
+ });
821
+ } finally {
822
+ await closeCdpClient(cdp.client);
823
+ }
702
824
  }
703
825
  async function listCdpPageTargets(ctx) {
704
826
  if (ctx.options.cdp.wsEndpoint) {
@@ -745,7 +867,7 @@ function getPathname(url) {
745
867
  }
746
868
 
747
869
  // src/mcp/tools/screenshot.ts
748
- var import_zod5 = require("zod");
870
+ var import_zod6 = require("zod");
749
871
 
750
872
  // src/cdp/cdpScreenshot.ts
751
873
  async function cdpCaptureScreenshot(options) {
@@ -849,18 +971,70 @@ function isElementRect(value) {
849
971
  return typeof rect.x === "number" && typeof rect.y === "number" && typeof rect.width === "number" && rect.width > 0 && typeof rect.height === "number" && rect.height > 0;
850
972
  }
851
973
 
974
+ // src/mcp/tools/screenshotOutput.ts
975
+ var import_node_crypto = require("crypto");
976
+ var import_promises = require("fs/promises");
977
+ var import_node_path2 = __toESM(require("path"), 1);
978
+ async function createScreenshotOutput(ctx, payload) {
979
+ if (ctx.options.screenshot.type === "base64") {
980
+ return payload;
981
+ }
982
+ const saveDir = resolveScreenshotSaveDir(ctx);
983
+ await (0, import_promises.mkdir)(saveDir, { recursive: true });
984
+ const filePath = import_node_path2.default.join(saveDir, createScreenshotFileName(payload));
985
+ await (0, import_promises.writeFile)(filePath, Buffer.from(payload.data, "base64"));
986
+ return {
987
+ source: payload.source,
988
+ target: payload.target,
989
+ format: payload.format,
990
+ width: payload.width,
991
+ height: payload.height,
992
+ mimeType: payload.mimeType,
993
+ byteLength: payload.byteLength,
994
+ limitations: payload.limitations,
995
+ path: filePath,
996
+ relativePath: createProjectRelativePath(ctx, filePath)
997
+ };
998
+ }
999
+ function resolveScreenshotSaveDir(ctx) {
1000
+ const saveDir = ctx.options.screenshot.saveDir.trim();
1001
+ if (!saveDir) {
1002
+ throw new Error("screenshot.saveDir must be a non-empty string");
1003
+ }
1004
+ const root = ctx.server?.config.root;
1005
+ if (!root) {
1006
+ throw new Error("Vite server root is required for screenshot path output");
1007
+ }
1008
+ if (import_node_path2.default.isAbsolute(saveDir)) {
1009
+ return saveDir;
1010
+ }
1011
+ return import_node_path2.default.resolve(root, saveDir);
1012
+ }
1013
+ function createScreenshotFileName(payload) {
1014
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
1015
+ const suffix = (0, import_node_crypto.randomUUID)().slice(0, 8);
1016
+ return `${timestamp}-${payload.source}-${payload.target}-${suffix}.${payload.format}`;
1017
+ }
1018
+ function createProjectRelativePath(ctx, filePath) {
1019
+ const root = ctx.server?.config.root;
1020
+ if (!root) {
1021
+ throw new Error("Vite server root is required for screenshot path output");
1022
+ }
1023
+ return import_node_path2.default.relative(root, filePath).split(import_node_path2.default.sep).join("/");
1024
+ }
1025
+
852
1026
  // src/mcp/tools/screenshot.ts
853
1027
  var DEFAULT_SCREENSHOT_TARGET = "viewport";
854
1028
  var DEFAULT_SCREENSHOT_FORMAT = "png";
855
1029
  var screenshotInputSchema = {
856
- pageId: import_zod5.z.string().optional(),
857
- target: import_zod5.z.enum(["viewport", "fullPage", "element"]).optional(),
858
- selector: import_zod5.z.string().optional(),
859
- format: import_zod5.z.enum(["png", "jpeg", "webp"]).optional(),
860
- prefer: import_zod5.z.enum(["auto", "cdp", "runtime"]).optional(),
861
- quality: import_zod5.z.number().optional(),
862
- scale: import_zod5.z.number().optional(),
863
- snapdom: import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()).optional()
1030
+ pageId: import_zod6.z.string().optional(),
1031
+ target: import_zod6.z.enum(["viewport", "fullPage", "element"]).optional(),
1032
+ selector: import_zod6.z.string().optional(),
1033
+ format: import_zod6.z.enum(["png", "jpeg", "webp"]).optional(),
1034
+ prefer: import_zod6.z.enum(["auto", "cdp", "runtime"]).optional(),
1035
+ quality: import_zod6.z.number().optional(),
1036
+ scale: import_zod6.z.number().optional(),
1037
+ snapdom: import_zod6.z.record(import_zod6.z.string(), import_zod6.z.unknown()).optional()
864
1038
  };
865
1039
  function registerScreenshotTools(server, ctx) {
866
1040
  server.registerTool(
@@ -890,7 +1064,7 @@ async function handleTakeScreenshot(ctx, input) {
890
1064
  format,
891
1065
  quality: input.quality
892
1066
  });
893
- return createScreenshotResponse(ctx, {
1067
+ return await createScreenshotResponse(ctx, {
894
1068
  source: "cdp",
895
1069
  target,
896
1070
  format,
@@ -936,15 +1110,30 @@ async function createRuntimeScreenshot(ctx, input, normalized) {
936
1110
  if (!isPlainRecord(result)) {
937
1111
  return createToolError("runtime screenshot returned an invalid response");
938
1112
  }
939
- return createToolResponse(result);
1113
+ if (result.ok === false) {
1114
+ return createToolResponse(result);
1115
+ }
1116
+ if (!isScreenshotImagePayload(result)) {
1117
+ return createToolError("runtime screenshot returned an invalid response");
1118
+ }
1119
+ return createScreenshotResponse(ctx, {
1120
+ ...result,
1121
+ target: normalized.target,
1122
+ format: normalized.format
1123
+ });
940
1124
  }
941
- function createScreenshotResponse(ctx, result) {
1125
+ async function createScreenshotResponse(ctx, result) {
942
1126
  if (result.byteLength > ctx.options.screenshot.maxBytes) {
943
1127
  return createToolError(
944
1128
  `screenshot is too large: ${String(result.byteLength)} bytes`
945
1129
  );
946
1130
  }
947
- return createToolResponse(result);
1131
+ try {
1132
+ return createToolResponse(await createScreenshotOutput(ctx, result));
1133
+ } catch (error) {
1134
+ const message = error instanceof Error ? error.message : String(error);
1135
+ return createToolError(`failed to create screenshot output: ${message}`);
1136
+ }
948
1137
  }
949
1138
  function isScreenshotTooLarge(ctx, result) {
950
1139
  return isPlainRecord(result) && "byteLength" in result && typeof result.byteLength === "number" && result.byteLength > ctx.options.screenshot.maxBytes;
@@ -959,10 +1148,13 @@ function getBase64ByteLength(data) {
959
1148
  const padding = data.endsWith("==") ? 2 : data.endsWith("=") ? 1 : 0;
960
1149
  return Math.ceil(data.length * 3 / 4) - padding;
961
1150
  }
1151
+ function isScreenshotImagePayload(result) {
1152
+ return (result.source === "cdp" || result.source === "snapdom") && typeof result.data === "string" && typeof result.width === "number" && typeof result.height === "number" && typeof result.mimeType === "string" && typeof result.byteLength === "number";
1153
+ }
962
1154
 
963
1155
  // src/mcp/tools/vue.ts
964
1156
  var import_nanoid2 = require("nanoid");
965
- var import_zod6 = require("zod");
1157
+ var import_zod7 = require("zod");
966
1158
  function registerVueTools(server, ctx) {
967
1159
  server.registerTool(
968
1160
  MCP_TOOL_NAMES.getComponentTree,
@@ -975,7 +1167,7 @@ function registerVueTools(server, ctx) {
975
1167
  MCP_TOOL_NAMES.getComponentState,
976
1168
  {
977
1169
  description: "Get Vue component state.",
978
- inputSchema: { componentName: import_zod6.z.string() }
1170
+ inputSchema: { componentName: import_zod7.z.string() }
979
1171
  },
980
1172
  async ({ componentName }) => requestVueData(ctx, (event) => {
981
1173
  void ctx.rpcServer?.getInspectorState({ event, componentName });
@@ -986,19 +1178,19 @@ function registerVueTools(server, ctx) {
986
1178
  {
987
1179
  description: "Edit Vue component state.",
988
1180
  inputSchema: {
989
- componentName: import_zod6.z.string(),
990
- path: import_zod6.z.array(import_zod6.z.string()),
991
- value: import_zod6.z.string(),
992
- valueType: import_zod6.z.enum(["string", "number", "boolean", "object", "array"])
1181
+ componentName: import_zod7.z.string(),
1182
+ path: import_zod7.z.array(import_zod7.z.string()),
1183
+ value: import_zod7.z.string(),
1184
+ valueType: import_zod7.z.enum(["string", "number", "boolean", "object", "array"])
993
1185
  }
994
1186
  },
995
- ({ componentName, path: path5, value, valueType }) => {
1187
+ ({ componentName, path: path6, value, valueType }) => {
996
1188
  if (!ctx.rpcServer) {
997
1189
  return vueBridgeUnavailable();
998
1190
  }
999
1191
  void ctx.rpcServer.editComponentState({
1000
1192
  componentName,
1001
- path: path5,
1193
+ path: path6,
1002
1194
  value,
1003
1195
  valueType
1004
1196
  });
@@ -1009,7 +1201,7 @@ function registerVueTools(server, ctx) {
1009
1201
  MCP_TOOL_NAMES.highlightComponent,
1010
1202
  {
1011
1203
  description: "Highlight a Vue component.",
1012
- inputSchema: { componentName: import_zod6.z.string() }
1204
+ inputSchema: { componentName: import_zod7.z.string() }
1013
1205
  },
1014
1206
  ({ componentName }) => {
1015
1207
  if (!ctx.rpcServer) {
@@ -1037,7 +1229,7 @@ function registerVueTools(server, ctx) {
1037
1229
  MCP_TOOL_NAMES.getPiniaState,
1038
1230
  {
1039
1231
  description: "Get Pinia store state.",
1040
- inputSchema: { storeName: import_zod6.z.string() }
1232
+ inputSchema: { storeName: import_zod7.z.string() }
1041
1233
  },
1042
1234
  async ({ storeName }) => requestVueData(ctx, (event) => {
1043
1235
  void ctx.rpcServer?.getPiniaState({ event, storeName });
@@ -1159,6 +1351,10 @@ function createServerVueRuntimeRpc(ctx) {
1159
1351
  onDomQueryUpdated: (event, data) => {
1160
1352
  void ctx.hooks.callHook(event, data);
1161
1353
  },
1354
+ reloadPage: () => void 0,
1355
+ onPageReloaded: (event, data) => {
1356
+ void ctx.hooks.callHook(event, data);
1357
+ },
1162
1358
  evaluateScript: () => void 0,
1163
1359
  onEvaluateScriptUpdated: (event, data) => {
1164
1360
  void ctx.hooks.callHook(event, data);
@@ -1452,6 +1648,8 @@ async function startCdpObservers(ctx, target, client) {
1452
1648
  }
1453
1649
 
1454
1650
  // src/plugin/injectRuntime.ts
1651
+ var import_node_module = require("module");
1652
+ var import_node_path3 = require("path");
1455
1653
  function createRuntimeInjectionController(options, getConfig) {
1456
1654
  return {
1457
1655
  resolveId(importee) {
@@ -1461,15 +1659,21 @@ function createRuntimeInjectionController(options, getConfig) {
1461
1659
  if (importee === VIRTUAL_SCREENSHOT_CONFIG_ID) {
1462
1660
  return RESOLVED_VIRTUAL_SCREENSHOT_CONFIG_ID;
1463
1661
  }
1662
+ if (importee === VIRTUAL_SNAPDOM_LOADER_ID) {
1663
+ return RESOLVED_VIRTUAL_SNAPDOM_LOADER_ID;
1664
+ }
1464
1665
  return void 0;
1465
1666
  },
1466
1667
  load(id) {
1467
1668
  if (id === RESOLVED_VIRTUAL_RUNTIME_ID) {
1468
- return "import { startRuntimeClient } from '@xiaou66/vite-plugin-vue-mcp-next/runtime/client';\nvoid startRuntimeClient();";
1669
+ return createRuntimeModule();
1469
1670
  }
1470
1671
  if (id === RESOLVED_VIRTUAL_SCREENSHOT_CONFIG_ID) {
1471
1672
  return createScreenshotConfigModule(options);
1472
1673
  }
1674
+ if (id === RESOLVED_VIRTUAL_SNAPDOM_LOADER_ID) {
1675
+ return createSnapdomLoaderModule(getConfig()?.root);
1676
+ }
1473
1677
  return void 0;
1474
1678
  },
1475
1679
  transformIndexHtml(html) {
@@ -1505,6 +1709,41 @@ ${code}`;
1505
1709
  }
1506
1710
  };
1507
1711
  }
1712
+ function createRuntimeModule() {
1713
+ return [
1714
+ "import { setScreenshotModuleRegistry, setSnapdomLoader, startRuntimeClient } from '@xiaou66/vite-plugin-vue-mcp-next/runtime/client';",
1715
+ `import { screenshotModuleRegistry } from '${VIRTUAL_SCREENSHOT_CONFIG_ID}';`,
1716
+ `import { loadSnapdom } from '${VIRTUAL_SNAPDOM_LOADER_ID}';`,
1717
+ "setScreenshotModuleRegistry(screenshotModuleRegistry);",
1718
+ "setSnapdomLoader(loadSnapdom);",
1719
+ "void startRuntimeClient();"
1720
+ ].join("\n");
1721
+ }
1722
+ function createSnapdomLoaderModule(root) {
1723
+ if (!canResolveSnapdomFromProject(root)) {
1724
+ return [
1725
+ "export const loadSnapdom = () =>",
1726
+ ` Promise.reject(new Error(${JSON.stringify(createMissingSnapdomMessage())}));`
1727
+ ].join("\n");
1728
+ }
1729
+ return [
1730
+ "import { snapdom } from '@zumer/snapdom';",
1731
+ "export const loadSnapdom = () => Promise.resolve({ snapdom });"
1732
+ ].join("\n");
1733
+ }
1734
+ function canResolveSnapdomFromProject(root) {
1735
+ try {
1736
+ (0, import_node_module.createRequire)((0, import_node_path3.join)(root ?? process.cwd(), "package.json")).resolve(
1737
+ "@zumer/snapdom"
1738
+ );
1739
+ return true;
1740
+ } catch {
1741
+ return false;
1742
+ }
1743
+ }
1744
+ function createMissingSnapdomMessage() {
1745
+ return "\u7F3A\u5C11\u53EF\u9009\u4F9D\u8D56 @zumer/snapdom\u3002DOM \u622A\u56FE\u964D\u7EA7\u9700\u8981\u8BE5\u4F9D\u8D56\uFF0C\u8BF7\u6267\u884C\uFF1Apnpm add -D @zumer/snapdom";
1746
+ }
1508
1747
  function createScreenshotConfigModule(options) {
1509
1748
  const paths = collectScreenshotImportPaths(options);
1510
1749
  const imports = paths.map((item, index) => `import * as m${String(index)} from ${JSON.stringify(item)};`).join("\n");
@@ -1533,17 +1772,17 @@ function getPluginPath(plugin) {
1533
1772
  }
1534
1773
 
1535
1774
  // src/plugin/mcpClientConfig/index.ts
1536
- var import_node_path4 = __toESM(require("path"), 1);
1775
+ var import_node_path6 = __toESM(require("path"), 1);
1537
1776
 
1538
1777
  // src/plugin/mcpClientConfig/codexConfig.ts
1539
- var import_promises = __toESM(require("fs/promises"), 1);
1540
- var import_node_path2 = __toESM(require("path"), 1);
1778
+ var import_promises2 = __toESM(require("fs/promises"), 1);
1779
+ var import_node_path4 = __toESM(require("path"), 1);
1541
1780
  async function updateCodexMcpClientConfig(options) {
1542
1781
  try {
1543
1782
  const current = await readOptionalTextFile(options.configPath);
1544
1783
  const next = replaceOrAppendOwnedBlock(current, options);
1545
- await import_promises.default.mkdir(import_node_path2.default.dirname(options.configPath), { recursive: true });
1546
- await import_promises.default.writeFile(options.configPath, next);
1784
+ await import_promises2.default.mkdir(import_node_path4.default.dirname(options.configPath), { recursive: true });
1785
+ await import_promises2.default.writeFile(options.configPath, next);
1547
1786
  } catch (error) {
1548
1787
  console.warn(
1549
1788
  `[vite-plugin-vue-mcp-next] Failed to update Codex MCP config at ${options.configPath}: ${formatError(error)}`
@@ -1585,7 +1824,7 @@ function quoteTomlString(value) {
1585
1824
  }
1586
1825
  async function readOptionalTextFile(filePath) {
1587
1826
  try {
1588
- return await import_promises.default.readFile(filePath, "utf-8");
1827
+ return await import_promises2.default.readFile(filePath, "utf-8");
1589
1828
  } catch (error) {
1590
1829
  if (isNodeError(error) && error.code === "ENOENT") {
1591
1830
  return "";
@@ -1611,8 +1850,8 @@ function isNodeError(error) {
1611
1850
  }
1612
1851
 
1613
1852
  // src/plugin/mcpClientConfig/jsonConfig.ts
1614
- var import_promises2 = __toESM(require("fs/promises"), 1);
1615
- var import_node_path3 = __toESM(require("path"), 1);
1853
+ var import_promises3 = __toESM(require("fs/promises"), 1);
1854
+ var import_node_path5 = __toESM(require("path"), 1);
1616
1855
  async function updateJsonMcpClientConfig(options) {
1617
1856
  try {
1618
1857
  const config = await readJsonConfig(options.configPath);
@@ -1626,8 +1865,8 @@ async function updateJsonMcpClientConfig(options) {
1626
1865
  }
1627
1866
  mcpServers[options.serverName] = { type: "sse", url: options.mcpUrl };
1628
1867
  config.mcpServers = mcpServers;
1629
- await import_promises2.default.mkdir(import_node_path3.default.dirname(options.configPath), { recursive: true });
1630
- await import_promises2.default.writeFile(
1868
+ await import_promises3.default.mkdir(import_node_path5.default.dirname(options.configPath), { recursive: true });
1869
+ await import_promises3.default.writeFile(
1631
1870
  options.configPath,
1632
1871
  `${JSON.stringify(config, null, 2)}
1633
1872
  `
@@ -1645,7 +1884,7 @@ async function readJsonConfig(configPath) {
1645
1884
  }
1646
1885
  async function readOptionalTextFile2(filePath) {
1647
1886
  try {
1648
- return await import_promises2.default.readFile(filePath, "utf-8");
1887
+ return await import_promises3.default.readFile(filePath, "utf-8");
1649
1888
  } catch (error) {
1650
1889
  if (isNodeError2(error) && error.code === "ENOENT") {
1651
1890
  return "{}";
@@ -1676,7 +1915,7 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
1676
1915
  jobs.push(
1677
1916
  updateJsonMcpClientConfig({
1678
1917
  clientName: "Cursor",
1679
- configPath: import_node_path4.default.join(root, ".cursor", "mcp.json"),
1918
+ configPath: import_node_path6.default.join(root, ".cursor", "mcp.json"),
1680
1919
  mcpUrl: sseUrl,
1681
1920
  serverName
1682
1921
  })
@@ -1685,7 +1924,7 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
1685
1924
  if (options.codex) {
1686
1925
  jobs.push(
1687
1926
  updateCodexMcpClientConfig({
1688
- configPath: import_node_path4.default.join(root, ".codex", "config.toml"),
1927
+ configPath: import_node_path6.default.join(root, ".codex", "config.toml"),
1689
1928
  mcpUrl: streamableHttpUrl,
1690
1929
  serverName
1691
1930
  })
@@ -1695,7 +1934,7 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
1695
1934
  jobs.push(
1696
1935
  updateJsonMcpClientConfig({
1697
1936
  clientName: "Claude Code",
1698
- configPath: import_node_path4.default.join(root, ".mcp.json"),
1937
+ configPath: import_node_path6.default.join(root, ".mcp.json"),
1699
1938
  mcpUrl: sseUrl,
1700
1939
  serverName
1701
1940
  })
@@ -1705,7 +1944,7 @@ async function updateMcpClientConfigs(root, sseUrl, streamableHttpUrl, options)
1705
1944
  jobs.push(
1706
1945
  updateJsonMcpClientConfig({
1707
1946
  clientName: "Trae",
1708
- configPath: import_node_path4.default.join(root, ".trae", "mcp.json"),
1947
+ configPath: import_node_path6.default.join(root, ".trae", "mcp.json"),
1709
1948
  mcpUrl: sseUrl,
1710
1949
  serverName
1711
1950
  })
@@ -1752,6 +1991,7 @@ function vueMcpNext(userOptions = {}) {
1752
1991
  (payload) => {
1753
1992
  if (isRuntimePageTarget(payload)) {
1754
1993
  ctx.pages.upsert(payload);
1994
+ void ctx.hooks.callHook(RUNTIME_PAGE_RECONNECTED_EVENT, payload);
1755
1995
  void cdpLifecycle.connectPage(payload);
1756
1996
  }
1757
1997
  }