From 9fb8ce34ec836372b6a68f5429febbd4d0ec8672 Mon Sep 17 00:00:00 2001 From: newblacc Date: Sun, 29 Mar 2026 20:00:27 +0200 Subject: [PATCH] chore: rename project to excalidraw-mcp-sentinel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .github/workflows/docker.yml | 4 +- .github/workflows/npm-publish.yml | 2 +- .github/workflows/release.yml | 16 ++++---- AGENTS.md | 8 ++-- CHANGELOG.md | 14 +++++++ CLAUDE.md | 6 +-- README.md | 67 ++++++++++++++++++------------- claude_desktop_config.json | 2 +- docker-compose.yml | 4 +- package-lock.json | 34 +++++++++++----- package.json | 21 ++++++---- skills/excalidraw-skill/SKILL.md | 2 +- src/index.ts | 2 +- src/security.ts | 2 +- src/setup.ts | 12 +++--- 15 files changed, 122 insertions(+), 74 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a2a6eb0..456a776 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -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: diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index d652358..e9b1e1b 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -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" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 08021cb..3290b9a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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 diff --git a/AGENTS.md b/AGENTS.md index 76b49d4..a6c019c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f26b67..905f6f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/CLAUDE.md b/CLAUDE.md index d185ae7..301b50e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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 diff --git a/README.md b/README.md index d9d6cdf..738bbd4 100644 --- a/README.md +++ b/README.md @@ -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 ```
Example session ``` -$ 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 ```
Example session ``` -$ 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" } } } diff --git a/claude_desktop_config.json b/claude_desktop_config.json index aa7766b..f7cc7ce 100644 --- a/claude_desktop_config.json +++ b/claude_desktop_config.json @@ -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" } diff --git a/docker-compose.yml b/docker-compose.yml index d9e4929..f607a5a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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 diff --git a/package-lock.json b/package-lock.json index bfe742a..3836788 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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" } diff --git a/package.json b/package.json index c8e0f95..ea40517 100644 --- a/package.json +++ b/package.json @@ -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": [ diff --git a/skills/excalidraw-skill/SKILL.md b/skills/excalidraw-skill/SKILL.md index 93fb44c..6096581 100644 --- a/skills/excalidraw-skill/SKILL.md +++ b/skills/excalidraw-skill/SKILL.md @@ -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. diff --git a/src/index.ts b/src/index.ts index c915136..0a1ac27 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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`); } diff --git a/src/security.ts b/src/security.ts index 64b8f4d..cb9ad08 100644 --- a/src/security.ts +++ b/src/security.ts @@ -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. diff --git a/src/setup.ts b/src/setup.ts index 6d4c2c3..f1e2bca 100644 --- a/src/setup.ts +++ b/src/setup.ts @@ -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 { 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 { 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; }