A comprehensive Kanban board application demonstrating all features of the @mcp-apps-kit SDK.
| Feature | Description | Example in Code |
|---|---|---|
| Tool Definitions | Type-safe tool definitions with Zod schemas | All tools use z.object() for input/output |
| Tool Annotations | Behavioral hints for AI models | readOnlyHint, destructiveHint, openWorldHint, idempotentHint |
| ToolContext | Client-provided metadata in handlers | context.locale, context.userLocation, context.subject, context.widgetSessionId |
| fileParams | Enable file upload parameters | createTask tool with fileParams: ["attachmentId"] |
| widgetDescription | Human-readable summary for AI | UI resource with widgetDescription |
| ClientToolsFromCore | End-to-end typed UI client | UI imports KanbanClientTools (from ClientToolsFromCore<typeof app.tools>) |
| _text | Human-friendly model-facing output | Tools that return message also set _text: message |
| _closeWidget | Dismiss widget after action | clearCompleted tool returns _closeWidget: true |
| visibility | Control who can invoke tools | "model", "app", "both" |
| widgetAccessible | Allow widget to call tool | All widget-only tools |
| invokingMessage/invokedMessage | Loading state messages | createTask, deleteTask, etc. |
| title | Human-readable tool title | All tools have title property |
| Hook | Description | Usage in App |
|---|---|---|
| useAppsClient | Access typed client for tool calls | Main tool call interface |
| useToolInput | Access initial tool input | Debug panel display |
| useHostContext | Access theme, viewport, locale | Theme and context display |
| useWidgetState | Persist state across reloads | Collapsed columns, debug panel |
| useHostStyleVariables | Apply host CSS variables | Applied in App component |
| useDocumentTheme | Apply theme class to document | Light/dark mode |
| useDisplayMode | Access/change display mode | Debug panel display |
| useSafeAreaInsets | Mobile safe area padding | Container padding |
| useOnToolCancelled | Handle tool cancellation | Cancellation message |
| useOnTeardown | Cleanup on widget teardown | Console logging |
| useFileUpload | Upload files (ChatGPT) | Task attachment |
| useIntrinsicHeight | Report widget height | Auto-height container |
| useView | Access view identifier | Debug panel display |
| useModal | Host-owned modal dialogs | Delete confirmation |
# Install dependencies
npm install
# Start both server and UI dev mode
npm run dev
# Or start individually
npm run dev:server # Server only
npm run dev:ui # UI dev server only
# Build for production
npm run buildThe server starts at http://localhost:3001.
| Tool | Description | Features Used |
|---|---|---|
listTasks |
List all tasks (optional filter) | readOnlyHint, idempotentHint, visibility: "app" |
createTask |
Create task with attachment | fileParams, invokingMessage |
moveTask |
Move task between columns | idempotentHint |
updateTask |
Update task details | Widget-accessible |
deleteTask |
Delete a task | destructiveHint |
clearCompleted |
Clear done tasks | _closeWidget |
exportBoard |
Export board data | openWorldHint |
getBoardSummary |
Get board overview | ui: "kanban-board" |
{
"tool": "createTask",
"arguments": {
"title": "Review document",
"description": "Review the attached document",
"attachmentId": "file-abc123"
}
}{
"tool": "clearCompleted",
"arguments": {
"closeWidget": true
}
}{
"tool": "exportBoard",
"arguments": {
"format": "csv",
"includeMetadata": false
}
}Click the 🔧 button to open the SDK Feature Status panel, showing:
- Host context (theme, platform, locale, viewport)
- Display mode and available modes
- Safe area insets
- Platform feature support (file upload, modal, intrinsic height)
- Current view identifier
- Tool input
The following preferences are persisted using useWidgetState:
- Collapsed columns (click column header to toggle)
- Debug panel visibility
On supported platforms (ChatGPT), delete confirmation uses native host modals via useModal. Falls back to confirm() on other platforms.
On supported platforms (ChatGPT), the Add Task modal includes a file upload option using useFileUpload.
kanban-mcp-example/
├── api/
│ └── index.ts # Vercel serverless function
├── public/
│ └── index.html # Built UI output
├── src/
│ ├── index.ts # Server with all SDK features
│ └── ui/
│ ├── App.tsx # React app with all hooks
│ ├── main.tsx # Entry point with AppsProvider
│ ├── index.html # HTML template
│ └── styles.css # Comprehensive styling
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── vercel.json
└── vite.config.ts
{
"mcpServers": {
"kanban": {
"command": "npx",
"args": ["tsx", "/path/to/kanban-mcp-example/src/index.ts"]
}
}
}// In src/index.ts
config: {
protocol: "openai", // Change from "mcp" to "openai"
}# Type checking
npm run typecheck
# Build UI
npm run build:ui
# Build server
npm run build:server
# Build everything
npm run buildThis project is configured for deployment on Vercel:
# Deploy preview
vercel
# Deploy to production
vercel --prod