chore: rename project to excalidraw-mcp-sentinel
- Package name: @sanjibdevnath/mcp-excalidraw-local → excalidraw-mcp-sentinel - GitHub repo: celstnblacc/mcp-excalidraw-local → celstnblacc/excalidraw-mcp-sentinel - Docker images, CLI binary, CI workflows, docs all updated - Version reset to 1.0.0 for independent release track - Added "Why this fork?" section to README - Removed superseded planning docs (PLAN.md, PLAN_v2.md, REVIEW.md, HANDOFF.md) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
8f9fe3fa08
commit
9fb8ce34ec
@@ -17,8 +17,8 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
IMAGE_NAME_MCP: sanjibdevnath/mcp-excalidraw-local
|
||||
IMAGE_NAME_CANVAS: sanjibdevnath/mcp-excalidraw-local-canvas
|
||||
IMAGE_NAME_MCP: celstnblacc/excalidraw-mcp-sentinel
|
||||
IMAGE_NAME_CANVAS: celstnblacc/excalidraw-mcp-sentinel-canvas
|
||||
|
||||
jobs:
|
||||
check-changes:
|
||||
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
- name: Check if version exists on NPM
|
||||
id: check
|
||||
run: |
|
||||
if npm view @sanjibdevnath/mcp-excalidraw-local@${{ steps.version.outputs.version }} version 2>/dev/null; then
|
||||
if npm view excalidraw-mcp-sentinel@${{ steps.version.outputs.version }} version 2>/dev/null; then
|
||||
echo "exists=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "exists=false" >> "$GITHUB_OUTPUT"
|
||||
|
||||
@@ -140,8 +140,8 @@ jobs:
|
||||
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config user.name "sanjibdevnathlabs-release-bot[bot]"
|
||||
git config user.email "${{ secrets.APP_ID }}+sanjibdevnathlabs-release-bot[bot]@users.noreply.github.com"
|
||||
git config user.name "excalidraw-sentinel-release-bot[bot]"
|
||||
git config user.email "${{ secrets.APP_ID }}+excalidraw-sentinel-release-bot[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Bump version in package.json
|
||||
run: |
|
||||
@@ -170,7 +170,7 @@ jobs:
|
||||
|
||||
---
|
||||
```
|
||||
npm install @sanjibdevnath/mcp-excalidraw-local@${{ needs.check.outputs.new_version }}
|
||||
npm install excalidraw-mcp-sentinel@${{ needs.check.outputs.new_version }}
|
||||
```
|
||||
draft: false
|
||||
prerelease: false
|
||||
@@ -208,7 +208,7 @@ jobs:
|
||||
id: check-npm
|
||||
run: |
|
||||
VERSION=$(node -p "require('./package.json').version")
|
||||
if npm view @sanjibdevnath/mcp-excalidraw-local@$VERSION version 2>/dev/null; then
|
||||
if npm view excalidraw-mcp-sentinel@$VERSION version 2>/dev/null; then
|
||||
echo "exists=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "exists=false" >> "$GITHUB_OUTPUT"
|
||||
@@ -253,8 +253,8 @@ jobs:
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
sanjibdevnath/mcp-excalidraw-local:latest
|
||||
sanjibdevnath/mcp-excalidraw-local:v${{ needs.release.outputs.version }}
|
||||
celstnblacc/excalidraw-mcp-sentinel:latest
|
||||
celstnblacc/excalidraw-mcp-sentinel:v${{ needs.release.outputs.version }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
platforms: linux/amd64,linux/arm64
|
||||
@@ -266,8 +266,8 @@ jobs:
|
||||
file: ./Dockerfile.canvas
|
||||
push: true
|
||||
tags: |
|
||||
sanjibdevnath/mcp-excalidraw-local-canvas:latest
|
||||
sanjibdevnath/mcp-excalidraw-local-canvas:v${{ needs.release.outputs.version }}
|
||||
celstnblacc/excalidraw-mcp-sentinel-canvas:latest
|
||||
celstnblacc/excalidraw-mcp-sentinel-canvas:v${{ needs.release.outputs.version }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# AGENTS.md
|
||||
|
||||
Agent instructions for mcp-excalidraw-local. Read this before starting any task.
|
||||
Agent instructions for excalidraw-mcp-sentinel. Read this before starting any task.
|
||||
|
||||
## What This Is
|
||||
|
||||
A fully local, self-hosted Excalidraw MCP server. Single Node.js/TypeScript process
|
||||
A hardened, self-hosted Excalidraw MCP server (`excalidraw-mcp-sentinel`). Single Node.js/TypeScript process
|
||||
running an MCP server (stdio, 32 tools), an Express+WebSocket canvas server, and
|
||||
SQLite persistence with multi-tenancy.
|
||||
SQLite persistence with multi-tenancy. Forked from [sanjibdevnathlabs/mcp-excalidraw-local](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local).
|
||||
|
||||
## Commands
|
||||
|
||||
@@ -100,7 +100,7 @@ All middleware lives here — do not duplicate in routes:
|
||||
|
||||
## Before `npm publish`
|
||||
|
||||
- [ ] Bump `version` in `package.json` (current: `1.6.2`, next: `1.6.3`)
|
||||
- [ ] Bump `version` in `package.json` (current: `1.0.0`)
|
||||
- [ ] `npm test` → 369/369
|
||||
- [ ] `npm run build` → zero errors
|
||||
- [ ] `shipguard scan .` → 0 CRITICAL
|
||||
|
||||
@@ -5,6 +5,20 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.0.0] - 2026-03-29
|
||||
|
||||
### Changed
|
||||
- Renamed project from `@sanjibdevnath/mcp-excalidraw-local` to `excalidraw-mcp-sentinel`
|
||||
- New npm package name: `excalidraw-mcp-sentinel` (unscoped)
|
||||
- GitHub repo: `celstnblacc/excalidraw-mcp-sentinel`
|
||||
- Docker images: `celstnblacc/excalidraw-mcp-sentinel` and `celstnblacc/excalidraw-mcp-sentinel-canvas`
|
||||
- CLI binary renamed: `excalidraw-mcp-sentinel`
|
||||
- Version reset to 1.0.0 for independent release track
|
||||
- Added "Why this fork?" section to README with full attribution
|
||||
|
||||
### Removed
|
||||
- Superseded planning docs (PLAN.md, PLAN_v2.md, REVIEW.md, HANDOFF.md)
|
||||
|
||||
## [1.6.3] - 2026-03-29
|
||||
|
||||
### Security
|
||||
|
||||
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## What This Is
|
||||
|
||||
A fully local, self-hosted Excalidraw MCP server. Single Node.js process that runs an MCP server (stdio, 32 tools), an embedded Express+WebSocket canvas server, and SQLite persistence with multi-tenancy. Forked from [yctimlin/mcp_excalidraw](https://github.com/yctimlin/mcp_excalidraw).
|
||||
A hardened, self-hosted Excalidraw MCP server (`excalidraw-mcp-sentinel`). Single Node.js process that runs an MCP server (stdio, 32 tools), an embedded Express+WebSocket canvas server, and SQLite persistence with multi-tenancy. Forked from [sanjibdevnathlabs/mcp-excalidraw-local](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local) (itself from [yctimlin/mcp_excalidraw](https://github.com/yctimlin/mcp_excalidraw)).
|
||||
|
||||
## Build & Development Commands
|
||||
|
||||
@@ -38,7 +38,7 @@ node dist/server.js
|
||||
curl http://localhost:3000/health
|
||||
```
|
||||
|
||||
There are no unit tests. Validation is done via type checking (`pnpm run type-check`) and build verification. The CI runs `type-check` then `build` across Node 18/20/22.
|
||||
369 tests across unit, API, WebSocket, and regression suites. Run `npm test` or `pnpm test`. CI runs `type-check` then `build` then `test` across Node 18/20/22.
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -116,7 +116,7 @@ Two Dockerfiles: `Dockerfile` (MCP server only), `Dockerfile.canvas` (canvas wit
|
||||
- Docker: non-root user, resource limits, hardened `.dockerignore`
|
||||
|
||||
### Before running `npm publish`
|
||||
- [ ] Bump `version` in `package.json` to match `CHANGELOG.md` entry (currently `1.6.2` — next is `1.6.3`)
|
||||
- [ ] Bump `version` in `package.json` to match `CHANGELOG.md` entry (currently `1.0.0`)
|
||||
- [ ] Run `npm test` — must be 369/369
|
||||
- [ ] Run `npm run build` — must be zero TS errors
|
||||
- [ ] Run `shipguard scan .` — must be 0 CRITICAL findings
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# MCP Excalidraw Local
|
||||
# Excalidraw MCP Sentinel
|
||||
|
||||
[](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/ci.yml)
|
||||
[](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/release.yml)
|
||||
[](https://github.com/celstnblacc/excalidraw-mcp-sentinel/actions/workflows/ci.yml)
|
||||
[](https://github.com/celstnblacc/excalidraw-mcp-sentinel/actions/workflows/release.yml)
|
||||
[](LICENSE)
|
||||
|
||||
A fully local, self-hosted Excalidraw MCP server with **SQLite persistence**, **multi-tenancy**, and **auto-sync** — designed to run entirely on your machine without depending on `excalidraw.com`.
|
||||
A **hardened**, fully local, self-hosted Excalidraw MCP server with **SQLite persistence**, **multi-tenancy**, **auto-sync**, and **production-grade security** — designed to run entirely on your machine without depending on `excalidraw.com`.
|
||||
|
||||
Run a live Excalidraw canvas and control it from any AI agent. This repo provides:
|
||||
|
||||
@@ -13,10 +13,23 @@ Run a live Excalidraw canvas and control it from any AI agent. This repo provide
|
||||
- **Live Canvas**: Real-time Excalidraw UI synced via WebSocket
|
||||
- **SQLite Persistence**: Elements survive restarts, with versioning and search
|
||||
- **Multi-Tenancy**: Isolated canvases per workspace, auto-detected
|
||||
- **Security Hardened**: Helmet, rate limiting, API key auth, prototype pollution guard, WS challenge-response
|
||||
- **369 Tests**: Full test coverage across unit, API, WebSocket, and regression tests
|
||||
|
||||
> **Fork notice:** This project is forked from [yctimlin/mcp_excalidraw](https://github.com/yctimlin/mcp_excalidraw) and extends it with persistence, multi-workspace support, and numerous UX improvements. Full credit to the original author for the excellent foundation. See [What Changed From Upstream](#what-changed-from-upstream) for details.
|
||||
## Why this fork?
|
||||
|
||||
Keywords: Excalidraw MCP server, AI diagramming, local Excalidraw, self-hosted, SQLite persistence, multi-tenant, Mermaid to Excalidraw.
|
||||
Forked from [celstnblacc/excalidraw-mcp-sentinel](https://github.com/celstnblacc/excalidraw-mcp-sentinel) (itself a fork of [yctimlin/mcp_excalidraw](https://github.com/yctimlin/mcp_excalidraw)) with production hardening:
|
||||
|
||||
- **369 tests** (upstream has none) — unit, API, WebSocket, and regression
|
||||
- **Security middleware** (`src/security.ts`): helmet, CORS allowlist, timing-safe API key auth, prototype pollution guard, input sanitization
|
||||
- **3-tier rate limiting**: general, destructive, and write-burst ceilings
|
||||
- **WebSocket challenge-response authentication**
|
||||
- **Docker hardening**: non-root user, resource limits, hardened `.dockerignore`
|
||||
- **Full gauntlet security audit pass**
|
||||
|
||||
Full credit to [@sanjibdevnathlabs](https://github.com/sanjibdevnathlabs) and [@yctimlin](https://github.com/yctimlin) for the excellent foundation. See [What Changed From Upstream](#what-changed-from-upstream) for the full diff.
|
||||
|
||||
Keywords: Excalidraw MCP server, AI diagramming, local Excalidraw, self-hosted, SQLite persistence, multi-tenant, Mermaid to Excalidraw, security hardened.
|
||||
|
||||
## Screenshots
|
||||
|
||||
@@ -87,14 +100,14 @@ Install "Desktop development with C++" from [Visual Studio Build Tools](https://
|
||||
The setup wizard checks your environment, optionally installs the agent skill, and configures MCP clients — all interactively. Every step is skippable.
|
||||
|
||||
```bash
|
||||
npx @sanjibdevnath/mcp-excalidraw-local setup
|
||||
npx excalidraw-mcp-sentinel setup
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Example session</summary>
|
||||
|
||||
```
|
||||
$ npx @sanjibdevnath/mcp-excalidraw-local setup
|
||||
$ npx excalidraw-mcp-sentinel setup
|
||||
|
||||
Excalidraw MCP — Setup
|
||||
|
||||
@@ -136,8 +149,8 @@ $ npx @sanjibdevnath/mcp-excalidraw-local setup
|
||||
### Path B: From Source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/sanjibdevnathlabs/mcp-excalidraw-local.git
|
||||
cd mcp-excalidraw-local
|
||||
git clone https://github.com/celstnblacc/excalidraw-mcp-sentinel.git
|
||||
cd excalidraw-mcp-sentinel
|
||||
|
||||
npm install
|
||||
npm run build
|
||||
@@ -156,7 +169,7 @@ Open `http://localhost:3000` in your browser.
|
||||
|
||||
Canvas server:
|
||||
```bash
|
||||
docker run -d -p 3000:3000 --name mcp-excalidraw-canvas sanjibdevnath/mcp-excalidraw-local-canvas:latest
|
||||
docker run -d -p 3000:3000 --name mcp-excalidraw-canvas celstnblacc/excalidraw-mcp-sentinel-canvas:latest
|
||||
```
|
||||
|
||||
MCP server (stdio) is typically launched by your MCP client:
|
||||
@@ -168,7 +181,7 @@ MCP server (stdio) is typically launched by your MCP client:
|
||||
"args": [
|
||||
"run", "-i", "--rm",
|
||||
"-e", "CANVAS_PORT=3000",
|
||||
"sanjibdevnath/mcp-excalidraw-local:latest"
|
||||
"celstnblacc/excalidraw-mcp-sentinel:latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -190,7 +203,7 @@ Add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per-project):
|
||||
"mcpServers": {
|
||||
"excalidraw-canvas": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@sanjibdevnath/mcp-excalidraw-local"],
|
||||
"args": ["-y", "excalidraw-mcp-sentinel"],
|
||||
"env": {
|
||||
"CANVAS_PORT": "3000"
|
||||
}
|
||||
@@ -224,7 +237,7 @@ Add to `claude_desktop_config.json`:
|
||||
"mcpServers": {
|
||||
"excalidraw-canvas": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@sanjibdevnath/mcp-excalidraw-local"],
|
||||
"args": ["-y", "excalidraw-mcp-sentinel"],
|
||||
"env": {
|
||||
"CANVAS_PORT": "3000"
|
||||
}
|
||||
@@ -238,7 +251,7 @@ Add to `claude_desktop_config.json`:
|
||||
```bash
|
||||
claude mcp add excalidraw-canvas --scope user \
|
||||
-e CANVAS_PORT=3000 \
|
||||
-- npx -y @sanjibdevnath/mcp-excalidraw-local
|
||||
-- npx -y excalidraw-mcp-sentinel
|
||||
```
|
||||
|
||||
### Codex CLI
|
||||
@@ -250,7 +263,7 @@ Add to `~/.codex/mcp.json`:
|
||||
"mcpServers": {
|
||||
"excalidraw-canvas": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@sanjibdevnath/mcp-excalidraw-local"],
|
||||
"args": ["-y", "excalidraw-mcp-sentinel"],
|
||||
"env": {
|
||||
"CANVAS_PORT": "3000"
|
||||
}
|
||||
@@ -288,14 +301,14 @@ Already installed a previous version? The interactive update wizard is the easie
|
||||
### Interactive Update (recommended)
|
||||
|
||||
```bash
|
||||
npx @sanjibdevnath/mcp-excalidraw-local@latest update
|
||||
npx excalidraw-mcp-sentinel@latest update
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Example session</summary>
|
||||
|
||||
```
|
||||
$ npx @sanjibdevnath/mcp-excalidraw-local@latest update
|
||||
$ npx excalidraw-mcp-sentinel@latest update
|
||||
|
||||
Excalidraw MCP — Update v1.2.0
|
||||
|
||||
@@ -333,7 +346,7 @@ If you prefer to update manually, follow the steps for your installation method,
|
||||
|
||||
#### npx users
|
||||
|
||||
If your MCP config uses `npx -y @sanjibdevnath/mcp-excalidraw-local`, npx caches the package locally and won't automatically fetch new versions.
|
||||
If your MCP config uses `npx -y excalidraw-mcp-sentinel`, npx caches the package locally and won't automatically fetch new versions.
|
||||
|
||||
**Option A — Clear the cache (one-time):**
|
||||
```bash
|
||||
@@ -349,7 +362,7 @@ Update the `args` in your MCP config to include `@latest`:
|
||||
"mcpServers": {
|
||||
"excalidraw-canvas": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@sanjibdevnath/mcp-excalidraw-local@latest"],
|
||||
"args": ["-y", "excalidraw-mcp-sentinel@latest"],
|
||||
"env": { "CANVAS_PORT": "3000" }
|
||||
}
|
||||
}
|
||||
@@ -370,8 +383,8 @@ npm run build
|
||||
#### Docker users
|
||||
|
||||
```bash
|
||||
docker pull sanjibdevnath/mcp-excalidraw-local:latest
|
||||
docker pull sanjibdevnath/mcp-excalidraw-local-canvas:latest
|
||||
docker pull celstnblacc/excalidraw-mcp-sentinel:latest
|
||||
docker pull celstnblacc/excalidraw-mcp-sentinel-canvas:latest
|
||||
```
|
||||
|
||||
Then recreate your containers (`docker compose up -d` or `docker run` again).
|
||||
@@ -391,7 +404,7 @@ cp -R skills/excalidraw-skill ~/.claude/skills/excalidraw-skill
|
||||
curl -s http://localhost:3000/health
|
||||
|
||||
# Or check the installed package version
|
||||
npx @sanjibdevnath/mcp-excalidraw-local --version
|
||||
npx excalidraw-mcp-sentinel --version
|
||||
```
|
||||
|
||||
## How We Differ from the Official Excalidraw MCP
|
||||
@@ -503,7 +516,7 @@ This repo includes a skill at `skills/excalidraw-skill/` that provides:
|
||||
The easiest way to install the skill:
|
||||
|
||||
```bash
|
||||
npx @sanjibdevnath/mcp-excalidraw-local setup
|
||||
npx excalidraw-mcp-sentinel setup
|
||||
```
|
||||
|
||||
The wizard detects your installed agents and lets you choose which ones get the skill.
|
||||
@@ -589,7 +602,7 @@ This is the most common installation issue. `better-sqlite3` is a native Node.js
|
||||
```
|
||||
3. Or run the setup wizard which handles this automatically:
|
||||
```bash
|
||||
npx @sanjibdevnath/mcp-excalidraw-local setup
|
||||
npx excalidraw-mcp-sentinel setup
|
||||
```
|
||||
|
||||
### EADDRINUSE (port already in use)
|
||||
@@ -619,7 +632,7 @@ node dist/index.js # restart
|
||||
|
||||
### NVM / path issues with npx
|
||||
|
||||
**Symptom:** `npx @sanjibdevnath/mcp-excalidraw-local` hangs or uses the wrong Node version.
|
||||
**Symptom:** `npx excalidraw-mcp-sentinel` hangs or uses the wrong Node version.
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
@@ -639,7 +652,7 @@ Then use the full path in your MCP config:
|
||||
"mcpServers": {
|
||||
"excalidraw-canvas": {
|
||||
"command": "/Users/you/.nvm/versions/node/v22.12.0/bin/npx",
|
||||
"args": ["-y", "@sanjibdevnath/mcp-excalidraw-local"],
|
||||
"args": ["-y", "excalidraw-mcp-sentinel"],
|
||||
"env": { "CANVAS_PORT": "3000" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"mcpServers": {
|
||||
"excalidraw-canvas": {
|
||||
"command": "node",
|
||||
"args": ["/absolute/path/to/mcp-excalidraw-local/dist/index.js"],
|
||||
"args": ["/absolute/path/to/excalidraw-mcp-sentinel/dist/index.js"],
|
||||
"env": {
|
||||
"CANVAS_PORT": "3000"
|
||||
}
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.canvas
|
||||
image: sanjibdevnath/mcp-excalidraw-local-canvas:latest
|
||||
image: celstnblacc/excalidraw-mcp-sentinel-canvas:latest
|
||||
container_name: mcp-excalidraw-canvas
|
||||
ports:
|
||||
- "3000:3000"
|
||||
@@ -51,7 +51,7 @@ services:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: sanjibdevnath/mcp-excalidraw-local:latest
|
||||
image: celstnblacc/excalidraw-mcp-sentinel:latest
|
||||
container_name: mcp-excalidraw-mcp
|
||||
stdin_open: true
|
||||
tty: true
|
||||
|
||||
Generated
+25
-9
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@sanjibdevnath/mcp-excalidraw-local",
|
||||
"version": "1.6.2",
|
||||
"name": "excalidraw-mcp-sentinel",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@sanjibdevnath/mcp-excalidraw-local",
|
||||
"version": "1.6.2",
|
||||
"name": "excalidraw-mcp-sentinel",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@excalidraw/excalidraw": "^0.18.0",
|
||||
@@ -28,7 +28,7 @@
|
||||
"zod-to-json-schema": "^3.22.3"
|
||||
},
|
||||
"bin": {
|
||||
"mcp-excalidraw-local": "dist/index.js"
|
||||
"excalidraw-mcp-sentinel": "dist/index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.58.2",
|
||||
@@ -119,6 +119,7 @@
|
||||
"integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
@@ -3212,7 +3213,7 @@
|
||||
"version": "15.7.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
|
||||
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/qs": {
|
||||
@@ -3233,8 +3234,9 @@
|
||||
"version": "18.3.23",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz",
|
||||
"integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^3.0.2"
|
||||
@@ -3244,8 +3246,9 @@
|
||||
"version": "18.3.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
|
||||
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@types/react": "^18.0.0"
|
||||
}
|
||||
@@ -3835,6 +3838,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001726",
|
||||
"electron-to-chromium": "^1.5.173",
|
||||
@@ -3979,6 +3983,7 @@
|
||||
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.1.2.tgz",
|
||||
"integrity": "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@chevrotain/cst-dts-gen": "11.1.2",
|
||||
"@chevrotain/gast": "11.1.2",
|
||||
@@ -4327,7 +4332,7 @@
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cytoscape": {
|
||||
@@ -4335,6 +4340,7 @@
|
||||
"resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz",
|
||||
"integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
@@ -4735,6 +4741,7 @@
|
||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
@@ -5727,6 +5734,7 @@
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.7.tgz",
|
||||
"integrity": "sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
}
|
||||
@@ -5973,6 +5981,7 @@
|
||||
"resolved": "https://registry.npmjs.org/jotai/-/jotai-2.11.0.tgz",
|
||||
"integrity": "sha512-zKfoBBD1uDw3rljwHkt0fWuja1B76R7CjznuBO+mSX6jpsO1EBeWNRKpeaQho9yPI/pvCv4recGfgOXGxwPZvQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
},
|
||||
@@ -7527,6 +7536,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
@@ -7539,6 +7549,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.2"
|
||||
@@ -8401,6 +8412,7 @@
|
||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -8700,6 +8712,7 @@
|
||||
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.4.4",
|
||||
@@ -8790,6 +8803,7 @@
|
||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -8803,6 +8817,7 @@
|
||||
"integrity": "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vitest/expect": "4.1.0",
|
||||
"@vitest/mocker": "4.1.0",
|
||||
@@ -9126,6 +9141,7 @@
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.5.tgz",
|
||||
"integrity": "sha512-ualArhgJydGAKkSdtxQyu6RXFW8nHFKWaw20jey8UFXU9uzkHYqWXJ93Iz+hUVVJb37VpF4LCCsOOfj6xaCVRQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
|
||||
+13
-8
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "@sanjibdevnath/mcp-excalidraw-local",
|
||||
"version": "1.6.2",
|
||||
"description": "Fully local MCP server for Excalidraw with SQLite persistence, multi-tenancy, auto-sync, real-time canvas, and 32 tools",
|
||||
"name": "excalidraw-mcp-sentinel",
|
||||
"version": "1.0.0",
|
||||
"description": "Hardened, self-hosted Excalidraw MCP server with SQLite persistence, multi-tenancy, auto-sync, security middleware, and 369 tests",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"mcp-excalidraw-local": "dist/index.js"
|
||||
"excalidraw-mcp-sentinel": "dist/index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "npm run build:server && node dist/index.js",
|
||||
@@ -84,9 +84,14 @@
|
||||
"local"
|
||||
],
|
||||
"author": {
|
||||
"name": "sanjibdevnathlabs"
|
||||
"name": "celstnblacc",
|
||||
"url": "https://github.com/celstnblacc"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "sanjibdevnathlabs",
|
||||
"url": "https://github.com/sanjibdevnathlabs"
|
||||
},
|
||||
{
|
||||
"name": "yctimlin",
|
||||
"email": "c22647809@gmail.com",
|
||||
@@ -96,11 +101,11 @@
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sanjibdevnathlabs/mcp-excalidraw-local.git"
|
||||
"url": "https://github.com/celstnblacc/excalidraw-mcp-sentinel.git"
|
||||
},
|
||||
"homepage": "https://github.com/sanjibdevnathlabs/mcp-excalidraw-local#readme",
|
||||
"homepage": "https://github.com/celstnblacc/excalidraw-mcp-sentinel#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/issues"
|
||||
"url": "https://github.com/celstnblacc/excalidraw-mcp-sentinel/issues"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
|
||||
@@ -11,7 +11,7 @@ Run these checks **in order**:
|
||||
|
||||
1. **MCP Server** (best): If tools like `batch_create_elements` are available → use MCP mode.
|
||||
2. **REST API** (fallback): `curl -s http://localhost:3000/health` returns `{"status":"ok"}` → use REST API mode.
|
||||
3. **Nothing works**: Guide user to install (clone `sanjibdevnathlabs/mcp-excalidraw-local`, build, configure MCP).
|
||||
3. **Nothing works**: Guide user to install (clone `celstnblacc/excalidraw-mcp-sentinel`, build, configure MCP).
|
||||
|
||||
See `references/cheatsheet.md` for the full MCP-vs-REST mapping and REST API gotchas.
|
||||
|
||||
|
||||
+1
-1
@@ -2923,7 +2923,7 @@ if (isMainModule()) {
|
||||
try {
|
||||
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
||||
if (arg === '--help' || arg === '-h') {
|
||||
process.stdout.write(`${pkg.name} v${pkg.version}\n\nUsage:\n mcp-excalidraw-local Start MCP server (stdio transport)\n mcp-excalidraw-local setup Interactive setup wizard\n mcp-excalidraw-local update Update agent skills and MCP config\n mcp-excalidraw-local --help Show this help\n mcp-excalidraw-local --version Show version\n`);
|
||||
process.stdout.write(`${pkg.name} v${pkg.version}\n\nUsage:\n excalidraw-mcp-sentinel Start MCP server (stdio transport)\n excalidraw-mcp-sentinel setup Interactive setup wizard\n excalidraw-mcp-sentinel update Update agent skills and MCP config\n excalidraw-mcp-sentinel --help Show this help\n excalidraw-mcp-sentinel --version Show version\n`);
|
||||
} else {
|
||||
process.stdout.write(`${pkg.version}\n`);
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Security middleware for mcp-excalidraw-local.
|
||||
* Security middleware for excalidraw-mcp-sentinel.
|
||||
*
|
||||
* All env vars are read at request/connection time (not at module init)
|
||||
* so that tests can mutate process.env between cases.
|
||||
|
||||
+6
-6
@@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Interactive setup wizard for mcp-excalidraw-local.
|
||||
* Runs via: npx @sanjibdevnath/mcp-excalidraw-local setup
|
||||
* Interactive setup wizard for excalidraw-mcp-sentinel.
|
||||
* Runs via: npx excalidraw-mcp-sentinel setup
|
||||
*
|
||||
* Uses only Node.js built-ins — no third-party dependencies.
|
||||
* Every phase is optional and skippable.
|
||||
@@ -92,7 +92,7 @@ function getAgents(): AgentDef[] {
|
||||
},
|
||||
mcpConfigType: 'cli-command',
|
||||
mcpCliRemove: 'claude mcp remove excalidraw-canvas --scope user',
|
||||
mcpCliCommand: 'claude mcp add excalidraw-canvas --scope user -e CANVAS_PORT=3000 -- npx -y @sanjibdevnath/mcp-excalidraw-local@latest',
|
||||
mcpCliCommand: 'claude mcp add excalidraw-canvas --scope user -e CANVAS_PORT=3000 -- npx -y excalidraw-mcp-sentinel@latest',
|
||||
instructionConfig: {
|
||||
global: path.join(home, '.claude', 'CLAUDE.md'),
|
||||
local: path.join(process.cwd(), 'CLAUDE.md'),
|
||||
@@ -493,7 +493,7 @@ async function phaseMcpConfig(rl: readline.Interface): Promise<void> {
|
||||
function mergeJsonConfig(configPath: string): void {
|
||||
const mcpEntry = {
|
||||
command: 'npx',
|
||||
args: ['-y', '@sanjibdevnath/mcp-excalidraw-local@latest'],
|
||||
args: ['-y', 'excalidraw-mcp-sentinel@latest'],
|
||||
env: { CANVAS_PORT: '3000' },
|
||||
};
|
||||
|
||||
@@ -549,7 +549,7 @@ function printManualConfig(): void {
|
||||
"mcpServers": {
|
||||
"excalidraw-canvas": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@sanjibdevnath/mcp-excalidraw-local@latest"],
|
||||
"args": ["-y", "excalidraw-mcp-sentinel@latest"],
|
||||
"env": { "CANVAS_PORT": "3000" }
|
||||
}
|
||||
}
|
||||
@@ -619,7 +619,7 @@ export async function runUpdate(): Promise<void> {
|
||||
const skillSource = path.resolve(__dirname, '..', 'skills', 'excalidraw-skill');
|
||||
if (!fs.existsSync(skillSource)) {
|
||||
fail(`Skill source not found at ${skillSource}`);
|
||||
fail('This can happen with corrupted installs. Try: npx @sanjibdevnath/mcp-excalidraw-local@latest setup');
|
||||
fail('This can happen with corrupted installs. Try: npx excalidraw-mcp-sentinel@latest setup');
|
||||
rl.close();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user