@shuffleio/shuffle-mcps 0.0.37 → 0.0.38

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- <img src="https://security.shuffler.io/mcp/agent-icon.png" alt="Shuffle MCPs" width="96" />
3
+ <img src="https://shuffle.security/mcp/agent-icon.png" alt="Shuffle MCPs" width="96" />
4
4
 
5
5
  # Shuffle MCPs
6
6
 
@@ -26,11 +26,11 @@ Turn 3,000+ SaaS tools into MCP servers your agents can use. One search, one cli
26
26
  </tr>
27
27
  <tr>
28
28
  <td align="center" width="50%">
29
- <img src="https://security.shuffler.io/mcp/search-preview.png" alt="Search 3,000+ integrations" width="380" style="border-radius: 12px;" />
29
+ <img src="https://shuffle.security/mcp/search-preview.png" alt="Search 3,000+ integrations" width="380" style="border-radius: 12px;" />
30
30
  <br/><sub><b>3. Search any of 3,000+ tools</b></sub>
31
31
  </td>
32
32
  <td align="center" width="50%">
33
- <img src="https://security.shuffler.io/mcp/app-detail-preview.png" alt="Authenticate and use as MCP" width="380" style="border-radius: 12px;" />
33
+ <img src="https://shuffle.security/mcp/app-detail-preview.png" alt="Authenticate and use as MCP" width="380" style="border-radius: 12px;" />
34
34
  <br/><sub><b>4. Authenticate — your agent uses it instantly</b></sub>
35
35
  </td>
36
36
  </tr>
@@ -38,7 +38,7 @@ Turn 3,000+ SaaS tools into MCP servers your agents can use. One search, one cli
38
38
 
39
39
  &nbsp;
40
40
 
41
- > **See it live:** [security.shuffler.io/shuffle-mcp-demo](https://security.shuffler.io/shuffle-mcp-demo) — a fully working demo of every component in this package (inline search, search drawer, app detail drawer, auth, Try MCP, and Try individual actions). No login required.
41
+ > **See it live:** [shuffle.security/shuffle-mcp-demo](https://shuffle.security/shuffle-mcp-demo) — a fully working demo of every component in this package (inline search, search drawer, app detail drawer, auth, Try MCP, and Try individual actions). No login required.
42
42
 
43
43
  > **No SDK required.** Once a tool is authenticated in Shuffle, it is live as an MCP server immediately — call it from any agent over plain HTTP. This npm package is the optional UI layer for embedding the search-and-connect flow inside your own product.
44
44
 
@@ -99,13 +99,13 @@ The library exports six React components — use one or all of them. They share
99
99
 
100
100
  | Component | What it does | Live demo |
101
101
  |---|---|---|
102
- | [`<ShuffleMCP />`](#1-shufflemcp--inline-search) | Inline search box that merges Algolia's 3,000+ public app catalog with the current user's private apps | [/shuffle-mcp-demo §1](https://security.shuffler.io/shuffle-mcp-demo) |
103
- | [`<AppSearchDrawer />`](#2-appsearchdrawer--full-search-drawer) | Right-side drawer wrapping `<ShuffleMCP />` plus a "Your apps" status row. This is the exact "Add Ingestion Source" drawer used in production | [/shuffle-mcp-demo §2](https://security.shuffler.io/shuffle-mcp-demo) |
104
- | [`<AppDetailDrawer />`](#3-appdetaildrawer--single-app-config) | Right-side drawer for a single app: list/edit/test authentications and try the MCP `tools/call` endpoint inline | [/shuffle-mcp-demo §3](https://security.shuffler.io/shuffle-mcp-demo) |
105
- | [`<AgentUI />`](#4-agentui--start--debug-agents) | Standalone "What do you want to do?" hero prompt + live decision-by-decision debugger for `/api/v1/agent` runs. Drop-in replacement for the legacy Shuffle Core agent page | [/agents](https://security.shuffler.io/agents) |
106
- | [`<AgentRunDrawer />`](#5-agentrundrawer--run-agent-side-panel) | Right-side drawer that hosts `<AgentUI />` in compact mode plus optional caller-provided **Permissions** and **Local LLM** tabs (slot-driven, no host context required) | [/shuffle-mcp-demo §1b](https://security.shuffler.io/shuffle-mcp-demo) |
107
- | [`<AgentActivityList />`](#6-agentactivitylist--past-executions) | Searchable, status-filterable list of past `/api/v1/agent` runs. Pair with `<AgentExecutionDrawer />` to inspect any row in the canonical Simple/Detailed view | [/shuffle-mcp-demo §8](https://security.shuffler.io/shuffle-mcp-demo) |
108
- | [`<AgentExecutionDrawer />`](#7-agentexecutiondrawer--inspect-one-run) | Right-side drawer that pre-loads a single `AgentRun` into `<AgentUI />` (no `authorization` token required) for read-only inspection | [/agents](https://security.shuffler.io/agents) |
102
+ | [`<ShuffleMCP />`](#1-shufflemcp--inline-search) | Inline search box that merges Algolia's 3,000+ public app catalog with the current user's private apps | [/shuffle-mcp-demo §1](https://shuffle.security/shuffle-mcp-demo) |
103
+ | [`<AppSearchDrawer />`](#2-appsearchdrawer--full-search-drawer) | Right-side drawer wrapping `<ShuffleMCP />` plus a "Your apps" status row. This is the exact "Add Ingestion Source" drawer used in production | [/shuffle-mcp-demo §2](https://shuffle.security/shuffle-mcp-demo) |
104
+ | [`<AppDetailDrawer />`](#3-appdetaildrawer--single-app-config) | Right-side drawer for a single app: list/edit/test authentications and try the MCP `tools/call` endpoint inline | [/shuffle-mcp-demo §3](https://shuffle.security/shuffle-mcp-demo) |
105
+ | [`<AgentUI />`](#4-agentui--start--debug-agents) | Standalone "What do you want to do?" hero prompt + live decision-by-decision debugger for `/api/v1/agent` runs. Drop-in replacement for the legacy Shuffle Core agent page | [/agents](https://shuffle.security/agents) |
106
+ | [`<AgentRunDrawer />`](#5-agentrundrawer--run-agent-side-panel) | Right-side drawer that hosts `<AgentUI />` in compact mode plus optional caller-provided **Permissions** and **Local LLM** tabs (slot-driven, no host context required) | [/shuffle-mcp-demo §1b](https://shuffle.security/shuffle-mcp-demo) |
107
+ | [`<AgentActivityList />`](#6-agentactivitylist--past-executions) | Searchable, status-filterable list of past `/api/v1/agent` runs. Pair with `<AgentExecutionDrawer />` to inspect any row in the canonical Simple/Detailed view | [/shuffle-mcp-demo §8](https://shuffle.security/shuffle-mcp-demo) |
108
+ | [`<AgentExecutionDrawer />`](#7-agentexecutiondrawer--inspect-one-run) | Right-side drawer that pre-loads a single `AgentRun` into `<AgentUI />` (no `authorization` token required) for read-only inspection | [/agents](https://shuffle.security/agents) |
109
109
 
110
110
  ### 1. `<ShuffleMCP />` — inline search
111
111
 
@@ -252,7 +252,7 @@ Useful props:
252
252
  | `onRun` | `(info) => void` | Fires whenever a run finishes (success or failure) |
253
253
  | `className` / `sx` / `contentSx` | `string` / `SxProps` | Style overrides for the root container and inner content column |
254
254
 
255
- Reference page in production: [`src/pages/dashboard/AgentsPage.tsx`](../pages/dashboard/AgentsPage.tsx) (mounted at [`/agents`](https://security.shuffler.io/agents)).
255
+ Reference page in production: [`src/pages/dashboard/AgentsPage.tsx`](../pages/dashboard/AgentsPage.tsx) (mounted at [`/agents`](https://shuffle.security/agents)).
256
256
 
257
257
  ### 5. `<AgentRunDrawer />` — Run Agent side panel
258
258
 
@@ -2,7 +2,7 @@ import {
2
2
  fetchApps,
3
3
  fetchAppsViaApiConfig,
4
4
  invalidateAppsCache
5
- } from "./chunk-5ZQ2BL47.mjs";
5
+ } from "./chunk-DCHKGFML.mjs";
6
6
  export {
7
7
  fetchApps,
8
8
  fetchAppsViaApiConfig,
@@ -175,11 +175,65 @@ var installFetchBreaker = () => {
175
175
  });
176
176
  };
177
177
 
178
+ // ../lib/platform.ts
179
+ var getPlatform = () => {
180
+ if (typeof window === "undefined") return "web";
181
+ const cap = window.Capacitor;
182
+ if (cap?.isNativePlatform && cap.isNativePlatform()) {
183
+ const platform = typeof cap.getPlatform === "function" ? cap.getPlatform() : "";
184
+ if (platform === "ios") return "ios";
185
+ if (platform === "android") return "android";
186
+ }
187
+ const ua = window.navigator?.userAgent || "";
188
+ if (/iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1) {
189
+ return "ios";
190
+ }
191
+ if (/android/i.test(ua)) {
192
+ return "android";
193
+ }
194
+ return "web";
195
+ };
196
+ var isCapacitorNative = () => {
197
+ if (typeof window === "undefined") return false;
198
+ const cap = window.Capacitor;
199
+ return Boolean(cap?.isNativePlatform && cap.isNativePlatform());
200
+ };
201
+ var isIosWebView = () => {
202
+ if (typeof window === "undefined") return false;
203
+ const cap = window.Capacitor;
204
+ if (cap?.isNativePlatform && cap.isNativePlatform()) {
205
+ return typeof cap.getPlatform === "function" ? cap.getPlatform() === "ios" : true;
206
+ }
207
+ const ua = window.navigator?.userAgent || "";
208
+ const isIosDevice = /iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
209
+ const isStandalonePwa = window.navigator.standalone === true || typeof window.matchMedia === "function" && window.matchMedia("(display-mode: standalone)").matches;
210
+ const isEmbeddedWebview = /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(ua);
211
+ return isIosDevice && (isStandalonePwa || isEmbeddedWebview);
212
+ };
213
+ var isAndroidWebView = () => {
214
+ if (typeof window === "undefined") return false;
215
+ const cap = window.Capacitor;
216
+ if (cap?.isNativePlatform && cap.isNativePlatform()) {
217
+ return typeof cap.getPlatform === "function" ? cap.getPlatform() === "android" : false;
218
+ }
219
+ const ua = window.navigator?.userAgent || "";
220
+ const isAndroidDevice = /android/i.test(ua);
221
+ const isStandalone = typeof window.matchMedia === "function" && window.matchMedia("(display-mode: standalone)").matches;
222
+ const isWebview = /;\s*wv|Version\/[\d.]+/i.test(ua) && isAndroidDevice;
223
+ return isAndroidDevice && (isStandalone || isWebview);
224
+ };
225
+ if (typeof window !== "undefined") {
226
+ window.isCapacitorNative = isCapacitorNative;
227
+ window.isIosWebView = isIosWebView;
228
+ window.isAndroidWebView = isAndroidWebView;
229
+ window.getPlatform = getPlatform;
230
+ }
231
+
178
232
  // api.ts
179
233
  installFetchBreaker();
180
234
  var DEV_BACKEND = "https://tunnel.schemaless.org";
181
235
  var PROD_BACKEND = "https://shuffler.io";
182
- var CLOUD_DOMAINS = ["security.shuffler.io", "shutdown.no"];
236
+ var CLOUD_DOMAINS = ["shuffle.security", "www.shuffle.security", "security.shuffler.io", "shutdown.no", "www.shutdown.no"];
183
237
  var getEnvVar = (key) => {
184
238
  try {
185
239
  const meta = new Function("try { return import.meta } catch { return undefined }")();
@@ -194,6 +248,7 @@ var isDevEnvironment = () => {
194
248
  return hostname.includes("lovableproject.com") || hostname.includes("id-preview--") || hostname.endsWith(".lovable.app") || hostname.endsWith(".lovable.dev");
195
249
  };
196
250
  var isCloudDomain = () => {
251
+ if (isCapacitorNative()) return true;
197
252
  const hostname = typeof window !== "undefined" ? window.location.hostname : "";
198
253
  return CLOUD_DOMAINS.includes(hostname);
199
254
  };
@@ -205,6 +260,7 @@ var getDefaultBaseUrl = () => {
205
260
  return envUrl;
206
261
  }
207
262
  if (isDevEnvironment()) return DEV_BACKEND;
263
+ if (isCapacitorNative()) return PROD_BACKEND;
208
264
  if (isCloudDomain()) return PROD_BACKEND;
209
265
  if (typeof window !== "undefined") {
210
266
  return window.location.origin;
@@ -225,8 +281,17 @@ var readCachedRegion = () => {
225
281
  };
226
282
  var cached = readCachedRegion();
227
283
  var _regionUrl = cached.url;
284
+ var readCachedCustomHost = () => {
285
+ if (typeof window === "undefined") return null;
286
+ try {
287
+ const raw = localStorage.getItem("shuffle_custom_host_url");
288
+ return raw ? raw.trim().replace(/\/+$/, "") : null;
289
+ } catch {
290
+ return null;
291
+ }
292
+ };
228
293
  var _trackedOrgId = cached.orgId;
229
- var _hostBaseUrl = null;
294
+ var _hostBaseUrl = readCachedCustomHost();
230
295
  var REGION_EVENT = "shuffle:region-url";
231
296
  var _lastBroadcastUrl = cached.url;
232
297
  var persistRegion = (url, orgId) => {
@@ -375,6 +440,14 @@ var getAuthHeader = (overrideOrgId) => {
375
440
  }
376
441
  return headers;
377
442
  };
443
+ var hasShuffleAuth = () => {
444
+ try {
445
+ if (API_CONFIG.apiKey) return true;
446
+ return !!(localStorage.getItem("session_token") || localStorage.getItem("shuffle_user_info"));
447
+ } catch {
448
+ return false;
449
+ }
450
+ };
378
451
 
379
452
  // appsCache.ts
380
453
  var TTL_MS = 3e4;
@@ -431,6 +504,7 @@ var fetchAppsViaApiConfig = () => {
431
504
  export {
432
505
  registerProtectedOrigin,
433
506
  installFetchBreaker,
507
+ isCapacitorNative,
434
508
  isCloudDomain,
435
509
  isCloud,
436
510
  isOnprem,
@@ -444,6 +518,7 @@ export {
444
518
  getApiUrl,
445
519
  shuffleFetch,
446
520
  getAuthHeader,
521
+ hasShuffleAuth,
447
522
  fetchApps,
448
523
  invalidateAppsCache,
449
524
  fetchAppsViaApiConfig
package/dist/index.d.mts CHANGED
@@ -359,6 +359,11 @@ interface AgentPreset {
359
359
  id?: string;
360
360
  icon?: string;
361
361
  }>;
362
+ /**
363
+ * Tools this skill cannot run without. They are always selected and cannot
364
+ * be removed from the Tools chip row while the skill is active.
365
+ */
366
+ requiredApps?: string[];
362
367
  }
363
368
  declare const AGENT_PRESETS: AgentPreset[];
364
369
  interface AgentPresetsProps {
@@ -789,6 +794,8 @@ interface AgentActivityResponse {
789
794
  interface AgentActivityParams {
790
795
  cursor?: string;
791
796
  limit?: number;
797
+ /** Optional page size sent as the `?top` query parameter. */
798
+ top?: number;
792
799
  status?: string;
793
800
  startTime?: string;
794
801
  endTime?: string;
@@ -870,6 +877,8 @@ interface AgentActivityListProps extends ShuffleHostProps {
870
877
  showStatusChips?: boolean;
871
878
  /** Page size. Default: 50. */
872
879
  limit?: number;
880
+ /** Optional page size sent as the `?top` query parameter. */
881
+ top?: number;
873
882
  /** Empty-state heading. */
874
883
  emptyTitle?: string;
875
884
  /** Empty-state subtitle. */
package/dist/index.d.ts CHANGED
@@ -359,6 +359,11 @@ interface AgentPreset {
359
359
  id?: string;
360
360
  icon?: string;
361
361
  }>;
362
+ /**
363
+ * Tools this skill cannot run without. They are always selected and cannot
364
+ * be removed from the Tools chip row while the skill is active.
365
+ */
366
+ requiredApps?: string[];
362
367
  }
363
368
  declare const AGENT_PRESETS: AgentPreset[];
364
369
  interface AgentPresetsProps {
@@ -789,6 +794,8 @@ interface AgentActivityResponse {
789
794
  interface AgentActivityParams {
790
795
  cursor?: string;
791
796
  limit?: number;
797
+ /** Optional page size sent as the `?top` query parameter. */
798
+ top?: number;
792
799
  status?: string;
793
800
  startTime?: string;
794
801
  endTime?: string;
@@ -870,6 +877,8 @@ interface AgentActivityListProps extends ShuffleHostProps {
870
877
  showStatusChips?: boolean;
871
878
  /** Page size. Default: 50. */
872
879
  limit?: number;
880
+ /** Optional page size sent as the `?top` query parameter. */
881
+ top?: number;
873
882
  /** Empty-state heading. */
874
883
  emptyTitle?: string;
875
884
  /** Empty-state subtitle. */