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:
newblacc
2026-03-29 20:00:27 +02:00
co-authored by Claude Opus 4.6
parent 8f9fe3fa08
commit 9fb8ce34ec
15 changed files with 122 additions and 74 deletions
+2 -2
View File
@@ -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:
+1 -1
View File
@@ -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"
+8 -8
View File
@@ -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
+4 -4
View File
@@ -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
+14
View File
@@ -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
+3 -3
View File
@@ -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
+40 -27
View File
@@ -1,10 +1,10 @@
# MCP Excalidraw Local
# Excalidraw MCP Sentinel
[![CI](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/ci.yml/badge.svg)](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/ci.yml)
[![Release & Publish](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/release.yml/badge.svg)](https://github.com/sanjibdevnathlabs/mcp-excalidraw-local/actions/workflows/release.yml)
[![CI](https://github.com/celstnblacc/excalidraw-mcp-sentinel/actions/workflows/ci.yml/badge.svg)](https://github.com/celstnblacc/excalidraw-mcp-sentinel/actions/workflows/ci.yml)
[![Release & Publish](https://github.com/celstnblacc/excalidraw-mcp-sentinel/actions/workflows/release.yml/badge.svg)](https://github.com/celstnblacc/excalidraw-mcp-sentinel/actions/workflows/release.yml)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](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" }
}
}
+1 -1
View File
@@ -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
View File
@@ -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
+25 -9
View File
@@ -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
View File
@@ -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": [
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}