@shuffleio/shuffle-mcps 0.0.28 → 0.0.30

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.d.mts CHANGED
@@ -810,10 +810,14 @@ interface AgentsViewProps extends ShuffleHostProps {
810
810
  localLLMSlot?: React.ReactNode;
811
811
  /** Content for the built-in AgentRunDrawer's Permissions tab. Optional. */
812
812
  permissionsSlot?: React.ReactNode;
813
- /** Pre-fill the starter chip row on mount (e.g. from persisted host state). */
813
+ /** Pre-fill the starter chip row on mount (e.g. from persisted host state). When omitted, AgentsView restores its own persisted selection from localStorage (24h TTL). */
814
814
  initialApps?: AgentUIApp[];
815
- /** Called whenever the chip row under the prompt changes. */
815
+ /** Called whenever the chip row under the prompt changes. When omitted, AgentsView still persists internally. */
816
816
  onAppsChange?: (apps: AgentUIApp[]) => void;
817
+ /** Disable AgentsView's internal localStorage persistence of the chip row. */
818
+ disableAppsPersistence?: boolean;
819
+ /** Storage key for internal chip-row persistence. Defaults to `shuffle-agents-selected-apps`. */
820
+ appsStorageKey?: string;
817
821
  }
818
822
 
819
823
  interface AgentLocalModel {
package/dist/index.d.ts CHANGED
@@ -810,10 +810,14 @@ interface AgentsViewProps extends ShuffleHostProps {
810
810
  localLLMSlot?: React.ReactNode;
811
811
  /** Content for the built-in AgentRunDrawer's Permissions tab. Optional. */
812
812
  permissionsSlot?: React.ReactNode;
813
- /** Pre-fill the starter chip row on mount (e.g. from persisted host state). */
813
+ /** Pre-fill the starter chip row on mount (e.g. from persisted host state). When omitted, AgentsView restores its own persisted selection from localStorage (24h TTL). */
814
814
  initialApps?: AgentUIApp[];
815
- /** Called whenever the chip row under the prompt changes. */
815
+ /** Called whenever the chip row under the prompt changes. When omitted, AgentsView still persists internally. */
816
816
  onAppsChange?: (apps: AgentUIApp[]) => void;
817
+ /** Disable AgentsView's internal localStorage persistence of the chip row. */
818
+ disableAppsPersistence?: boolean;
819
+ /** Storage key for internal chip-row persistence. Defaults to `shuffle-agents-selected-apps`. */
820
+ appsStorageKey?: string;
817
821
  }
818
822
 
819
823
  interface AgentLocalModel {
package/dist/index.js CHANGED
@@ -7072,7 +7072,11 @@ function AppSearchDrawer({
7072
7072
  paper: {
7073
7073
  className: scopeClassName,
7074
7074
  sx: {
7075
- width: { xs: "100%", sm: width },
7075
+ // Strict, environment-independent sizing so the drawer
7076
+ // looks identical on every host (Shuffle Security, /agents,
7077
+ // test page, embedded library, etc.). No breakpoint variance.
7078
+ width: `min(${width}px, 100vw)`,
7079
+ minWidth: `min(${width}px, 100vw)`,
7076
7080
  maxWidth: "100vw",
7077
7081
  height: "100vh",
7078
7082
  display: "flex",
@@ -7182,32 +7186,34 @@ function AppSearchDrawer({
7182
7186
  overflowY: "auto"
7183
7187
  },
7184
7188
  "& .singul-results-grid": {
7185
- gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
7186
- gridAutoRows: "78px",
7187
- gap: "12px"
7189
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr)) !important",
7190
+ gridAutoRows: "78px !important",
7191
+ gap: "12px !important"
7188
7192
  },
7189
7193
  "& .singul-results-grid .singul-dropdown-item": {
7190
7194
  minWidth: 0,
7191
- minHeight: 78,
7192
- maxHeight: 78,
7193
- height: 78,
7194
- padding: "10px 14px",
7195
+ minHeight: "78px !important",
7196
+ maxHeight: "78px !important",
7197
+ height: "78px !important",
7198
+ padding: "10px 14px !important",
7195
7199
  alignItems: "center",
7196
- overflow: "hidden"
7200
+ overflow: "hidden",
7201
+ boxSizing: "border-box"
7197
7202
  },
7198
7203
  "& .singul-results-grid .singul-app-info": {
7199
7204
  alignItems: "center",
7200
- gap: "12px"
7205
+ gap: "12px !important"
7201
7206
  },
7202
7207
  "& .singul-results-grid .singul-app-icon": {
7203
- width: 36,
7204
- height: 36,
7205
- borderRadius: 8,
7206
- padding: 4
7208
+ width: "36px !important",
7209
+ height: "36px !important",
7210
+ minWidth: "36px !important",
7211
+ borderRadius: "8px !important",
7212
+ padding: "4px !important"
7207
7213
  },
7208
7214
  "& .singul-results-grid .singul-app-details": { minWidth: 0 },
7209
7215
  "& .singul-results-grid .singul-app-name": { maxWidth: "100%" },
7210
- "& .singul-results-grid .singul-checkbox": { marginLeft: "auto" },
7216
+ "& .singul-results-grid .singul-checkbox": { marginLeft: "auto", flexShrink: 0 },
7211
7217
  ...highlightActive && highlightAppName ? {
7212
7218
  [`& .singul-dropdown-item[data-app-name="${highlightAppName}"]`]: {
7213
7219
  borderColor: "hsl(var(--primary)) !important",
@@ -14182,7 +14188,35 @@ var AgentExecutionDrawer_default = AgentExecutionDrawer;
14182
14188
  // views/AgentsView.tsx
14183
14189
  var import_react20 = require("react");
14184
14190
  var import_material22 = require("@mui/material");
14191
+ init_api();
14185
14192
  var import_jsx_runtime26 = require("react/jsx-runtime");
14193
+ var APPS_TTL_MS = 24 * 60 * 60 * 1e3;
14194
+ var DEFAULT_APPS_STORAGE_KEY = "shuffle-agents-selected-apps";
14195
+ var readPersistedApps = (storageKey) => {
14196
+ try {
14197
+ if (typeof window === "undefined") return void 0;
14198
+ const raw = window.localStorage.getItem(storageKey);
14199
+ if (!raw) return void 0;
14200
+ const parsed = JSON.parse(raw);
14201
+ if (!parsed?.savedAt || !Array.isArray(parsed.apps) || parsed.apps.length === 0) return void 0;
14202
+ if (Date.now() - parsed.savedAt > APPS_TTL_MS) {
14203
+ window.localStorage.removeItem(storageKey);
14204
+ return void 0;
14205
+ }
14206
+ return parsed.apps.filter((a) => a && typeof a.name === "string");
14207
+ } catch {
14208
+ return void 0;
14209
+ }
14210
+ };
14211
+ var resolveTheme = (theme) => {
14212
+ if (theme === "light" || theme === "dark") return theme;
14213
+ if (typeof window === "undefined" || !window.matchMedia) return theme;
14214
+ try {
14215
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
14216
+ } catch {
14217
+ return void 0;
14218
+ }
14219
+ };
14186
14220
  var AgentsView = ({
14187
14221
  onSchedule,
14188
14222
  maxWidth = 820,
@@ -14192,7 +14226,9 @@ var AgentsView = ({
14192
14226
  permissionsSlot,
14193
14227
  initialApps,
14194
14228
  onAppsChange,
14195
- globalUrl,
14229
+ disableAppsPersistence,
14230
+ appsStorageKey = DEFAULT_APPS_STORAGE_KEY,
14231
+ globalUrl = API_CONFIG.baseUrl,
14196
14232
  isLoaded,
14197
14233
  isLoggedIn,
14198
14234
  userdata,
@@ -14203,14 +14239,44 @@ var AgentsView = ({
14203
14239
  orgId
14204
14240
  }) => {
14205
14241
  useSyncHostBaseUrl(globalUrl);
14242
+ const resolvedTheme = (0, import_react20.useMemo)(() => resolveTheme(theme), [theme]);
14243
+ const hydratedInitialApps = (0, import_react20.useMemo)(() => {
14244
+ if (initialApps && initialApps.length > 0) return initialApps;
14245
+ if (disableAppsPersistence) return [];
14246
+ return readPersistedApps(appsStorageKey) ?? [];
14247
+ }, []);
14206
14248
  const [selectedRun, setSelectedRun] = (0, import_react20.useState)(null);
14207
14249
  const [agentView, setAgentView] = (0, import_react20.useState)("start");
14208
14250
  const [prefill, setPrefill] = (0, import_react20.useState)({
14209
14251
  input: "",
14210
- apps: initialApps && initialApps.length > 0 ? initialApps : [],
14252
+ apps: hydratedInitialApps,
14211
14253
  key: 0
14212
14254
  });
14213
14255
  const [editing, setEditing] = (0, import_react20.useState)(null);
14256
+ const handleAppsChange = (0, import_react20.useCallback)((apps) => {
14257
+ if (onAppsChange) {
14258
+ try {
14259
+ onAppsChange(apps);
14260
+ } catch {
14261
+ }
14262
+ }
14263
+ if (disableAppsPersistence) return;
14264
+ try {
14265
+ if (typeof window === "undefined") return;
14266
+ if (!apps || apps.length === 0) {
14267
+ window.localStorage.removeItem(appsStorageKey);
14268
+ return;
14269
+ }
14270
+ const slim = apps.filter((a) => a && typeof a.name === "string").map((a) => ({ name: a.name, id: a.id, icon: a.icon }));
14271
+ window.localStorage.setItem(
14272
+ appsStorageKey,
14273
+ JSON.stringify({ savedAt: Date.now(), apps: slim })
14274
+ );
14275
+ } catch {
14276
+ }
14277
+ }, [onAppsChange, disableAppsPersistence, appsStorageKey]);
14278
+ (0, import_react20.useEffect)(() => {
14279
+ }, [handleAppsChange]);
14214
14280
  const [builtInDrawer, setBuiltInDrawer] = (0, import_react20.useState)({
14215
14281
  open: false,
14216
14282
  tab: "localLLM"
@@ -14231,23 +14297,17 @@ var AgentsView = ({
14231
14297
  isLoaded,
14232
14298
  isLoggedIn,
14233
14299
  serverside,
14234
- theme,
14300
+ theme: resolvedTheme,
14235
14301
  colorMode
14236
14302
  }
14237
14303
  ),
14238
- [localLLMSlot, globalUrl, userdata, isLoaded, isLoggedIn, serverside, theme, colorMode]
14304
+ [localLLMSlot, globalUrl, userdata, isLoaded, isLoggedIn, serverside, resolvedTheme, colorMode]
14239
14305
  );
14240
14306
  const handleChooseLLM = (0, import_react20.useCallback)(() => {
14241
14307
  if (onChooseLLM) {
14242
14308
  onChooseLLM();
14243
14309
  return;
14244
14310
  }
14245
- if (typeof window !== "undefined" && window.__shuffleAgentDrawerMounted > 0) {
14246
- window.dispatchEvent(
14247
- new CustomEvent("agent-drawer-open", { detail: { tab: "localLLM" } })
14248
- );
14249
- return;
14250
- }
14251
14311
  setBuiltInDrawer({ open: true, tab: "localLLM" });
14252
14312
  }, [onChooseLLM]);
14253
14313
  const handleEditWorkflow = (0, import_react20.useCallback)(
@@ -14341,9 +14401,9 @@ var AgentsView = ({
14341
14401
  submitTooltip: editing ? "\u2318+Enter to save" : void 0,
14342
14402
  disableSchedule: Boolean(editing),
14343
14403
  disableScheduleTooltip: editing ? "Scheduling is disabled while editing an existing schedule" : void 0,
14344
- theme,
14404
+ theme: resolvedTheme,
14345
14405
  colorMode,
14346
- onAppsChange
14406
+ onAppsChange: handleAppsChange
14347
14407
  },
14348
14408
  prefill.key
14349
14409
  ),
@@ -14368,7 +14428,7 @@ var AgentsView = ({
14368
14428
  onSchedule: effectiveSchedule,
14369
14429
  apiKey,
14370
14430
  orgId,
14371
- theme,
14431
+ theme: resolvedTheme,
14372
14432
  colorMode
14373
14433
  }
14374
14434
  ),
@@ -14381,9 +14441,9 @@ var AgentsView = ({
14381
14441
  globalUrl,
14382
14442
  localLLMSlot: effectiveLocalLLMSlot,
14383
14443
  permissionsSlot,
14384
- theme,
14444
+ theme: resolvedTheme,
14385
14445
  colorMode,
14386
- agentUIProps: { onSchedule: effectiveSchedule, apiBaseUrl: globalUrl, apiKey, orgId, theme, colorMode }
14446
+ agentUIProps: { onSchedule: effectiveSchedule, apiBaseUrl: globalUrl, apiKey, orgId, theme: resolvedTheme, colorMode }
14387
14447
  }
14388
14448
  )
14389
14449
  ] });
package/dist/index.mjs CHANGED
@@ -6686,7 +6686,11 @@ function AppSearchDrawer({
6686
6686
  paper: {
6687
6687
  className: scopeClassName,
6688
6688
  sx: {
6689
- width: { xs: "100%", sm: width },
6689
+ // Strict, environment-independent sizing so the drawer
6690
+ // looks identical on every host (Shuffle Security, /agents,
6691
+ // test page, embedded library, etc.). No breakpoint variance.
6692
+ width: `min(${width}px, 100vw)`,
6693
+ minWidth: `min(${width}px, 100vw)`,
6690
6694
  maxWidth: "100vw",
6691
6695
  height: "100vh",
6692
6696
  display: "flex",
@@ -6796,32 +6800,34 @@ function AppSearchDrawer({
6796
6800
  overflowY: "auto"
6797
6801
  },
6798
6802
  "& .singul-results-grid": {
6799
- gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
6800
- gridAutoRows: "78px",
6801
- gap: "12px"
6803
+ gridTemplateColumns: "repeat(2, minmax(0, 1fr)) !important",
6804
+ gridAutoRows: "78px !important",
6805
+ gap: "12px !important"
6802
6806
  },
6803
6807
  "& .singul-results-grid .singul-dropdown-item": {
6804
6808
  minWidth: 0,
6805
- minHeight: 78,
6806
- maxHeight: 78,
6807
- height: 78,
6808
- padding: "10px 14px",
6809
+ minHeight: "78px !important",
6810
+ maxHeight: "78px !important",
6811
+ height: "78px !important",
6812
+ padding: "10px 14px !important",
6809
6813
  alignItems: "center",
6810
- overflow: "hidden"
6814
+ overflow: "hidden",
6815
+ boxSizing: "border-box"
6811
6816
  },
6812
6817
  "& .singul-results-grid .singul-app-info": {
6813
6818
  alignItems: "center",
6814
- gap: "12px"
6819
+ gap: "12px !important"
6815
6820
  },
6816
6821
  "& .singul-results-grid .singul-app-icon": {
6817
- width: 36,
6818
- height: 36,
6819
- borderRadius: 8,
6820
- padding: 4
6822
+ width: "36px !important",
6823
+ height: "36px !important",
6824
+ minWidth: "36px !important",
6825
+ borderRadius: "8px !important",
6826
+ padding: "4px !important"
6821
6827
  },
6822
6828
  "& .singul-results-grid .singul-app-details": { minWidth: 0 },
6823
6829
  "& .singul-results-grid .singul-app-name": { maxWidth: "100%" },
6824
- "& .singul-results-grid .singul-checkbox": { marginLeft: "auto" },
6830
+ "& .singul-results-grid .singul-checkbox": { marginLeft: "auto", flexShrink: 0 },
6825
6831
  ...highlightActive && highlightAppName ? {
6826
6832
  [`& .singul-dropdown-item[data-app-name="${highlightAppName}"]`]: {
6827
6833
  borderColor: "hsl(var(--primary)) !important",
@@ -13879,9 +13885,36 @@ var AgentExecutionDrawer = ({
13879
13885
  var AgentExecutionDrawer_default = AgentExecutionDrawer;
13880
13886
 
13881
13887
  // views/AgentsView.tsx
13882
- import { useCallback as useCallback10, useMemo as useMemo8, useState as useState16 } from "react";
13888
+ import { useCallback as useCallback10, useEffect as useEffect15, useMemo as useMemo8, useState as useState16 } from "react";
13883
13889
  import { Box as Box20, Stack, Typography as Typography19 } from "@mui/material";
13884
13890
  import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
13891
+ var APPS_TTL_MS = 24 * 60 * 60 * 1e3;
13892
+ var DEFAULT_APPS_STORAGE_KEY = "shuffle-agents-selected-apps";
13893
+ var readPersistedApps = (storageKey) => {
13894
+ try {
13895
+ if (typeof window === "undefined") return void 0;
13896
+ const raw = window.localStorage.getItem(storageKey);
13897
+ if (!raw) return void 0;
13898
+ const parsed = JSON.parse(raw);
13899
+ if (!parsed?.savedAt || !Array.isArray(parsed.apps) || parsed.apps.length === 0) return void 0;
13900
+ if (Date.now() - parsed.savedAt > APPS_TTL_MS) {
13901
+ window.localStorage.removeItem(storageKey);
13902
+ return void 0;
13903
+ }
13904
+ return parsed.apps.filter((a) => a && typeof a.name === "string");
13905
+ } catch {
13906
+ return void 0;
13907
+ }
13908
+ };
13909
+ var resolveTheme = (theme) => {
13910
+ if (theme === "light" || theme === "dark") return theme;
13911
+ if (typeof window === "undefined" || !window.matchMedia) return theme;
13912
+ try {
13913
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
13914
+ } catch {
13915
+ return void 0;
13916
+ }
13917
+ };
13885
13918
  var AgentsView = ({
13886
13919
  onSchedule,
13887
13920
  maxWidth = 820,
@@ -13891,7 +13924,9 @@ var AgentsView = ({
13891
13924
  permissionsSlot,
13892
13925
  initialApps,
13893
13926
  onAppsChange,
13894
- globalUrl,
13927
+ disableAppsPersistence,
13928
+ appsStorageKey = DEFAULT_APPS_STORAGE_KEY,
13929
+ globalUrl = API_CONFIG.baseUrl,
13895
13930
  isLoaded,
13896
13931
  isLoggedIn,
13897
13932
  userdata,
@@ -13902,14 +13937,44 @@ var AgentsView = ({
13902
13937
  orgId
13903
13938
  }) => {
13904
13939
  useSyncHostBaseUrl(globalUrl);
13940
+ const resolvedTheme = useMemo8(() => resolveTheme(theme), [theme]);
13941
+ const hydratedInitialApps = useMemo8(() => {
13942
+ if (initialApps && initialApps.length > 0) return initialApps;
13943
+ if (disableAppsPersistence) return [];
13944
+ return readPersistedApps(appsStorageKey) ?? [];
13945
+ }, []);
13905
13946
  const [selectedRun, setSelectedRun] = useState16(null);
13906
13947
  const [agentView, setAgentView] = useState16("start");
13907
13948
  const [prefill, setPrefill] = useState16({
13908
13949
  input: "",
13909
- apps: initialApps && initialApps.length > 0 ? initialApps : [],
13950
+ apps: hydratedInitialApps,
13910
13951
  key: 0
13911
13952
  });
13912
13953
  const [editing, setEditing] = useState16(null);
13954
+ const handleAppsChange = useCallback10((apps) => {
13955
+ if (onAppsChange) {
13956
+ try {
13957
+ onAppsChange(apps);
13958
+ } catch {
13959
+ }
13960
+ }
13961
+ if (disableAppsPersistence) return;
13962
+ try {
13963
+ if (typeof window === "undefined") return;
13964
+ if (!apps || apps.length === 0) {
13965
+ window.localStorage.removeItem(appsStorageKey);
13966
+ return;
13967
+ }
13968
+ const slim = apps.filter((a) => a && typeof a.name === "string").map((a) => ({ name: a.name, id: a.id, icon: a.icon }));
13969
+ window.localStorage.setItem(
13970
+ appsStorageKey,
13971
+ JSON.stringify({ savedAt: Date.now(), apps: slim })
13972
+ );
13973
+ } catch {
13974
+ }
13975
+ }, [onAppsChange, disableAppsPersistence, appsStorageKey]);
13976
+ useEffect15(() => {
13977
+ }, [handleAppsChange]);
13913
13978
  const [builtInDrawer, setBuiltInDrawer] = useState16({
13914
13979
  open: false,
13915
13980
  tab: "localLLM"
@@ -13930,23 +13995,17 @@ var AgentsView = ({
13930
13995
  isLoaded,
13931
13996
  isLoggedIn,
13932
13997
  serverside,
13933
- theme,
13998
+ theme: resolvedTheme,
13934
13999
  colorMode
13935
14000
  }
13936
14001
  ),
13937
- [localLLMSlot, globalUrl, userdata, isLoaded, isLoggedIn, serverside, theme, colorMode]
14002
+ [localLLMSlot, globalUrl, userdata, isLoaded, isLoggedIn, serverside, resolvedTheme, colorMode]
13938
14003
  );
13939
14004
  const handleChooseLLM = useCallback10(() => {
13940
14005
  if (onChooseLLM) {
13941
14006
  onChooseLLM();
13942
14007
  return;
13943
14008
  }
13944
- if (typeof window !== "undefined" && window.__shuffleAgentDrawerMounted > 0) {
13945
- window.dispatchEvent(
13946
- new CustomEvent("agent-drawer-open", { detail: { tab: "localLLM" } })
13947
- );
13948
- return;
13949
- }
13950
14009
  setBuiltInDrawer({ open: true, tab: "localLLM" });
13951
14010
  }, [onChooseLLM]);
13952
14011
  const handleEditWorkflow = useCallback10(
@@ -14040,9 +14099,9 @@ var AgentsView = ({
14040
14099
  submitTooltip: editing ? "\u2318+Enter to save" : void 0,
14041
14100
  disableSchedule: Boolean(editing),
14042
14101
  disableScheduleTooltip: editing ? "Scheduling is disabled while editing an existing schedule" : void 0,
14043
- theme,
14102
+ theme: resolvedTheme,
14044
14103
  colorMode,
14045
- onAppsChange
14104
+ onAppsChange: handleAppsChange
14046
14105
  },
14047
14106
  prefill.key
14048
14107
  ),
@@ -14067,7 +14126,7 @@ var AgentsView = ({
14067
14126
  onSchedule: effectiveSchedule,
14068
14127
  apiKey,
14069
14128
  orgId,
14070
- theme,
14129
+ theme: resolvedTheme,
14071
14130
  colorMode
14072
14131
  }
14073
14132
  ),
@@ -14080,9 +14139,9 @@ var AgentsView = ({
14080
14139
  globalUrl,
14081
14140
  localLLMSlot: effectiveLocalLLMSlot,
14082
14141
  permissionsSlot,
14083
- theme,
14142
+ theme: resolvedTheme,
14084
14143
  colorMode,
14085
- agentUIProps: { onSchedule: effectiveSchedule, apiBaseUrl: globalUrl, apiKey, orgId, theme, colorMode }
14144
+ agentUIProps: { onSchedule: effectiveSchedule, apiBaseUrl: globalUrl, apiKey, orgId, theme: resolvedTheme, colorMode }
14086
14145
  }
14087
14146
  )
14088
14147
  ] });
@@ -14090,7 +14149,7 @@ var AgentsView = ({
14090
14149
  var AgentsView_default = AgentsView;
14091
14150
 
14092
14151
  // useAppLookup.ts
14093
- import { useEffect as useEffect15, useMemo as useMemo9, useState as useState17 } from "react";
14152
+ import { useEffect as useEffect16, useMemo as useMemo9, useState as useState17 } from "react";
14094
14153
  var norm3 = (s) => s.toLowerCase().replace(/[\s_\-]+/g, "_");
14095
14154
  function useAppLookup(appName) {
14096
14155
  const [loading, setLoading] = useState17(false);
@@ -14104,7 +14163,7 @@ function useAppLookup(appName) {
14104
14163
  handleSaveAuth,
14105
14164
  refreshAuth
14106
14165
  } = useAppAuth();
14107
- useEffect15(() => {
14166
+ useEffect16(() => {
14108
14167
  if (!appName) {
14109
14168
  setInfo(null);
14110
14169
  setAlgoliaId(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuffleio/shuffle-mcps",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
4
4
  "description": "Turn 3,000+ SaaS tools into MCP servers your agents can use. Headless React component for search, selection, and OAuth handoff.",
5
5
  "license": "MIT",
6
6
  "repository": {