This repository is a proof-of-concept demonstrating how the @lg-mcp-ui/core package can augment MCP Server tool responses with UI resources according to the mcp-ui specification.
This POC serves as a working example that engineers can clone and run to understand:
- How
augmentWithUI()works to add UI resources to MCP tool responses - How embeddable UIs are hosted and rendered in iframes
- How MCP clients extract and forward render data to embeddable UIs
- The complete end-to-end flow from tool execution to UI rendering
Note: This is demonstration code. The production implementation will integrate with the MongoDB MCP Server.
This monorepo contains:
mcp-ui-core(@mcp-poc/core) - The core augmentation library containingaugmentWithUI()mcp-server(@mcp-poc/mcp-server) - Mock MCP server demonstrating tool integrationmcp-ui-app(@mcp-poc/mcp-ui-app) - Next.js app hosting embeddable UI componentsmcp-client(@mcp-poc/mcp-client) - Demo React client that renders MCP-UI resourcesmongodb-mcp-server- Reference implementation (clone of MongoDB MCP Server)
- Node.js (v18+)
- pnpm (v8+)
# Install dependencies
pnpm installRun all services concurrently:
pnpm devThis starts:
- MCP Server on
http://localhost:3000 - MCP Client on
http://localhost:3001(or next available port) - MCP UI App on
http://localhost:3003
You can also run services individually:
# MCP Server only
pnpm mcp-server:dev
# MCP Client only
pnpm mcp-client:dev
# MCP UI App only
pnpm mcp-ui-app:dev- Open the MCP Client: Navigate to
http://localhost:3001in your browser - Execute a Tool: Click on any available tool (e.g., "Hello World", "Cluster Metrics", "List Databases")
- View the UI: The tool response will include both:
- Text content (standard MCP response)
- Embedded UI component (rendered in an iframe)
hello_world- Simple greeting message with timestampcluster_metrics- Mock cluster metrics displayed as a time-series chartlist_databases- Database list displayed in a Card component
mcp-ui/
├── packages/
│ ├── mcp-ui-core/ # Core augmentation library
│ │ └── src/
│ │ ├── augmentWithUI.ts # Main augmentation function
│ │ ├── schemas.ts # Zod schemas for validation
│ │ └── index.ts # Public exports
│ │
│ ├── mcp-server/ # Mock MCP server (demo only)
│ │ └── src/
│ │ └── index.ts # Tool implementations
│ │
│ ├── mcp-ui-app/ # Next.js app hosting embeddable UIs
│ │ └── src/
│ │ ├── app/ # Route pages for each UI
│ │ └── hooks/
│ │ └── useRenderData.ts # Data extraction hook
│ │
│ ├── mcp-client/ # Demo React client
│ │ └── src/
│ │ └── components/
│ │ └── UIRenderer/ # MCP-UI resource renderer
│ │
│ └── mongodb-mcp-server/ # Reference implementation
│
└── README.md # This file
The MCP server executes a tool and creates a CallToolResult:
const toolResult: CallToolResult = {
content: [{ type: "text", text: "Found 3 databases" }],
};The server calls augmentWithUI() to add a UI resource:
return augmentWithUI(toolResult, {
toolName: "list-databases",
renderData: {
databases: [...],
totalCount: 3,
},
});augmentWithUI() creates a UIResource with:
- External URL pointing to the embeddable UI route
- Render data embedded in
uiMetadata['initial-render-data']
The MCP client:
- Extracts render data from
uiMetadata - Renders an iframe pointing to the UI route
- Sends render data to the iframe via
postMessage
The embeddable UI component:
- Receives render data via
useRenderData()hook - Validates data against Zod schemas
- Renders using LeafyGreen components
packages/mcp-ui-core/README.md- Core package documentationpackages/mcp-server/README.md- Mock server documentationpackages/mcp-ui-app/README.md- UI hosting app documentationpackages/mcp-client/README.md- Demo client documentation
Two-layer validation ensures data integrity:
- Server-side:
augmentWithUI()validates render data before creating UI resources - Component-level: UI components validate props before rendering
UI augmentation is non-blocking and non-fatal:
- If augmentation fails, the original
CallToolResultis returned unchanged - Tools continue to work even if UI augmentation is unavailable
Embeddable UIs communicate with the parent client via postMessage:
- Read flow: Client sends render data to iframe
- Write flow: Iframe sends action requests to client
- This is proof-of-concept code for demonstration purposes
- The mock server and client are not production code
- Production implementation will integrate with the real MongoDB MCP Server
MIT