@miragon/mcp-toolkit-ui 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/app/builder/BuilderBanners.d.ts +19 -0
- package/dist/app/builder/BuilderBanners.d.ts.map +1 -0
- package/dist/app/builder/BuilderBanners.js +22 -0
- package/dist/app/builder/BuilderBanners.js.map +1 -0
- package/dist/app/builder/CanvasRow.d.ts +26 -0
- package/dist/app/builder/CanvasRow.d.ts.map +1 -0
- package/dist/app/builder/CanvasRow.js +98 -0
- package/dist/app/builder/CanvasRow.js.map +1 -0
- package/dist/app/builder/CellPropsSheet.d.ts +19 -0
- package/dist/app/builder/CellPropsSheet.d.ts.map +1 -0
- package/dist/app/builder/CellPropsSheet.js +28 -0
- package/dist/app/builder/CellPropsSheet.js.map +1 -0
- package/dist/app/builder/EmptyHint.d.ts +6 -0
- package/dist/app/builder/EmptyHint.d.ts.map +1 -0
- package/dist/app/builder/EmptyHint.js +10 -0
- package/dist/app/builder/EmptyHint.js.map +1 -0
- package/dist/app/builder/LayoutSurface.d.ts +27 -0
- package/dist/app/builder/LayoutSurface.d.ts.map +1 -0
- package/dist/app/builder/LayoutSurface.js +45 -0
- package/dist/app/builder/LayoutSurface.js.map +1 -0
- package/dist/app/builder/Workspace.d.ts +9 -3
- package/dist/app/builder/Workspace.d.ts.map +1 -1
- package/dist/app/builder/Workspace.js +3 -97
- package/dist/app/builder/Workspace.js.map +1 -1
- package/dist/app/builder/builder-reducer.d.ts.map +1 -1
- package/dist/app/builder/builder-reducer.js +176 -164
- package/dist/app/builder/builder-reducer.js.map +1 -1
- package/dist/app/builder/use-builder-catalogue.d.ts +33 -0
- package/dist/app/builder/use-builder-catalogue.d.ts.map +1 -0
- package/dist/app/builder/use-builder-catalogue.js +155 -0
- package/dist/app/builder/use-builder-catalogue.js.map +1 -0
- package/dist/app/builder/use-key-step-entries.d.ts +22 -0
- package/dist/app/builder/use-key-step-entries.d.ts.map +1 -0
- package/dist/app/builder/use-key-step-entries.js +46 -0
- package/dist/app/builder/use-key-step-entries.js.map +1 -0
- package/dist/app/builder/use-save-dashboard.d.ts +33 -0
- package/dist/app/builder/use-save-dashboard.d.ts.map +1 -0
- package/dist/app/builder/use-save-dashboard.js +78 -0
- package/dist/app/builder/use-save-dashboard.js.map +1 -0
- package/dist/app/host-bridge.d.ts +4 -4
- package/dist/app/host-bridge.js +2 -2
- package/dist/app/layout-builder.d.ts.map +1 -1
- package/dist/app/layout-builder.js +46 -277
- package/dist/app/layout-builder.js.map +1 -1
- package/dist/app/mcp-app-view-chrome.d.ts +77 -0
- package/dist/app/mcp-app-view-chrome.d.ts.map +1 -0
- package/dist/app/mcp-app-view-chrome.js +53 -0
- package/dist/app/mcp-app-view-chrome.js.map +1 -0
- package/dist/app/mcp-app-view.d.ts +3 -9
- package/dist/app/mcp-app-view.d.ts.map +1 -1
- package/dist/app/mcp-app-view.js +4 -31
- package/dist/app/mcp-app-view.js.map +1 -1
- package/dist/render-cases-primitives.d.ts +17 -0
- package/dist/render-cases-primitives.d.ts.map +1 -0
- package/dist/render-cases-primitives.js +88 -0
- package/dist/render-cases-primitives.js.map +1 -0
- package/dist/render-cases.d.ts +4 -0
- package/dist/render-cases.d.ts.map +1 -0
- package/dist/render-cases.js +140 -0
- package/dist/render-cases.js.map +1 -0
- package/package.json +12 -7
- package/src/app/builder/BuilderBanners.tsx +61 -0
- package/src/app/builder/CanvasRow.tsx +316 -0
- package/src/app/builder/CellPropsSheet.tsx +47 -0
- package/src/app/builder/EmptyHint.tsx +29 -0
- package/src/app/builder/LayoutSurface.tsx +140 -0
- package/src/app/builder/Workspace.tsx +33 -342
- package/src/app/builder/builder-reducer.ts +204 -170
- package/src/app/builder/use-builder-catalogue.ts +187 -0
- package/src/app/builder/use-key-step-entries.ts +60 -0
- package/src/app/builder/use-save-dashboard.ts +97 -0
- package/src/app/host-bridge.tsx +4 -4
- package/src/app/layout-builder.tsx +92 -497
- package/src/app/mcp-app-view-chrome.tsx +204 -0
- package/src/app/mcp-app-view.tsx +32 -140
- package/src/lib/parse-tool-result.property.test.ts +90 -0
- package/src/render-cases-primitives.tsx +255 -0
- package/src/render-cases.tsx +239 -0
- package/src/render-smoke.test.tsx +100 -0
- package/src/ui-catalog.test.ts +52 -0
- package/ui-catalog.json +1 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { useCallback, useState } from "react"
|
|
2
|
+
import type { PipelineStepRef } from "@miragon/mcp-toolkit-core"
|
|
3
|
+
import { parseToolResult } from "../../lib/parse-tool-result.js"
|
|
4
|
+
import { draftToLayout, entriesToKeys, type DraftLayout, type KeyEntry } from "./builder-model.js"
|
|
5
|
+
|
|
6
|
+
// -------------------------------------------------------------------------- //
|
|
7
|
+
// Save-dashboard hook — dialog state + the `save-dashboard` call
|
|
8
|
+
// -------------------------------------------------------------------------- //
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Owns the save dialog's state (open flag, name/description inputs, busy
|
|
12
|
+
* flag, inline error) and the `save-dashboard` call. Extracted from
|
|
13
|
+
* `layout-builder.tsx` unchanged: a rejected save surfaces its reason
|
|
14
|
+
* inline in the SaveDialog instead of failing silently (Finding [3]).
|
|
15
|
+
*/
|
|
16
|
+
export function useSaveDashboard({
|
|
17
|
+
callTool,
|
|
18
|
+
saveToolName,
|
|
19
|
+
dashboardId,
|
|
20
|
+
title,
|
|
21
|
+
keyEntries,
|
|
22
|
+
stepEntries,
|
|
23
|
+
draft,
|
|
24
|
+
onSaved,
|
|
25
|
+
}: {
|
|
26
|
+
callTool: (name: string, args: object) => Promise<unknown>
|
|
27
|
+
saveToolName: string
|
|
28
|
+
dashboardId?: string
|
|
29
|
+
title?: string
|
|
30
|
+
keyEntries: KeyEntry[]
|
|
31
|
+
stepEntries: PipelineStepRef[]
|
|
32
|
+
draft: DraftLayout
|
|
33
|
+
onSaved?: (result: { id: string; name: string }) => void
|
|
34
|
+
}) {
|
|
35
|
+
const [isBusy, setBusy] = useState(false)
|
|
36
|
+
const [saveOpen, setSaveOpen] = useState(false)
|
|
37
|
+
const [saveName, setSaveName] = useState(title ?? "")
|
|
38
|
+
const [saveDescription, setSaveDescription] = useState("")
|
|
39
|
+
// Last save failure (Finding [3]). Shown inline in the SaveDialog so a
|
|
40
|
+
// rejected `save-dashboard` call no longer fails silently.
|
|
41
|
+
const [saveError, setSaveError] = useState<string | null>(null)
|
|
42
|
+
|
|
43
|
+
const saveDraft = useCallback(async () => {
|
|
44
|
+
if (!saveName.trim()) return
|
|
45
|
+
setBusy(true)
|
|
46
|
+
setSaveError(null)
|
|
47
|
+
try {
|
|
48
|
+
const result = await callTool(saveToolName, {
|
|
49
|
+
id: dashboardId,
|
|
50
|
+
name: saveName.trim(),
|
|
51
|
+
description: saveDescription.trim() || undefined,
|
|
52
|
+
keys: entriesToKeys(keyEntries),
|
|
53
|
+
steps: stepEntries.filter((s) => s.step.trim().length > 0),
|
|
54
|
+
layout: draftToLayout(draft),
|
|
55
|
+
title,
|
|
56
|
+
})
|
|
57
|
+
const saved = parseToolResult<{ id?: string; name?: string } | null>(result)
|
|
58
|
+
setSaveOpen(false)
|
|
59
|
+
if (saved?.id && onSaved) {
|
|
60
|
+
onSaved({
|
|
61
|
+
id: saved.id,
|
|
62
|
+
name: saved.name ?? saveName.trim(),
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
} catch (err) {
|
|
66
|
+
// Previously uncaught: a rejected `save-dashboard` left the dialog open
|
|
67
|
+
// with no feedback. Surface the reason inline (Finding [3]).
|
|
68
|
+
setSaveError(err instanceof Error ? err.message : String(err))
|
|
69
|
+
} finally {
|
|
70
|
+
setBusy(false)
|
|
71
|
+
}
|
|
72
|
+
}, [
|
|
73
|
+
callTool,
|
|
74
|
+
dashboardId,
|
|
75
|
+
draft,
|
|
76
|
+
keyEntries,
|
|
77
|
+
onSaved,
|
|
78
|
+
saveDescription,
|
|
79
|
+
saveName,
|
|
80
|
+
saveToolName,
|
|
81
|
+
stepEntries,
|
|
82
|
+
title,
|
|
83
|
+
])
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
isBusy,
|
|
87
|
+
saveOpen,
|
|
88
|
+
setSaveOpen,
|
|
89
|
+
saveName,
|
|
90
|
+
setSaveName,
|
|
91
|
+
saveDescription,
|
|
92
|
+
setSaveDescription,
|
|
93
|
+
saveError,
|
|
94
|
+
setSaveError,
|
|
95
|
+
saveDraft,
|
|
96
|
+
}
|
|
97
|
+
}
|
package/src/app/host-bridge.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { createContext, useContext, type ReactNode } from "react"
|
|
|
5
5
|
* host runtime. A `HostBridge` is the single seam a portable widget talks to:
|
|
6
6
|
* write the widget against {@link useHostBridge} and it runs unchanged in our
|
|
7
7
|
* own `mcp-use` host, inside ChatGPT (OpenAI Apps SDK), or as a standalone web
|
|
8
|
-
* app driven directly by a `@modelcontextprotocol/
|
|
8
|
+
* app driven directly by a `@modelcontextprotocol/client` client — only the
|
|
9
9
|
* surrounding adapter changes.
|
|
10
10
|
*
|
|
11
11
|
* This is deliberately the *minimum* a deterministic UI needs, not a mirror of
|
|
@@ -288,7 +288,7 @@ export function createChatGptHostBridge(sdk?: OpenAiAppsSdk | null): HostBridge
|
|
|
288
288
|
export interface StandaloneHostBridgeOptions {
|
|
289
289
|
/**
|
|
290
290
|
* The only required capability: how to call a tool on the server. In a
|
|
291
|
-
* standalone web app this typically wraps a `@modelcontextprotocol/
|
|
291
|
+
* standalone web app this typically wraps a `@modelcontextprotocol/client`
|
|
292
292
|
* `Client.callTool({ name, arguments })`, but any function with this shape
|
|
293
293
|
* works — that injection is the whole point: hand-built widgets render
|
|
294
294
|
* against *any* existing MCP server without the toolkit's host runtime.
|
|
@@ -322,7 +322,7 @@ export interface StandaloneHostBridgeOptions {
|
|
|
322
322
|
/**
|
|
323
323
|
* Build a {@link HostBridge} for a standalone web app driven against an existing
|
|
324
324
|
* MCP server — no toolkit host, no `createFrameworkApp`. You inject `callTool`
|
|
325
|
-
* (usually a thin wrapper over a `@modelcontextprotocol/
|
|
325
|
+
* (usually a thin wrapper over a `@modelcontextprotocol/client` client); the
|
|
326
326
|
* conversation-shaped verbs (`sendFollowup`, `setModelContext`) are no-ops
|
|
327
327
|
* unless you wire handlers, and `openExternal` defaults to `window.open`.
|
|
328
328
|
*
|
|
@@ -332,7 +332,7 @@ export interface StandaloneHostBridgeOptions {
|
|
|
332
332
|
* harness also builds on this factory so host simulation has a single source.
|
|
333
333
|
*
|
|
334
334
|
* @example
|
|
335
|
-
* const client = new Client(…) // @modelcontextprotocol/
|
|
335
|
+
* const client = new Client(…) // @modelcontextprotocol/client
|
|
336
336
|
* const bridge = createStandaloneHostBridge({
|
|
337
337
|
* callTool: (name, args) => client.callTool({ name, arguments: args }),
|
|
338
338
|
* getData: () => currentRecord,
|