@miragon/mcp-toolkit-ui 0.10.1
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 +36 -0
- package/dist/app/adapt-data-widget.d.ts +33 -0
- package/dist/app/adapt-data-widget.d.ts.map +1 -0
- package/dist/app/adapt-data-widget.js +35 -0
- package/dist/app/adapt-data-widget.js.map +1 -0
- package/dist/app/builder/CatalogueSheet.d.ts +13 -0
- package/dist/app/builder/CatalogueSheet.d.ts.map +1 -0
- package/dist/app/builder/CatalogueSheet.js +33 -0
- package/dist/app/builder/CatalogueSheet.js.map +1 -0
- package/dist/app/builder/PipelineStrip.d.ts +22 -0
- package/dist/app/builder/PipelineStrip.d.ts.map +1 -0
- package/dist/app/builder/PipelineStrip.js +31 -0
- package/dist/app/builder/PipelineStrip.js.map +1 -0
- package/dist/app/builder/PreviewPane.d.ts +13 -0
- package/dist/app/builder/PreviewPane.d.ts.map +1 -0
- package/dist/app/builder/PreviewPane.js +21 -0
- package/dist/app/builder/PreviewPane.js.map +1 -0
- package/dist/app/builder/SaveDialog.d.ts +14 -0
- package/dist/app/builder/SaveDialog.d.ts.map +1 -0
- package/dist/app/builder/SaveDialog.js +14 -0
- package/dist/app/builder/SaveDialog.js.map +1 -0
- package/dist/app/builder/Toolbar.d.ts +17 -0
- package/dist/app/builder/Toolbar.d.ts.map +1 -0
- package/dist/app/builder/Toolbar.js +15 -0
- package/dist/app/builder/Toolbar.js.map +1 -0
- package/dist/app/builder/Workspace.d.ts +28 -0
- package/dist/app/builder/Workspace.d.ts.map +1 -0
- package/dist/app/builder/Workspace.js +117 -0
- package/dist/app/builder/Workspace.js.map +1 -0
- package/dist/app/builder/builder-model.d.ts +86 -0
- package/dist/app/builder/builder-model.d.ts.map +1 -0
- package/dist/app/builder/builder-model.js +174 -0
- package/dist/app/builder/builder-model.js.map +1 -0
- package/dist/app/builder/builder-reducer.d.ts +71 -0
- package/dist/app/builder/builder-reducer.d.ts.map +1 -0
- package/dist/app/builder/builder-reducer.js +201 -0
- package/dist/app/builder/builder-reducer.js.map +1 -0
- package/dist/app/builder/labels.d.ts +78 -0
- package/dist/app/builder/labels.d.ts.map +1 -0
- package/dist/app/builder/labels.js +71 -0
- package/dist/app/builder/labels.js.map +1 -0
- package/dist/app/builder/status-chip.d.ts +10 -0
- package/dist/app/builder/status-chip.d.ts.map +1 -0
- package/dist/app/builder/status-chip.js +16 -0
- package/dist/app/builder/status-chip.js.map +1 -0
- package/dist/app/host-bridge.d.ts +211 -0
- package/dist/app/host-bridge.d.ts.map +1 -0
- package/dist/app/host-bridge.js +247 -0
- package/dist/app/host-bridge.js.map +1 -0
- package/dist/app/index.d.ts +16 -0
- package/dist/app/index.d.ts.map +1 -0
- package/dist/app/index.js +18 -0
- package/dist/app/index.js.map +1 -0
- package/dist/app/layout-builder.d.ts +48 -0
- package/dist/app/layout-builder.d.ts.map +1 -0
- package/dist/app/layout-builder.js +418 -0
- package/dist/app/layout-builder.js.map +1 -0
- package/dist/app/mcp-app-view.d.ts +43 -0
- package/dist/app/mcp-app-view.d.ts.map +1 -0
- package/dist/app/mcp-app-view.js +169 -0
- package/dist/app/mcp-app-view.js.map +1 -0
- package/dist/app/mcp-toolkit-app.d.ts +18 -0
- package/dist/app/mcp-toolkit-app.d.ts.map +1 -0
- package/dist/app/mcp-toolkit-app.js +22 -0
- package/dist/app/mcp-toolkit-app.js.map +1 -0
- package/dist/app/use-host-actions.d.ts +57 -0
- package/dist/app/use-host-actions.d.ts.map +1 -0
- package/dist/app/use-host-actions.js +42 -0
- package/dist/app/use-host-actions.js.map +1 -0
- package/dist/app/widget-fixture.d.ts +180 -0
- package/dist/app/widget-fixture.d.ts.map +1 -0
- package/dist/app/widget-fixture.js +273 -0
- package/dist/app/widget-fixture.js.map +1 -0
- package/dist/app/widget-props-sheet.d.ts +20 -0
- package/dist/app/widget-props-sheet.d.ts.map +1 -0
- package/dist/app/widget-props-sheet.js +87 -0
- package/dist/app/widget-props-sheet.js.map +1 -0
- package/dist/app/widget-renderer.d.ts +87 -0
- package/dist/app/widget-renderer.d.ts.map +1 -0
- package/dist/app/widget-renderer.js +105 -0
- package/dist/app/widget-renderer.js.map +1 -0
- package/dist/components/DrillButton.d.ts +22 -0
- package/dist/components/DrillButton.d.ts.map +1 -0
- package/dist/components/DrillButton.js +13 -0
- package/dist/components/DrillButton.js.map +1 -0
- package/dist/components/FilterBar.d.ts +28 -0
- package/dist/components/FilterBar.d.ts.map +1 -0
- package/dist/components/FilterBar.js +12 -0
- package/dist/components/FilterBar.js.map +1 -0
- package/dist/components/GridLayout.d.ts +26 -0
- package/dist/components/GridLayout.d.ts.map +1 -0
- package/dist/components/GridLayout.js +31 -0
- package/dist/components/GridLayout.js.map +1 -0
- package/dist/components/GroupCard.d.ts +21 -0
- package/dist/components/GroupCard.d.ts.map +1 -0
- package/dist/components/GroupCard.js +24 -0
- package/dist/components/GroupCard.js.map +1 -0
- package/dist/components/KpiGrid.d.ts +43 -0
- package/dist/components/KpiGrid.d.ts.map +1 -0
- package/dist/components/KpiGrid.js +35 -0
- package/dist/components/KpiGrid.js.map +1 -0
- package/dist/components/ListFooter.d.ts +22 -0
- package/dist/components/ListFooter.d.ts.map +1 -0
- package/dist/components/ListFooter.js +13 -0
- package/dist/components/ListFooter.js.map +1 -0
- package/dist/components/Pills.d.ts +25 -0
- package/dist/components/Pills.d.ts.map +1 -0
- package/dist/components/Pills.js +17 -0
- package/dist/components/Pills.js.map +1 -0
- package/dist/components/SectionHeading.d.ts +16 -0
- package/dist/components/SectionHeading.d.ts.map +1 -0
- package/dist/components/SectionHeading.js +10 -0
- package/dist/components/SectionHeading.js.map +1 -0
- package/dist/components/WidgetHeader.d.ts +21 -0
- package/dist/components/WidgetHeader.d.ts.map +1 -0
- package/dist/components/WidgetHeader.js +11 -0
- package/dist/components/WidgetHeader.js.map +1 -0
- package/dist/hooks/index.d.ts +11 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/use-debounced-value.d.ts +7 -0
- package/dist/hooks/use-debounced-value.d.ts.map +1 -0
- package/dist/hooks/use-debounced-value.js +15 -0
- package/dist/hooks/use-debounced-value.js.map +1 -0
- package/dist/hooks/use-mobile.d.ts +6 -0
- package/dist/hooks/use-mobile.d.ts.map +1 -0
- package/dist/hooks/use-mobile.js +19 -0
- package/dist/hooks/use-mobile.js.map +1 -0
- package/dist/hooks/use-tool-query.d.ts +21 -0
- package/dist/hooks/use-tool-query.d.ts.map +1 -0
- package/dist/hooks/use-tool-query.js +47 -0
- package/dist/hooks/use-tool-query.js.map +1 -0
- package/dist/hooks/use-tool-result-recovery.d.ts +54 -0
- package/dist/hooks/use-tool-result-recovery.d.ts.map +1 -0
- package/dist/hooks/use-tool-result-recovery.js +93 -0
- package/dist/hooks/use-tool-result-recovery.js.map +1 -0
- package/dist/hooks/use-view-data.d.ts +19 -0
- package/dist/hooks/use-view-data.d.ts.map +1 -0
- package/dist/hooks/use-view-data.js +18 -0
- package/dist/hooks/use-view-data.js.map +1 -0
- package/dist/hooks/use-view-tool-query.d.ts +18 -0
- package/dist/hooks/use-view-tool-query.d.ts.map +1 -0
- package/dist/hooks/use-view-tool-query.js +29 -0
- package/dist/hooks/use-view-tool-query.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/parse-tool-result.d.ts +39 -0
- package/dist/lib/parse-tool-result.d.ts.map +1 -0
- package/dist/lib/parse-tool-result.js +66 -0
- package/dist/lib/parse-tool-result.js.map +1 -0
- package/dist/lib/tone-utils.d.ts +18 -0
- package/dist/lib/tone-utils.d.ts.map +1 -0
- package/dist/lib/tone-utils.js +25 -0
- package/dist/lib/tone-utils.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/locale/index.d.ts +3 -0
- package/dist/locale/index.d.ts.map +1 -0
- package/dist/locale/index.js +7 -0
- package/dist/locale/index.js.map +1 -0
- package/dist/locale/locale-provider.d.ts +50 -0
- package/dist/locale/locale-provider.d.ts.map +1 -0
- package/dist/locale/locale-provider.js +47 -0
- package/dist/locale/locale-provider.js.map +1 -0
- package/dist/primitives/alert.d.ts +10 -0
- package/dist/primitives/alert.d.ts.map +1 -0
- package/dist/primitives/alert.js +25 -0
- package/dist/primitives/alert.js.map +1 -0
- package/dist/primitives/badge.d.ts +8 -0
- package/dist/primitives/badge.d.ts.map +1 -0
- package/dist/primitives/badge.js +34 -0
- package/dist/primitives/badge.js.map +1 -0
- package/dist/primitives/button.d.ts +11 -0
- package/dist/primitives/button.d.ts.map +1 -0
- package/dist/primitives/button.js +36 -0
- package/dist/primitives/button.js.map +1 -0
- package/dist/primitives/card.d.ts +12 -0
- package/dist/primitives/card.d.ts.map +1 -0
- package/dist/primitives/card.js +25 -0
- package/dist/primitives/card.js.map +1 -0
- package/dist/primitives/dialog.d.ts +18 -0
- package/dist/primitives/dialog.d.ts.map +1 -0
- package/dist/primitives/dialog.js +38 -0
- package/dist/primitives/dialog.js.map +1 -0
- package/dist/primitives/input.d.ts +4 -0
- package/dist/primitives/input.d.ts.map +1 -0
- package/dist/primitives/input.js +7 -0
- package/dist/primitives/input.js.map +1 -0
- package/dist/primitives/scroll-area.d.ts +6 -0
- package/dist/primitives/scroll-area.d.ts.map +1 -0
- package/dist/primitives/scroll-area.js +11 -0
- package/dist/primitives/scroll-area.js.map +1 -0
- package/dist/primitives/select.d.ts +16 -0
- package/dist/primitives/select.d.ts.map +1 -0
- package/dist/primitives/select.js +38 -0
- package/dist/primitives/select.js.map +1 -0
- package/dist/primitives/separator.d.ts +4 -0
- package/dist/primitives/separator.d.ts.map +1 -0
- package/dist/primitives/separator.js +9 -0
- package/dist/primitives/separator.js.map +1 -0
- package/dist/primitives/sheet.d.ts +15 -0
- package/dist/primitives/sheet.d.ts.map +1 -0
- package/dist/primitives/sheet.js +41 -0
- package/dist/primitives/sheet.js.map +1 -0
- package/dist/primitives/skeleton.d.ts +3 -0
- package/dist/primitives/skeleton.d.ts.map +1 -0
- package/dist/primitives/skeleton.js +7 -0
- package/dist/primitives/skeleton.js.map +1 -0
- package/dist/primitives/switch.d.ts +5 -0
- package/dist/primitives/switch.d.ts.map +1 -0
- package/dist/primitives/switch.js +8 -0
- package/dist/primitives/switch.js.map +1 -0
- package/dist/primitives/table.d.ts +11 -0
- package/dist/primitives/table.d.ts.map +1 -0
- package/dist/primitives/table.js +28 -0
- package/dist/primitives/table.js.map +1 -0
- package/dist/primitives/tabs.d.ts +12 -0
- package/dist/primitives/tabs.d.ts.map +1 -0
- package/dist/primitives/tabs.js +29 -0
- package/dist/primitives/tabs.js.map +1 -0
- package/dist/providers/query-provider.d.ts +11 -0
- package/dist/providers/query-provider.d.ts.map +1 -0
- package/dist/providers/query-provider.js +20 -0
- package/dist/providers/query-provider.js.map +1 -0
- package/dist/theme/create-theme.d.ts +130 -0
- package/dist/theme/create-theme.d.ts.map +1 -0
- package/dist/theme/create-theme.js +65 -0
- package/dist/theme/create-theme.js.map +1 -0
- package/dist/theme/index.d.ts +7 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +7 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/presets.d.ts +25 -0
- package/dist/theme/presets.d.ts.map +1 -0
- package/dist/theme/presets.js +68 -0
- package/dist/theme/presets.js.map +1 -0
- package/dist/theme/theme-provider.d.ts +69 -0
- package/dist/theme/theme-provider.d.ts.map +1 -0
- package/dist/theme/theme-provider.js +79 -0
- package/dist/theme/theme-provider.js.map +1 -0
- package/package.json +71 -0
- package/src/app/adapt-data-widget.tsx +51 -0
- package/src/app/builder/CatalogueSheet.tsx +230 -0
- package/src/app/builder/PipelineStrip.tsx +260 -0
- package/src/app/builder/PreviewPane.tsx +72 -0
- package/src/app/builder/SaveDialog.tsx +95 -0
- package/src/app/builder/Toolbar.tsx +95 -0
- package/src/app/builder/Workspace.tsx +483 -0
- package/src/app/builder/builder-model.test.ts +351 -0
- package/src/app/builder/builder-model.ts +213 -0
- package/src/app/builder/builder-reducer.test.ts +441 -0
- package/src/app/builder/builder-reducer.ts +289 -0
- package/src/app/builder/labels.ts +139 -0
- package/src/app/builder/status-chip.tsx +37 -0
- package/src/app/host-bridge.test.ts +206 -0
- package/src/app/host-bridge.tsx +371 -0
- package/src/app/index.ts +51 -0
- package/src/app/layout-builder.tsx +872 -0
- package/src/app/mcp-app-view.tsx +367 -0
- package/src/app/mcp-toolkit-app.tsx +25 -0
- package/src/app/use-host-actions.test.ts +16 -0
- package/src/app/use-host-actions.tsx +88 -0
- package/src/app/widget-fixture.test.ts +108 -0
- package/src/app/widget-fixture.tsx +441 -0
- package/src/app/widget-props-sheet.tsx +285 -0
- package/src/app/widget-renderer.test.ts +42 -0
- package/src/app/widget-renderer.tsx +200 -0
- package/src/components/DrillButton.tsx +37 -0
- package/src/components/FilterBar.tsx +68 -0
- package/src/components/GridLayout.tsx +49 -0
- package/src/components/GroupCard.tsx +52 -0
- package/src/components/KpiGrid.tsx +134 -0
- package/src/components/ListFooter.tsx +48 -0
- package/src/components/Pills.tsx +45 -0
- package/src/components/SectionHeading.tsx +26 -0
- package/src/components/WidgetHeader.tsx +51 -0
- package/src/globals.css +168 -0
- package/src/hooks/index.ts +17 -0
- package/src/hooks/use-debounced-value.ts +15 -0
- package/src/hooks/use-mobile.ts +24 -0
- package/src/hooks/use-tool-query.ts +63 -0
- package/src/hooks/use-tool-result-recovery.test.ts +65 -0
- package/src/hooks/use-tool-result-recovery.ts +144 -0
- package/src/hooks/use-view-data.ts +31 -0
- package/src/hooks/use-view-tool-query.ts +38 -0
- package/src/index.ts +134 -0
- package/src/lib/parse-tool-result.test.ts +139 -0
- package/src/lib/parse-tool-result.ts +89 -0
- package/src/lib/tone-utils.test.ts +35 -0
- package/src/lib/tone-utils.ts +38 -0
- package/src/lib/utils.ts +6 -0
- package/src/locale/index.ts +7 -0
- package/src/locale/locale-provider.tsx +81 -0
- package/src/primitives/alert.tsx +60 -0
- package/src/primitives/badge.tsx +49 -0
- package/src/primitives/button.tsx +62 -0
- package/src/primitives/card.tsx +92 -0
- package/src/primitives/dialog.tsx +144 -0
- package/src/primitives/input.tsx +21 -0
- package/src/primitives/scroll-area.tsx +54 -0
- package/src/primitives/select.tsx +173 -0
- package/src/primitives/separator.tsx +21 -0
- package/src/primitives/sheet.tsx +134 -0
- package/src/primitives/skeleton.tsx +13 -0
- package/src/primitives/switch.tsx +24 -0
- package/src/primitives/table.tsx +87 -0
- package/src/primitives/tabs.tsx +79 -0
- package/src/providers/query-provider.tsx +38 -0
- package/src/theme/create-theme.test.ts +108 -0
- package/src/theme/create-theme.ts +158 -0
- package/src/theme/index.ts +9 -0
- package/src/theme/presets.ts +82 -0
- package/src/theme/theme-provider.tsx +152 -0
- package/src/ui-catalog.test.ts +112 -0
- package/ui-catalog.json +1280 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type WidgetComponent } from "./widget-renderer.js";
|
|
2
|
+
export interface McpAppViewLabels {
|
|
3
|
+
loading?: string;
|
|
4
|
+
refresh?: string;
|
|
5
|
+
refreshing?: string;
|
|
6
|
+
enterFullscreen?: string;
|
|
7
|
+
exitFullscreen?: string;
|
|
8
|
+
build?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface McpAppViewProps {
|
|
11
|
+
/**
|
|
12
|
+
* Map of widget ID to React component. The consumer aggregates this from
|
|
13
|
+
* each module's widget exports and passes it in at the bundled `main.tsx`
|
|
14
|
+
* entry point. All widgets are host-bundled — the framework never fetches
|
|
15
|
+
* widget code at render time.
|
|
16
|
+
*/
|
|
17
|
+
widgets: Record<string, WidgetComponent>;
|
|
18
|
+
/**
|
|
19
|
+
* Name of the MCP tool that the refresh button invokes. Consumers typically
|
|
20
|
+
* register this tool as a thin wrapper around `renderView(...)` from
|
|
21
|
+
* `@miragon/mcp-toolkit-core`. Defaults to `"refresh-view"`.
|
|
22
|
+
*/
|
|
23
|
+
refreshToolName?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Explicit override for the Build / edit (Pencil) affordance. Leave it
|
|
26
|
+
* `undefined` (the default) to let the shell follow the server's own
|
|
27
|
+
* signal — `render-view` reports `structuredContent.builderAvailable`,
|
|
28
|
+
* derived from `createFrameworkApp`'s `app.builder`, so the button appears
|
|
29
|
+
* only when the `get-builder-catalogue` tool is actually registered. Set it
|
|
30
|
+
* to `true` / `false` only to force the affordance on or off regardless of
|
|
31
|
+
* that signal (e.g. a custom server that registers the catalogue tool by
|
|
32
|
+
* hand). Even when forced on, the LayoutBuilder's catalogue fetch fails
|
|
33
|
+
* soft (no crash) if the tool is absent.
|
|
34
|
+
*/
|
|
35
|
+
builderEnabled?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Override UI strings (loading, refresh, fullscreen, build).
|
|
38
|
+
* Defaults to English.
|
|
39
|
+
*/
|
|
40
|
+
labels?: McpAppViewLabels;
|
|
41
|
+
}
|
|
42
|
+
export declare function McpAppView({ widgets, refreshToolName, builderEnabled, labels, }: McpAppViewProps): import("react").JSX.Element;
|
|
43
|
+
//# sourceMappingURL=mcp-app-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-app-view.d.ts","sourceRoot":"","sources":["../../src/app/mcp-app-view.tsx"],"names":[],"mappings":"AASA,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE3E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAkDD,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IACxC;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;;;;;;;;OAUG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;OAGG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAC1B;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,eAAgC,EAChC,cAAc,EACd,MAAM,GACP,EAAE,eAAe,+BAoQjB"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useCallback } from "react";
|
|
3
|
+
import { useWidget } from "mcp-use/react";
|
|
4
|
+
import { Maximize2, Minimize2, Pencil, RefreshCw } from "lucide-react";
|
|
5
|
+
import { Skeleton } from "../primitives/skeleton.js";
|
|
6
|
+
import { AppQueryProvider, queryClient } from "../providers/query-provider.js";
|
|
7
|
+
import { useToolResultRecovery } from "../hooks/use-tool-result-recovery.js";
|
|
8
|
+
import { parseToolResult } from "../lib/parse-tool-result.js";
|
|
9
|
+
import { LayoutBuilder } from "./layout-builder.js";
|
|
10
|
+
import { WidgetRenderer } from "./widget-renderer.js";
|
|
11
|
+
const DEFAULT_LABELS = {
|
|
12
|
+
loading: "Waiting for pipeline result...",
|
|
13
|
+
refresh: "Refresh",
|
|
14
|
+
refreshing: "Loading...",
|
|
15
|
+
enterFullscreen: "Fullscreen",
|
|
16
|
+
exitFullscreen: "Collapse",
|
|
17
|
+
build: "Build",
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* A renderable view payload: the envelope `render-view`/`show_*` tools emit
|
|
21
|
+
* as `structuredContent`. Module-level so it is referentially stable as the
|
|
22
|
+
* recovery hook's `isValid` dependency.
|
|
23
|
+
*/
|
|
24
|
+
function isCompleteViewData(value) {
|
|
25
|
+
const v = value;
|
|
26
|
+
return Boolean(v?.context && v?.layout);
|
|
27
|
+
}
|
|
28
|
+
export function McpAppView({ widgets, refreshToolName = "refresh-view", builderEnabled, labels, }) {
|
|
29
|
+
const effectiveLabels = { ...DEFAULT_LABELS, ...labels };
|
|
30
|
+
const { props: initialViewData, isPending, callTool, displayMode: currentDisplayMode, requestDisplayMode, safeArea, toolInput, hostContext, } = useWidget();
|
|
31
|
+
const [viewData, setViewData] = useState(null);
|
|
32
|
+
const [displayMode, setDisplayMode] = useState(currentDisplayMode ?? "inline");
|
|
33
|
+
const [prevCurrentDisplayMode, setPrevCurrentDisplayMode] = useState(currentDisplayMode);
|
|
34
|
+
if (currentDisplayMode !== prevCurrentDisplayMode) {
|
|
35
|
+
setPrevCurrentDisplayMode(currentDisplayMode);
|
|
36
|
+
if (currentDisplayMode)
|
|
37
|
+
setDisplayMode(currentDisplayMode);
|
|
38
|
+
}
|
|
39
|
+
const [isRefreshing, setIsRefreshing] = useState(false);
|
|
40
|
+
// In-iframe build mode is purely a UI state — the LLM never sees the
|
|
41
|
+
// catalogue, the user toggles into build by clicking the toolbar button.
|
|
42
|
+
const [buildMode, setBuildMode] = useState(false);
|
|
43
|
+
// Sync host-provided initialViewData → local viewData via render-phase
|
|
44
|
+
// setState (rather than an effect) so the React Compiler doesn't flag a
|
|
45
|
+
// cascading render. The guard against transient empty toolOutput stays:
|
|
46
|
+
// widgetProps may briefly drop `context`/`layout` when displayMode toggles,
|
|
47
|
+
// and we don't want that to clobber a valid viewData.
|
|
48
|
+
//
|
|
49
|
+
// `prev` MUST start as `null`, not `initialViewData`: hosts that expose the
|
|
50
|
+
// complete tool output before the app's first render (e.g. window.openai
|
|
51
|
+
// globals injected ahead of script execution) would otherwise never trip the
|
|
52
|
+
// identity check — initialViewData never changes again, the sync never runs,
|
|
53
|
+
// and the app idles on the loading skeleton forever.
|
|
54
|
+
const [prevInitialViewData, setPrevInitialViewData] = useState(null);
|
|
55
|
+
if (initialViewData !== prevInitialViewData) {
|
|
56
|
+
setPrevInitialViewData(initialViewData);
|
|
57
|
+
if (!isPending && isCompleteViewData(initialViewData)) {
|
|
58
|
+
setViewData(initialViewData);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Hosts that strip `structuredContent` from the tool-result notification
|
|
62
|
+
// (claude.ai / Claude Desktop) leave `initialViewData` empty forever; the
|
|
63
|
+
// recovery re-executes the originating tool once via `callTool` (responses
|
|
64
|
+
// carry `structuredContent` intact) and fills the gap. Conforming hosts
|
|
65
|
+
// deliver a valid payload up front, so this never fires there.
|
|
66
|
+
const recovery = useToolResultRecovery({
|
|
67
|
+
resultReady: !isPending,
|
|
68
|
+
props: initialViewData,
|
|
69
|
+
isValid: isCompleteViewData,
|
|
70
|
+
toolInput,
|
|
71
|
+
hostContext,
|
|
72
|
+
callTool,
|
|
73
|
+
});
|
|
74
|
+
const [prevRecovered, setPrevRecovered] = useState(null);
|
|
75
|
+
if (recovery.data !== prevRecovered) {
|
|
76
|
+
setPrevRecovered(recovery.data);
|
|
77
|
+
// The host-delivered payload always wins; recovery only fills the gap.
|
|
78
|
+
if (recovery.data && !viewData)
|
|
79
|
+
setViewData(recovery.data);
|
|
80
|
+
}
|
|
81
|
+
const toggleFullscreen = useCallback(async () => {
|
|
82
|
+
const newMode = displayMode === "fullscreen" ? "inline" : "fullscreen";
|
|
83
|
+
try {
|
|
84
|
+
const result = await requestDisplayMode(newMode);
|
|
85
|
+
setDisplayMode(result.mode);
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
console.error("Failed to toggle display mode:", e);
|
|
89
|
+
}
|
|
90
|
+
}, [displayMode, requestDisplayMode]);
|
|
91
|
+
// Stable callTool callback (avoids a new object reference on every render)
|
|
92
|
+
const callToolFn = useCallback(async (name, args) => {
|
|
93
|
+
return callTool(name, args);
|
|
94
|
+
}, [callTool]);
|
|
95
|
+
const refreshView = useCallback(async () => {
|
|
96
|
+
if (!viewData?._refreshParams)
|
|
97
|
+
return;
|
|
98
|
+
setIsRefreshing(true);
|
|
99
|
+
try {
|
|
100
|
+
const result = await callTool(refreshToolName, viewData._refreshParams);
|
|
101
|
+
// Decode through the shared structured-first parser (one convention with
|
|
102
|
+
// `useToolQuery`); a refresh returns the view envelope as `structuredContent`.
|
|
103
|
+
const refreshed = parseToolResult(result);
|
|
104
|
+
if (refreshed?.context && refreshed?.layout) {
|
|
105
|
+
setViewData(refreshed);
|
|
106
|
+
}
|
|
107
|
+
void queryClient.invalidateQueries();
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
console.error("Failed to refresh view:", e);
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
setIsRefreshing(false);
|
|
114
|
+
}
|
|
115
|
+
}, [callTool, refreshToolName, viewData]);
|
|
116
|
+
// Called by LayoutBuilder when the user clicks Done. Commits the draft
|
|
117
|
+
// layout (and any keys/steps edits) into the parent viewData so the
|
|
118
|
+
// WidgetRenderer takes over showing the just-built layout.
|
|
119
|
+
const exitBuildMode = useCallback((commit) => {
|
|
120
|
+
if (commit) {
|
|
121
|
+
setViewData((prev) => prev
|
|
122
|
+
? {
|
|
123
|
+
...prev,
|
|
124
|
+
layout: commit.layout,
|
|
125
|
+
title: commit.title ?? prev.title,
|
|
126
|
+
context: commit.context ?? prev.context,
|
|
127
|
+
_refreshParams: {
|
|
128
|
+
keys: commit.keys,
|
|
129
|
+
steps: commit.steps,
|
|
130
|
+
layout: commit.layout,
|
|
131
|
+
title: commit.title ?? prev.title,
|
|
132
|
+
},
|
|
133
|
+
}
|
|
134
|
+
: prev);
|
|
135
|
+
}
|
|
136
|
+
setBuildMode(false);
|
|
137
|
+
}, []);
|
|
138
|
+
if (isPending || !viewData) {
|
|
139
|
+
return (_jsxs("div", { className: "flex flex-col gap-4 p-4", children: [_jsx(Skeleton, { className: "h-8 w-48" }), _jsx(Skeleton, { className: "h-32 w-full" }), _jsx("p", { className: "text-muted-foreground text-sm", children: effectiveLabels.loading })] }));
|
|
140
|
+
}
|
|
141
|
+
const showHeader = !buildMode;
|
|
142
|
+
// Follow the server's own signal by default: render-view reports
|
|
143
|
+
// `builderAvailable` (derived from `app.builder`), so the Build button only
|
|
144
|
+
// shows when the catalogue/dashboard tools are actually registered. An
|
|
145
|
+
// explicit `builderEnabled` prop forces the affordance on or off.
|
|
146
|
+
const builderAvailable = builderEnabled ?? viewData.builderAvailable ?? false;
|
|
147
|
+
return (_jsxs("main", { style: {
|
|
148
|
+
// Fullscreen: the widget owns the viewport, so we take the full window
|
|
149
|
+
// and handle our own scrolling. Inline: the host (Claude, ChatGPT) owns
|
|
150
|
+
// sizing + scrolling and is notified of our intrinsic height via
|
|
151
|
+
// `McpUseProvider`, so we let content dictate height and avoid setting
|
|
152
|
+
// overflowY (which would clip our own content inside a host that's
|
|
153
|
+
// already auto-sized to us).
|
|
154
|
+
...(displayMode === "fullscreen"
|
|
155
|
+
? { minHeight: "100vh", overflowY: "auto" }
|
|
156
|
+
: null),
|
|
157
|
+
paddingTop: safeArea?.insets?.top,
|
|
158
|
+
paddingRight: safeArea?.insets?.right,
|
|
159
|
+
paddingBottom: safeArea?.insets?.bottom,
|
|
160
|
+
paddingLeft: safeArea?.insets?.left,
|
|
161
|
+
}, children: [showHeader && (_jsxs("div", { className: "mb-4 flex items-center justify-between", children: [viewData.title && _jsx("h2", { className: "text-xl font-bold", children: viewData.title }), _jsxs("div", { className: "ml-auto flex items-center gap-2", children: [viewData._refreshParams && viewData.layout && (_jsxs("button", { onClick: () => {
|
|
162
|
+
void refreshView();
|
|
163
|
+
}, disabled: isRefreshing, className: "hover:bg-accent hover:text-accent-foreground inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors disabled:opacity-50", children: [_jsx(RefreshCw, { "aria-hidden": "true", className: `h-4 w-4 ${isRefreshing ? "animate-spin" : ""}` }), isRefreshing ? effectiveLabels.refreshing : effectiveLabels.refresh] })), builderAvailable && viewData._refreshParams && (_jsxs("button", { onClick: () => setBuildMode(true), className: "hover:bg-accent hover:text-accent-foreground inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors", children: [_jsx(Pencil, { className: "h-4 w-4" }), effectiveLabels.build] })), _jsxs("button", { onClick: () => {
|
|
164
|
+
void toggleFullscreen();
|
|
165
|
+
}, className: "hover:bg-accent hover:text-accent-foreground inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors", children: [displayMode === "fullscreen" ? (_jsx(Minimize2, { "aria-hidden": "true", className: "h-4 w-4" })) : (_jsx(Maximize2, { "aria-hidden": "true", className: "h-4 w-4" })), displayMode === "fullscreen"
|
|
166
|
+
? effectiveLabels.exitFullscreen
|
|
167
|
+
: effectiveLabels.enterFullscreen] })] })] })), !buildMode && viewData.context.errors.length > 0 && (_jsx("div", { className: "mb-4 flex flex-col gap-2", children: viewData.context.errors.map((err) => (_jsxs("div", { className: "bg-destructive/10 text-destructive rounded-lg p-3 text-sm", children: [_jsxs("strong", { children: [err.stepId, ":"] }), " ", err.reason] }, err.stepId))) })), _jsx(AppQueryProvider, { callTool: callToolFn, children: buildMode ? (_jsx(LayoutBuilder, { initialLayout: viewData.layout, title: viewData.title, initialKeys: viewData._refreshParams?.keys, initialSteps: viewData._refreshParams?.steps, widgets: widgets, callTool: callToolFn, onExit: exitBuildMode })) : viewData.layout ? (_jsx(WidgetRenderer, { layout: viewData.layout, keys: viewData.context.keys, stepData: viewData.context.stepData, errors: viewData.context.errors, widgets: widgets })) : null })] }));
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=mcp-app-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-app-view.js","sourceRoot":"","sources":["../../src/app/mcp-app-view.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type McpAppViewProps } from "./mcp-app-view.js";
|
|
2
|
+
/**
|
|
3
|
+
* Consumer-facing root for a toolkit-rendered MCP App. Wraps `McpAppView`
|
|
4
|
+
* in `McpUseProvider` so the host (Claude, ChatGPT Apps SDK) receives
|
|
5
|
+
* intrinsic-height notifications and the widget auto-sizes inside the
|
|
6
|
+
* host's inline container.
|
|
7
|
+
*
|
|
8
|
+
* Usage at the bundle entry point:
|
|
9
|
+
*
|
|
10
|
+
* ```tsx
|
|
11
|
+
* createRoot(root).render(<McpToolkitApp widgets={widgets} />)
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* `McpUseProvider` also installs StrictMode, a default ErrorBoundary, and
|
|
15
|
+
* the theme plumbing used by the toolkit primitives.
|
|
16
|
+
*/
|
|
17
|
+
export declare function McpToolkitApp(props: McpAppViewProps): import("react").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=mcp-toolkit-app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-toolkit-app.d.ts","sourceRoot":"","sources":["../../src/app/mcp-toolkit-app.tsx"],"names":[],"mappings":"AACA,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAEpE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,eAAe,+BAMnD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { McpUseProvider } from "mcp-use/react";
|
|
3
|
+
import { McpAppView } from "./mcp-app-view.js";
|
|
4
|
+
/**
|
|
5
|
+
* Consumer-facing root for a toolkit-rendered MCP App. Wraps `McpAppView`
|
|
6
|
+
* in `McpUseProvider` so the host (Claude, ChatGPT Apps SDK) receives
|
|
7
|
+
* intrinsic-height notifications and the widget auto-sizes inside the
|
|
8
|
+
* host's inline container.
|
|
9
|
+
*
|
|
10
|
+
* Usage at the bundle entry point:
|
|
11
|
+
*
|
|
12
|
+
* ```tsx
|
|
13
|
+
* createRoot(root).render(<McpToolkitApp widgets={widgets} />)
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* `McpUseProvider` also installs StrictMode, a default ErrorBoundary, and
|
|
17
|
+
* the theme plumbing used by the toolkit primitives.
|
|
18
|
+
*/
|
|
19
|
+
export function McpToolkitApp(props) {
|
|
20
|
+
return (_jsx(McpUseProvider, { children: _jsx(McpAppView, { ...props }) }));
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=mcp-toolkit-app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-toolkit-app.js","sourceRoot":"","sources":["../../src/app/mcp-toolkit-app.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAwB,MAAM,mBAAmB,CAAA;AAEpE;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAAC,KAAsB;IAClD,OAAO,CACL,KAAC,cAAc,cACb,KAAC,UAAU,OAAK,KAAK,GAAI,GACV,CAClB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export interface HostActions {
|
|
2
|
+
/**
|
|
3
|
+
* Open an external URL in a new browser tab via the host bridge
|
|
4
|
+
* (`bridge.openLink` / `window.openai.openExternal`). Works inside the
|
|
5
|
+
* sandboxed iframe where raw `window.open` is blocked. Falls back to
|
|
6
|
+
* `window.open` only when no MCP host bridge is available (dev preview).
|
|
7
|
+
*/
|
|
8
|
+
openLink: (url: string) => void;
|
|
9
|
+
/**
|
|
10
|
+
* Ask the host to render another tool's widget by sending a follow-up
|
|
11
|
+
* user message into the conversation (`bridge.sendMessage` /
|
|
12
|
+
* `window.openai.sendFollowUpMessage`). The agent interprets the prompt
|
|
13
|
+
* and invokes the matching tool, whose widget then appears as the next
|
|
14
|
+
* chat turn — the proper MCP-Apps pattern for in-widget navigation.
|
|
15
|
+
*
|
|
16
|
+
* The prompt should be natural language and include enough hints
|
|
17
|
+
* (preferably the tool name in parentheses) for the agent to pick the
|
|
18
|
+
* right tool unambiguously.
|
|
19
|
+
*/
|
|
20
|
+
showWidget: (prompt: string) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Hand an open-ended, judgment task to the agent in the conversation
|
|
23
|
+
* (`sendFollowUpMessage`) — root-cause analysis, "explain this", migration
|
|
24
|
+
* planning, ticket drafting. Same bridge as {@link HostActions.showWidget}
|
|
25
|
+
* but a distinct affordance: this crosses the UI→chat boundary deliberately,
|
|
26
|
+
* for things the deterministic UI cannot do. The prompt should be
|
|
27
|
+
* self-contained — inline the relevant IDs/keys rather than relying on
|
|
28
|
+
* ambient ModelContext alone.
|
|
29
|
+
*/
|
|
30
|
+
askAi: (prompt: string) => void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Builds the natural-language intent string passed to {@link HostActions.showWidget}.
|
|
34
|
+
* The host agent reads the trailing `(use <toolName>)` hint to pick the right
|
|
35
|
+
* tool unambiguously. Centralised so every in-widget navigation handoff phrases
|
|
36
|
+
* the hint identically (and a tool rename only has to flow through the imported
|
|
37
|
+
* `*_SHOW_*` tool-name constant).
|
|
38
|
+
*
|
|
39
|
+
* @example host.showWidget(buildShowWidgetIntent(SHOW_PROCESS_DETAIL, `Show the process detail for \`${key}\``))
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildShowWidgetIntent(toolName: string, description: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Bridge-aware host actions for widgets. A thin, intent-named facade over
|
|
44
|
+
* {@link useHostBridge}: `openLink` → `bridge.openExternal`, and both
|
|
45
|
+
* `showWidget` and `askAi` → `bridge.sendFollowup` (kept as two affordances
|
|
46
|
+
* because they cross the UI→chat boundary for different reasons — see above).
|
|
47
|
+
*
|
|
48
|
+
* Relationship to {@link useHostBridge}: this hook resolves the active bridge
|
|
49
|
+
* through `useHostBridge()`, so it honours an explicit `HostBridgeProvider`
|
|
50
|
+
* (ChatGPT / standalone) when one is present, and otherwise falls back to the
|
|
51
|
+
* default `mcp-use` bridge — exactly the behaviour widgets had before the bridge
|
|
52
|
+
* abstraction existed, so no existing widget or test breaks. Prefer
|
|
53
|
+
* `useHostBridge` directly in new portable widgets; `useHostActions` stays for
|
|
54
|
+
* its named affordances and backward compatibility.
|
|
55
|
+
*/
|
|
56
|
+
export declare function useHostActions(): HostActions;
|
|
57
|
+
//# sourceMappingURL=use-host-actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-host-actions.d.ts","sourceRoot":"","sources":["../../src/app/use-host-actions.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B;;;;;;;;;;OAUG;IACH,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC;;;;;;;;OAQG;IACH,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEnF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAyB5C"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { useHostBridge } from "./host-bridge.js";
|
|
3
|
+
/**
|
|
4
|
+
* Builds the natural-language intent string passed to {@link HostActions.showWidget}.
|
|
5
|
+
* The host agent reads the trailing `(use <toolName>)` hint to pick the right
|
|
6
|
+
* tool unambiguously. Centralised so every in-widget navigation handoff phrases
|
|
7
|
+
* the hint identically (and a tool rename only has to flow through the imported
|
|
8
|
+
* `*_SHOW_*` tool-name constant).
|
|
9
|
+
*
|
|
10
|
+
* @example host.showWidget(buildShowWidgetIntent(SHOW_PROCESS_DETAIL, `Show the process detail for \`${key}\``))
|
|
11
|
+
*/
|
|
12
|
+
export function buildShowWidgetIntent(toolName, description) {
|
|
13
|
+
return `${description} (use ${toolName})`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Bridge-aware host actions for widgets. A thin, intent-named facade over
|
|
17
|
+
* {@link useHostBridge}: `openLink` → `bridge.openExternal`, and both
|
|
18
|
+
* `showWidget` and `askAi` → `bridge.sendFollowup` (kept as two affordances
|
|
19
|
+
* because they cross the UI→chat boundary for different reasons — see above).
|
|
20
|
+
*
|
|
21
|
+
* Relationship to {@link useHostBridge}: this hook resolves the active bridge
|
|
22
|
+
* through `useHostBridge()`, so it honours an explicit `HostBridgeProvider`
|
|
23
|
+
* (ChatGPT / standalone) when one is present, and otherwise falls back to the
|
|
24
|
+
* default `mcp-use` bridge — exactly the behaviour widgets had before the bridge
|
|
25
|
+
* abstraction existed, so no existing widget or test breaks. Prefer
|
|
26
|
+
* `useHostBridge` directly in new portable widgets; `useHostActions` stays for
|
|
27
|
+
* its named affordances and backward compatibility.
|
|
28
|
+
*/
|
|
29
|
+
export function useHostActions() {
|
|
30
|
+
const bridge = useHostBridge();
|
|
31
|
+
const openLink = useCallback((url) => {
|
|
32
|
+
bridge.openExternal(url);
|
|
33
|
+
}, [bridge]);
|
|
34
|
+
const showWidget = useCallback((prompt) => {
|
|
35
|
+
bridge.sendFollowup(prompt);
|
|
36
|
+
}, [bridge]);
|
|
37
|
+
const askAi = useCallback((prompt) => {
|
|
38
|
+
bridge.sendFollowup(prompt);
|
|
39
|
+
}, [bridge]);
|
|
40
|
+
return { openLink, showWidget, askAi };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=use-host-actions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-host-actions.js","sourceRoot":"","sources":["../../src/app/use-host-actions.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAkChD;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAgB,EAAE,WAAmB;IACzE,OAAO,GAAG,WAAW,SAAS,QAAQ,GAAG,CAAA;AAC3C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,MAAM,GAAG,aAAa,EAAE,CAAA;IAE9B,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,GAAW,EAAE,EAAE;QACd,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC,EACD,CAAC,MAAM,CAAC,CACT,CAAA;IAED,MAAM,UAAU,GAAG,WAAW,CAC5B,CAAC,MAAc,EAAE,EAAE;QACjB,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;IAC7B,CAAC,EACD,CAAC,MAAM,CAAC,CACT,CAAA;IAED,MAAM,KAAK,GAAG,WAAW,CACvB,CAAC,MAAc,EAAE,EAAE;QACjB,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;IAC7B,CAAC,EACD,CAAC,MAAM,CAAC,CACT,CAAA;IAED,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAA;AACxC,CAAC"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { type ComponentType, type ReactNode } from "react";
|
|
2
|
+
import type { WidgetProps } from "@miragon/mcp-toolkit-core";
|
|
3
|
+
/**
|
|
4
|
+
* Minimal shape of a tool-call response the harness hands back to widgets.
|
|
5
|
+
* Mirrors `mcp-use`'s `CallToolResponse` closely enough that both the toolkit's
|
|
6
|
+
* `parseToolResult` (structured-first) and `mcp-use`'s `useCallTool`
|
|
7
|
+
* (`result`/`content` text) can decode a fixture result without a real host.
|
|
8
|
+
*
|
|
9
|
+
* A fixture entry may also be a bare value: the registry wraps it into this
|
|
10
|
+
* envelope under `structuredContent`, which is what `parseToolResult` reads
|
|
11
|
+
* first — so a fixture can be written as just the data the widget expects.
|
|
12
|
+
*/
|
|
13
|
+
export interface FixtureToolResult {
|
|
14
|
+
structuredContent?: unknown;
|
|
15
|
+
content?: {
|
|
16
|
+
type: string;
|
|
17
|
+
text?: string;
|
|
18
|
+
}[];
|
|
19
|
+
isError?: boolean;
|
|
20
|
+
_meta?: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A handler fixture: invoked with the call args, may return a value or a
|
|
24
|
+
* promise (the registry `await`s it either way).
|
|
25
|
+
*/
|
|
26
|
+
export type FixtureToolHandler = (args: Record<string, unknown>) => unknown;
|
|
27
|
+
/**
|
|
28
|
+
* A fixture for one tool: either a static result returned verbatim, or a
|
|
29
|
+
* {@link FixtureToolHandler} invoked with the call args. Handlers let a fixture
|
|
30
|
+
* react to the widget's input — e.g. echo back a filtered list. Any registered
|
|
31
|
+
* function is treated as a handler (so a fixture cannot itself *be* the data
|
|
32
|
+
* `Function`, which is never JSON tool output anyway).
|
|
33
|
+
*/
|
|
34
|
+
export type FixtureToolEntry = unknown;
|
|
35
|
+
/**
|
|
36
|
+
* Pure, host-free registry of fake tool implementations. Drives every
|
|
37
|
+
* `callTool` path the harness exposes (`window.openai.callTool`, the toolkit's
|
|
38
|
+
* `AppQueryProvider` bridge). Kept free of React/DOM so its semantics are unit
|
|
39
|
+
* testable in a plain Node environment.
|
|
40
|
+
*
|
|
41
|
+
* Resolution rules:
|
|
42
|
+
* - A registered **function** entry is called with `args` and its return value
|
|
43
|
+
* (awaited) is wrapped into a {@link FixtureToolResult}.
|
|
44
|
+
* - A registered **value** entry is returned as-is when it already looks like a
|
|
45
|
+
* tool response (has `structuredContent`/`content`), otherwise wrapped under
|
|
46
|
+
* `structuredContent` so widgets that read structured data Just Work.
|
|
47
|
+
* - An **unknown** tool rejects with a descriptive error. This is the
|
|
48
|
+
* error-friendly path: the rejection flows into the widget's own error state
|
|
49
|
+
* (TanStack Query `error`, `mcp-use` `isError`) instead of crashing the
|
|
50
|
+
* harness, and the message names the missing tool so the gap is obvious.
|
|
51
|
+
*/
|
|
52
|
+
export declare class FixtureCallToolRegistry {
|
|
53
|
+
private readonly entries;
|
|
54
|
+
constructor(initial?: Record<string, FixtureToolEntry>);
|
|
55
|
+
/** Register (or overwrite) the fixture for a tool name. */
|
|
56
|
+
register(name: string, resultOrHandler: FixtureToolEntry): this;
|
|
57
|
+
/** True if a fixture is registered for `name`. */
|
|
58
|
+
has(name: string): boolean;
|
|
59
|
+
/** Registered tool names, for diagnostics / the harness log. */
|
|
60
|
+
names(): string[];
|
|
61
|
+
/**
|
|
62
|
+
* Resolve a tool call against the registered fixtures. Always returns a
|
|
63
|
+
* promise so callers can `await` uniformly regardless of whether the fixture
|
|
64
|
+
* was a static value or an async handler.
|
|
65
|
+
*/
|
|
66
|
+
call(name: string, args?: Record<string, unknown>): Promise<FixtureToolResult>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A host action a widget asked the host to perform, surfaced to the harness so
|
|
70
|
+
* it can render an activity log. Mirrors the `mcp-use` bridge verbs that
|
|
71
|
+
* {@link useHostActions} and `useWidget` route through `window.openai`.
|
|
72
|
+
*/
|
|
73
|
+
export type HostActionLog = {
|
|
74
|
+
type: "callTool";
|
|
75
|
+
name: string;
|
|
76
|
+
args: Record<string, unknown>;
|
|
77
|
+
} | {
|
|
78
|
+
type: "sendFollowUpMessage";
|
|
79
|
+
prompt: string;
|
|
80
|
+
} | {
|
|
81
|
+
type: "openExternal";
|
|
82
|
+
href: string;
|
|
83
|
+
} | {
|
|
84
|
+
type: "requestDisplayMode";
|
|
85
|
+
mode: string;
|
|
86
|
+
} | {
|
|
87
|
+
type: "setWidgetState";
|
|
88
|
+
state: Record<string, unknown>;
|
|
89
|
+
};
|
|
90
|
+
interface FixtureHostValue {
|
|
91
|
+
registry: FixtureCallToolRegistry;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Access the active fixture registry from inside a {@link WidgetFixtureHost}.
|
|
95
|
+
* Returns `null` outside a harness — callers should treat that as "no fixture
|
|
96
|
+
* host present" rather than an error.
|
|
97
|
+
*/
|
|
98
|
+
export declare function useFixtureHost(): FixtureHostValue | null;
|
|
99
|
+
/**
|
|
100
|
+
* Either an `adaptDataWidget`-style component (receives {@link WidgetProps}) or
|
|
101
|
+
* a "raw" single-data component (`({ data }) | ({ keys })`). The harness builds
|
|
102
|
+
* a `WidgetProps` envelope from the fixture and spreads it so both shapes work
|
|
103
|
+
* without the author declaring which they wrote.
|
|
104
|
+
*/
|
|
105
|
+
export type FixtureWidget = ComponentType<WidgetProps> | ComponentType<Record<string, unknown>>;
|
|
106
|
+
export interface WidgetFixtureHostProps {
|
|
107
|
+
/** The widget component under development. */
|
|
108
|
+
widget: FixtureWidget;
|
|
109
|
+
/**
|
|
110
|
+
* Fixture data for the widget. Shaped however the widget reads it:
|
|
111
|
+
* - widgets reading `keys["ns:thing"]` (the common pattern) → pass the keys map
|
|
112
|
+
* - `adaptDataWidget` components → also pass {@link WidgetFixtureHostProps.dataType}
|
|
113
|
+
* so the harness seeds a matching pipeline step the adapter can find
|
|
114
|
+
* - raw `({ data })` widgets → the same object is forwarded as `data`
|
|
115
|
+
*/
|
|
116
|
+
data?: Record<string, unknown>;
|
|
117
|
+
/**
|
|
118
|
+
* `dataType` to register the fixture step under, for `adaptDataWidget`
|
|
119
|
+
* components (which look up the step whose `_dataType` matches). When set,
|
|
120
|
+
* `data` is placed in `context.steps[<id>].data` so the adapter resolves it.
|
|
121
|
+
*/
|
|
122
|
+
dataType?: string;
|
|
123
|
+
/**
|
|
124
|
+
* Tool fixtures keyed by tool name. Each value is a static result or a
|
|
125
|
+
* handler — see {@link FixtureToolEntry}. Drives both `mcp-use`'s
|
|
126
|
+
* `useCallTool` and the toolkit's `useToolQuery`.
|
|
127
|
+
*/
|
|
128
|
+
tools?: Record<string, FixtureToolEntry>;
|
|
129
|
+
/**
|
|
130
|
+
* Host context globals to override (theme, displayMode, locale, …). Merged
|
|
131
|
+
* over {@link DEFAULT_GLOBALS}.
|
|
132
|
+
*/
|
|
133
|
+
globals?: Record<string, unknown>;
|
|
134
|
+
/**
|
|
135
|
+
* Called with the serialized model-context string the widget reports via
|
|
136
|
+
* `<ModelContext>` / `modelContext.set`. This is exactly what the model would
|
|
137
|
+
* see in a real host — surfacing it in the harness is the didactic point.
|
|
138
|
+
*/
|
|
139
|
+
onModelContext?: (text: string) => void;
|
|
140
|
+
/** Called for every host action the widget triggers (tool call, link, …). */
|
|
141
|
+
onHostAction?: (action: HostActionLog) => void;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Build the `WidgetProps` envelope the harness passes to the widget. Seeds a
|
|
145
|
+
* single pipeline step from `data` (keyed by `dataType` when given) and uses
|
|
146
|
+
* `data` as the `keys` map, so widgets that read `keys[...]` and adapted
|
|
147
|
+
* widgets that scan `context.steps` are both satisfied from one fixture.
|
|
148
|
+
*
|
|
149
|
+
* Exported for unit testing the envelope shape without rendering React.
|
|
150
|
+
*/
|
|
151
|
+
export declare function buildFixtureWidgetProps(data: Record<string, unknown>, dataType?: string): WidgetProps;
|
|
152
|
+
/**
|
|
153
|
+
* Storybook-style harness for MCP widgets. Renders a single widget with fixture
|
|
154
|
+
* data and a mocked host environment so it can be developed in isolation —
|
|
155
|
+
* without booting a real MCP host or backend.
|
|
156
|
+
*
|
|
157
|
+
* ### What it mocks
|
|
158
|
+
* - **`window.openai`** — the `mcp-use` Apps-SDK bridge `useWidget`/`useCallTool`
|
|
159
|
+
* read from. Installed on mount, removed on unmount. `callTool` is routed to a
|
|
160
|
+
* {@link FixtureCallToolRegistry} built from `tools`; `sendFollowUpMessage`,
|
|
161
|
+
* `openExternal`, etc. are reported to `onHostAction`.
|
|
162
|
+
* - **The toolkit `AppQueryProvider`** — so widgets that fetch via `useToolQuery`
|
|
163
|
+
* (e.g. generated `use*` hooks) resolve against the same registry.
|
|
164
|
+
* - **`ModelContext`** — a flush handler captures the serialized context string
|
|
165
|
+
* and forwards it to `onModelContext`, so you can *see* what the model would.
|
|
166
|
+
* - **A {@link HostBridge}** — a `createStandaloneHostBridge` over the same
|
|
167
|
+
* registry and callbacks, provided via `HostBridgeProvider`, so widgets
|
|
168
|
+
* written against `useHostBridge` (the host-portable pattern) are simulated
|
|
169
|
+
* from the same single source as the `window.openai` shim above.
|
|
170
|
+
*
|
|
171
|
+
* ### Boundaries
|
|
172
|
+
* `mcp-use`'s hooks select their provider from `window.openai` presence; this
|
|
173
|
+
* harness deliberately drives the Apps-SDK path (sets `window.openai`) rather
|
|
174
|
+
* than the `postMessage` bridge, which only activates inside a cross-origin
|
|
175
|
+
* iframe. The shim is intentionally minimal — it is not a host, and host
|
|
176
|
+
* features beyond the bridge verbs above are out of scope.
|
|
177
|
+
*/
|
|
178
|
+
export declare function WidgetFixtureHost({ widget: Widget, data, dataType, tools, globals, onModelContext, onHostAction, }: WidgetFixtureHostProps): ReactNode;
|
|
179
|
+
export {};
|
|
180
|
+
//# sourceMappingURL=widget-fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget-fixture.d.ts","sourceRoot":"","sources":["../../src/app/widget-fixture.tsx"],"names":[],"mappings":"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"}
|