update readme
This commit is contained in:
parent
b2f633699f
commit
924e78d387
218
README.md
218
README.md
@ -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
|
||||||
|
|
||||||
```
|
```bash
|
||||||
┌─────────────────────────┐
|
npm install @mcp-ui-kit
|
||||||
│ 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 │
|
|
||||||
└─────────────────────────┘
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 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
|
```bash
|
||||||
npm install
|
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
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user