@frontmcp/uipack 1.9.6 → 1.10.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 +183 -315
- package/esm/bridge-runtime/index.mjs +0 -3
- package/esm/package.json +14 -11
- package/esm/resolver/index.mjs +0 -3
- package/esm/shell/index.mjs +0 -3
- package/esm/types/index.mjs +0 -3
- package/esm/typings/index.mjs +0 -3
- package/esm/utils/index.mjs +0 -3
- package/package.json +14 -11
package/README.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# @frontmcp/uipack
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@frontmcp/uipack` is the React-free core FrontMCP builds widget pages with, on the server. It renders a tool's template into a full HTML page with a Content Security Policy, the call's data and the bridge script that talks to the host; resolves a widget's imports to CDN URLs; and bundles React widget files. `@frontmcp/sdk` depends on it, so a FrontMCP server already has it. Import it yourself to split a template into functions with `html`, to test a template without a server with `renderToolTemplate()`, or to build widget pages for a host of your own.
|
|
4
4
|
|
|
5
|
-
[](../../LICENSE)
|
|
5
|
+
[](https://www.npmjs.com/package/@frontmcp/uipack) [](https://github.com/agentfront/frontmcp/blob/main/LICENSE)
|
|
7
6
|
|
|
8
7
|
## Install
|
|
9
8
|
|
|
@@ -11,388 +10,257 @@ HTML shell builder, pluggable import resolver, and NPM component loader for MCP
|
|
|
11
10
|
npm install @frontmcp/uipack
|
|
12
11
|
```
|
|
13
12
|
|
|
14
|
-
No React
|
|
13
|
+
- No React. The one runtime dependency is `zod`; npm 7 and later also install the peer `@frontmcp/lazy-zod`, at the same version.
|
|
14
|
+
- `esbuild` is an optional peer, needed only to bundle `.tsx` and `.jsx` widget files. Install it as a dependency, not a dev dependency, since it's loaded when a widget is rendered.
|
|
15
|
+
- It runs on Node.js 24 or later.
|
|
15
16
|
|
|
16
|
-
##
|
|
17
|
+
## Usage
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
Render a template the way a tool call does, without a server:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { html, renderToolTemplate, type TemplateContext } from '@frontmcp/uipack';
|
|
23
|
+
|
|
24
|
+
type Weather = { city: string; tempC: number };
|
|
25
|
+
|
|
26
|
+
const badge = (text: string) => html`<span class="badge">${text}</span>`;
|
|
27
|
+
|
|
28
|
+
const result = renderToolTemplate({
|
|
29
|
+
toolName: 'get_weather',
|
|
30
|
+
input: { city: 'Oslo' },
|
|
31
|
+
output: { city: 'Oslo', tempC: 21 },
|
|
32
|
+
template: (ctx: TemplateContext<{ city: string }, Weather>) =>
|
|
33
|
+
html`<h2>${ctx.output.city} ${badge(`${ctx.output.tempC}°C`)}</h2>`,
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`result.html` is a whole HTML document whose body is `<h2>Oslo <span class="badge">21°C</span></h2>`, `result.uiType` is `"html"`, and `result.meta["ui/mimeType"]` is `"text/html;profile=mcp-app"`. Values interpolated into `html` are escaped, so a city of `<script>` renders as `<script>`; markup built with `html` or `trustedHtml()` isn't escaped twice. `html` is the same builder as a tool template's `ctx.helpers.html`, so pieces of a widget can live in their own file and be tested on their own ([Splitting a template into functions](https://frontmcp.dev/reference/ui/components#splitting-a-template-into-functions)).
|
|
38
|
+
|
|
39
|
+
### Building a page around your own markup
|
|
19
40
|
|
|
20
41
|
```ts
|
|
21
42
|
import { buildShell } from '@frontmcp/uipack/shell';
|
|
22
43
|
|
|
23
|
-
const
|
|
44
|
+
const { html, hash, size } = buildShell('<div id="root"></div>', {
|
|
24
45
|
toolName: 'get_weather',
|
|
25
46
|
input: { city: 'London' },
|
|
26
47
|
output: { temp: 18 },
|
|
27
48
|
includeBridge: true,
|
|
28
49
|
csp: { connectDomains: ['https://api.weather.com'] },
|
|
29
50
|
});
|
|
30
|
-
|
|
31
|
-
// result.html -> full HTML document with CSP, data injection, bridge IIFE
|
|
32
|
-
// result.hash -> fast 32-bit content hash
|
|
33
|
-
// result.size -> byte length
|
|
34
51
|
```
|
|
35
52
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
```ts
|
|
39
|
-
import { renderComponent } from '@frontmcp/uipack/component';
|
|
53
|
+
`hash` is a short, non-cryptographic hash of the page, for cache keys, and `size` its length in bytes. The page looks like this, with the bridge script shortened:
|
|
40
54
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
```html
|
|
56
|
+
<!DOCTYPE html>
|
|
57
|
+
<html lang="en">
|
|
58
|
+
<head>
|
|
59
|
+
<meta charset="UTF-8" />
|
|
60
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
61
|
+
<meta
|
|
62
|
+
http-equiv="Content-Security-Policy"
|
|
63
|
+
content="default-src 'none'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net ... https://esm.sh; ... connect-src https://cdn.jsdelivr.net ... https://esm.sh https://api.weather.com; ..."
|
|
64
|
+
/>
|
|
65
|
+
<script>
|
|
66
|
+
window.__mcpAppsEnabled = true;
|
|
67
|
+
window.__mcpToolName = 'get_weather';
|
|
68
|
+
window.__mcpToolInput = { city: 'London' };
|
|
69
|
+
window.__mcpToolOutput = { temp: 18 };
|
|
70
|
+
window.__mcpStructuredContent = null;
|
|
71
|
+
</script>
|
|
72
|
+
<script>
|
|
73
|
+
/* the bridge: picks an adapter for the host and sets window.FrontMcpBridge */
|
|
74
|
+
</script>
|
|
75
|
+
</head>
|
|
76
|
+
<body>
|
|
77
|
+
<div id="root"></div>
|
|
78
|
+
</body>
|
|
79
|
+
</html>
|
|
45
80
|
```
|
|
46
81
|
|
|
47
|
-
###
|
|
82
|
+
### Resolving imports to CDN URLs
|
|
48
83
|
|
|
49
84
|
```ts
|
|
50
|
-
import { createEsmShResolver,
|
|
85
|
+
import { createEsmShResolver, rewriteImports } from '@frontmcp/uipack/resolver';
|
|
51
86
|
|
|
52
87
|
const resolver = createEsmShResolver({ providerOrder: ['cloudflare', 'jsdelivr'] });
|
|
53
|
-
const result = resolver.resolve('chart.js');
|
|
54
|
-
// -> { value: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.1/chart.umd.min.js', type: 'url' }
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Generate Bridge IIFE
|
|
58
88
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// Use pre-generated universal script
|
|
63
|
-
const script = `<script>${UNIVERSAL_BRIDGE_SCRIPT}</script>`;
|
|
89
|
+
resolver.resolve('chart.js');
|
|
90
|
+
// { value: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.1/chart.umd.min.js', type: 'url' }
|
|
64
91
|
|
|
65
|
-
|
|
66
|
-
|
|
92
|
+
rewriteImports("import { format } from 'date-fns';", { resolver }).code;
|
|
93
|
+
// "import { format } from 'https://esm.sh/date-fns';"
|
|
67
94
|
```
|
|
68
95
|
|
|
69
|
-
|
|
96
|
+
A package in the CDN registry (`react`, `react-dom`, `chart.js`, `d3`, `lodash`) resolves to its registered URL, trying the providers in `providerOrder`; any other package resolves to `https://esm.sh/<specifier>`.
|
|
70
97
|
|
|
71
|
-
|
|
72
|
-
import { createTypeFetcher } from '@frontmcp/uipack/typings';
|
|
98
|
+
### Rendering a component from npm
|
|
73
99
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
maxDepth: 3,
|
|
77
|
-
});
|
|
100
|
+
```ts
|
|
101
|
+
import { renderComponent } from '@frontmcp/uipack/component';
|
|
78
102
|
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
|
|
103
|
+
const { html } = renderComponent(
|
|
104
|
+
{ source: { npm: 'my-weather-widget', exportName: 'WeatherCard' } },
|
|
105
|
+
{ toolName: 'get_weather', output: { temp: 18 } },
|
|
106
|
+
);
|
|
83
107
|
```
|
|
84
108
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
- **Shell builder** — Full HTML documents with CSP, data injection, and bridge runtime
|
|
88
|
-
- **Import resolver** — Pluggable CDN resolution (esm.sh, Cloudflare, jsDelivr, unpkg)
|
|
89
|
-
- **Component loader** — 4 source modes: npm, file, URL, inline function
|
|
90
|
-
- **Bridge IIFE** — Platform-aware vanilla JS bridge (OpenAI, ExtApps, Claude, Gemini, Generic)
|
|
91
|
-
- **Type fetching** — Download `.d.ts` from esm.sh with recursive dependency resolution
|
|
92
|
-
- **XSS utilities** — `escapeHtml`, `safeJsonForScript`, `escapeScriptClose`, and more
|
|
93
|
-
- **Custom shells** — Load shell templates from npm, URL, or inline HTML
|
|
94
|
-
- **Standalone types** — SDK-independent type definitions for widget configuration
|
|
95
|
-
|
|
96
|
-
## Entry Points
|
|
97
|
-
|
|
98
|
-
| Path | Purpose |
|
|
99
|
-
| --------------------------------- | ------------------------------------ |
|
|
100
|
-
| `@frontmcp/uipack` | Main barrel (re-exports all modules) |
|
|
101
|
-
| `@frontmcp/uipack/resolver` | Pluggable import resolution |
|
|
102
|
-
| `@frontmcp/uipack/shell` | HTML shell builder |
|
|
103
|
-
| `@frontmcp/uipack/component` | Polymorphic component loader |
|
|
104
|
-
| `@frontmcp/uipack/bridge-runtime` | Platform bridge IIFE generator |
|
|
105
|
-
| `@frontmcp/uipack/typings` | TypeScript .d.ts fetching engine |
|
|
106
|
-
| `@frontmcp/uipack/types` | Standalone type definitions |
|
|
107
|
-
| `@frontmcp/uipack/utils` | XSS-safe escaping utilities |
|
|
109
|
+
`renderComponent()` is synchronous. The page imports the component from `https://esm.sh/my-weather-widget`, loads React from esm.sh through an import map, and renders the component into `#root` with the tool's output as its props. The source can be any of these:
|
|
108
110
|
|
|
109
|
-
|
|
111
|
+
| Source | Shape | What happens |
|
|
112
|
+
| -------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
113
|
+
| npm | `{ npm: 'my-chart', exportName?, version? }` | Loaded from its CDN registry entry, or from esm.sh. |
|
|
114
|
+
| file | `{ file: '/abs/path/widget.tsx', exportName?, inline? }` | A local file. `.tsx` and `.jsx` files are bundled with esbuild; a relative path resolves from the working directory. |
|
|
115
|
+
| import | `{ import: 'https://cdn.example.com/widget.js', exportName? }` | A module URL, used as it is. |
|
|
116
|
+
| function | `(input, output) => '<div>…</div>'` | Returns the HTML. |
|
|
110
117
|
|
|
111
|
-
###
|
|
118
|
+
### Generating the bridge script
|
|
112
119
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
| `createEsmShResolver(opts?)` | function | Default resolver using esm.sh with CDN registry fallback |
|
|
116
|
-
| `DEFAULT_CDN_REGISTRY` | constant | Pre-configured entries for react, react-dom, chart.js, d3, lodash |
|
|
117
|
-
| `parseImports(source)` | function | Parse source code for named, default, namespace, dynamic imports |
|
|
118
|
-
| `rewriteImports(source, resolver, overrides?)` | function | Rewrite bare specifiers to CDN URLs |
|
|
119
|
-
| `createImportMap(overrides?)` | function | Generate browser-standard import map |
|
|
120
|
-
| `mergeImportMaps(...maps)` | function | Deep-merge multiple import maps |
|
|
121
|
-
| `generateImportMapScriptTag(map)` | function | `<script type="importmap">` generation |
|
|
122
|
-
| `lookupPackage(name)` | function | Query the CDN registry for a package |
|
|
123
|
-
| `getPackageCDNUrl(name, provider?)` | function | Resolve package to best CDN URL |
|
|
124
|
-
| `extractExternalPackages(code)` | function | Extract external package names from source |
|
|
120
|
+
```ts
|
|
121
|
+
import { BRIDGE_SCRIPT_TAGS, generateBridgeIIFE } from '@frontmcp/uipack/bridge-runtime';
|
|
125
122
|
|
|
126
|
-
|
|
123
|
+
const everyHost = BRIDGE_SCRIPT_TAGS.universal;
|
|
124
|
+
const openAiOnly = `<script>${generateBridgeIIFE({ adapters: ['openai', 'generic'], minify: true })}</script>`;
|
|
125
|
+
```
|
|
127
126
|
|
|
128
|
-
|
|
129
|
-
| ------------------------------------------------------------ | -------- | ----------------------------------------------------------------------------------------------- |
|
|
130
|
-
| `buildShell(content, config)` | function | Main entry point -> `ShellResult` |
|
|
131
|
-
| `buildCSPMetaTag(config?)` | function | Generate `<meta>` CSP tag |
|
|
132
|
-
| `buildCSPDirectives(config?)` | function | Merge custom domains with defaults |
|
|
133
|
-
| `buildDataInjectionScript(toolName, input?, output?)` | function | `<script>` setting `window.__mcp*` globals |
|
|
134
|
-
| `createTemplateHelpers(toolName)` | function | `html`, `trustedHtml`, `escapeHtml`, `formatDate`, `formatCurrency`, `uniqueId`, `jsonEmbed` |
|
|
135
|
-
| `` html`…` ``, `trustedHtml(markup)`, `isTrustedHtml(value)` | function | Build / mark / detect `TrustedHtml` template markup (interpolated values in `html` are escaped) |
|
|
136
|
-
| `resolveShellTemplate(opts)` | function | Resolve custom shell from npm/URL/inline |
|
|
137
|
-
| `applyShellTemplate(template, values)` | function | Apply values to resolved template |
|
|
138
|
-
| `validateShellTemplate(template)` | function | Validate a custom shell template |
|
|
139
|
-
| `DEFAULT_CDN_DOMAINS` | constant | jsDelivr, Cloudflare, Google Fonts |
|
|
127
|
+
The script detects the host and sets `window.FrontMcpBridge`:
|
|
140
128
|
|
|
141
|
-
|
|
129
|
+
| Member | Description |
|
|
130
|
+
| ---------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
|
131
|
+
| `adapterId`, `initialized`, `capabilities` | The adapter picked for the host, whether it's ready, and what it can do. |
|
|
132
|
+
| `getToolInput()`, `getToolOutput()`, `getStructuredContent()` | The call's data, from the page and then from each result the host sends. |
|
|
133
|
+
| `callTool(name, args)` | Calls a tool through the host and returns the host's result. |
|
|
134
|
+
| `onToolResult(callback)`, `onContextChange(callback)` | Subscribe to results and to host changes. Each returns an unsubscribe function. |
|
|
135
|
+
| `getTheme()`, `getDisplayMode()`, `getHostContext()`, `hasCapability(name)` | What the host said about itself. |
|
|
136
|
+
| `sendMessage(text)`, `openLink(url)` | Add a message to the conversation, open a link, through the host. |
|
|
137
|
+
| `requestDisplayMode(mode)`, `setSize({ width?, height? })`, `requestClose()` | Ask for `inline`, `fullscreen` or `pip`, report the widget's size, ask to remove the widget. |
|
|
138
|
+
| `updateModelContext(data, merge?)` | Tell the host what the model should know, where the host supports it. |
|
|
139
|
+
| `getWidgetState()`, `setWidgetState(state)` | State kept in `localStorage`. |
|
|
142
140
|
|
|
143
|
-
|
|
144
|
-
| ------------------------------------------------------------------- | -------- | -------------------------------------------------- |
|
|
145
|
-
| `renderComponent(config, shell)` | function | Top-level compositor -> `ShellResult` |
|
|
146
|
-
| `resolveUISource(source, opts)` | function | Resolve any source to `ResolvedComponent` |
|
|
147
|
-
| `generateMountScript(resolved, data)` | function | ES module mount script for React/module components |
|
|
148
|
-
| `isNpmSource`, `isFileSource`, `isImportSource`, `isFunctionSource` | guards | Type narrowing helpers |
|
|
141
|
+
### Fetching TypeScript definitions
|
|
149
142
|
|
|
150
|
-
|
|
143
|
+
```ts
|
|
144
|
+
import { createTypeFetcher } from '@frontmcp/uipack/typings';
|
|
151
145
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
| `UNIVERSAL_BRIDGE_SCRIPT` | constant | Pre-generated script with all adapters |
|
|
157
|
-
| `BRIDGE_SCRIPT_TAGS` | constant | `{ universal, chatgpt, claude, gemini }` pre-wrapped `<script>` tags |
|
|
146
|
+
const fetcher = createTypeFetcher({ allowedPackages: ['@myorg/*'], maxDepth: 3 });
|
|
147
|
+
const { results, errors } = await fetcher.fetchBatch({ imports: ["import { z } from 'zod'"] });
|
|
148
|
+
// results[0].files: the .d.ts files, at virtual node_modules/ paths
|
|
149
|
+
```
|
|
158
150
|
|
|
159
|
-
|
|
151
|
+
It fetches the `.d.ts` files of each import from esm.sh, following their own imports up to `maxDepth` (default 2). Only allowed packages are fetched: `react`, `react-dom`, `react/jsx-runtime`, `zod` and `@frontmcp/*`, plus `allowedPackages`, or any package with `allowedPackages: false`.
|
|
160
152
|
|
|
161
|
-
|
|
162
|
-
| ----------------------------- | -------- | ------------------------------------------------------------- |
|
|
163
|
-
| `createTypeFetcher(opts?)` | function | Factory creating a `TypeFetcher` instance |
|
|
164
|
-
| `TypeFetcher` | class | Main fetcher with caching and recursive dependency resolution |
|
|
165
|
-
| `MemoryTypeCache` | class | LRU cache with TTL support |
|
|
166
|
-
| `globalTypeCache` | constant | Module-level singleton cache (500 entries, 1h TTL) |
|
|
167
|
-
| `parseDtsImports(content)` | function | Parse `.d.ts` files for imports/references |
|
|
168
|
-
| `combineDtsContents(results)` | function | Combine multiple `.d.ts` files into one |
|
|
153
|
+
## Entry points
|
|
169
154
|
|
|
170
|
-
|
|
155
|
+
`@frontmcp/uipack` exports everything below. Each module is also its own entry point:
|
|
171
156
|
|
|
172
|
-
|
|
|
173
|
-
|
|
|
174
|
-
| `
|
|
175
|
-
| `
|
|
176
|
-
| `
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
157
|
+
| Import | What's in it |
|
|
158
|
+
| --------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
159
|
+
| `@frontmcp/uipack/adapters` | `renderToolTemplate()`, `MCP_APPS_MIME_TYPE`, and the helpers the SDK uses to build a tool's widget response. |
|
|
160
|
+
| `@frontmcp/uipack/shell` | `buildShell()`, `html`, `trustedHtml()`, template helpers, CSP, custom shells. |
|
|
161
|
+
| `@frontmcp/uipack/resolver` | Import resolution, the CDN registry, import maps. |
|
|
162
|
+
| `@frontmcp/uipack/component` | `renderComponent()` and the component sources. |
|
|
163
|
+
| `@frontmcp/uipack/bridge-runtime` | The bridge script generator. |
|
|
164
|
+
| `@frontmcp/uipack/typings` | The `.d.ts` fetcher and its cache. |
|
|
165
|
+
| `@frontmcp/uipack/types` | Types for widget configuration, such as `UITemplateConfig` and `TemplateContext`. |
|
|
166
|
+
| `@frontmcp/uipack/utils` | Escaping helpers. |
|
|
180
167
|
|
|
181
|
-
|
|
168
|
+
### Adapters
|
|
182
169
|
|
|
183
|
-
|
|
170
|
+
| Export | Description |
|
|
171
|
+
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
172
|
+
| `renderToolTemplate(options)` | Renders a template as a call does: `{ html, uiType, hash, size, meta }`. Options: `toolName`, `input`, `output`, `template`, `platformType?`, `resourceMode?`, `sizing?`, `csp?`, `escapeStringResults?`. |
|
|
173
|
+
| `MCP_APPS_MIME_TYPE` | `"text/html;profile=mcp-app"`. |
|
|
184
174
|
|
|
185
|
-
|
|
186
|
-
<!DOCTYPE html>
|
|
187
|
-
<html lang="en">
|
|
188
|
-
<head>
|
|
189
|
-
<meta charset="UTF-8" />
|
|
190
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
191
|
-
<title>get_weather</title>
|
|
175
|
+
### Shell
|
|
192
176
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
177
|
+
| Export | Description |
|
|
178
|
+
| ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
179
|
+
| `buildShell(content, config)` | A page around `content`: `{ html, hash, size }`. `config`: `toolName` (required), `input`, `output`, `structuredContent`, `csp`, `includeBridge` (default `true`), `withShell` (default `true`; `false` returns the data script and the content only), `title`, `sizing`, `displayMode`, `customShell`. |
|
|
180
|
+
| `` html`…` ``, `trustedHtml(markup)`, `isTrustedHtml(value)` | Build, mark and detect trusted markup. Values interpolated into `html` are escaped. |
|
|
181
|
+
| `createTemplateHelpers()` | A new set of template helpers: `escapeHtml`, `formatDate`, `formatCurrency`, `uniqueId`, `jsonEmbed`, `html`, `trustedHtml`. |
|
|
182
|
+
| `buildCSPDirectives(csp?)`, `buildCSPMetaTag(csp?)` | The page's policy: the default CDN origins plus `connectDomains` and `resourceDomains`. |
|
|
183
|
+
| `buildDataInjectionScript({ toolName, input?, output?, structuredContent?, sizing?, displayMode? })` | The `<script>` that sets `window.__mcpToolName`, `__mcpToolInput`, `__mcpToolOutput` and `__mcpStructuredContent`. |
|
|
184
|
+
| `resolveShellTemplate(source, options?)` | Async. Loads a custom shell from `{ inline }`, `{ url, timeout? }` or `{ npm, exportName?, version? }`, and validates it. |
|
|
185
|
+
| `validateShellTemplate(template)`, `applyShellTemplate(template, values)` | Check and fill a custom shell's placeholders: `{{CONTENT}}` (required), `{{CSP}}`, `{{DATA}}`, `{{BRIDGE}}`, `{{TITLE}}`. |
|
|
186
|
+
| `DEFAULT_CDN_DOMAINS` | The origins every page allows: jsDelivr, cdnjs, Google Fonts and esm.sh. |
|
|
198
187
|
|
|
199
|
-
|
|
200
|
-
<script>
|
|
201
|
-
window.__mcpToolName = 'get_weather';
|
|
202
|
-
window.__mcpToolInput = { city: 'London' };
|
|
203
|
-
window.__mcpToolOutput = { temp: 18 };
|
|
204
|
-
window.__mcpStructuredContent = null;
|
|
205
|
-
</script>
|
|
188
|
+
### Resolver
|
|
206
189
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
<script type="importmap">
|
|
217
|
-
{ "imports": { "react": "https://esm.sh/react@19" } }
|
|
218
|
-
</script>
|
|
219
|
-
<div id="root"></div>
|
|
220
|
-
<script type="module">
|
|
221
|
-
import { WeatherCard } from 'https://esm.sh/my-weather-widget';
|
|
190
|
+
| Export | Description |
|
|
191
|
+
| ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
192
|
+
| `createEsmShResolver({ registry?, providerOrder?, fallbackCdnBase? })` | The default resolver. |
|
|
193
|
+
| `createResolverWithOverrides(overrides, options?)` | The default resolver, with fixed URLs for some packages. |
|
|
194
|
+
| `DEFAULT_CDN_REGISTRY`, `mergeRegistries(custom)` | The registry (`react`, `react-dom`, `chart.js`, `d3`, `lodash`), and it merged with your entries. |
|
|
195
|
+
| `lookupPackage(name, registry?)`, `getPackageCDNUrl(name, providerOrder?, registry?)` | Query the registry. |
|
|
196
|
+
| `parseImports(source)`, `extractExternalPackages(source)` | The imports in source code, and the packages they name. |
|
|
197
|
+
| `rewriteImports(source, { resolver?, skipPackages?, overrides? })` | Replaces bare specifiers with CDN URLs: `{ code, rewrittenCount, rewrites, fallbackPackages }`. |
|
|
198
|
+
| `createImportMap(dependencies)`, `mergeImportMaps(...maps)`, `generateImportMapScriptTag(map)` | Build, merge and write a browser import map. |
|
|
222
199
|
|
|
223
|
-
|
|
224
|
-
</script>
|
|
225
|
-
</body>
|
|
226
|
-
</html>
|
|
227
|
-
```
|
|
200
|
+
### Component
|
|
228
201
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
|
232
|
-
|
|
|
233
|
-
|
|
|
234
|
-
|
|
|
235
|
-
|
|
|
236
|
-
| **inline** | `(input, output) => '<div>...</div>'` | Function returning HTML string |
|
|
237
|
-
|
|
238
|
-
## Bridge API
|
|
239
|
-
|
|
240
|
-
The bridge IIFE exposes `window.FrontMcpBridge` with the following API:
|
|
241
|
-
|
|
242
|
-
| Method | Description |
|
|
243
|
-
| --------------------------- | ------------------------------------ |
|
|
244
|
-
| `callTool(name, args)` | Invoke an MCP tool from the widget |
|
|
245
|
-
| `getToolOutput()` | Read injected tool output data |
|
|
246
|
-
| `getToolInput()` | Read injected tool input data |
|
|
247
|
-
| `sendMessage(content)` | Send message to host |
|
|
248
|
-
| `openLink(url)` | Open a URL via platform adapter |
|
|
249
|
-
| `requestDisplayMode(mode)` | Switch inline / fullscreen / pip |
|
|
250
|
-
| `setWidgetState(state)` | Persist widget state to localStorage |
|
|
251
|
-
| `onContextChange(callback)` | Subscribe to host context changes |
|
|
252
|
-
| `onToolResult(callback)` | Subscribe to tool result events |
|
|
253
|
-
| `hasCapability(cap)` | Check adapter capabilities |
|
|
254
|
-
| `getTheme()` | Get current theme from host |
|
|
255
|
-
| `getDisplayMode()` | Get current display mode |
|
|
256
|
-
| `getHostContext()` | Get host context metadata |
|
|
202
|
+
| Export | Description |
|
|
203
|
+
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
|
|
204
|
+
| `renderComponent(config, shellConfig)` | Resolves `config.source` and builds the page around it: `{ html, hash, size }`. |
|
|
205
|
+
| `resolveUISource(source, options?)` | Resolves a source to a `ResolvedComponent`. |
|
|
206
|
+
| `generateMountScript(resolved, propsMapping?)` | The module script that imports and mounts a module component. |
|
|
207
|
+
| `bundleFileSource()`, `transpileReactSource()` | Bundle or transpile a `.tsx` or `.jsx` widget with esbuild. |
|
|
208
|
+
| `isNpmSource`, `isFileSource`, `isImportSource`, `isFunctionSource` | Type guards for the sources. |
|
|
257
209
|
|
|
258
|
-
|
|
210
|
+
### Bridge runtime
|
|
259
211
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
subgraph bridge-runtime["bridge-runtime/"]
|
|
268
|
-
BR_IIFE["iife-generator.ts<br/>5 platform adapters:<br/>OpenAI, ExtApps, Claude,<br/>Gemini, Generic"]
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
subgraph component["component/"]
|
|
272
|
-
CO_TYPES["types.ts<br/>NpmSource, FileSource,<br/>ImportSource, FunctionSource"]
|
|
273
|
-
CO_LOAD["loader.ts<br/>resolveUISource(),<br/>generateMountScript()"]
|
|
274
|
-
CO_REND["renderer.ts<br/>renderComponent()"]
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
subgraph resolver["resolver/"]
|
|
278
|
-
RE_CDN["cdn-registry.ts<br/>DEFAULT_CDN_REGISTRY,<br/>lookupPackage()"]
|
|
279
|
-
RE_ESM["esm-sh.resolver.ts<br/>createEsmShResolver()"]
|
|
280
|
-
RE_PARSE["import-parser.ts<br/>parseImports()"]
|
|
281
|
-
RE_REWRITE["import-rewriter.ts<br/>rewriteImports()"]
|
|
282
|
-
RE_MAP["import-map.ts<br/>createImportMap(),<br/>mergeImportMaps()"]
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
subgraph shell["shell/"]
|
|
286
|
-
SH_BUILD["builder.ts<br/>buildShell()"]
|
|
287
|
-
SH_CSP["csp.ts<br/>CSP directives + meta tag"]
|
|
288
|
-
SH_DATA["data-injector.ts<br/>window.__mcp* globals"]
|
|
289
|
-
SH_CUSTOM["custom-shell-*.ts<br/>Resolve, validate, apply<br/>custom shell templates"]
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
subgraph types["types/"]
|
|
293
|
-
TY_CFG["ui-config.ts<br/>UITemplateConfig,<br/>WidgetServingMode"]
|
|
294
|
-
TY_RT["ui-runtime.ts<br/>UIType, WidgetManifest,<br/>WidgetConfig"]
|
|
295
|
-
end
|
|
296
|
-
|
|
297
|
-
subgraph typings["typings/"]
|
|
298
|
-
TP_FETCH["type-fetcher.ts<br/>TypeFetcher class"]
|
|
299
|
-
TP_DTS["dts-parser.ts<br/>parseDtsImports()"]
|
|
300
|
-
TP_SCHEMA["schemas.ts<br/>Zod validation"]
|
|
301
|
-
TP_CACHE["cache/<br/>MemoryTypeCache (LRU + TTL)"]
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
subgraph utils["utils/"]
|
|
305
|
-
UT["escapeHtml, safeJsonForScript,<br/>escapeScriptClose, safeStringify"]
|
|
306
|
-
end
|
|
307
|
-
end
|
|
308
|
-
```
|
|
212
|
+
| Export | Description |
|
|
213
|
+
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
|
214
|
+
| `generateBridgeIIFE(options?)` | The bridge script. Options: `adapters` (from `openai`, `ext-apps`, `claude`, `gemini`, `generic`), `debug`, `trustedOrigins`, `minify`. |
|
|
215
|
+
| `generatePlatformBundle(platform, options?)` | The script for `chatgpt`, `claude`, `gemini` or `universal`. |
|
|
216
|
+
| `UNIVERSAL_BRIDGE_SCRIPT` | The script with every adapter. |
|
|
217
|
+
| `BRIDGE_SCRIPT_TAGS` | `{ universal, chatgpt, claude, gemini }`, each wrapped in `<script>`. |
|
|
309
218
|
|
|
310
|
-
###
|
|
311
|
-
|
|
312
|
-
```mermaid
|
|
313
|
-
graph BT
|
|
314
|
-
utils["utils<br/><i>foundation, zero deps</i>"]
|
|
315
|
-
resolver["resolver<br/><i>import resolution</i>"]
|
|
316
|
-
shell["shell<br/><i>HTML shell builder</i>"]
|
|
317
|
-
bridge["bridge-runtime<br/><i>IIFE generator, standalone</i>"]
|
|
318
|
-
component["component<br/><i>polymorphic loader</i>"]
|
|
319
|
-
types["types<br/><i>standalone, no internal deps</i>"]
|
|
320
|
-
typings["typings<br/><i>standalone, uses zod</i>"]
|
|
321
|
-
|
|
322
|
-
resolver --> utils
|
|
323
|
-
shell --> utils
|
|
324
|
-
shell --> resolver
|
|
325
|
-
shell --> bridge
|
|
326
|
-
component --> utils
|
|
327
|
-
component --> resolver
|
|
328
|
-
component --> shell
|
|
329
|
-
```
|
|
219
|
+
### Typings
|
|
330
220
|
|
|
331
|
-
|
|
221
|
+
| Export | Description |
|
|
222
|
+
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
223
|
+
| `createTypeFetcher(options?, cache?)` | A `TypeFetcher`. Options: `allowedPackages`, `maxDepth`, `timeout` (10 s per request), `maxConcurrency` (5), `cdnBaseUrl`, `fetch`. |
|
|
224
|
+
| `TypeFetcher` | `fetchBatch({ imports, maxDepth?, timeout? })`: `{ results, errors, totalTimeMs, cacheHits }`. |
|
|
225
|
+
| `MemoryTypeCache`, `globalTypeCache` | A least-recently-used cache with expiry; the shared one keeps up to 500 entries for an hour. |
|
|
226
|
+
| `parseDtsImports(content)`, `combineDtsContents(contents)` | Parse a `.d.ts` file's imports; join several files into one. |
|
|
332
227
|
|
|
333
|
-
|
|
228
|
+
### Utils
|
|
334
229
|
|
|
335
|
-
|
|
230
|
+
| Export | Description |
|
|
231
|
+
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
232
|
+
| `escapeHtml(value)` | Escapes `&`, `<`, `>`, `"` and `'`, and U+2028 and U+2029. `null` and `undefined` give `''`. |
|
|
233
|
+
| `escapeHtmlAttr(value)` | Escapes `&` and `"`, for attribute values. |
|
|
234
|
+
| `escapeJsString(value)` | Escapes a string for a JavaScript string literal. |
|
|
235
|
+
| `escapeScriptClose(json)` | Replaces `</` with `<\/`, so the text can't close a `<script>`. |
|
|
236
|
+
| `safeJsonForScript(value)` | JSON safe to put in a `<script>`: `<`, `>` and `&` escaped, BigInt as a string, and `{"error":"Value could not be serialized"}` for a value JSON can't hold, such as a circular one. |
|
|
237
|
+
| `safeStringify(value, space?)` | `JSON.stringify` that writes `[Circular]` for circular references. |
|
|
336
238
|
|
|
337
|
-
|
|
239
|
+
## Docs
|
|
338
240
|
|
|
339
|
-
|
|
241
|
+
- [Widget components](https://frontmcp.dev/reference/ui/components): `@frontmcp/uipack` in a server, `html` and `renderToolTemplate()`
|
|
242
|
+
- [The `ui` option](https://frontmcp.dev/reference/ui): templates, serving modes, Content Security Policy
|
|
243
|
+
- [Hosts and platforms](https://frontmcp.dev/reference/ui/hosts): the bridge, `window.FrontMcpBridge`, and what each host gets
|
|
244
|
+
- [Choosing how a widget is served](https://frontmcp.dev/learn/choosing-how-a-widget-is-served): inline and static pages, and what a widget can load
|
|
340
245
|
|
|
341
|
-
|
|
342
|
-
sequenceDiagram
|
|
343
|
-
participant Dev as Developer
|
|
344
|
-
participant SDK as @frontmcp/sdk
|
|
345
|
-
participant UP as @frontmcp/uipack
|
|
346
|
-
participant Browser
|
|
347
|
-
participant UI as @frontmcp/ui
|
|
246
|
+
## Related packages
|
|
348
247
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
UP->>UP: build shell (CSP + data injection)
|
|
353
|
-
UP->>UP: inject bridge IIFE
|
|
354
|
-
UP-->>SDK: ShellResult { html, hash, size }
|
|
248
|
+
- [`@frontmcp/sdk`](https://www.npmjs.com/package/@frontmcp/sdk): the server framework; it renders a tool's `ui` with this package.
|
|
249
|
+
- [`@frontmcp/ui`](https://www.npmjs.com/package/@frontmcp/ui): the React components, hooks and renderers for widget files.
|
|
250
|
+
- [`@frontmcp/testing`](https://www.npmjs.com/package/@frontmcp/testing): test helpers, with matchers for a tool's rendered widget.
|
|
355
251
|
|
|
356
|
-
|
|
357
|
-
SDK-->>Browser: cached HTML
|
|
252
|
+
## Contributing
|
|
358
253
|
|
|
359
|
-
|
|
360
|
-
Browser->>UI: Mount React components
|
|
361
|
-
UI->>UI: Bridge hooks read window.__mcp* globals
|
|
362
|
-
UI->>Browser: Interactive widget rendered
|
|
363
|
-
```
|
|
254
|
+
Source: [`libs/uipack`](https://github.com/agentfront/frontmcp/tree/main/libs/uipack). Issues and pull requests are welcome; see [CONTRIBUTING.md](https://github.com/agentfront/frontmcp/blob/main/CONTRIBUTING.md).
|
|
364
255
|
|
|
365
|
-
|
|
256
|
+
The source has one folder per entry point under `src/`: `adapters/`, `shell/`, `resolver/`, `component/`, `bridge-runtime/`, `typings/`, `types/` and `utils/`. `utils` and `bridge-runtime` depend on nothing else; `resolver` uses `utils`; `shell` uses `utils`, `resolver` and `bridge-runtime`; `component` builds on `shell`; `adapters` uses them all; `typings` stands alone, and `types` only imports types. Test escaping and Content Security Policy changes with hostile input. In the monorepo:
|
|
366
257
|
|
|
367
258
|
```bash
|
|
368
|
-
# Build
|
|
369
259
|
nx build uipack
|
|
370
|
-
|
|
371
|
-
# Test
|
|
372
260
|
nx test uipack
|
|
373
|
-
|
|
374
|
-
# Lint
|
|
375
261
|
nx lint uipack
|
|
376
262
|
```
|
|
377
263
|
|
|
378
|
-
### Testing
|
|
379
|
-
|
|
380
|
-
- 95%+ coverage required across statements, branches, functions, lines
|
|
381
|
-
- **XSS tests** are critical — test all escaping functions with malicious input
|
|
382
|
-
- **CSP tests** — verify generated Content-Security-Policy headers are correct
|
|
383
|
-
- Test all 4 component source modes (npm, file, import, inline)
|
|
384
|
-
- Test bridge IIFE generation for each platform
|
|
385
|
-
|
|
386
|
-
## Requirements
|
|
387
|
-
|
|
388
|
-
- Node.js >= 22.0.0
|
|
389
|
-
|
|
390
|
-
## Related Packages
|
|
391
|
-
|
|
392
|
-
- [`@frontmcp/ui`](../ui) — React components, hooks, and renderers that consume uipack output
|
|
393
|
-
- [`@frontmcp/sdk`](../sdk) — Core FrontMCP SDK with `ToolUIRegistry`
|
|
394
|
-
- [`@frontmcp/testing`](../testing) — UI test assertions
|
|
395
|
-
|
|
396
264
|
## License
|
|
397
265
|
|
|
398
|
-
Apache-2.0
|
|
266
|
+
Apache-2.0. See [LICENSE](https://github.com/agentfront/frontmcp/blob/main/LICENSE).
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : undefined;
|
|
2
|
-
const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
|
|
3
|
-
// __frontmcpCreateRequire
|
|
4
1
|
// libs/uipack/src/bridge-runtime/iife-generator.ts
|
|
5
2
|
var WIDGET_CALL_META_KEY = "frontmcp/widgetCall";
|
|
6
3
|
var MCP_APPS_DISPLAY_MODES = ["inline", "fullscreen", "pip"];
|
package/esm/package.json
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/uipack",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "FrontMCP
|
|
3
|
+
"version": "1.10.0",
|
|
4
|
+
"description": "React-free core that builds FrontMCP widget pages: HTML shell with CSP and bridge, template rendering, CDN import resolution",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
|
-
"homepage": "https://frontmcp.dev/reference/ui",
|
|
6
|
+
"homepage": "https://frontmcp.dev/reference/ui/components#frontmcpuipack",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"keywords": [
|
|
9
|
+
"frontmcp",
|
|
9
10
|
"mcp",
|
|
11
|
+
"model-context-protocol",
|
|
12
|
+
"mcp-apps",
|
|
13
|
+
"widgets",
|
|
10
14
|
"ui",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"framework",
|
|
16
|
-
"typescript"
|
|
15
|
+
"html",
|
|
16
|
+
"csp",
|
|
17
|
+
"import-map",
|
|
18
|
+
"agentfront"
|
|
17
19
|
],
|
|
18
20
|
"repository": {
|
|
19
21
|
"type": "git",
|
|
20
|
-
"url": "git+https://github.com/agentfront/frontmcp.git"
|
|
22
|
+
"url": "git+https://github.com/agentfront/frontmcp.git",
|
|
23
|
+
"directory": "libs/uipack"
|
|
21
24
|
},
|
|
22
25
|
"bugs": {
|
|
23
26
|
"url": "https://github.com/agentfront/frontmcp/issues"
|
|
@@ -61,7 +64,7 @@
|
|
|
61
64
|
"typescript": "^5.9.3"
|
|
62
65
|
},
|
|
63
66
|
"peerDependencies": {
|
|
64
|
-
"@frontmcp/lazy-zod": "1.
|
|
67
|
+
"@frontmcp/lazy-zod": "1.10.0",
|
|
65
68
|
"esbuild": ">=0.27.0 <1"
|
|
66
69
|
},
|
|
67
70
|
"peerDependenciesMeta": {
|
package/esm/resolver/index.mjs
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : undefined;
|
|
2
|
-
const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
|
|
3
|
-
// __frontmcpCreateRequire
|
|
4
1
|
// libs/uipack/src/resolver/cdn-registry.ts
|
|
5
2
|
var DEFAULT_CDN_REGISTRY = {
|
|
6
3
|
react: {
|
package/esm/shell/index.mjs
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : undefined;
|
|
2
|
-
const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
|
|
3
|
-
// __frontmcpCreateRequire
|
|
4
1
|
// libs/uipack/src/bridge-runtime/iife-generator.ts
|
|
5
2
|
var WIDGET_CALL_META_KEY = "frontmcp/widgetCall";
|
|
6
3
|
var MCP_APPS_DISPLAY_MODES = ["inline", "fullscreen", "pip"];
|
package/esm/types/index.mjs
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : undefined;
|
|
2
|
-
const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
|
|
3
|
-
// __frontmcpCreateRequire
|
|
4
1
|
// libs/uipack/src/types/ui-runtime.ts
|
|
5
2
|
function isUIType(value) {
|
|
6
3
|
return typeof value === "string" && ["html", "react", "mdx", "markdown", "auto"].includes(value);
|
package/esm/typings/index.mjs
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : undefined;
|
|
2
|
-
const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
|
|
3
|
-
// __frontmcpCreateRequire
|
|
4
1
|
// libs/uipack/src/typings/types.ts
|
|
5
2
|
var DEFAULT_ALLOWED_PACKAGES = ["react", "react-dom", "react/jsx-runtime", "zod", "@frontmcp/*"];
|
|
6
3
|
var DEFAULT_TYPE_FETCHER_OPTIONS = {
|
package/esm/utils/index.mjs
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
var __frontmcpModule = typeof process !== "undefined" && typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("module") : undefined;
|
|
2
|
-
const require = __frontmcpModule ? __frontmcpModule.createRequire(import.meta.url || 'file:///') : undefined;
|
|
3
|
-
// __frontmcpCreateRequire
|
|
4
1
|
// libs/uipack/src/utils/index.ts
|
|
5
2
|
function safeStringify(value, space) {
|
|
6
3
|
const seen = /* @__PURE__ */ new WeakSet();
|
package/package.json
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/uipack",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "FrontMCP
|
|
3
|
+
"version": "1.10.0",
|
|
4
|
+
"description": "React-free core that builds FrontMCP widget pages: HTML shell with CSP and bridge, template rendering, CDN import resolution",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
|
-
"homepage": "https://frontmcp.dev/reference/ui",
|
|
6
|
+
"homepage": "https://frontmcp.dev/reference/ui/components#frontmcpuipack",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"keywords": [
|
|
9
|
+
"frontmcp",
|
|
9
10
|
"mcp",
|
|
11
|
+
"model-context-protocol",
|
|
12
|
+
"mcp-apps",
|
|
13
|
+
"widgets",
|
|
10
14
|
"ui",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"framework",
|
|
16
|
-
"typescript"
|
|
15
|
+
"html",
|
|
16
|
+
"csp",
|
|
17
|
+
"import-map",
|
|
18
|
+
"agentfront"
|
|
17
19
|
],
|
|
18
20
|
"repository": {
|
|
19
21
|
"type": "git",
|
|
20
|
-
"url": "git+https://github.com/agentfront/frontmcp.git"
|
|
22
|
+
"url": "git+https://github.com/agentfront/frontmcp.git",
|
|
23
|
+
"directory": "libs/uipack"
|
|
21
24
|
},
|
|
22
25
|
"bugs": {
|
|
23
26
|
"url": "https://github.com/agentfront/frontmcp/issues"
|
|
@@ -61,7 +64,7 @@
|
|
|
61
64
|
"typescript": "^5.9.3"
|
|
62
65
|
},
|
|
63
66
|
"peerDependencies": {
|
|
64
|
-
"@frontmcp/lazy-zod": "1.
|
|
67
|
+
"@frontmcp/lazy-zod": "1.10.0",
|
|
65
68
|
"esbuild": ">=0.27.0 <1"
|
|
66
69
|
},
|
|
67
70
|
"peerDependenciesMeta": {
|