sunpeak 0.16.11 → 0.16.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.
Files changed (64) hide show
  1. package/README.md +12 -11
  2. package/bin/commands/dev.mjs +12 -6
  3. package/dist/chatgpt/globals.css +20 -10
  4. package/dist/chatgpt/index.cjs +2 -2
  5. package/dist/chatgpt/index.js +2 -2
  6. package/dist/claude/index.cjs +1 -1
  7. package/dist/claude/index.js +1 -1
  8. package/dist/hooks/index.d.ts +10 -4
  9. package/dist/hooks/use-download-file.d.ts +42 -0
  10. package/dist/hooks/use-list-server-resources.d.ts +56 -0
  11. package/dist/hooks/use-read-server-resource.d.ts +47 -0
  12. package/dist/{index-POfU7IR6.cjs → index-B8WZDM6g.cjs} +2 -2
  13. package/dist/index-B8WZDM6g.cjs.map +1 -0
  14. package/dist/{index-DJt59490.js → index-Ccuh7yMs.js} +2 -2
  15. package/dist/index-Ccuh7yMs.js.map +1 -0
  16. package/dist/{index-Dyoz9lnx.js → index-CsGD9XQo.js} +2 -2
  17. package/dist/{index-Dyoz9lnx.js.map → index-CsGD9XQo.js.map} +1 -1
  18. package/dist/{index-BsWYp00t.cjs → index-DoKDj4GA.cjs} +2 -2
  19. package/dist/{index-BsWYp00t.cjs.map → index-DoKDj4GA.cjs.map} +1 -1
  20. package/dist/index.cjs +702 -469
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.ts +3 -3
  23. package/dist/index.js +3681 -3448
  24. package/dist/index.js.map +1 -1
  25. package/dist/mcp/index.cjs +886 -682
  26. package/dist/mcp/index.cjs.map +1 -1
  27. package/dist/mcp/index.js +886 -682
  28. package/dist/mcp/index.js.map +1 -1
  29. package/dist/platform/chatgpt/index.cjs +1 -1
  30. package/dist/platform/chatgpt/index.cjs.map +1 -1
  31. package/dist/platform/chatgpt/index.d.ts +3 -2
  32. package/dist/platform/chatgpt/index.js +1 -1
  33. package/dist/platform/chatgpt/index.js.map +1 -1
  34. package/dist/platform/chatgpt/use-file-download.d.ts +3 -0
  35. package/dist/{protocol-BD5jDQEx.js → protocol-CF-P_kw5.js} +1985 -1427
  36. package/dist/protocol-CF-P_kw5.js.map +1 -0
  37. package/dist/{protocol-BOjXuK6l.cjs → protocol-CfvM5B6z.cjs} +1936 -1378
  38. package/dist/protocol-CfvM5B6z.cjs.map +1 -0
  39. package/dist/simulator/index.cjs +1 -1
  40. package/dist/simulator/index.js +1 -1
  41. package/dist/simulator/mcp-app-host.d.ts +1 -0
  42. package/dist/{simulator-BUF-_85b.js → simulator-BAcm4Pby.js} +599 -561
  43. package/dist/simulator-BAcm4Pby.js.map +1 -0
  44. package/dist/{simulator-tkLFRzjr.cjs → simulator-CiVQFdZN.cjs} +599 -561
  45. package/dist/simulator-CiVQFdZN.cjs.map +1 -0
  46. package/dist/style.css +20 -10
  47. package/dist/{use-app-BpAJqzdE.cjs → use-app-CaTJmpgj.cjs} +741 -705
  48. package/dist/use-app-CaTJmpgj.cjs.map +1 -0
  49. package/dist/{use-app-WOUdh1PR.js → use-app-DTTzqi-0.js} +754 -718
  50. package/dist/use-app-DTTzqi-0.js.map +1 -0
  51. package/package.json +19 -19
  52. package/template/README.md +3 -2
  53. package/template/node_modules/.bin/playwright +2 -2
  54. package/template/node_modules/.bin/vite +2 -2
  55. package/template/node_modules/.bin/vitest +2 -2
  56. package/template/package.json +16 -16
  57. package/dist/index-DJt59490.js.map +0 -1
  58. package/dist/index-POfU7IR6.cjs.map +0 -1
  59. package/dist/protocol-BD5jDQEx.js.map +0 -1
  60. package/dist/protocol-BOjXuK6l.cjs.map +0 -1
  61. package/dist/simulator-BUF-_85b.js.map +0 -1
  62. package/dist/simulator-tkLFRzjr.cjs.map +0 -1
  63. package/dist/use-app-BpAJqzdE.cjs.map +0 -1
  64. package/dist/use-app-WOUdh1PR.js.map +0 -1
package/README.md CHANGED
@@ -22,7 +22,7 @@ Quickstart, build, test, and ship your Claude or ChatGPT App!
22
22
 
23
23
  [Demo (Hosted)](https://sunpeak.ai/simulator) ~
24
24
  [Demo (Video)](https://cdn.sunpeak.ai/sunpeak-demo-prod.mp4) ~
25
- [Discord (NEW)](https://discord.gg/FB2QNXqRnw) ~
25
+ [Discord](https://discord.gg/FB2QNXqRnw) ~
26
26
  [Documentation](https://sunpeak.ai/docs) ~
27
27
  [GitHub](https://github.com/Sunpeak-AI/sunpeak)
28
28
 
@@ -45,7 +45,7 @@ sunpeak new
45
45
 
46
46
  ## Overview
47
47
 
48
- `sunpeak` is an npm package that helps you build MCP Apps (interactive UI resources) while keeping your MCP server client-agnostic. Built on the [MCP Apps SDK](https://github.com/modelcontextprotocol/ext-apps) (`@modelcontextprotocol/ext-apps`). `sunpeak` consists of:
48
+ `sunpeak` is an npm package that helps you build MCP Apps (interactive UI [resources](https://sunpeak.ai/docs/mcp-apps/mcp/resources)) while keeping your [MCP server](https://sunpeak.ai/docs/mcp-apps/mcp/overview) client-agnostic. Built on the [MCP Apps SDK](https://github.com/modelcontextprotocol/ext-apps) (`@modelcontextprotocol/ext-apps`). `sunpeak` consists of:
49
49
 
50
50
  ### The `sunpeak` library
51
51
 
@@ -55,21 +55,21 @@ sunpeak new
55
55
 
56
56
  ### The `sunpeak` framework
57
57
 
58
- Next.js for MCP Apps. Using an example App `my-app` with a `Review` UI (MCP resource), `sunpeak` projects look like:
58
+ Next.js for MCP Apps. Using an example App `my-app` with a `Review` UI ([MCP resource](https://sunpeak.ai/docs/mcp-apps/mcp/resources)), `sunpeak` projects look like:
59
59
 
60
60
  ```bash
61
61
  my-app/
62
62
  ├── src/
63
63
  │ ├── resources/
64
64
  │ │ └── review/
65
- │ │ └── review.tsx # Review UI component + resource metadata.
65
+ │ │ └── review.tsx # Review UI component + resource metadata.
66
66
  │ ├── tools/
67
- │ │ ├── review-diff.ts # Tool with handler, schema, and resource reference.
68
- │ │ └── review-post.ts # Multiple tools can share one resource.
69
- │ └── server.ts # Optional: auth, server config.
67
+ │ │ ├── review-diff.ts # Tool with handler, schema, and resource reference.
68
+ │ │ └── review-post.ts # Multiple tools can share one resource.
69
+ │ └── server.ts # Optional: auth, server config.
70
70
  ├── tests/simulations/
71
- │ ├── review-diff.json # Mock state for testing.
72
- │ └── review-post.json # Mock state for testing.
71
+ │ ├── review-diff.json # Mock state for testing.
72
+ │ └── review-post.json # Mock state for testing.
73
73
  └── package.json
74
74
  ```
75
75
 
@@ -92,11 +92,11 @@ Commands for managing MCP Apps:
92
92
 
93
93
  ## Example App
94
94
 
95
- Example `Resource`, `Simulation`, and testing file (using the `Simulator`) for an MCP resource called "Review".
95
+ Example `Resource`, `Simulation`, and testing file (using the `Simulator`) for an [MCP resource](https://sunpeak.ai/docs/mcp-apps/mcp/resources) called "Review".
96
96
 
97
97
  ### `Resource` Component
98
98
 
99
- Each resource `.tsx` file exports both the React component and the MCP resource metadata:
99
+ Each resource `.tsx` file exports both the React component and the [MCP resource](https://sunpeak.ai/docs/mcp-apps/mcp/resources) metadata:
100
100
 
101
101
  ```tsx
102
102
  // src/resources/review/review.tsx
@@ -222,5 +222,6 @@ npx skills add Sunpeak-AI/sunpeak@create-sunpeak-app
222
222
  ## Resources
223
223
 
224
224
  - [MCP Apps Documentation](https://sunpeak.ai/docs/mcp-apps/introduction)
225
+ - [MCP Overview](https://sunpeak.ai/docs/mcp-apps/mcp/overview) · [Tools](https://sunpeak.ai/docs/mcp-apps/mcp/tools) · [Resources](https://sunpeak.ai/docs/mcp-apps/mcp/resources)
225
226
  - [MCP Apps SDK](https://github.com/modelcontextprotocol/ext-apps)
226
227
  - [ChatGPT Apps SDK Design Guidelines](https://developers.openai.com/apps-sdk/concepts/design-guidelines)
@@ -158,18 +158,19 @@ export async function dev(projectRoot = process.cwd(), args = []) {
158
158
 
159
159
  // Import sunpeak modules (MCP server and discovery utilities)
160
160
  // Use discovery-cli which only exports Node.js-safe utilities (no React components)
161
- let sunpeakMcp, sunpeakDiscovery;
161
+ let sunpeakMcp, sunpeakDiscovery, loaderServer;
162
162
  if (isTemplate) {
163
- // In workspace dev mode, use Vite to load TypeScript source directly
164
- const loaderServer = await createServer({
163
+ // In workspace dev mode, use Vite to load TypeScript source directly.
164
+ // Keep the loader server alive — Vite 7's module runner invalidates loaded
165
+ // modules on close, breaking dynamic imports (e.g. `await import('esbuild')`).
166
+ loaderServer = await createServer({
165
167
  root: resolve(projectRoot, '..'),
166
- server: { middlewareMode: true },
168
+ server: { middlewareMode: true, hmr: false },
167
169
  appType: 'custom',
168
170
  logLevel: 'silent',
169
171
  });
170
172
  sunpeakMcp = await loaderServer.ssrLoadModule('./src/mcp/index.ts');
171
173
  sunpeakDiscovery = await loaderServer.ssrLoadModule('./src/lib/discovery-cli.ts');
172
- await loaderServer.close();
173
174
  } else {
174
175
  // Import from installed sunpeak package
175
176
  const sunpeakBase = require.resolve('sunpeak').replace(/dist\/index\.(c)?js$/, '');
@@ -364,6 +365,7 @@ if (import.meta.hot) {
364
365
  },
365
366
  server: {
366
367
  middlewareMode: true,
368
+ hmr: { port: 24679 },
367
369
  allowedHosts: true,
368
370
  watch: {
369
371
  // Only watch files that affect the UI bundle (not JSON, tests, etc.)
@@ -400,26 +402,30 @@ if (import.meta.hot) {
400
402
  // On successful builds, mcpHandle.invalidateResources() notifies tunnel sessions.
401
403
  startBuildWatcher(projectRoot, resourcesDir, mcpHandle);
402
404
 
403
- // Handle signals - close both servers
405
+ // Handle signals - close all servers
404
406
  process.on('SIGINT', async () => {
405
407
  await mcpViteServer.close();
408
+ if (loaderServer) await loaderServer.close();
406
409
  await server.close();
407
410
  process.exit(0);
408
411
  });
409
412
 
410
413
  process.on('SIGTERM', async () => {
411
414
  await mcpViteServer.close();
415
+ if (loaderServer) await loaderServer.close();
412
416
  await server.close();
413
417
  process.exit(0);
414
418
  });
415
419
  } else {
416
420
  // No simulations - just handle signals for the dev server
417
421
  process.on('SIGINT', async () => {
422
+ if (loaderServer) await loaderServer.close();
418
423
  await server.close();
419
424
  process.exit(0);
420
425
  });
421
426
 
422
427
  process.on('SIGTERM', async () => {
428
+ if (loaderServer) await loaderServer.close();
423
429
  await server.close();
424
430
  process.exit(0);
425
431
  });
@@ -83,7 +83,7 @@
83
83
  }
84
84
 
85
85
  /* Bundled component styles */
86
- /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
86
+ /*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */
87
87
  @layer properties {
88
88
  @supports (((-webkit-hyphens: none)) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color: rgb(from red r g b)))) {
89
89
  *, :before, :after, ::backdrop {
@@ -157,8 +157,10 @@
157
157
 
158
158
  @layer theme {
159
159
  :root, :host {
160
- --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
161
- --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
160
+ --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
161
+ "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
162
+ --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
163
+ "Courier New", monospace;
162
164
  --color-black: #000;
163
165
  --color-white: #fff;
164
166
  --spacing: .25rem;
@@ -512,6 +514,10 @@
512
514
  inset-inline-start: calc(var(--spacing) * -2);
513
515
  }
514
516
 
517
+ .start {
518
+ inset-inline-start: var(--spacing);
519
+ }
520
+
515
521
  .start-0 {
516
522
  inset-inline-start: calc(var(--spacing) * 0);
517
523
  }
@@ -520,6 +526,10 @@
520
526
  inset-inline-start: calc(var(--spacing) * 4);
521
527
  }
522
528
 
529
+ .end {
530
+ inset-inline-end: var(--spacing);
531
+ }
532
+
523
533
  .end-0 {
524
534
  inset-inline-end: calc(var(--spacing) * 0);
525
535
  }
@@ -984,7 +994,7 @@
984
994
  }
985
995
 
986
996
  .transform {
987
- transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
997
+ transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
988
998
  }
989
999
 
990
1000
  .animate-spin {
@@ -1001,7 +1011,7 @@
1001
1011
 
1002
1012
  .touch-pan-y {
1003
1013
  --tw-pan-y: pan-y;
1004
- touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
1014
+ touch-action: var(--tw-pan-x, ) var(--tw-pan-y, ) var(--tw-pinch-zoom, );
1005
1015
  }
1006
1016
 
1007
1017
  .resize {
@@ -1745,7 +1755,7 @@
1745
1755
  }
1746
1756
 
1747
1757
  .ring {
1748
- --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
1758
+ --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
1749
1759
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
1750
1760
  }
1751
1761
 
@@ -1765,13 +1775,13 @@
1765
1775
  }
1766
1776
 
1767
1777
  .filter {
1768
- filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
1778
+ filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
1769
1779
  }
1770
1780
 
1771
1781
  .backdrop-blur-sm {
1772
1782
  --tw-backdrop-blur: blur(var(--blur-sm));
1773
- -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
1774
- backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
1783
+ -webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
1784
+ backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
1775
1785
  }
1776
1786
 
1777
1787
  .transition {
@@ -2132,7 +2142,7 @@
2132
2142
  }
2133
2143
 
2134
2144
  .xl\:ring {
2135
- --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
2145
+ --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
2136
2146
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2137
2147
  }
2138
2148
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const simulator = require("../simulator-tkLFRzjr.cjs");
4
- const chatgpt_index = require("../index-BsWYp00t.cjs");
3
+ const simulator = require("../simulator-CiVQFdZN.cjs");
4
+ const chatgpt_index = require("../index-DoKDj4GA.cjs");
5
5
  const simulatorUrl = require("../simulator-url-rgg_KYOg.cjs");
6
6
  const discovery = require("../discovery-DmB8_4QL.cjs");
7
7
  exports.IframeResource = simulator.IframeResource;
@@ -1,5 +1,5 @@
1
- import { I, M, a, S, T, j, m } from "../simulator-BUF-_85b.js";
2
- import { C } from "../index-Dyoz9lnx.js";
1
+ import { I, M, a, S, T, j, m } from "../simulator-BAcm4Pby.js";
2
+ import { C } from "../index-CsGD9XQo.js";
3
3
  import { c } from "../simulator-url-CuLqtnSS.js";
4
4
  import { b, a as a2, c as c2, d, e, f, g, h, i, t } from "../discovery-CH80W5l9.js";
5
5
  export {
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const simulator = require("../simulator-tkLFRzjr.cjs");
3
+ const simulator = require("../simulator-CiVQFdZN.cjs");
4
4
  exports.ClaudeSimulator = simulator.Simulator;
5
5
  //# sourceMappingURL=index.cjs.map
@@ -1,4 +1,4 @@
1
- import { S } from "../simulator-BUF-_85b.js";
1
+ import { S } from "../simulator-BAcm4Pby.js";
2
2
  export {
3
3
  S as ClaudeSimulator
4
4
  };
@@ -18,16 +18,22 @@ export { SafeArea } from './safe-area';
18
18
  export type { SafeAreaProps } from './safe-area';
19
19
  export { useCallServerTool } from './use-call-server-tool';
20
20
  export type { CallServerToolParams, CallServerToolResult } from './use-call-server-tool';
21
- export { useSendMessage } from './use-send-message';
22
- export type { SendMessageParams, MessageContent } from './use-send-message';
23
- export { useUpdateModelContext } from './use-update-model-context';
24
- export type { UpdateModelContextParams } from './use-update-model-context';
21
+ export { useDownloadFile } from './use-download-file';
22
+ export type { DownloadFileParams, DownloadFileResult } from './use-download-file';
23
+ export { useListServerResources } from './use-list-server-resources';
24
+ export type { ListServerResourcesParams, ListServerResourcesResult, ServerResource, } from './use-list-server-resources';
25
25
  export { useOpenLink } from './use-open-link';
26
26
  export type { OpenLinkParams } from './use-open-link';
27
+ export { useReadServerResource } from './use-read-server-resource';
28
+ export type { ReadServerResourceParams, ReadServerResourceResult, } from './use-read-server-resource';
27
29
  export { useRequestDisplayMode } from './use-request-display-mode';
28
30
  export type { AppDisplayMode } from './use-request-display-mode';
29
31
  export { useSendLog } from './use-send-log';
30
32
  export type { LogLevel, SendLogParams } from './use-send-log';
33
+ export { useSendMessage } from './use-send-message';
34
+ export type { SendMessageParams, MessageContent } from './use-send-message';
35
+ export { useUpdateModelContext } from './use-update-model-context';
36
+ export type { UpdateModelContextParams } from './use-update-model-context';
31
37
  export { useHostInfo } from './use-host-info';
32
38
  export type { HostVersion, HostCapabilities } from './use-host-info';
33
39
  export { useTeardown } from './use-teardown';
@@ -0,0 +1,42 @@
1
+ import { McpUiDownloadFileRequest } from '@modelcontextprotocol/ext-apps';
2
+ /**
3
+ * Parameters for downloading a file through the host.
4
+ */
5
+ export type DownloadFileParams = McpUiDownloadFileRequest['params'];
6
+ /**
7
+ * Result from a file download request.
8
+ */
9
+ export interface DownloadFileResult {
10
+ /** Whether the download failed (e.g. user cancelled or host denied). */
11
+ isError?: boolean;
12
+ }
13
+ /**
14
+ * Hook to download files through the host.
15
+ *
16
+ * Since MCP Apps run in sandboxed iframes where direct downloads are blocked,
17
+ * this provides a host-mediated mechanism for file exports. Supports embedded
18
+ * text/binary content and resource links.
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * function ExportButton({ data }: { data: unknown }) {
23
+ * const downloadFile = useDownloadFile();
24
+ *
25
+ * const handleExport = async () => {
26
+ * await downloadFile({
27
+ * contents: [{
28
+ * type: 'resource',
29
+ * resource: {
30
+ * uri: 'file:///export.json',
31
+ * mimeType: 'application/json',
32
+ * text: JSON.stringify(data, null, 2),
33
+ * },
34
+ * }],
35
+ * });
36
+ * };
37
+ *
38
+ * return <button onClick={handleExport}>Export JSON</button>;
39
+ * }
40
+ * ```
41
+ */
42
+ export declare function useDownloadFile(): (params: DownloadFileParams) => Promise<DownloadFileResult | undefined>;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Parameters for listing server resources.
3
+ */
4
+ export interface ListServerResourcesParams {
5
+ /** Pagination cursor from a previous response. */
6
+ cursor?: string;
7
+ }
8
+ /**
9
+ * A resource available on the MCP server.
10
+ */
11
+ export interface ServerResource {
12
+ /** Resource URI. */
13
+ uri: string;
14
+ /** Human-readable name. */
15
+ name: string;
16
+ /** Optional description. */
17
+ description?: string;
18
+ /** MIME type hint. */
19
+ mimeType?: string;
20
+ }
21
+ /**
22
+ * Result from listing server resources.
23
+ */
24
+ export interface ListServerResourcesResult {
25
+ /** Available resources. */
26
+ resources: ServerResource[];
27
+ /** Cursor for fetching the next page, if more results exist. */
28
+ nextCursor?: string;
29
+ }
30
+ /**
31
+ * Hook to discover available resources on the originating MCP server.
32
+ *
33
+ * Resources are proxied through the host. Supports pagination via cursor.
34
+ * Use {@link useReadServerResource} to read a discovered resource.
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * function ResourcePicker() {
39
+ * const listServerResources = useListServerResources();
40
+ * const [resources, setResources] = useState<ServerResource[]>([]);
41
+ *
42
+ * useEffect(() => {
43
+ * listServerResources().then(result => {
44
+ * if (result) setResources(result.resources);
45
+ * });
46
+ * }, [listServerResources]);
47
+ *
48
+ * return (
49
+ * <ul>
50
+ * {resources.map(r => <li key={r.uri}>{r.name}</li>)}
51
+ * </ul>
52
+ * );
53
+ * }
54
+ * ```
55
+ */
56
+ export declare function useListServerResources(): (params?: ListServerResourcesParams) => Promise<ListServerResourcesResult | undefined>;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Parameters for reading a server resource.
3
+ */
4
+ export interface ReadServerResourceParams {
5
+ /** URI of the resource to read (e.g. `file:///path` or custom scheme). */
6
+ uri: string;
7
+ }
8
+ /**
9
+ * Result from reading a server resource.
10
+ */
11
+ export interface ReadServerResourceResult {
12
+ /** Resource contents returned by the server. */
13
+ contents: Array<{
14
+ uri: string;
15
+ mimeType?: string;
16
+ text?: string;
17
+ blob?: string;
18
+ }>;
19
+ }
20
+ /**
21
+ * Hook to read resources from the originating MCP server.
22
+ *
23
+ * Resources are proxied through the host. Use {@link useListServerResources}
24
+ * to discover available resources first.
25
+ *
26
+ * @example
27
+ * ```tsx
28
+ * function VideoPlayer() {
29
+ * const readServerResource = useReadServerResource();
30
+ * const [src, setSrc] = useState<string>();
31
+ *
32
+ * const loadVideo = async (uri: string) => {
33
+ * const result = await readServerResource({ uri });
34
+ * const content = result?.contents[0];
35
+ * if (content && 'blob' in content && content.blob) {
36
+ * const binary = atob(content.blob);
37
+ * const bytes = Uint8Array.from(binary, c => c.charCodeAt(0));
38
+ * const blob = new Blob([bytes], { type: content.mimeType });
39
+ * setSrc(URL.createObjectURL(blob));
40
+ * }
41
+ * };
42
+ *
43
+ * return src ? <video src={src} controls /> : <button onClick={() => loadVideo('videos://intro')}>Load</button>;
44
+ * }
45
+ * ```
46
+ */
47
+ export declare function useReadServerResource(): (params: ReadServerResourceParams) => Promise<ReadServerResourceResult | undefined>;
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const simulator = require("./simulator-tkLFRzjr.cjs");
2
+ const simulator = require("./simulator-CiVQFdZN.cjs");
3
3
  const simulatorUrl = require("./simulator-url-rgg_KYOg.cjs");
4
4
  const discovery = require("./discovery-DmB8_4QL.cjs");
5
5
  const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -36,4 +36,4 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
36
36
  useThemeContext: simulator.useThemeContext
37
37
  }, Symbol.toStringTag, { value: "Module" }));
38
38
  exports.index = index;
39
- //# sourceMappingURL=index-POfU7IR6.cjs.map
39
+ //# sourceMappingURL=index-B8WZDM6g.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-B8WZDM6g.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,4 +1,4 @@
1
- import { I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, b as SidebarCheckbox, c as SidebarCollapsibleControl, d as SidebarControl, e as SidebarInput, f as SidebarSelect, g as SidebarTextarea, h as SidebarToggle, i as SimpleSidebar, S as Simulator, T as ThemeProvider, j as extractResourceCSP, k as getHostShell, l as getRegisteredHosts, r as registerHostShell, u as useSimulatorState, m as useThemeContext } from "./simulator-BUF-_85b.js";
1
+ import { I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, b as SidebarCheckbox, c as SidebarCollapsibleControl, d as SidebarControl, e as SidebarInput, f as SidebarSelect, g as SidebarTextarea, h as SidebarToggle, i as SimpleSidebar, S as Simulator, T as ThemeProvider, j as extractResourceCSP, k as getHostShell, l as getRegisteredHosts, r as registerHostShell, u as useSimulatorState, m as useThemeContext } from "./simulator-BAcm4Pby.js";
2
2
  import { c as createSimulatorUrl } from "./simulator-url-CuLqtnSS.js";
3
3
  import { b as buildDevSimulations, a as buildResourceMap, c as buildSimulations, d as createResourceExports, e as extractResourceKey, f as extractSimulationKey, g as findResourceDirs, h as findResourceKey, i as getComponentName, t as toPascalCase } from "./discovery-CH80W5l9.js";
4
4
  const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -37,4 +37,4 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
37
37
  export {
38
38
  index as i
39
39
  };
40
- //# sourceMappingURL=index-DJt59490.js.map
40
+ //# sourceMappingURL=index-Ccuh7yMs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-Ccuh7yMs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,4 +1,4 @@
1
- import { j as extractResourceCSP, T as ThemeProvider, i as SimpleSidebar, C as Conversation, d as SidebarControl, f as SidebarSelect, c as SidebarCollapsibleControl, h as SidebarToggle, e as SidebarInput, b as SidebarCheckbox, g as SidebarTextarea, I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, S as Simulator, m as useThemeContext } from "./simulator-BUF-_85b.js";
1
+ import { j as extractResourceCSP, T as ThemeProvider, i as SimpleSidebar, C as Conversation, d as SidebarControl, f as SidebarSelect, c as SidebarCollapsibleControl, h as SidebarToggle, e as SidebarInput, b as SidebarCheckbox, g as SidebarTextarea, I as IframeResource, M as McpAppHost, a as SCREEN_WIDTHS, S as Simulator, m as useThemeContext } from "./simulator-BAcm4Pby.js";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { useMemo, useState, useCallback, useEffect } from "react";
@@ -508,4 +508,4 @@ export {
508
508
  ChatGPTSimulator as C,
509
509
  index as i
510
510
  };
511
- //# sourceMappingURL=index-Dyoz9lnx.js.map
511
+ //# sourceMappingURL=index-CsGD9XQo.js.map