
Research
/Security News
CanisterWorm: npm Publisher Compromise Deploys Backdoor Across 29+ Packages
The worm-enabled campaign hit @emilgroup and @teale.io, then used an ICP canister to deliver follow-on payloads.
@mcp-apps-kit/ui-react-builder
Advanced tools
Build tool for React-based MCP application UIs.
@mcp-apps-kit/ui-react-builder allows you to define UI resources using React components instead of pre-built HTML files. The framework handles bundling React, ReactDOM, and @mcp-apps-kit/ui-react into self-contained HTML that works with both MCP Apps (Claude Desktop) and ChatGPT.
Building interactive UI widgets for MCP applications traditionally requires manually bundling React components into self-contained HTML files. This package automates that process, letting you define UIs with React components directly in your tool definitions.
defineReactUI() helper for type-safe React component definitions@typescript-eslint/typescript-estree for reliable detectiondefineTool() from @mcp-apps-kit/core>= 18@mcp-apps-kit/core ^0.2.0@mcp-apps-kit/ui-react ^0.2.0react and react-dom ^18 || ^19vite ^5 || ^6 || ^7 (optional, for Vite plugin)npm install @mcp-apps-kit/ui-react-builder
Define your React component:
// src/ui/GreetingWidget.tsx
import { useToolResult, useHostContext } from "@mcp-apps-kit/ui-react";
export function GreetingWidget() {
const result = useToolResult();
const { theme } = useHostContext();
return (
<div data-theme={theme}>
<h1>{result?.greet?.message}</h1>
</div>
);
}
Use defineReactUI in your tool definition:
// src/index.ts
import { createApp, defineTool } from "@mcp-apps-kit/core";
import { defineReactUI } from "@mcp-apps-kit/ui-react-builder";
import { GreetingWidget } from "./ui/GreetingWidget";
import { z } from "zod";
const app = createApp({
name: "my-app",
version: "1.0.0",
tools: {
greet: defineTool({
description: "Greet someone",
input: z.object({ name: z.string() }),
output: z.object({ message: z.string() }),
ui: defineReactUI({
component: GreetingWidget,
name: "Greeting Widget",
prefersBorder: true,
}),
handler: async ({ name }) => ({
message: `Hello, ${name}!`,
}),
}),
},
});
The Vite plugin automatically discovers defineReactUI calls and builds them into self-contained HTML files.
// vite.config.ts
import { defineConfig } from "vite";
import { mcpReactUI } from "@mcp-apps-kit/ui-react-builder/vite";
export default defineConfig({
plugins: [
mcpReactUI({
// Server entry point to scan for defineReactUI calls
serverEntry: "./src/index.ts",
// Output directory for built HTML files
outDir: "./src/ui/dist",
// Optional: Global CSS to include in all UIs
globalCss: "./src/ui/styles.css",
// Optional: Standalone mode takes over the Vite build and outputs only UI HTML.
// Use this if this Vite config exists solely to build MCP UI widgets.
// standalone: true,
}),
],
});
serverEntry file for defineReactUI calls using AST parsing@mcp-apps-kit/ui-reactoutDirThe plugin uses @typescript-eslint/typescript-estree for reliable AST-based detection of imports and defineReactUI calls. This is more robust than regex-based parsing and correctly handles:
defineReactUI calls (e.g., inside defineTool)The plugin discovers defineReactUI calls using static analysis. For reliable detection:
import { MyWidget } from "./ui/MyWidget"; // ✓ Works
import { MyWidget } from "./ui"; // ✗ Barrel imports not supported
name property:
name: "My Widget"; // ✓ Works
name: `My ${type}`; // ✗ Template literals not supported
component: MyWidget; // ✓ Works
component: widgets.MyWidget; // ✗ Property access not supported
If you need patterns not supported by auto-discovery, use defineUI({ html: "..." }) with manual Vite bundling.
{
"scripts": {
"dev": "concurrently \"pnpm dev:server\" \"pnpm dev:ui\"",
"dev:server": "tsx watch src/index.ts",
"dev:ui": "vite build --watch",
"build": "pnpm build:ui && tsc",
"build:ui": "vite build"
}
}
| Export | Description |
|---|---|
defineReactUI | Define a UI using a React component |
isReactUIDef | Type guard to check if a value is a ReactUIDef |
| Type | Description |
|---|---|
ReactUIInput | Input type for defineReactUI() |
ReactUIDef | Output type (extends UIDef from core) |
BuildOptions | Options for the build process |
BuildResult | Result of building React UIs |
PluginLogger | Logger interface for Vite plugin |
| Export | Description |
|---|---|
buildReactUIs | Build multiple React UIs to HTML |
buildReactUI | Build a single React UI to HTML |
Note: The programmatic build functions (
buildReactUIs,buildReactUI) serialize components using.toString(), which has limitations:
- No external imports (components cannot import other modules)
- No closures (components that capture external variables won't work)
- Simple components only (best for self-contained components)
For production use, prefer the Vite plugin which uses file paths for proper import resolution.
| Export | Description |
|---|---|
transformToCoreDefs | Convert ReactUIDefs to standard UIDefs |
transformSingleToCoreDef | Convert a single ReactUIDef to UIDef |
extractReactUIs | Separate React UIs from standard UIs |
buildAndTransform | Build and transform in one step |
| Export | Description |
|---|---|
generateHTML | Generate HTML document from bundled JS |
generateEntryPoint | Generate React entry point code |
import { mcpReactUI } from "@mcp-apps-kit/ui-react-builder/vite";
| Option | Type | Default | Description |
|---|---|---|---|
serverEntry | string | (required) | Server entry point to scan |
outDir | string | "./dist/ui" | Output directory for HTML files |
minify | boolean | true in prod | Minify output JavaScript |
globalCss | string | - | Path to global CSS file |
logger | PluginLogger | false | console | Custom logger or false to disable logging |
standalone | boolean | false | Take over Vite build (emit only UI HTML) |
// Disable all logging
mcpReactUI({
serverEntry: "./src/index.ts",
logger: false,
});
// Custom logger
mcpReactUI({
serverEntry: "./src/index.ts",
logger: {
info: (msg) => myLogger.info(msg),
warn: (msg) => myLogger.warn(msg),
error: (msg) => myLogger.error(msg),
},
});
../../examples/minimal - Simple hello world with React UISee ../../CONTRIBUTING.md for development setup and guidelines. Issues and pull requests are welcome.
MIT
FAQs
Build tool for React-based MCP application UIs
The npm package @mcp-apps-kit/ui-react-builder receives a total of 3 weekly downloads. As such, @mcp-apps-kit/ui-react-builder popularity was classified as not popular.
We found that @mcp-apps-kit/ui-react-builder demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
The worm-enabled campaign hit @emilgroup and @teale.io, then used an ICP canister to deliver follow-on payloads.

Research
/Security News
Attackers compromised Trivy GitHub Actions by force-updating tags to deliver malware, exposing CI/CD secrets across affected pipelines.

Security News
ENISA’s new package manager advisory outlines the dependency security practices companies will need to demonstrate as the EU’s Cyber Resilience Act begins enforcing software supply chain requirements.