update readme

This commit is contained in:
Fredrik Jensen 2025-12-05 21:08:05 +01:00
parent b2f633699f
commit 924e78d387

218
README.md
View File

@ -1,162 +1,74 @@
# MCP-UI Weather Dashboard Server
# MCP UI Kit
A clean example of an MCP server that provides an interactive weather dashboard UI using React and remoteDom.
Build interactive React UIs for MCP tools.
## Architecture
## Installation
```
┌─────────────────────────┐
│ React Component (TSX) │
│ server/components/ │
└───────────┬─────────────┘
▼ esbuild bundles
┌─────────────────────────┐
│ Bundle (JS) │
│ dist/ │
└───────────┬─────────────┘
▼ loaded by server
┌─────────────────────────┐
│ MCP Server │
│ Creates remoteDom │
│ resource │
└───────────┬─────────────┘
▼ MCP protocol
┌─────────────────────────┐
│ Client (nanobot, etc.) │
│ Renders in sandbox │
│ with React provided │
└─────────────────────────┘
```bash
npm install @mcp-ui-kit
```
## Setup
## Server Usage
Create UI components that bundle on-demand:
```typescript
import { createUI } from '@mcp-ui-kit/server';
const dashboardUI = createUI('my-dashboard', import.meta.resolve('./MyComponent.tsx'));
server.registerTool('dashboard', {
description: 'Interactive dashboard'
}, async () => ({
content: [
{ type: 'text', text: 'Dashboard loaded' },
await dashboardUI.component({ props: { title: 'Hello' } })
]
}));
```
## Client Usage
Helper functions for your React components:
```typescript
import { sendPrompt, callTool, useProps } from '@mcp-ui-kit/react';
function MyComponent() {
const { title } = useProps({ title: 'Default' });
return (
<div>
<h1>{title}</h1>
<button onClick={() => sendPrompt('Analyze this data')}>
Ask AI
</button>
<button onClick={() => callTool('get_data', { id: 123 })}>
Fetch Data
</button>
</div>
);
}
```
## API
### Server (`@mcp-ui-kit/server`)
**`createUI(name, entryUrl)`** - Creates a UI component
- `name`: Component identifier
- `entryUrl`: Path from `import.meta.resolve()`
- Returns: `{ component(opts?) }` where opts: `{ props?, frameSize? }`
### UI (`@mcp-ui/library/ui`)
- **`useProps(defaults)`** - Get props passed from the server
- **`sendPrompt(message)`** - Send a message to the AI chat
- **`callTool(name, params)`** - Invoke an MCP tool
## Development
### Install Dependencies
```bash
npm install
npm run dev:all # Start demo server + inspector
```
### Build the UI Bundle
```bash
npm run build:ui
```
This bundles the React component using esbuild:
- Input: `server/components/index.tsx`
- Output: `dist/weather-dashboard.bundle.js`
### Start the Server
```bash
npm start
```
This will:
1. Build the UI bundle
2. Start the MCP server on `http://localhost:3000/mcp`
### Development with Auto-reload
```bash
npm run watch
```
Rebuilds UI and restarts server on file changes.
## How It Works
### 1. React Component (`server/components/WeatherDashboard.tsx`)
- Written in modern React with hooks, JSX, TypeScript
- Includes interactive city selection, weather data, forecast
- Uses `postMessage` to send data back to chat via MCP-UI protocol
### 2. Build Step (`build-ui.mjs`)
- Uses esbuild to bundle the React component
- Transpiles JSX → JavaScript
- Bundles imports (except React/ReactDOM which host provides)
- Output: Single IIFE bundle
### 3. Server (`server/ui.ts`)
- Reads the bundled JavaScript
- Creates a `remoteDom` UI resource with MIME type:
`application/vnd.mcp-ui.remote-dom+javascript; framework=react`
- Server sends this to clients via MCP protocol
### 4. Client Rendering
- Client (nanobot, etc.) receives the bundle as text
- Provides React/ReactDOM in a sandboxed environment
- Executes the bundle, which renders the component
- Handles `postMessage` events from the UI
## Available Scripts
- `npm run build:ui` - Build the React UI bundle
- `npm start` - Build UI + start server
- `npm run watch` - Development mode with auto-reload
- `npm run nanobot` - Start nanobot client
## Key Files
- `server/components/WeatherDashboard.tsx` - Main React component
- `server/components/index.tsx` - Entry point for bundle
- `build-ui.mjs` - esbuild configuration
- `server/ui.ts` - Creates MCP-UI resource
- `server/index.ts` - MCP server setup
- `dist/weather-dashboard.bundle.js` - Generated bundle
## remoteDom vs rawHtml
### remoteDom (current)
- ✅ Full React with hooks, state management
- ✅ Better component architecture
- ✅ Type safety with TypeScript
- ⚠️ Requires client support for remoteDom
- ⚠️ Requires build step
### rawHtml (alternative)
- ✅ Works everywhere
- ✅ No build step needed
- ⚠️ Vanilla JS only
- ⚠️ Manual DOM manipulation
## Testing
### With Nanobot
```bash
npm run nanobot
```
Then in the nanobot chat:
```
Can you show me the weather dashboard?
```
Or directly call the tool:
```
weather_dashboard
```
### Features
The UI allows:
- Switching between cities (Oslo, San Francisco, New York)
- Viewing current weather and 5-day forecast
- Sending weather data back to chat with "Send to Chat" button
## Project Structure
```
mcp-ui/
├── server/
│ ├── components/
│ │ ├── WeatherDashboard.tsx # React component
│ │ └── index.tsx # Entry point
│ ├── index.ts # MCP server
│ └── ui.ts # UI resource definition
├── dist/
│ └── weather-dashboard.bundle.js # Generated bundle
├── build-ui.mjs # esbuild configuration
├── nanobot.yaml # Nanobot configuration
├── package.json
└── README.md
```