Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions apps/mcp/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
node_modules/
npm-debug.log
.git
.gitignore
README.md
.env.example
.DS_Store
dist/
.turbo/
12 changes: 12 additions & 0 deletions apps/mcp/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Server Configuration
MCP_PORT=3100
NODE_ENV=development

# CORS (comma-separated origins, default: * for development)
ALLOWED_ORIGINS=*

# Skills directory (default: ./skills relative to package root)
SKILLS_DIR=./skills

# Logging
LOG_LEVEL=info
12 changes: 12 additions & 0 deletions apps/mcp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
node_modules/
dist/
.env
.env.local
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.DS_Store
.turbo/
.venv/
pnpm-lock.yaml
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conflict with Dockerfile: The .gitignore excludes pnpm-lock.yaml, but the Dockerfile (line 11) copies it for --frozen-lockfile install. The Docker build will fail unless the lockfile exists at build time.

Either remove this line (and commit the lockfile) or update the Dockerfile to not rely on --frozen-lockfile.

53 changes: 53 additions & 0 deletions apps/mcp/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Multi-stage build for production
FROM node:20-alpine AS builder

WORKDIR /app

# Install build dependencies
RUN apk add --no-cache python3 make g++

# Copy package files
COPY package.json pnpm-lock.yaml ./

# Install pnpm
RUN npm install -g pnpm@9

# Install dependencies
RUN pnpm install --prod --frozen-lockfile

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: --prod flag breaks the build step

--prod skips devDependencies, but tsc (used on line 23 via pnpm build) is listed under devDependencies. This Docker build will fail at the RUN pnpm build step.

Should be:

RUN pnpm install --frozen-lockfile

Or split into two stages — full install for build, then prune to prod for the runtime image.

# Copy source
COPY tsconfig.json ./
COPY src ./src
COPY skills ./skills

# Build
RUN pnpm build

# Production image
FROM node:20-alpine

WORKDIR /app

# Install dumb-init for proper signal handling
RUN apk add --no-cache dumb-init

# Copy built application from builder
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/skills ./skills
COPY --from=builder /app/node_modules ./node_modules
COPY package.json ./

# Non-root user
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001

USER nodejs

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:${MCP_PORT:-3100}/health || exit 1

EXPOSE 3100

ENTRYPOINT ["/sbin/dumb-init", "--"]
CMD ["node", "dist/index.js"]
261 changes: 261 additions & 0 deletions apps/mcp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
# OpenGenerativeUI MCP Server

A standalone, independently deployable [Model Context Protocol](https://modelcontextprotocol.io) server that exposes OpenGenerativeUI's design system, skills, and document renderer to any MCP-compatible client.

## Features

- **Design System Tool** — `assemble_document` wraps HTML fragments with OpenGenerativeUI's complete CSS design system and bridge JavaScript
- **Skill Resources** — Browse and read skill instruction documents via `skills://list` and `skills://{name}`
- **Prompt Templates** — Pre-composed prompts for common visualization tasks: `create_widget`, `create_svg_diagram`, `create_visualization`
- **Standalone** — No dependencies on other packages; can be deployed independently
- **Configurable** — Environment variables for port, CORS origins, skills directory, and logging

## Quick Start

### Prerequisites
- Node.js >= 18
- pnpm or npm

### Installation

```bash
# Navigate to the MCP package
cd apps/mcp

# Install dependencies
pnpm install

# Start the development server
pnpm dev
# → MCP server running on http://localhost:3100/mcp

# Health check
curl http://localhost:3100/health
# → {"status":"ok"}
```

### Build for Production

```bash
pnpm build
pnpm start
```

## Configuration

Create a `.env` file in the package root (copy from `.env.example`):

```bash
# Server port (default: 3100)
MCP_PORT=3100

# CORS origins, comma-separated (default: * for development)
ALLOWED_ORIGINS=*

# Skills directory path (default: ./skills)
SKILLS_DIR=./skills

# Log level (default: info)
LOG_LEVEL=info
```

## Usage

### From Claude Code

Add to `.mcp.json`:

```json
{
"openGenerativeUI": {
"url": "http://localhost:3100/mcp"
}
}
```

Then use the available tools and resources in Claude conversations.

### From Any MCP Client

Connect via HTTP MCP transport to `http://localhost:3100/mcp`.

## API Reference

### Tool: `assemble_document`

Wraps an HTML fragment with the complete OpenGenerativeUI design system.

**Input:**
```typescript
{
title: string; // Short title, e.g., "Binary Search Visualization"
description: string; // One-sentence explanation
html: string; // Self-contained HTML fragment (inline <style> and <script> OK)
}
```

**Output:**
```typescript
{
content: [{
type: "text",
text: string // Complete HTML document, ready to render in iframe
}]
}
```

**Example:**
```javascript
const result = await client.callTool("assemble_document", {
title: "Interactive Algorithm Visualizer",
description: "Step-by-step visualization of the quicksort algorithm",
html: `
<div id="viz">
<p>Click to start visualization</p>
<script>
// Your visualization code here
</script>
</div>
`
});

// result.content[0].text is a complete HTML document
// Render in: <iframe sandbox="allow-scripts allow-same-origin" srcdoc={result.content[0].text} />
```

### Resource: `skills://list`

Returns a JSON array of available skill names.

**Example:**
```bash
curl -X POST http://localhost:3100/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/read",
"params": { "uri": "skills://list" }
}'
```

### Resource: `skills://{name}`

Retrieve the full text content of a specific skill.

Available skills:
- `master-agent-playbook` — When and how to create interactive HTML widgets
- `svg-diagram-skill` — SVG diagram templates and patterns
- `agent-skills-vol2` — Advanced visualizations, dashboards, simulations

**Example:**
```bash
curl -X POST http://localhost:3100/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "resources/read",
"params": { "uri": "skills://master-agent-playbook" }
}'
```

### Prompts

#### `create_widget`
Instructions for creating interactive HTML widgets.

#### `create_svg_diagram`
Instructions for creating inline SVG diagrams with canonical templates.

#### `create_visualization`
Advanced visualization instructions: dashboards, simulations, UI mockups.

## Deployment

### Docker

```bash
# Build image
docker build -t open-generative-ui-mcp .

# Run container
docker run -p 3100:3100 open-generative-ui-mcp

# With custom port and CORS
docker run \
-p 3100:3100 \
-e MCP_PORT=3100 \
-e ALLOWED_ORIGINS="http://localhost:3000,https://myapp.com" \
open-generative-ui-mcp
```

### Node.js

```bash
# Install globally or locally
npm install -g open-generative-ui-mcp

# Run
MCP_PORT=3100 ALLOWED_ORIGINS="*" open-generative-ui-mcp

# Or with node
node dist/index.js
```

### Cloud Deployment

The server is a standard Node.js application and can be deployed to:
- **Heroku**: `Procfile: web: node dist/index.js`
- **Railway**: Connect the repo, select Node.js, set `start` script
- **Vercel**: Use serverless function (requires adapter)
- **AWS Lambda**: Package with Node.js runtime
- **Google Cloud Run**: Use Dockerfile

## Development

### Project Structure

```
apps/mcp/
├── package.json # Standalone package definition
├── tsconfig.json # TypeScript config
├── .env.example # Configuration template
├── Dockerfile # Container definition
├── skills/ # Skill instruction files (copied from source)
└── src/
├── index.ts # Hono HTTP server entry point
├── server.ts # MCP server construction
├── skills.ts # Skill file loader
└── renderer.ts # Design system CSS + assembleDocument
```

### Extending Skills

Add new skill files to `skills/` directory as `.txt` files. They'll automatically be available as resources and can be used in prompts.

### Modifying the Design System

Edit `src/renderer.ts` to update:
- `THEME_CSS` — Theme colors and variables
- `SVG_CLASSES_CSS` — Pre-built SVG helper classes
- `FORM_STYLES_CSS` — Form element styling
- `BRIDGE_JS` — Communication bridge between iframe and parent

## License

MIT

## Support

For issues, feature requests, or questions, visit the [OpenGenerativeUI repository](https://github.com/CopilotKit/OpenGenerativeUI).

## Contributing

This is a standalone deployment package. To contribute improvements:

1. Fork the main [OpenGenerativeUI repository](https://github.com/CopilotKit/OpenGenerativeUI)
2. Make changes to `apps/mcp/` (or the source files it's forked from)
3. Submit a pull request

When updating skills or the design system in the main repo, the MCP package should be updated accordingly.
30 changes: 30 additions & 0 deletions apps/mcp/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "open-generative-ui-mcp",
"version": "0.1.0",
"description": "Standalone MCP server for OpenGenerativeUI design system and skills",
"type": "module",
"main": "dist/index.js",
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"lint": "tsc --noEmit"
},
"keywords": ["mcp", "model-context-protocol", "generative-ui", "design-system"],
"author": "CopilotKit",
"license": "MIT",
"dependencies": {
"@hono/node-server": "^1",
"@modelcontextprotocol/sdk": "^1.25.3",
"hono": "^4",
"zod": "^3.23"
},
"devDependencies": {
"@types/node": "^20",
"tsx": "^4",
"typescript": "^5"
},
"engines": {
"node": ">=18"
}
}
Loading
Loading