support npx
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
# Logging level (debug, info, warn, error)
|
||||
LOG_LEVEL=info
|
||||
|
||||
# Enable debug mode (true/false)
|
||||
DEBUG=false
|
||||
|
||||
# Default theme (light/dark)
|
||||
DEFAULT_THEME=light
|
||||
@@ -1,3 +1,4 @@
|
||||
node_modules
|
||||
.env
|
||||
package-lock.json
|
||||
.cursor
|
||||
@@ -1,7 +1,29 @@
|
||||
# Excalidraw MCP Server: Powerful Drawing API for LLM Integration
|
||||
|
||||
> **📣 NEWS: We're excited to announce npx support!** You can now run Excalidraw MCP directly using `npx excalidraw-mcp` without installation. See Quick Start below for details.
|
||||
|
||||
A comprehensive Model Context Protocol (MCP) server that enables seamless interaction with Excalidraw diagrams and drawings. This server provides LLMs (Large Language Models) with the ability to create, modify, query, and manipulate Excalidraw drawings through a structured, developer-friendly API.
|
||||
|
||||
## Quick Start
|
||||
|
||||
You can run the Excalidraw MCP server directly using npx:
|
||||
|
||||
```bash
|
||||
npx excalidraw-mcp
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
Run with default options:
|
||||
```bash
|
||||
npx excalidraw-mcp
|
||||
```
|
||||
|
||||
Enable debug logging:
|
||||
```bash
|
||||
npx excalidraw-mcp --debug
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- **Full Excalidraw Element Control**: Create, update, delete, and query any Excalidraw element
|
||||
@@ -71,13 +93,24 @@ To use this server with the Claude Desktop application, add the following config
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"excalidraw": {
|
||||
"command": "node",
|
||||
"args": ["src/index.js"],
|
||||
"env": {
|
||||
"LOG_LEVEL": "info",
|
||||
"DEBUG": "false"
|
||||
}
|
||||
"mcp_excalidraw": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "excalidraw-mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Integration with Cursor
|
||||
|
||||
To use this server with the Cursor application, add the following configuration to the "mcpServers" section of your `.cursor/mcp.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"mcp_excalidraw": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "excalidraw-mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,3 +205,19 @@ Here are some practical examples of how to use the Excalidraw MCP server:
|
||||
## License
|
||||
|
||||
This Excalidraw MCP server is licensed under the MIT License. You are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.
|
||||
|
||||
## Development
|
||||
|
||||
Clone the repository and install dependencies:
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd excalidraw-mcp
|
||||
npm install
|
||||
```
|
||||
|
||||
Start the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
@@ -1,14 +1,8 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"excalidraw": {
|
||||
"command": "node",
|
||||
"args": [
|
||||
"src/index.js"
|
||||
],
|
||||
"env": {
|
||||
"LOG_LEVEL": "info",
|
||||
"DEBUG": "false"
|
||||
}
|
||||
"mcp_excalidraw": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "excalidraw-mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-2
@@ -14,7 +14,8 @@
|
||||
"lint": "eslint src/**/*.js",
|
||||
"build": "tsc",
|
||||
"docker:build": "docker build -t mcp/excalidraw .",
|
||||
"docker:run": "docker run -p 3000:3000 mcp/excalidraw"
|
||||
"docker:run": "docker run -p 3000:3000 mcp/excalidraw",
|
||||
"prepare": "node -e \"try { require('fs').chmodSync('./src/cli.js', '755') } catch(e) { console.log(e) }\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "latest",
|
||||
@@ -37,5 +38,16 @@
|
||||
"drawing"
|
||||
],
|
||||
"author": "",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"files": [
|
||||
"src/**/*",
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
]
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { parseArgs } from 'node:util';
|
||||
import { resolve } from 'path';
|
||||
import dotenv from 'dotenv';
|
||||
import logger from './utils/logger.js';
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
// Parse command line arguments
|
||||
const options = {
|
||||
port: {
|
||||
type: 'string',
|
||||
short: 'p',
|
||||
default: process.env.PORT || '3000'
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
short: 'h',
|
||||
default: process.env.HOST || 'localhost'
|
||||
},
|
||||
mode: {
|
||||
type: 'string',
|
||||
short: 'm',
|
||||
default: 'stdio'
|
||||
},
|
||||
debug: {
|
||||
type: 'boolean',
|
||||
short: 'd',
|
||||
default: false
|
||||
},
|
||||
help: {
|
||||
type: 'boolean',
|
||||
short: '?',
|
||||
default: false
|
||||
}
|
||||
};
|
||||
|
||||
const { values, positionals } = parseArgs({
|
||||
options,
|
||||
allowPositionals: true,
|
||||
strict: false
|
||||
});
|
||||
|
||||
// Show help if requested
|
||||
if (values.help) {
|
||||
showHelp();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Set debug mode if requested
|
||||
if (values.debug) {
|
||||
process.env.DEBUG = 'true';
|
||||
logger.level = 'debug';
|
||||
logger.debug('Debug mode enabled');
|
||||
}
|
||||
|
||||
// Set the mode for server transport
|
||||
process.env.MCP_TRANSPORT_MODE = values.mode;
|
||||
|
||||
// Set port and host
|
||||
process.env.PORT = values.port;
|
||||
process.env.HOST = values.host;
|
||||
|
||||
// Import and run server
|
||||
const { default: runServer } = await import('./index.js');
|
||||
await runServer();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error starting MCP server:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function showHelp() {
|
||||
console.log(`
|
||||
Excalidraw MCP Server
|
||||
|
||||
Usage:
|
||||
npx excalidraw-mcp [options]
|
||||
|
||||
Options:
|
||||
-p, --port <port> Port to run the server on (default: 3000)
|
||||
-h, --host <host> Host to bind the server to (default: localhost)
|
||||
-m, --mode <mode> Transport mode: 'stdio' or 'http' (default: stdio)
|
||||
-d, --debug Enable debug logging
|
||||
-?, --help Show this help message
|
||||
|
||||
Examples:
|
||||
npx excalidraw-mcp
|
||||
npx excalidraw-mcp --port 4000
|
||||
npx excalidraw-mcp --mode http
|
||||
npx excalidraw-mcp --debug
|
||||
`);
|
||||
}
|
||||
|
||||
main().catch(error => {
|
||||
console.error('Fatal error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
+47
-5
@@ -685,23 +685,65 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
return { tools };
|
||||
});
|
||||
|
||||
// Start server with STDIO transport
|
||||
// Start server with transport based on mode
|
||||
async function runServer() {
|
||||
try {
|
||||
const transport = new StdioServerTransport();
|
||||
logger.info('Starting Excalidraw MCP server...');
|
||||
|
||||
const transportMode = process.env.MCP_TRANSPORT_MODE || 'stdio';
|
||||
let transport;
|
||||
|
||||
if (transportMode === 'http') {
|
||||
const port = parseInt(process.env.PORT || '3000', 10);
|
||||
const host = process.env.HOST || 'localhost';
|
||||
|
||||
logger.info(`Starting HTTP server on ${host}:${port}`);
|
||||
// Here you would create an HTTP transport
|
||||
// This is a placeholder - actual HTTP transport implementation would need to be added
|
||||
transport = new StdioServerTransport(); // Fallback to stdio for now
|
||||
} else {
|
||||
// Default to stdio transport
|
||||
transport = new StdioServerTransport();
|
||||
}
|
||||
|
||||
// Add a debug message before connecting
|
||||
logger.debug('Connecting to transport...');
|
||||
|
||||
await server.connect(transport);
|
||||
logger.info('Excalidraw MCP server running on stdio');
|
||||
logger.info(`Excalidraw MCP server running on ${transportMode}`);
|
||||
|
||||
// Keep the process running
|
||||
process.stdin.resume();
|
||||
} catch (error) {
|
||||
logger.error('Error starting server:', error);
|
||||
console.error('Failed to start MCP server:', error.message, error.stack);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
runServer();
|
||||
// Add global error handlers
|
||||
process.on('uncaughtException', (error) => {
|
||||
logger.error('Uncaught exception:', error);
|
||||
console.error('UNCAUGHT EXCEPTION:', error.message, error.stack);
|
||||
// Don't exit immediately to allow logging
|
||||
setTimeout(() => process.exit(1), 1000);
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
logger.error('Unhandled promise rejection:', reason);
|
||||
console.error('UNHANDLED REJECTION:', reason);
|
||||
// Don't exit immediately to allow logging
|
||||
setTimeout(() => process.exit(1), 1000);
|
||||
});
|
||||
|
||||
// Only run the server directly if this file is executed directly (not imported)
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
runServer();
|
||||
}
|
||||
|
||||
// For testing and debugging purposes
|
||||
if (process.env.DEBUG === 'true') {
|
||||
logger.debug('Debug mode enabled');
|
||||
}
|
||||
|
||||
export default server;
|
||||
export default runServer;
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
||||
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
||||
|
||||
console.log('MCP SDK imports successful');
|
||||
console.log('Server:', Server);
|
||||
console.log('StdioServerTransport:', StdioServerTransport);
|
||||
|
||||
// Exit gracefully
|
||||
process.exit(0);
|
||||
Reference in New Issue
Block a user