@@ -0,0 +1,55 @@
|
||||
# Dependencies
|
||||
node_modules
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Build outputs
|
||||
dist
|
||||
build
|
||||
*.log
|
||||
|
||||
# Git
|
||||
.git
|
||||
.gitignore
|
||||
.gitattributes
|
||||
|
||||
# IDE
|
||||
.vscode
|
||||
.idea
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Testing
|
||||
coverage
|
||||
.nyc_output
|
||||
*.test.ts
|
||||
*.spec.ts
|
||||
|
||||
# CI/CD
|
||||
.github
|
||||
|
||||
# Documentation
|
||||
*.md
|
||||
!README.md
|
||||
docs
|
||||
|
||||
# Docker
|
||||
Dockerfile*
|
||||
docker-compose*.yml
|
||||
.dockerignore
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Misc
|
||||
tmp
|
||||
temp
|
||||
*.tmp
|
||||
@@ -0,0 +1,72 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
name: Build and Type Check
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x, 20.x, 22.x]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run TypeScript type check
|
||||
run: npm run type-check
|
||||
|
||||
- name: Build project
|
||||
run: npm run build
|
||||
|
||||
- name: Check build artifacts
|
||||
run: |
|
||||
echo "Checking if build artifacts exist..."
|
||||
test -f dist/index.js || (echo "dist/index.js not found" && exit 1)
|
||||
test -f dist/server.js || (echo "dist/server.js not found" && exit 1)
|
||||
test -d dist/frontend || (echo "dist/frontend not found" && exit 1)
|
||||
echo "All build artifacts present!"
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.node-version == '20.x'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
path: |
|
||||
dist/
|
||||
retention-days: 7
|
||||
|
||||
lint-check:
|
||||
name: Lint Check
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Check for TypeScript errors
|
||||
run: npm run type-check
|
||||
@@ -0,0 +1,146 @@
|
||||
name: Docker Build & Push
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME_MCP: ${{ github.repository }}
|
||||
IMAGE_NAME_CANVAS: ${{ github.repository }}-canvas
|
||||
|
||||
jobs:
|
||||
build-and-push-mcp:
|
||||
name: Build and Push MCP Server Image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for MCP Server
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MCP }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha,prefix=sha-
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Build and push MCP Server image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
build-and-push-canvas:
|
||||
name: Build and Push Canvas Server Image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata for Canvas Server
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_CANVAS }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha,prefix=sha-
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Build and push Canvas Server image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.canvas
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
test-docker-images:
|
||||
name: Test Docker Images
|
||||
needs: [build-and-push-mcp, build-and-push-canvas]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Determine image tag
|
||||
id: tag
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||
echo "value=pr-${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "value=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Test Canvas Server image
|
||||
run: |
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_CANVAS }}:${{ steps.tag.outputs.value }}
|
||||
docker run -d -p 3000:3000 --name test-canvas ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_CANVAS }}:${{ steps.tag.outputs.value }}
|
||||
sleep 10
|
||||
curl -f http://localhost:3000/health || exit 1
|
||||
docker logs test-canvas
|
||||
docker stop test-canvas
|
||||
|
||||
- name: Test MCP Server image
|
||||
run: |
|
||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MCP }}:${{ steps.tag.outputs.value }}
|
||||
echo "MCP Server image pulled successfully"
|
||||
@@ -0,0 +1,106 @@
|
||||
name: Publish to NPM
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Tag to publish (e.g., latest, beta, next)'
|
||||
required: true
|
||||
default: 'latest'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish to NPM Registry
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run type check
|
||||
run: npm run type-check
|
||||
|
||||
- name: Build project
|
||||
run: npm run build
|
||||
|
||||
- name: Verify build artifacts
|
||||
run: |
|
||||
echo "Verifying build artifacts..."
|
||||
test -f dist/index.js || (echo "ERROR: dist/index.js not found" && exit 1)
|
||||
test -f dist/server.js || (echo "ERROR: dist/server.js not found" && exit 1)
|
||||
test -d dist/frontend || (echo "ERROR: dist/frontend not found" && exit 1)
|
||||
echo "All required artifacts present!"
|
||||
|
||||
- name: Get package version
|
||||
id: package-version
|
||||
run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check if version exists on NPM
|
||||
id: check-version
|
||||
run: |
|
||||
if npm view mcp-excalidraw-server@${{ steps.package-version.outputs.version }} version 2>/dev/null; then
|
||||
echo "exists=true" >> $GITHUB_OUTPUT
|
||||
echo "Version ${{ steps.package-version.outputs.version }} already exists on NPM"
|
||||
else
|
||||
echo "exists=false" >> $GITHUB_OUTPUT
|
||||
echo "Version ${{ steps.package-version.outputs.version }} does not exist on NPM"
|
||||
fi
|
||||
|
||||
- name: Publish to NPM (Release)
|
||||
if: github.event_name == 'release' && steps.check-version.outputs.exists == 'false'
|
||||
run: npm publish --provenance --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Publish to NPM (Manual)
|
||||
if: github.event_name == 'workflow_dispatch' && steps.check-version.outputs.exists == 'false'
|
||||
run: npm publish --tag ${{ github.event.inputs.tag }} --provenance --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Skip publishing (version exists)
|
||||
if: steps.check-version.outputs.exists == 'true'
|
||||
run: |
|
||||
echo "⚠️ Skipping publish - version ${{ steps.package-version.outputs.version }} already exists on NPM"
|
||||
echo "Please bump the version in package.json before publishing"
|
||||
|
||||
- name: Create GitHub Release Assets
|
||||
if: github.event_name == 'release'
|
||||
run: |
|
||||
tar -czf mcp-excalidraw-server-${{ steps.package-version.outputs.version }}.tar.gz dist/
|
||||
|
||||
- name: Upload Release Assets
|
||||
if: github.event_name == 'release'
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: |
|
||||
mcp-excalidraw-server-${{ steps.package-version.outputs.version }}.tar.gz
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
notify:
|
||||
name: Publish Notification
|
||||
needs: publish
|
||||
runs-on: ubuntu-latest
|
||||
if: success()
|
||||
|
||||
steps:
|
||||
- name: Success notification
|
||||
run: |
|
||||
echo "✅ Package successfully published to NPM!"
|
||||
echo "View at: https://www.npmjs.com/package/mcp-excalidraw-server"
|
||||
@@ -1,6 +1,5 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
package-lock.json
|
||||
|
||||
# Build artifacts
|
||||
dist/
|
||||
|
||||
+40
-10
@@ -1,5 +1,27 @@
|
||||
# Production stage - MCP Backend Only
|
||||
FROM node:18-slim
|
||||
# Dockerfile for MCP Excalidraw Server
|
||||
# This builds the MCP server only (core product for CI/CD and GHCR)
|
||||
# The canvas server is optional and runs separately
|
||||
|
||||
# Stage 1: Build backend (TypeScript compilation)
|
||||
FROM node:18-slim AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install all dependencies (including TypeScript compiler)
|
||||
RUN npm ci && npm cache clean --force
|
||||
|
||||
# Copy backend source
|
||||
COPY src ./src
|
||||
COPY tsconfig.json ./
|
||||
|
||||
# Compile TypeScript
|
||||
RUN npm run build:server
|
||||
|
||||
# Stage 2: Production MCP Server
|
||||
FROM node:18-slim AS production
|
||||
|
||||
# Create non-root user for security
|
||||
RUN addgroup --system --gid 1001 nodejs && \
|
||||
@@ -13,16 +35,24 @@ COPY package*.json ./
|
||||
# Install only production dependencies
|
||||
RUN npm ci --only=production && npm cache clean --force
|
||||
|
||||
# Copy source code (only backend files needed)
|
||||
COPY src ./src
|
||||
# Copy compiled backend (MCP server only)
|
||||
COPY --from=builder /app/dist ./dist
|
||||
|
||||
# Set environment variables
|
||||
ENV NODE_ENV=production
|
||||
ENV EXPRESS_SERVER_URL=http://localhost:3000
|
||||
ENV ENABLE_CANVAS_SYNC=true
|
||||
# Set ownership to nodejs user
|
||||
RUN chown -R nodejs:nodejs /app
|
||||
|
||||
# Switch to non-root user
|
||||
USER nodejs
|
||||
|
||||
# Run MCP server only
|
||||
CMD ["npm", "start"]
|
||||
# Set environment variables with defaults
|
||||
ENV NODE_ENV=production
|
||||
ENV EXPRESS_SERVER_URL=http://localhost:3000
|
||||
ENV ENABLE_CANVAS_SYNC=true
|
||||
|
||||
# Run MCP server (stdin/stdout protocol)
|
||||
CMD ["node", "dist/index.js"]
|
||||
|
||||
# Labels for metadata
|
||||
LABEL org.opencontainers.image.source="https://github.com/yctimlin/mcp_excalidraw"
|
||||
LABEL org.opencontainers.image.description="MCP Excalidraw Server - Model Context Protocol for AI agents"
|
||||
LABEL org.opencontainers.image.licenses="MIT"
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
# Dockerfile for Canvas Server (Optional)
|
||||
# This is for users who want to run the visual canvas UI
|
||||
# The canvas server provides the web interface and REST API
|
||||
|
||||
# Stage 1: Build frontend
|
||||
FROM node:18-slim AS frontend-builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install all dependencies (including dev dependencies for build)
|
||||
RUN npm ci && npm cache clean --force
|
||||
|
||||
# Copy frontend source
|
||||
COPY frontend ./frontend
|
||||
COPY vite.config.js ./
|
||||
|
||||
# Build frontend
|
||||
RUN npm run build:frontend
|
||||
|
||||
# Stage 2: Build backend (TypeScript compilation)
|
||||
FROM node:18-slim AS backend-builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install all dependencies (including TypeScript compiler)
|
||||
RUN npm ci && npm cache clean --force
|
||||
|
||||
# Copy backend source
|
||||
COPY src ./src
|
||||
COPY tsconfig.json ./
|
||||
|
||||
# Compile TypeScript
|
||||
RUN npm run build:server
|
||||
|
||||
# Stage 3: Production Canvas Server
|
||||
FROM node:18-slim AS production
|
||||
|
||||
# Create non-root user for security
|
||||
RUN addgroup --system --gid 1001 nodejs && \
|
||||
adduser --system --uid 1001 --gid 1001 nodejs
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install only production dependencies
|
||||
RUN npm ci --only=production && npm cache clean --force
|
||||
|
||||
# Copy compiled backend from builder stage
|
||||
COPY --from=backend-builder /app/dist ./dist
|
||||
|
||||
# Copy built frontend from frontend-builder stage
|
||||
COPY --from=frontend-builder /app/dist/frontend ./dist/frontend
|
||||
|
||||
# Set ownership to nodejs user
|
||||
RUN chown -R nodejs:nodejs /app
|
||||
|
||||
# Switch to non-root user
|
||||
USER nodejs
|
||||
|
||||
# Set environment variables with defaults
|
||||
ENV NODE_ENV=production
|
||||
ENV PORT=3000
|
||||
ENV HOST=0.0.0.0
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3000
|
||||
|
||||
# Run canvas server (web UI + REST API)
|
||||
CMD ["node", "dist/server.js"]
|
||||
|
||||
# Labels for metadata
|
||||
LABEL org.opencontainers.image.source="https://github.com/yctimlin/mcp_excalidraw"
|
||||
LABEL org.opencontainers.image.description="MCP Excalidraw Canvas Server - Web UI and REST API"
|
||||
LABEL org.opencontainers.image.licenses="MIT"
|
||||
@@ -1,25 +1,34 @@
|
||||
# MCP Excalidraw Server: Advanced Live Visual Diagramming with AI Integration
|
||||
|
||||
[](https://github.com/yctimlin/mcp_excalidraw/actions/workflows/ci.yml)
|
||||
[](https://github.com/yctimlin/mcp_excalidraw/actions/workflows/docker.yml)
|
||||
[](https://www.npmjs.com/package/mcp-excalidraw-server)
|
||||
[](LICENSE)
|
||||
|
||||
A comprehensive **TypeScript-based** system that combines **Excalidraw's powerful drawing capabilities** with **Model Context Protocol (MCP)** integration, enabling AI agents to create and manipulate diagrams in real-time on a live canvas.
|
||||
|
||||
## 🚦 Current Status & Version Information
|
||||
|
||||
> **📋 Choose Your Installation Method**
|
||||
|
||||
| Version | Status | Recommended For |
|
||||
|---------|--------|----------------|
|
||||
| **Local Development** | ✅ **FULLY TESTED** | **🎯 RECOMMENDED** |
|
||||
| **NPM Published** | 🔧 **DEBUGGING IN PROGRESS** | Development testing |
|
||||
| **Docker Version** | 🔧 **UNDER DEVELOPMENT** | Future deployment |
|
||||
| Component | Local | Docker | Status |
|
||||
|-----------|-------|--------|--------|
|
||||
| **Canvas Server** | ✅ Fully Working | ✅ Fully Working | **Production Ready** |
|
||||
| **MCP Server** | ✅ Fully Working | ✅ Fully Working | **Production Ready** |
|
||||
| **NPM Published** | 🔧 In Progress | N/A | Development testing |
|
||||
|
||||
### **Current Recommendation: Local Development**
|
||||
### **Important: Canvas and MCP Server Run Separately**
|
||||
|
||||
For the most stable experience, we recommend using the local development setup. We're actively working on improving the NPM package and Docker deployment options.
|
||||
This system consists of **two independent components**:
|
||||
|
||||
### **Development Notes**
|
||||
- **NPM Package**: Currently debugging MCP tool registration issues
|
||||
- **Docker Version**: Improving canvas synchronization reliability
|
||||
- **Local Version**: ✅ All features fully functional
|
||||
1. **Canvas Server** - Runs the live Excalidraw canvas (web interface)
|
||||
2. **MCP Server** - Connects to Claude Desktop/Claude Code/Cursor IDE
|
||||
|
||||
**You can choose any combination:**
|
||||
- Canvas: Local OR Docker
|
||||
- MCP Server: Local OR Docker
|
||||
|
||||
Both local and Docker setups are **fully working** and production-ready!
|
||||
|
||||
## 🚀 What This System Does
|
||||
|
||||
@@ -39,17 +48,47 @@ For the most stable experience, we recommend using the local development setup.
|
||||
|
||||
## 🏛️ Architecture Overview
|
||||
|
||||
### **Two Independent Components**
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
||||
│ AI Agent │───▶│ MCP Server │───▶│ Canvas Server │
|
||||
│ (Claude) │ │ (src/index.js) │ │ (src/server.js) │
|
||||
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Frontend │
|
||||
│ (React + WS) │
|
||||
└─────────────────┘
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Component 1 │
|
||||
│ 🎨 CANVAS SERVER │
|
||||
│ (Runs Independently) │
|
||||
│ │
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||||
│ │ Canvas Server │◀───────▶│ Frontend │ │
|
||||
│ │ (src/server.js) │ │ (React + WS) │ │
|
||||
│ │ Port 3000 │ │ Excalidraw UI │ │
|
||||
│ └─────────────────┘ └─────────────────┘ │
|
||||
│ │
|
||||
│ 📍 Start: npm run canvas OR docker run (canvas) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
|
||||
▲
|
||||
│ HTTP API
|
||||
│ (Optional)
|
||||
│
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Component 2 │
|
||||
│ 🤖 MCP SERVER │
|
||||
│ (Runs Independently) │
|
||||
│ │
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||||
│ │ AI Agent │◀───────▶│ MCP Server │ │
|
||||
│ │ (Claude) │ │ (src/index.js) │ │
|
||||
│ │ Desktop/Code │ stdio │ MCP Protocol │ │
|
||||
│ └─────────────────┘ └─────────────────┘ │
|
||||
│ │
|
||||
│ 📍 Configure in: claude_desktop_config.json OR .mcp.json │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
|
||||
🎯 Key Points:
|
||||
• Canvas and MCP server are SEPARATE processes
|
||||
• Canvas can run locally OR in Docker
|
||||
• MCP server can run locally OR in Docker
|
||||
• Canvas provides the visual interface (optional)
|
||||
• MCP server connects Claude to the canvas (via HTTP API)
|
||||
```
|
||||
|
||||
## 🌟 Key Features
|
||||
@@ -84,57 +123,78 @@ For the most stable experience, we recommend using the local development setup.
|
||||
|
||||
## 📦 Installation & Setup
|
||||
|
||||
### **✅ Recommended: Local Development Setup**
|
||||
### **Step 1: Choose Your Canvas Server Setup**
|
||||
|
||||
> **Most stable and feature-complete option**
|
||||
The canvas server provides the live Excalidraw interface.
|
||||
|
||||
#### **1. Clone the Repository**
|
||||
#### **Option A: Local Canvas Server**
|
||||
|
||||
1. **Clone and Install**
|
||||
```bash
|
||||
git clone https://github.com/yctimlin/mcp_excalidraw.git
|
||||
cd mcp_excalidraw
|
||||
npm install
|
||||
```
|
||||
|
||||
#### **2. Build the Frontend**
|
||||
2. **Build the Project**
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
#### **3. Start the System**
|
||||
|
||||
##### **Option A: Production Mode (Recommended)**
|
||||
3. **Start Canvas Server**
|
||||
```bash
|
||||
# Start canvas server (serves frontend + API)
|
||||
# Production mode (recommended)
|
||||
npm run canvas
|
||||
```
|
||||
|
||||
##### **Option B: Development Mode**
|
||||
```bash
|
||||
# Start both canvas server and Vite dev server
|
||||
npm run dev
|
||||
```
|
||||
|
||||
#### **4. Access the Canvas**
|
||||
Open your browser and navigate to:
|
||||
4. **Access the Canvas**
|
||||
```
|
||||
http://localhost:3000
|
||||
```
|
||||
|
||||
### **🔧 Alternative Installation Methods (In Development)**
|
||||
#### **Option B: Docker Canvas Server**
|
||||
|
||||
#### **NPM Package (Beta)**
|
||||
**Option B1: Use Pre-built Image from GHCR** (Recommended)
|
||||
```bash
|
||||
# Currently debugging tool registration - feedback welcome!
|
||||
npm install -g mcp-excalidraw-server
|
||||
npx mcp-excalidraw-server
|
||||
docker pull ghcr.io/yctimlin/mcp_excalidraw-canvas:latest
|
||||
docker run -d -p 3000:3000 --name mcp-excalidraw-canvas ghcr.io/yctimlin/mcp_excalidraw-canvas:latest
|
||||
```
|
||||
|
||||
#### **Docker Version (Coming Soon)**
|
||||
**Option B2: Build Locally**
|
||||
```bash
|
||||
# Canvas sync improvements in progress
|
||||
docker run -p 3000:3000 mcp-excalidraw-server
|
||||
git clone https://github.com/yctimlin/mcp_excalidraw.git
|
||||
cd mcp_excalidraw
|
||||
docker build -f Dockerfile.canvas -t mcp-excalidraw-canvas .
|
||||
docker run -d -p 3000:3000 --name mcp-excalidraw-canvas mcp-excalidraw-canvas
|
||||
```
|
||||
|
||||
3. **Access the Canvas**
|
||||
```
|
||||
http://localhost:3000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **Step 2: Configure MCP Server in Your IDE**
|
||||
|
||||
The MCP server connects your AI assistant (Claude) to the canvas. **Choose local OR Docker format** based on your preference.
|
||||
|
||||
#### **Setup Combinations**
|
||||
|
||||
You can mix and match any combination:
|
||||
|
||||
| Canvas Server | MCP Server | Status |
|
||||
|---------------|------------|--------|
|
||||
| ✅ Local | ✅ Local | Recommended |
|
||||
| ✅ Local | ✅ Docker | Fully Working |
|
||||
| ✅ Docker | ✅ Local | Fully Working |
|
||||
| ✅ Docker | ✅ Docker | Fully Working |
|
||||
|
||||
Configuration examples are provided in the next section for:
|
||||
- Claude Desktop
|
||||
- Claude Code
|
||||
- Cursor IDE
|
||||
|
||||
## 🔧 Available Scripts
|
||||
|
||||
| Script | Description |
|
||||
@@ -223,87 +283,221 @@ The MCP server provides these tools for creating visual diagrams:
|
||||
}
|
||||
```
|
||||
|
||||
## 🔌 Integration with Claude Desktop
|
||||
## 🔌 MCP Server Configuration for IDEs
|
||||
|
||||
### **✅ Recommended: Using Local Installation**
|
||||
### **Prerequisites**
|
||||
✅ Ensure your **canvas server is running** (from Step 1):
|
||||
- Local: `npm run canvas`
|
||||
- Docker: `docker run -d -p 3000:3000 mcp-excalidraw-canvas`
|
||||
|
||||
For the **local development version** (most stable), add this configuration to your `claude_desktop_config.json`:
|
||||
Canvas should be accessible at http://localhost:3000
|
||||
|
||||
### **Quick Reference**
|
||||
|
||||
Choose your configuration based on IDE and preference:
|
||||
|
||||
| IDE | Config File | Format Options |
|
||||
|-----|-------------|----------------|
|
||||
| **Claude Desktop** | `claude_desktop_config.json` | Local ⭐ / Docker ✅ |
|
||||
| **Claude Code** | `.mcp.json` (project root) | Local ⭐ / Docker ✅ |
|
||||
| **Cursor** | `.cursor/mcp.json` | Local ⭐ / Docker ✅ |
|
||||
|
||||
⭐ = Recommended | ✅ = Fully Working
|
||||
|
||||
---
|
||||
|
||||
## **Configuration for Claude Desktop**
|
||||
|
||||
Edit your `claude_desktop_config.json` file:
|
||||
|
||||
### **Format 1: Local MCP Server** ⭐ Recommended
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"excalidraw": {
|
||||
"command": "node",
|
||||
"args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Important**: Replace `/absolute/path/to/mcp_excalidraw` with the actual absolute path to your cloned repository. Note that the path now points to `dist/index.js` (the compiled TypeScript output).
|
||||
|
||||
### **🔧 Alternative Configurations (Beta)**
|
||||
|
||||
#### **NPM Package (Beta Testing)**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"excalidraw": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-excalidraw-server"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
*Currently debugging tool registration - let us know if you encounter issues!*
|
||||
|
||||
#### **Docker Version (Coming Soon)**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"excalidraw": {
|
||||
"command": "docker",
|
||||
"args": ["run", "-i", "--rm", "mcp-excalidraw-server"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
*Canvas sync improvements in progress.*
|
||||
|
||||
## 🔧 Integration with Other Tools
|
||||
|
||||
### **Cursor IDE**
|
||||
|
||||
Add to your `.cursor/mcp.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"excalidraw": {
|
||||
"command": "node",
|
||||
"args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **VS Code MCP Extension**
|
||||
|
||||
For VS Code MCP extension, add to your settings:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"excalidraw": {
|
||||
"command": "node",
|
||||
"args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"]
|
||||
"args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"],
|
||||
"env": {
|
||||
"EXPRESS_SERVER_URL": "http://localhost:3000",
|
||||
"ENABLE_CANVAS_SYNC": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Important:** Replace `/absolute/path/to/mcp_excalidraw` with your actual installation path.
|
||||
|
||||
### **Format 2: Docker MCP Server** ✅ Fully Working
|
||||
|
||||
**Using Pre-built Image from GHCR** (Recommended):
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"excalidraw": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
"-i",
|
||||
"--rm",
|
||||
"--network", "host",
|
||||
"-e", "EXPRESS_SERVER_URL=http://localhost:3000",
|
||||
"-e", "ENABLE_CANVAS_SYNC=true",
|
||||
"ghcr.io/yctimlin/mcp_excalidraw:latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**OR Build Locally**:
|
||||
```bash
|
||||
cd mcp_excalidraw
|
||||
docker build -f Dockerfile -t mcp-excalidraw .
|
||||
```
|
||||
|
||||
Then use `mcp-excalidraw` as the image name in the configuration above.
|
||||
|
||||
---
|
||||
|
||||
## **Configuration for Claude Code**
|
||||
|
||||
Create or edit `.mcp.json` in your project root:
|
||||
|
||||
### **Format 1: Local MCP Server** ⭐ Recommended
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"excalidraw": {
|
||||
"command": "node",
|
||||
"args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"],
|
||||
"env": {
|
||||
"EXPRESS_SERVER_URL": "http://localhost:3000",
|
||||
"ENABLE_CANVAS_SYNC": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Important:** Replace `/absolute/path/to/mcp_excalidraw` with your actual installation path.
|
||||
|
||||
### **Format 2: Docker MCP Server** ✅ Fully Working
|
||||
|
||||
**Using Pre-built Image from GHCR** (Recommended):
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"excalidraw": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
"-i",
|
||||
"--rm",
|
||||
"--network", "host",
|
||||
"-e", "EXPRESS_SERVER_URL=http://localhost:3000",
|
||||
"-e", "ENABLE_CANVAS_SYNC=true",
|
||||
"ghcr.io/yctimlin/mcp_excalidraw:latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**OR Build Locally**:
|
||||
```bash
|
||||
cd mcp_excalidraw
|
||||
docker build -f Dockerfile -t mcp-excalidraw .
|
||||
```
|
||||
|
||||
Then use `mcp-excalidraw` as the image name in the configuration above.
|
||||
|
||||
### **Alternative: Using Claude CLI**
|
||||
|
||||
```bash
|
||||
# Project-scoped (recommended)
|
||||
claude mcp add --scope project --transport stdio excalidraw \
|
||||
-- docker run -i --rm --network host \
|
||||
-e EXPRESS_SERVER_URL=http://localhost:3000 \
|
||||
-e ENABLE_CANVAS_SYNC=true \
|
||||
mcp-excalidraw
|
||||
|
||||
# User-scoped (available across all projects)
|
||||
claude mcp add --scope user --transport stdio excalidraw \
|
||||
-- docker run -i --rm --network host \
|
||||
-e EXPRESS_SERVER_URL=http://localhost:3000 \
|
||||
-e ENABLE_CANVAS_SYNC=true \
|
||||
mcp-excalidraw
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **Configuration for Cursor IDE**
|
||||
|
||||
Edit `.cursor/mcp.json`:
|
||||
|
||||
### **Format 1: Local MCP Server** ⭐ Recommended
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"excalidraw": {
|
||||
"command": "node",
|
||||
"args": ["/absolute/path/to/mcp_excalidraw/dist/index.js"],
|
||||
"env": {
|
||||
"EXPRESS_SERVER_URL": "http://localhost:3000",
|
||||
"ENABLE_CANVAS_SYNC": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **Format 2: Docker MCP Server** ✅ Fully Working
|
||||
|
||||
**Using Pre-built Image from GHCR** (Recommended):
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"excalidraw": {
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"run",
|
||||
"-i",
|
||||
"--rm",
|
||||
"--network", "host",
|
||||
"-e", "EXPRESS_SERVER_URL=http://localhost:3000",
|
||||
"-e", "ENABLE_CANVAS_SYNC=true",
|
||||
"ghcr.io/yctimlin/mcp_excalidraw:latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**OR Build Locally**:
|
||||
```bash
|
||||
cd mcp_excalidraw
|
||||
docker build -f Dockerfile -t mcp-excalidraw .
|
||||
```
|
||||
|
||||
Then use `mcp-excalidraw` as the image name in the configuration above.
|
||||
|
||||
---
|
||||
|
||||
## **Important Configuration Notes**
|
||||
|
||||
| Setting | Purpose | Required |
|
||||
|---------|---------|----------|
|
||||
| `EXPRESS_SERVER_URL` | Canvas server URL | Yes (default: http://localhost:3000) |
|
||||
| `ENABLE_CANVAS_SYNC` | Enable real-time canvas sync | Yes (set to "true") |
|
||||
| `--network host` | Docker access to localhost | Required for Docker |
|
||||
| `-i` flag | Interactive stdin/stdout | Required for Docker |
|
||||
|
||||
**Canvas is optional**: The MCP server works without the canvas in API-only mode (for programmatic access only).
|
||||
|
||||
## 🛠️ Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
@@ -378,37 +572,46 @@ The canvas server provides these REST endpoints:
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### **NPM Package Issues**
|
||||
- **Symptoms**: MCP tools not registering properly
|
||||
- **Temporary Solution**: Use local development setup
|
||||
- **Status**: Actively debugging - updates coming soon
|
||||
|
||||
### **Docker Version Notes**
|
||||
- **Symptoms**: Elements may not sync to canvas immediately
|
||||
- **Temporary Solution**: Use local development setup
|
||||
- **Status**: Improving synchronization reliability
|
||||
|
||||
### **Canvas Not Loading**
|
||||
- Ensure `npm run build` completed successfully
|
||||
- Check that `dist/index.html` exists
|
||||
- Check that `dist/index.html` and `dist/frontend/` directory exist
|
||||
- Verify canvas server is running on port 3000
|
||||
- Check if port 3000 is already in use: `lsof -i :3000` (macOS/Linux) or `netstat -ano | findstr :3000` (Windows)
|
||||
|
||||
### **Elements Not Syncing**
|
||||
- Confirm MCP server is running (`npm start`)
|
||||
- Check `ENABLE_CANVAS_SYNC=true` in environment
|
||||
- Verify canvas server is accessible at `EXPRESS_SERVER_URL`
|
||||
- Confirm canvas server is running and accessible at http://localhost:3000
|
||||
- Check `ENABLE_CANVAS_SYNC=true` in MCP server environment configuration
|
||||
- Verify `EXPRESS_SERVER_URL` points to correct canvas server URL
|
||||
- Check browser console for WebSocket connection errors
|
||||
- For Docker: Ensure `--network host` flag is used
|
||||
|
||||
### **WebSocket Connection Issues**
|
||||
- Check browser console for WebSocket errors
|
||||
- Ensure no firewall blocking WebSocket connections
|
||||
### **WebSocket Connection Issues**
|
||||
- Check browser console for WebSocket errors (F12 → Console tab)
|
||||
- Ensure no firewall blocking WebSocket connections on port 3000
|
||||
- Try refreshing the browser page
|
||||
- Verify canvas server is running: `curl http://localhost:3000/health`
|
||||
|
||||
### **Docker Issues**
|
||||
|
||||
**Canvas Container:**
|
||||
- Check if container is running: `docker ps | grep canvas`
|
||||
- View logs: `docker logs mcp-excalidraw-canvas`
|
||||
- Ensure port 3000 is not already in use
|
||||
|
||||
**MCP Container:**
|
||||
- For Docker MCP server, ensure `--network host` is used (required to access localhost:3000)
|
||||
- Verify `-i` flag is present (required for MCP stdin/stdout protocol)
|
||||
- Check environment variables are properly set
|
||||
|
||||
### **Build Errors**
|
||||
- Delete `node_modules` and run `npm install`
|
||||
- Check Node.js version (requires 16+)
|
||||
- Ensure all dependencies are installed
|
||||
- Delete `node_modules` and `dist/` directories, then run `npm install && npm run build`
|
||||
- Check Node.js version (requires 16+): `node --version`
|
||||
- Run `npm run type-check` to identify TypeScript issues
|
||||
- Verify `dist/` directory is created after `npm run build:server`
|
||||
- Verify `dist/` directory contains both `index.js`, `server.js`, and `frontend/` after build
|
||||
|
||||
### **NPM Package Issues**
|
||||
- **Status**: NPM package is under development
|
||||
- **Recommendation**: Use local or Docker installation methods for production use
|
||||
|
||||
## 📋 Project Structure
|
||||
|
||||
@@ -441,11 +644,12 @@ mcp_excalidraw/
|
||||
## 🔮 Development Roadmap
|
||||
|
||||
- ✅ **TypeScript Migration**: Complete type safety for enhanced development experience
|
||||
- **NPM Package**: Resolving MCP tool registration issues
|
||||
- **Docker Deployment**: Improving canvas synchronization
|
||||
- **Enhanced Features**: Additional MCP tools and capabilities
|
||||
- **Performance Optimization**: Real-time sync improvements
|
||||
- **Advanced TypeScript Features**: Stricter type checking and advanced type utilities
|
||||
- ✅ **Docker Deployment**: Both Canvas and MCP server fully working in Docker
|
||||
- 🔧 **NPM Package**: Resolving MCP tool registration issues
|
||||
- 🎯 **Enhanced Features**: Additional MCP tools and capabilities
|
||||
- 🎯 **Performance Optimization**: Real-time sync improvements
|
||||
- 🎯 **Advanced TypeScript Features**: Stricter type checking and advanced type utilities
|
||||
- 🎯 **Container Registry**: Publishing to GitHub Container Registry (GHCR)
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
version: '3.8'
|
||||
|
||||
# Docker Compose for MCP Excalidraw
|
||||
#
|
||||
# Usage scenarios:
|
||||
# 1. Canvas only: docker-compose up canvas
|
||||
# 2. MCP only: docker-compose up mcp (requires canvas running elsewhere)
|
||||
# 3. Both: docker-compose --profile full up
|
||||
#
|
||||
# Most common: Run canvas locally, MCP via Claude Desktop config
|
||||
|
||||
services:
|
||||
# Canvas server (optional) - Visual UI and REST API
|
||||
canvas:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.canvas
|
||||
image: mcp-excalidraw-canvas:latest
|
||||
container_name: mcp-excalidraw-canvas
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=3000
|
||||
- HOST=0.0.0.0
|
||||
- DEBUG=false
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
networks:
|
||||
- mcp-network
|
||||
|
||||
# MCP server - Core product (typically run via Claude Desktop, not docker-compose)
|
||||
# This is here for testing or special deployment scenarios
|
||||
mcp:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: mcp-excalidraw:latest
|
||||
container_name: mcp-excalidraw-mcp
|
||||
stdin_open: true
|
||||
tty: true
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- EXPRESS_SERVER_URL=http://canvas:3000
|
||||
- ENABLE_CANVAS_SYNC=true
|
||||
- DEBUG=false
|
||||
depends_on:
|
||||
canvas:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- mcp-network
|
||||
profiles:
|
||||
- full
|
||||
|
||||
networks:
|
||||
mcp-network:
|
||||
driver: bridge
|
||||
Generated
+6903
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -75,7 +75,7 @@
|
||||
"url": "https://github.com/yctimlin/mcp_excalidraw/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
|
||||
+17
-13
@@ -38,6 +38,7 @@ interface ApiResponse {
|
||||
element?: ServerElement;
|
||||
elements?: ServerElement[];
|
||||
message?: string;
|
||||
error?: string;
|
||||
count?: number;
|
||||
}
|
||||
|
||||
@@ -97,12 +98,15 @@ async function syncToCanvas(operation: string, data: any): Promise<SyncResponse
|
||||
|
||||
logger.debug(`Syncing to canvas: ${operation}`, { url, data });
|
||||
const response = await fetch(url, options);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Canvas sync failed: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
|
||||
// Parse JSON response regardless of HTTP status
|
||||
const result = await response.json() as ApiResponse;
|
||||
|
||||
if (!response.ok) {
|
||||
logger.warn(`Canvas sync returned error status: ${response.status}`, result);
|
||||
throw new Error(result.error || `Canvas sync failed: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
logger.debug(`Canvas sync successful: ${operation}`, result);
|
||||
return result as SyncResponse;
|
||||
|
||||
@@ -564,21 +568,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest)
|
||||
case 'delete_element': {
|
||||
const params = ElementIdSchema.parse(args);
|
||||
const { id } = params;
|
||||
|
||||
|
||||
// Delete element directly on HTTP server (no local storage)
|
||||
const canvasResult = await deleteElementOnCanvas(id);
|
||||
|
||||
if (!canvasResult) {
|
||||
|
||||
if (!canvasResult || !(canvasResult as ApiResponse).success) {
|
||||
throw new Error('Failed to delete element: HTTP server unavailable or element not found');
|
||||
}
|
||||
|
||||
|
||||
const result = { id, deleted: true, syncedToCanvas: true };
|
||||
logger.info('Element deleted via MCP and synced to canvas', result);
|
||||
|
||||
|
||||
return {
|
||||
content: [{
|
||||
type: 'text',
|
||||
text: `Element deleted successfully!\n\n${JSON.stringify(result, null, 2)}\n\n✅ Synced to canvas`
|
||||
content: [{
|
||||
type: 'text',
|
||||
text: `Element deleted successfully!\n\n${JSON.stringify(result, null, 2)}\n\n✅ Synced to canvas`
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
+3
-6
@@ -2,14 +2,11 @@ import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
export default defineConfig({
|
||||
root: 'frontend',
|
||||
plugins: [react()],
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
rollupOptions: {
|
||||
input: {
|
||||
main: './frontend/index.html',
|
||||
},
|
||||
},
|
||||
outDir: '../dist/frontend',
|
||||
emptyOutDir: true,
|
||||
},
|
||||
server: {
|
||||
port: 5173,
|
||||
|
||||
Reference in New Issue
Block a user