@xiaou66/vite-plugin-vue-mcp-next 1.1.0 → 1.2.0

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
@@ -35,6 +35,11 @@ var MCP_TOOL_NAMES = {
35
35
  getNetworkRequests: "get_network_requests",
36
36
  getNetworkRequestDetail: "get_network_request_detail",
37
37
  clearNetworkRequests: "clear_network_requests",
38
+ listStorage: "list_storage",
39
+ getStorageItem: "get_storage_item",
40
+ setStorageItem: "set_storage_item",
41
+ deleteStorageItem: "delete_storage_item",
42
+ clearStorage: "clear_storage",
38
43
  recordPerformance: "record_performance",
39
44
  startPerformanceRecording: "start_performance_recording",
40
45
  stopPerformanceRecording: "stop_performance_recording",
@@ -1506,9 +1511,431 @@ function getPathname(url) {
1506
1511
  }
1507
1512
  }
1508
1513
 
1509
- // src/mcp/tools/screenshot.ts
1514
+ // src/mcp/tools/storage.ts
1510
1515
  import { z as z7 } from "zod";
1511
1516
 
1517
+ // src/cdp/cdpStorage.ts
1518
+ function createCdpStorageAdapter(client) {
1519
+ return {
1520
+ async manageStorage(request) {
1521
+ try {
1522
+ return await manageCdpStorage(client, request);
1523
+ } catch (error) {
1524
+ return createCdpStorageError(
1525
+ request,
1526
+ error instanceof Error ? error.message : String(error)
1527
+ );
1528
+ }
1529
+ }
1530
+ };
1531
+ }
1532
+ async function manageCdpStorage(client, request) {
1533
+ if (request.scope === "cookie") {
1534
+ return manageCdpCookies(client, request);
1535
+ }
1536
+ if (request.scope === "indexedDB") {
1537
+ return manageCdpIndexedDb(client, request);
1538
+ }
1539
+ return manageCdpDomStorage(client, request);
1540
+ }
1541
+ async function manageCdpCookies(client, request) {
1542
+ if (request.action === "list" || request.action === "get") {
1543
+ const result2 = await client.Storage.getCookies();
1544
+ const cookies2 = result2.cookies.filter(
1545
+ (cookie) => isCookieInOrigin(cookie, request.origin)
1546
+ );
1547
+ return createCdpStorageSuccess(request, {
1548
+ origin: request.origin,
1549
+ cookies: request.action === "get" && request.cookie?.name ? cookies2.filter((cookie) => cookie.name === request.cookie?.name) : cookies2
1550
+ });
1551
+ }
1552
+ if (request.action === "set") {
1553
+ if (!request.cookie?.name) {
1554
+ throw new Error("Cookie name is required for set operation");
1555
+ }
1556
+ await client.Storage.setCookies({
1557
+ cookies: [
1558
+ {
1559
+ name: request.cookie.name,
1560
+ value: request.cookie.value ?? request.value ?? "",
1561
+ url: request.cookie.url ?? request.origin,
1562
+ domain: request.cookie.domain,
1563
+ path: request.cookie.path,
1564
+ httpOnly: request.cookie.httpOnly,
1565
+ secure: request.cookie.secure,
1566
+ sameSite: normalizeCookieSameSite(request.cookie.sameSite),
1567
+ expires: request.cookie.expires
1568
+ }
1569
+ ]
1570
+ });
1571
+ return createCdpStorageSuccess(request, { ok: true });
1572
+ }
1573
+ const result = await client.Storage.getCookies();
1574
+ const cookies = result.cookies.filter(
1575
+ (cookie) => isCookieInOrigin(cookie, request.origin)
1576
+ );
1577
+ const candidates = request.action === "delete" && request.cookie?.name ? cookies.filter((cookie) => cookie.name === request.cookie?.name) : cookies;
1578
+ const deletable = candidates.filter((cookie) => !cookie.httpOnly);
1579
+ const skippedHttpOnlyCount = candidates.length - deletable.length;
1580
+ for (const cookie of deletable) {
1581
+ await client.Network.deleteCookies({
1582
+ name: cookie.name,
1583
+ domain: cookie.domain,
1584
+ path: cookie.path
1585
+ });
1586
+ }
1587
+ return createCdpStorageSuccess(request, {
1588
+ deletedCount: deletable.length,
1589
+ skippedHttpOnlyCount
1590
+ });
1591
+ }
1592
+ async function manageCdpDomStorage(client, request) {
1593
+ const storageId = {
1594
+ securityOrigin: request.origin,
1595
+ isLocalStorage: request.scope === "localStorage"
1596
+ };
1597
+ if (request.action === "list") {
1598
+ const result2 = await client.DOMStorage.getDOMStorageItems({ storageId });
1599
+ return createCdpStorageSuccess(request, {
1600
+ origin: request.origin,
1601
+ scope: request.scope,
1602
+ entries: result2.entries.map(([key, value]) => ({ key, value }))
1603
+ });
1604
+ }
1605
+ if (request.action === "get") {
1606
+ assertStorageKey(request);
1607
+ const result2 = await client.DOMStorage.getDOMStorageItems({ storageId });
1608
+ const entry = result2.entries.find(([key]) => key === request.key);
1609
+ return createCdpStorageSuccess(request, {
1610
+ key: request.key,
1611
+ value: entry?.[1] ?? null
1612
+ });
1613
+ }
1614
+ if (request.action === "set") {
1615
+ assertStorageKey(request);
1616
+ await client.DOMStorage.setDOMStorageItem({
1617
+ storageId,
1618
+ key: request.key,
1619
+ value: request.value ?? ""
1620
+ });
1621
+ return createCdpStorageSuccess(request, { ok: true });
1622
+ }
1623
+ if (request.action === "delete") {
1624
+ assertStorageKey(request);
1625
+ await client.DOMStorage.removeDOMStorageItem({
1626
+ storageId,
1627
+ key: request.key
1628
+ });
1629
+ return createCdpStorageSuccess(request, { ok: true });
1630
+ }
1631
+ const result = await client.DOMStorage.getDOMStorageItems({ storageId });
1632
+ for (const [key] of result.entries) {
1633
+ await client.DOMStorage.removeDOMStorageItem({ storageId, key });
1634
+ }
1635
+ return createCdpStorageSuccess(request, { deletedCount: result.entries.length });
1636
+ }
1637
+ async function manageCdpIndexedDb(client, request) {
1638
+ if (request.action === "list") {
1639
+ const result = await client.IndexedDB.requestDatabaseNames({
1640
+ securityOrigin: request.origin
1641
+ });
1642
+ return createCdpStorageSuccess(request, {
1643
+ origin: request.origin,
1644
+ databases: result.databaseNames
1645
+ });
1646
+ }
1647
+ assertIndexedDbTarget(request);
1648
+ if (request.action === "get") {
1649
+ const result = await client.IndexedDB.requestData({
1650
+ securityOrigin: request.origin,
1651
+ databaseName: request.databaseName,
1652
+ objectStoreName: request.objectStoreName,
1653
+ indexName: request.indexName ?? "",
1654
+ skipCount: 0,
1655
+ pageSize: 100
1656
+ });
1657
+ return createCdpStorageSuccess(request, {
1658
+ entries: result.objectStoreDataEntries,
1659
+ hasMore: result.hasMore
1660
+ });
1661
+ }
1662
+ if (request.action === "delete") {
1663
+ assertStorageKey(request);
1664
+ await client.IndexedDB.deleteObjectStoreEntries({
1665
+ securityOrigin: request.origin,
1666
+ databaseName: request.databaseName,
1667
+ objectStoreName: request.objectStoreName,
1668
+ keyRange: createExactCdpKeyRange(request.key)
1669
+ });
1670
+ return createCdpStorageSuccess(request, { ok: true });
1671
+ }
1672
+ if (request.action === "clear") {
1673
+ if (request.objectStoreName) {
1674
+ await client.IndexedDB.clearObjectStore({
1675
+ securityOrigin: request.origin,
1676
+ databaseName: request.databaseName,
1677
+ objectStoreName: request.objectStoreName
1678
+ });
1679
+ return createCdpStorageSuccess(request, { ok: true });
1680
+ }
1681
+ await client.IndexedDB.deleteDatabase({
1682
+ securityOrigin: request.origin,
1683
+ databaseName: request.databaseName
1684
+ });
1685
+ return createCdpStorageSuccess(request, { ok: true });
1686
+ }
1687
+ return createCdpStorageError(
1688
+ request,
1689
+ "IndexedDB set operation requires runtime bridge"
1690
+ );
1691
+ }
1692
+ function isCookieInOrigin(cookie, origin) {
1693
+ const hostname = new URL(origin).hostname;
1694
+ const domain = cookie.domain?.replace(/^\./, "");
1695
+ return Boolean(domain && (hostname === domain || hostname.endsWith(`.${domain}`)));
1696
+ }
1697
+ function normalizeCookieSameSite(sameSite) {
1698
+ if (!sameSite) {
1699
+ return void 0;
1700
+ }
1701
+ if (sameSite === "strict") {
1702
+ return "Strict";
1703
+ }
1704
+ if (sameSite === "lax") {
1705
+ return "Lax";
1706
+ }
1707
+ return "None";
1708
+ }
1709
+ function createExactCdpKeyRange(key) {
1710
+ const parsedKey = parseJsonValue(key);
1711
+ return {
1712
+ lower: parsedKey,
1713
+ upper: parsedKey,
1714
+ lowerOpen: false,
1715
+ upperOpen: false
1716
+ };
1717
+ }
1718
+ function parseJsonValue(value) {
1719
+ try {
1720
+ return JSON.parse(value);
1721
+ } catch {
1722
+ return value;
1723
+ }
1724
+ }
1725
+ function assertStorageKey(request) {
1726
+ if (!request.key) {
1727
+ throw new Error("Storage key is required for this operation");
1728
+ }
1729
+ }
1730
+ function assertIndexedDbTarget(request) {
1731
+ if (!request.databaseName || !request.objectStoreName) {
1732
+ throw new Error("IndexedDB databaseName and objectStoreName are required");
1733
+ }
1734
+ }
1735
+ function createCdpStorageSuccess(request, data) {
1736
+ return {
1737
+ ok: true,
1738
+ source: "cdp",
1739
+ action: request.action,
1740
+ scope: request.scope,
1741
+ data
1742
+ };
1743
+ }
1744
+ function createCdpStorageError(request, error) {
1745
+ return {
1746
+ ok: false,
1747
+ source: "cdp",
1748
+ action: request.action,
1749
+ scope: request.scope,
1750
+ error
1751
+ };
1752
+ }
1753
+
1754
+ // src/mcp/tools/storage.ts
1755
+ function registerStorageTools(server, ctx) {
1756
+ registerStorageTool(server, MCP_TOOL_NAMES.listStorage, {
1757
+ description: "List same-origin storage and CDP cookies when available.",
1758
+ inputSchema: {
1759
+ pageId: z7.string().optional()
1760
+ },
1761
+ action: "list",
1762
+ handler: (input) => handleListStorage(ctx, input.pageId)
1763
+ });
1764
+ registerStorageTool(server, MCP_TOOL_NAMES.getStorageItem, {
1765
+ description: "Read one storage entry.",
1766
+ inputSchema: createStorageInputSchema(),
1767
+ action: "get",
1768
+ handler: (input) => handleStorageAction(ctx, { ...input, action: "get" })
1769
+ });
1770
+ registerStorageTool(server, MCP_TOOL_NAMES.setStorageItem, {
1771
+ description: "Write one storage entry.",
1772
+ inputSchema: createStorageInputSchema(),
1773
+ action: "set",
1774
+ handler: (input) => handleStorageAction(ctx, { ...input, action: "set" })
1775
+ });
1776
+ registerStorageTool(server, MCP_TOOL_NAMES.deleteStorageItem, {
1777
+ description: "Delete one storage entry.",
1778
+ inputSchema: createStorageInputSchema(),
1779
+ action: "delete",
1780
+ handler: (input) => handleStorageAction(ctx, { ...input, action: "delete" })
1781
+ });
1782
+ registerStorageTool(server, MCP_TOOL_NAMES.clearStorage, {
1783
+ description: "Clear one storage scope.",
1784
+ inputSchema: createStorageInputSchema(),
1785
+ action: "clear",
1786
+ handler: (input) => handleStorageAction(ctx, { ...input, action: "clear" })
1787
+ });
1788
+ }
1789
+ function registerStorageTool(server, name, options) {
1790
+ server.registerTool(
1791
+ name,
1792
+ {
1793
+ description: options.description,
1794
+ inputSchema: options.inputSchema
1795
+ },
1796
+ (async (input) => options.handler(
1797
+ input
1798
+ ))
1799
+ );
1800
+ }
1801
+ function createStorageInputSchema() {
1802
+ return {
1803
+ pageId: z7.string().optional(),
1804
+ scope: z7.enum(["localStorage", "sessionStorage", "indexedDB", "cookie"]).optional(),
1805
+ key: z7.string().optional(),
1806
+ value: z7.string().optional(),
1807
+ databaseName: z7.string().optional(),
1808
+ objectStoreName: z7.string().optional(),
1809
+ indexName: z7.string().optional(),
1810
+ cookie: z7.object({
1811
+ name: z7.string(),
1812
+ value: z7.string().optional(),
1813
+ domain: z7.string().optional(),
1814
+ path: z7.string().optional(),
1815
+ url: z7.string().optional(),
1816
+ httpOnly: z7.boolean().optional(),
1817
+ secure: z7.boolean().optional(),
1818
+ sameSite: z7.enum(["strict", "lax", "none"]).optional(),
1819
+ expires: z7.number().optional()
1820
+ }).optional()
1821
+ };
1822
+ }
1823
+ async function handleListStorage(ctx, pageId) {
1824
+ let baseRequest;
1825
+ try {
1826
+ baseRequest = createStorageRequest(ctx, {
1827
+ pageId,
1828
+ action: "list",
1829
+ scope: "localStorage"
1830
+ });
1831
+ } catch (error) {
1832
+ return createToolError(error instanceof Error ? error.message : String(error));
1833
+ }
1834
+ const [localStorage, sessionStorage, indexedDB] = await Promise.all([
1835
+ requestRuntimeStorage(ctx, { ...baseRequest, scope: "localStorage" }),
1836
+ requestRuntimeStorage(ctx, { ...baseRequest, scope: "sessionStorage" }),
1837
+ requestRuntimeStorage(ctx, { ...baseRequest, scope: "indexedDB" })
1838
+ ]);
1839
+ const cookie = await listCookiesIfCdpAvailable(ctx, baseRequest, pageId);
1840
+ return createToolResponse({
1841
+ ok: true,
1842
+ origin: baseRequest.origin,
1843
+ localStorage: extractStorageData(localStorage),
1844
+ sessionStorage: extractStorageData(sessionStorage),
1845
+ indexedDB: extractStorageData(indexedDB),
1846
+ cookie
1847
+ });
1848
+ }
1849
+ async function handleStorageAction(ctx, input) {
1850
+ let request;
1851
+ try {
1852
+ request = createStorageRequest(ctx, input);
1853
+ } catch (error) {
1854
+ return createToolError(error instanceof Error ? error.message : String(error));
1855
+ }
1856
+ const cdp = await connectCdpForPage(ctx, input.pageId);
1857
+ if (cdp && shouldUseCdpStorage(request)) {
1858
+ try {
1859
+ const result2 = await createCdpStorageAdapter(cdp.client).manageStorage(
1860
+ request
1861
+ );
1862
+ return createToolResponse(result2);
1863
+ } finally {
1864
+ await closeCdpClient(cdp.client);
1865
+ }
1866
+ }
1867
+ const result = await requestRuntimeStorage(ctx, request);
1868
+ return createToolResponse(result);
1869
+ }
1870
+ async function requestRuntimeStorage(ctx, request) {
1871
+ return requestRuntimeData(ctx, (event) => {
1872
+ void ctx.rpcServer?.manageStorage({
1873
+ ...request,
1874
+ event
1875
+ });
1876
+ });
1877
+ }
1878
+ async function listCookiesIfCdpAvailable(ctx, request, pageId) {
1879
+ if (!hasCdpConfig2(ctx)) {
1880
+ return extractStorageData(
1881
+ await requestRuntimeStorage(ctx, { ...request, scope: "cookie" })
1882
+ );
1883
+ }
1884
+ const cdp = await connectCdpForPage(ctx, pageId);
1885
+ if (!cdp) {
1886
+ return extractStorageData(
1887
+ await requestRuntimeStorage(ctx, { ...request, scope: "cookie" })
1888
+ );
1889
+ }
1890
+ try {
1891
+ const result = await createCdpStorageAdapter(cdp.client).manageStorage({
1892
+ ...request,
1893
+ scope: "cookie"
1894
+ });
1895
+ return extractStorageData(result);
1896
+ } finally {
1897
+ await closeCdpClient(cdp.client);
1898
+ }
1899
+ }
1900
+ function extractStorageData(result) {
1901
+ if (!isStorageResultRecord(result)) {
1902
+ return result;
1903
+ }
1904
+ return result.data ?? result;
1905
+ }
1906
+ function isStorageResultRecord(value) {
1907
+ return typeof value === "object" && value !== null && "ok" in value;
1908
+ }
1909
+ function shouldUseCdpStorage(request) {
1910
+ return request.scope === "cookie";
1911
+ }
1912
+ function createStorageRequest(ctx, input) {
1913
+ const page = resolvePageTarget(ctx, input.pageId);
1914
+ const origin = new URL(page.url).origin;
1915
+ return {
1916
+ event: "",
1917
+ pageId: page.pageId,
1918
+ origin,
1919
+ action: input.action,
1920
+ scope: normalizeScope(input.scope),
1921
+ key: input.key,
1922
+ value: input.value,
1923
+ databaseName: input.databaseName,
1924
+ objectStoreName: input.objectStoreName,
1925
+ indexName: input.indexName,
1926
+ cookie: input.cookie
1927
+ };
1928
+ }
1929
+ function normalizeScope(scope) {
1930
+ return scope ?? "localStorage";
1931
+ }
1932
+ function hasCdpConfig2(ctx) {
1933
+ return Boolean(ctx.options.cdp.browserUrl || ctx.options.cdp.wsEndpoint);
1934
+ }
1935
+
1936
+ // src/mcp/tools/screenshot.ts
1937
+ import { z as z8 } from "zod";
1938
+
1512
1939
  // src/cdp/cdpScreenshot.ts
1513
1940
  async function cdpCaptureScreenshot(options) {
1514
1941
  if (options.target === "element") {
@@ -1667,14 +2094,14 @@ function createProjectRelativePath(ctx, filePath) {
1667
2094
  var DEFAULT_SCREENSHOT_TARGET = "viewport";
1668
2095
  var DEFAULT_SCREENSHOT_FORMAT = "png";
1669
2096
  var screenshotInputSchema = {
1670
- pageId: z7.string().optional(),
1671
- target: z7.enum(["viewport", "fullPage", "element"]).optional(),
1672
- selector: z7.string().optional(),
1673
- format: z7.enum(["png", "jpeg", "webp"]).optional(),
1674
- prefer: z7.enum(["auto", "cdp", "runtime"]).optional(),
1675
- quality: z7.number().optional(),
1676
- scale: z7.number().optional(),
1677
- snapdom: z7.record(z7.string(), z7.unknown()).optional()
2097
+ pageId: z8.string().optional(),
2098
+ target: z8.enum(["viewport", "fullPage", "element"]).optional(),
2099
+ selector: z8.string().optional(),
2100
+ format: z8.enum(["png", "jpeg", "webp"]).optional(),
2101
+ prefer: z8.enum(["auto", "cdp", "runtime"]).optional(),
2102
+ quality: z8.number().optional(),
2103
+ scale: z8.number().optional(),
2104
+ snapdom: z8.record(z8.string(), z8.unknown()).optional()
1678
2105
  };
1679
2106
  function registerScreenshotTools(server, ctx) {
1680
2107
  server.registerTool(
@@ -1794,7 +2221,7 @@ function isScreenshotImagePayload(result) {
1794
2221
 
1795
2222
  // src/mcp/tools/vue.ts
1796
2223
  import { nanoid as nanoid3 } from "nanoid";
1797
- import { z as z8 } from "zod";
2224
+ import { z as z9 } from "zod";
1798
2225
  function registerVueTools(server, ctx) {
1799
2226
  server.registerTool(
1800
2227
  MCP_TOOL_NAMES.getComponentTree,
@@ -1807,7 +2234,7 @@ function registerVueTools(server, ctx) {
1807
2234
  MCP_TOOL_NAMES.getComponentState,
1808
2235
  {
1809
2236
  description: "Get Vue component state.",
1810
- inputSchema: { componentName: z8.string() }
2237
+ inputSchema: { componentName: z9.string() }
1811
2238
  },
1812
2239
  async ({ componentName }) => requestVueData(ctx, (event) => {
1813
2240
  void ctx.rpcServer?.getInspectorState({ event, componentName });
@@ -1818,10 +2245,10 @@ function registerVueTools(server, ctx) {
1818
2245
  {
1819
2246
  description: "Edit Vue component state.",
1820
2247
  inputSchema: {
1821
- componentName: z8.string(),
1822
- path: z8.array(z8.string()),
1823
- value: z8.string(),
1824
- valueType: z8.enum(["string", "number", "boolean", "object", "array"])
2248
+ componentName: z9.string(),
2249
+ path: z9.array(z9.string()),
2250
+ value: z9.string(),
2251
+ valueType: z9.enum(["string", "number", "boolean", "object", "array"])
1825
2252
  }
1826
2253
  },
1827
2254
  ({ componentName, path: path8, value, valueType }) => {
@@ -1841,7 +2268,7 @@ function registerVueTools(server, ctx) {
1841
2268
  MCP_TOOL_NAMES.highlightComponent,
1842
2269
  {
1843
2270
  description: "Highlight a Vue component.",
1844
- inputSchema: { componentName: z8.string() }
2271
+ inputSchema: { componentName: z9.string() }
1845
2272
  },
1846
2273
  ({ componentName }) => {
1847
2274
  if (!ctx.rpcServer) {
@@ -1869,7 +2296,7 @@ function registerVueTools(server, ctx) {
1869
2296
  MCP_TOOL_NAMES.getPiniaState,
1870
2297
  {
1871
2298
  description: "Get Pinia store state.",
1872
- inputSchema: { storeName: z8.string() }
2299
+ inputSchema: { storeName: z9.string() }
1873
2300
  },
1874
2301
  async ({ storeName }) => requestVueData(ctx, (event) => {
1875
2302
  void ctx.rpcServer?.getPiniaState({ event, storeName });
@@ -1916,6 +2343,7 @@ function createMcpServer(ctx, vite) {
1916
2343
  registerConsoleTools(server, ctx);
1917
2344
  registerEvaluateTools(server, ctx);
1918
2345
  registerNetworkTools(server, ctx);
2346
+ registerStorageTools(server, ctx);
1919
2347
  registerPerformanceTools(server, ctx);
1920
2348
  registerVueTools(server, ctx);
1921
2349
  return server;
@@ -2004,6 +2432,10 @@ function createServerVueRuntimeRpc(ctx) {
2004
2432
  onScreenshotTaken: (event, data) => {
2005
2433
  void ctx.hooks.callHook(event, data);
2006
2434
  },
2435
+ manageStorage: () => void 0,
2436
+ onStorageUpdated: (event, data) => {
2437
+ void ctx.hooks.callHook(event, data);
2438
+ },
2007
2439
  recordPerformance: () => void 0,
2008
2440
  onPerformanceRecorded: (event, data) => {
2009
2441
  void ctx.hooks.callHook(event, data);