@ frontmcp/ 邮包
@frontmcp/uipack 是 FrontMCP 创建部件页面的无反应核心,在服务器上。 它使一个工具的模板变成一个完整的HTML页面,其中包含内容安全政策,调用的数据和与主机交谈的桥接脚本;解决部件导入到CDN URL;并捆绑回放部件文件. @frontmcp/sdk 取决于它,所以FrontMCP服务器已经拥有了它. 将模板分割为函数 html,测试没有服务器的模板 renderToolTemplate(),或为您自己的一个主机构建部件页面.
安装
npm install @frontmcp/uipack
- 无反应依赖. 运行时间依赖是
zod财务报告和审定财务报表entities(HTML 字符引用解码器)sanitizeHtml(); npm 7 并随后安装对等点@frontmcp/lazy-zod,在同一版本中. esbuild是一个可选的对等点, 只需要捆绑.tsx财务报告和审定财务报表.jsx部件文件 。 安装它作为依赖性,而不是 dev 依赖性,因为它在部件被渲染时被装入.highlight.js是一个可选的同伴,仅需要用于markdown.highlightTheme(单位:千美元)ui.runtimeOptions.markdown.highlightTheme) (中文(简体) ). 当一个模板使用时,它会从您的项目中被载入.@mdx-js/mdx, (中文(简体) ),react财务报告和审定财务报表react-dom是可选的同位素,仅用于制作MDX模板(mdxComponents在服务器上,和remark-gfm给一个markdown.gfm。 。 。 .react财务报告和审定财务报表react-dom也可以在服务器上渲染一个组件(uiType: 'react'和一个水合(水合)部件hydrate) (中文(简体) ). 它们是从你的工程中加载的, 所以模板的组件和渲染器共享一个反应.- 它运行在节点.js24或后.
使用量
以工具调用的方式制作一个模板, 没有服务器 :
import { html, renderToolTemplate, type TemplateContext } from '@frontmcp/uipack';
type Weather = { city: string; tempC: number };
const badge = (text: string) => html`<span class="badge">${text}</span>`;
const result = renderToolTemplate({
toolName: 'get_weather',
input: { city: 'Oslo' },
output: { city: 'Oslo', tempC: 21 },
template: (ctx: TemplateContext<{ city: string }, Weather>) =>
html`<h2>${ctx.output.city} ${badge(`${ctx.output.tempC}°C`)}</h2>`,
});
result.html 是一个完整的 HTML 文档,其正文是 <h2>Oslo <span class="badge">21°C</span></h2>, (中文(简体) ), result.uiType 实值 "html",以及 result.meta["ui/mimeType"] 实值 "text/html;profile=mcp-app"内插值 html 被逃脱,所以一个城市 <script> 作为 <script>; 使用 html 或者说 trustedHtml() 没逃过两次. html 与工具模板的构建器相同 ctx.helpers.html,因此部件的片段可以活在自己的文件中,并被自己测试(将模板分割为函数) (中文(简体) ).
围绕自己的标记建立一页
import { buildShell } from '@frontmcp/uipack/shell';
const { html, hash, size } = buildShell('<div id="root"></div>', {
toolName: 'get_weather',
input: { city: 'London' },
output: { temp: 18 },
includeBridge: true,
csp: { connectDomains: ['https://api.weather.com'] },
});
hash 是一个短而非晶体散列的页面,用于缓存键,以及 size 其长度为字节。 页面看起来是这样,桥脚本缩短:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
http-equiv="Content-Security-Policy"
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; ..."
/>
<script>
window.__mcpAppsEnabled = true;
window.__mcpToolName = 'get_weather';
window.__mcpToolInput = { city: 'London' };
window.__mcpToolOutput = { temp: 18 };
window.__mcpStructuredContent = null;
</script>
<script>
/* the bridge: picks an adapter for the host and sets window.FrontMcpBridge */
</script>
</head>
<body>
<div id="root"></div>
</body>
</html>
解决对 CDN URL 的导入
import { createEsmShResolver, rewriteImports } from '@frontmcp/uipack/resolver';
const resolver = createEsmShResolver({ providerOrder: ['cloudflare', 'jsdelivr'] });
resolver.resolve('chart.js');
// { value: 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.1/chart.umd.min.js', type: 'url' }
rewriteImports("import { format } from 'date-fns';", { resolver }).code;
// "import { format } from 'https://esm.sh/date-fns';"
CDN 登记册中的软件包(react, (中文(简体) ), react-dom, (中文(简体) ), chart.js, (中文(简体) ), d3, (中文(简体) ), lodash解决其注册的 URL, 并尝试提供商 providerOrder;任何其他软件包决定 https://esm.sh/<specifier>。 。 。 .
从 npm 生成组件
import { renderComponent } from '@frontmcp/uipack/component';
const { html } = renderComponent(
{ source: { npm: 'my-weather-widget', exportName: 'WeatherCard' } },
{ toolName: 'get_weather', output: { temp: 18 } },
);
renderComponent() 是同步的。 页面从 https://esm.sh/my-weather-widget,通过导入地图从 esm.sh 装入 React,使组件进入 #root 以工具的输出为道具. 来源可以是:
| 来源 | 形状 | 发生什么事 |
|---|---|---|
| 无 | { npm: 'my-chart', exportName?, version? } | 从其CDN注册条目或esm.sh装入. |
| 文件 | { file: '/abs/path/widget.tsx', exportName?, inline? } | 一个本地文件. .tsx 财务报告和审定财务报表 .jsx 文件与 esbuilding 捆绑在一起; 从工作目录中解析一个相对路径. |
| 导入 | { import: 'https://cdn.example.com/widget.js', exportName? } | 模块 URL,按原样使用. |
| 函数 | (input, output) => '<div>…</div>' | 返回 HTML. |
生成桥脚本
import { BRIDGE_SCRIPT_TAGS, generateBridgeIIFE } from '@frontmcp/uipack/bridge-runtime';
const everyHost = BRIDGE_SCRIPT_TAGS.universal;
const openAiOnly = `<script>${generateBridgeIIFE({ adapters: ['openai', 'generic'], minify: true })}</script>`;
脚本检测主机和设定 window.FrontMcpBridge数字 :
| 成员 | 说明 |
|---|---|
adapterId, (中文(简体) ), initialized, (中文(简体) ), capabilities | 适配器为宿主所选,是否已就绪,能作何事. |
getToolInput(), (中文(简体) ), getToolOutput(), (中文(简体) ), getStructuredContent() | 呼叫的数据,从页面,然后从每个结果,主机发送. |
callTool(name, args) | 通过主机调用一个工具并返回主机的结果 . |
onToolResult(callback), (中文(简体) ), onContextChange(callback) | 订阅结果和主机更改。 每个返回一个未订阅的函数 . |
getTheme(), (中文(简体) ), getDisplayMode(), (中文(简体) ), getHostContext(), (中文(简体) ), hasCapability(name) | 主持人对自己说的话. |
sendMessage(text), (中文(简体) ), openLink(url) | 在对话中添加信息,打开链接,通过主机. |
requestDisplayMode(mode), (中文(简体) ), setSize({ width?, height? }), (中文(简体) ), requestClose() | 问 inline, (中文(简体) ), fullscreen 或者说 pip,报告部件大小,请删除部件. |
updateModelContext(data, merge?) | 告诉主机该知道什么,主机支持在哪里. |
getWidgetState(), (中文(简体) ), setWidgetState(state) | 保持状态 localStorage。 。 。 . |
获取类型脚本定义
import { createTypeFetcher } from '@frontmcp/uipack/typings';
const fetcher = createTypeFetcher({ allowedPackages: ['@myorg/*'], maxDepth: 3 });
const { results, errors } = await fetcher.fetchBatch({ imports: ["import { z } from 'zod'"] });
// results[0].files: the .d.ts files, at virtual node_modules/ paths
它会得到 .d.ts 从 esm.sh 导入的每个文件,在自导入之后一直到 maxDepth (默认2). 只获取允许的软件包 : react, (中文(简体) ), react-dom, (中文(简体) ), react/jsx-runtime, (中文(简体) ), zod 财务报告和审定财务报表 @frontmcp/*附加时 allowedPackages,或带有 allowedPackages: false。 。 。 .
入境点
@frontmcp/uipack 输出下面的一切。 每个单元也是自己的切入点:
| 导入 | 里面有什么东西 |
|---|---|
@frontmcp/uipack/adapters | renderToolTemplate(), (中文(简体) ), MCP_APPS_MIME_TYPE,而SDK用来构建工具部件响应的帮助者. |
@frontmcp/uipack/shell | buildShell(), (中文(简体) ), html, (中文(简体) ), trustedHtml(),模板助手,CSP,自定义贝壳. |
@frontmcp/uipack/resolver | 导入分辨率, CDN 注册, 导入地图 . |
@frontmcp/uipack/component | renderComponent() 和组件来源. |
@frontmcp/uipack/bridge-runtime | 桥脚本生成器. |
@frontmcp/uipack/typings | 这个 .d.ts 取取器及其缓存. |
@frontmcp/uipack/types | 部件配置的类型, 如 UITemplateConfig 财务报告和审定财务报表 TemplateContext。 。 。 . |
@frontmcp/uipack/utils | 出逃相助者. |
适配器
| 导出 | 说明 |
|---|---|
renderToolTemplate(options) | 以调用方式制作模板 : { html, uiType, hash, size, meta }选项: toolName, (中文(简体) ), input, (中文(简体) ), output, (中文(简体) ), template, (中文(简体) ), platformType?, (中文(简体) ), resourceMode?, (中文(简体) ), sizing?, (中文(简体) ), csp?, (中文(简体) ), escapeStringResults?, (中文(简体) ), contentSecurity? (对模板的标记进行卫生处理) sanitizeHtml(), (中文(简体) ), markdown? (单位:千美元){ gfm?, highlightTheme? } 用于Markdown或MDX模板, mdxComponents? (字符串模板是带有这些组件的服务器上渲染的MDX), uiType? (强迫渲染器: 'html', (中文(简体) ), 'markdown', (中文(简体) ), 'mdx', (中文(简体) ), 'react', (中文(简体) ), hydrate? (放弃a) { file } 服务器上的部件和水合物。 投出模板无法取用的选项; 在tsx下, await prepareRenderOptions() 在制作MDX之前. |
describeRenderOptionProblems(template, options) | 为它无法取取的模板设定的渲染选项,每句一; [] 当没有. |
MCP_APPS_MIME_TYPE | "text/html;profile=mcp-app"。 。 。 . |
贝壳
| 导出 | 说明 |
|---|---|
buildShell(content, config) | 一页左右 content数字 : { html, hash, size }。 。 。 . config数字 : toolName (必须), input, (中文(简体) ), output, (中文(简体) ), structuredContent, (中文(简体) ), csp, (中文(简体) ), includeBridge (默认) true, (中文(简体) ), withShell (默认) true· ; false 返回只包含数据脚本和内容, title, (中文(简体) ), sizing, (中文(简体) ), displayMode, (中文(简体) ), customShell。 。 。 . |
html`…`, (中文(简体) ), trustedHtml(markup), (中文(简体) ), isTrustedHtml(value) | 构建、标记和检测信任的标记。 内插值 html 被逃脱. |
sanitizeHtml(markup, policy?) | 什麽 ui.contentSecurity 已经 它读取了标记,就像浏览器的标记器所做的一样,写出每个标记,每个属性值一次解码,检查后写回逃出. 它可以删除 <script>, (中文(简体) ), on* 处理者, srcdoc, (中文(简体) ), <object>编号 :<embed>编号 :<applet>, (中文(简体) ), <base>, (中文(简体) ), <meta>SVG动画, data-tool-call编号 :data-tool-args,注释,其方案不是 URL 属性 http:, (中文(简体) ), https: 或者说 mailto:, (中文(简体) ), @import 内 <style>,交叉来源 <link rel=stylesheet>,以及 position: fixed编号 :sticky 内 style 属性. policy数字 : allowInlineScripts, (中文(简体) ), allowUnsafeLinks, (中文(简体) ), allowToolCallAttributes, (中文(简体) ), bypassSanitization, (中文(简体) ), maxMarkupLength (默认) DEFAULT_MAX_MARKUP_LENGTH,2个小米字符;更长的打分投出. 线性时间. |
describeContentSecurityProblems(policy) | 为什么一个值不能是一个 ui.contentSecurity 策略(不是平面对象,旗帜不是布尔,未知键),每个句子. |
createTemplateHelpers() | 一组新的模板助手 : escapeHtml, (中文(简体) ), formatDate, (中文(简体) ), formatCurrency, (中文(简体) ), uniqueId, (中文(简体) ), jsonEmbed, (中文(简体) ), html, (中文(简体) ), trustedHtml。 。 。 . |
buildCSPDirectives(csp?), (中文(简体) ), buildCSPMetaTag(csp?) | 页面政策:默认的 CDN 来源加 connectDomains 财务报告和审定财务报表 resourceDomains。 。 。 . |
buildDataInjectionScript({ toolName, input?, output?, structuredContent?, sizing?, displayMode? }) | 这个 <script> 设置 window.__mcpToolName, (中文(简体) ), __mcpToolInput, (中文(简体) ), __mcpToolOutput 财务报告和审定财务报表 __mcpStructuredContent。 。 。 . |
resolveShellTemplate(source, options?) | Async (英语). 装入自定义 shell 从 { inline }, (中文(简体) ), { url, timeout? } 或者说 { npm, exportName?, version? },并验证它. |
validateShellTemplate(template), (中文(简体) ), applyShellTemplate(template, values) | 检查并填入自定义 shell 的占位符 : {{CONTENT}} (必须), {{CSP}}, (中文(简体) ), {{DATA}}, (中文(简体) ), {{BRIDGE}}, (中文(简体) ), {{TITLE}}。 。 。 . |
DEFAULT_CDN_DOMAINS | 每个页面的出处允许:jsDelivr,cdnjs,Google字体和esm.sh. |
解析器
| 导出 | 说明 |
|---|---|
createEsmShResolver({ registry?, providerOrder?, fallbackCdnBase? }) | 默认解析器 . |
createResolverWithOverrides(overrides, options?) | 默认解析器, 某些软件包有固定的 URL . |
DEFAULT_CDN_REGISTRY, (中文(简体) ), mergeRegistries(custom) | 登记处react, (中文(简体) ), react-dom, (中文(简体) ), chart.js, (中文(简体) ), d3, (中文(简体) ), lodash),它与您的条目合并. |
lookupPackage(name, registry?), (中文(简体) ), getPackageCDNUrl(name, providerOrder?, registry?) | 查询注册. |
parseImports(source), (中文(简体) ), extractExternalPackages(source) | 源代码中的导入,以及它们命名的包. |
rewriteImports(source, { resolver?, skipPackages?, overrides? }) | 用 CDN URL 替换光标: { code, rewrittenCount, rewrites, fallbackPackages }。 。 。 . |
createImportMap(dependencies), (中文(简体) ), mergeImportMaps(...maps), (中文(简体) ), generateImportMapScriptTag(map) | 构建,合并并写入浏览器导入地图. |
构成部分
| 导出 | 说明 |
|---|---|
renderComponent(config, shellConfig) | 决定: config.source 并构建周围的页面: { html, hash, size }。 。 。 . |
resolveUISource(source, options?) | 决定源为 a ResolvedComponent。 。 。 . |
generateMountScript(resolved, propsMapping?) | 导入并挂载模块组件的模块脚本 . |
bundleFileSource(), (中文(简体) ), transpileReactSource() | 套装或倒装 a .tsx 或者说 .jsx 装有构件的部件 . |
isNpmSource, (中文(简体) ), isFileSource, (中文(简体) ), isImportSource, (中文(简体) ), isFunctionSource | 类型卫兵的源. |
桥梁运行时间
| 导出 | 说明 |
|---|---|
generateBridgeIIFE(options?) | 桥脚本. 选项 : adapters (从) openai, (中文(简体) ), ext-apps, (中文(简体) ), claude, (中文(简体) ), gemini, (中文(简体) ), generic, (中文(简体) ), debug, (中文(简体) ), trustedOrigins, (中文(简体) ), minify。 。 。 . |
generatePlatformBundle(platform, options?) | 脚本用于 chatgpt, (中文(简体) ), claude, (中文(简体) ), gemini 或者说 universal。 。 。 . |
UNIVERSAL_BRIDGE_SCRIPT | 每个适配器的脚本. |
BRIDGE_SCRIPT_TAGS | { universal, chatgpt, claude, gemini },每个包裹 <script>。 。 。 . |
键入
| 导出 | 说明 |
|---|---|
createTypeFetcher(options?, cache?) | A 类 TypeFetcher选项: allowedPackages, (中文(简体) ), maxDepth, (中文(简体) ), timeout (每个请求10 s), maxConcurrency (5), (中文), cdnBaseUrl, (中文(简体) ), fetch。 。 。 . |
TypeFetcher | fetchBatch({ imports, maxDepth?, timeout? })数字 : { results, errors, totalTimeMs, cacheHits }。 。 。 . |
MemoryTypeCache, (中文(简体) ), globalTypeCache | 最近使用最少但已过期的缓存;共享的缓存保存了最多500个条目长达1小时. |
parseDtsImports(content), (中文(简体) ), combineDtsContents(contents) | 分析a .d.ts 文件的导入; 将多个文件合并为一个文件. |
用户
| 导出 | 说明 |
|---|---|
escapeHtml(value) | 逃脱 &, (中文(简体) ), <, (中文(简体) ), >, (中文(简体) ), " 财务报告和审定财务报表 ',还有U+2028和U+2029. null 财务报告和审定财务报表 undefined 给 ''。 。 。 . |
escapeHtmlAttr(value) | 逃脱 & 财务报告和审定财务报表 ",用于属性值. |
escapeJsString(value) | 逃避 JavaScript 字符串的字符串 . |
escapeScriptClose(json) | 替换 </ 与 <\/,所以文本不能关闭 a <script>。 。 。 . |
safeJsonForScript(value) | JSON安全放进去 <script>数字 : <, (中文(简体) ), > 财务报告和审定财务报表 & 逃脱了,大英作为弦 {"error":"Value could not be serialized"} jSON不能持有的值,例如循环值. |
safeStringify(value, space?) | JSON.stringify 写着 [Circular] 用于循环参考. |
文档
- 部件数字 :
@frontmcp/uipack在服务器上,html财务报告和审定财务报表renderToolTemplate() - 这个
ui选项: 模板、服务模式、内容安全政策 - 主机和平台桥,
window.FrontMcpBridge,每个主机得到什么 - 选择部件如何服务: 内置和静态页面,以及部件可以装入的内容
相关软件包
@frontmcp/sdk: 服务器框架; 它使一个工具的ui这个包裹.@frontmcp/ui: 部件文件的反射组件、钩和渲染器.@frontmcp/testing: 测试助手, 并配对工具制成的部件 .
捐款
资料来源: libs/uipack欢迎提出问题和拉动请求;见 捐款额。 。 。 .
源代码下每个输入点有一个文件夹 src/数字 : adapters/, (中文(简体) ), shell/, (中文(简体) ), resolver/, (中文(简体) ), component/, (中文(简体) ), bridge-runtime/, (中文(简体) ), typings/, (中文(简体) ), types/ 财务报告和审定财务报表 utils/。 。 。 . utils 财务报告和审定财务报表 bridge-runtime - 没有别的依赖; resolver 用途 utils· ; shell 用途 utils, (中文(简体) ), resolver 财务报告和审定财务报表 bridge-runtime· ; component 以 shell· ; adapters 全部使用; typings 孤军奋战 types 只有进口类型。 测试出逃和内容安全政策有敌意的改变。 在单曲中:
nx build uipack
nx test uipack
nx lint uipack
许可证
阿帕奇2.0 (英语). 见 自由主义。 。 。 .