@atlisp/mcp 1.0.27 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/atlisp-mcp.js +155 -227
- package/src/cli.js +0 -59
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlisp/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "MCP Server for @lisp on CAD",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"atlisp-mcp": "./src/
|
|
7
|
+
"atlisp-mcp": "./src/atlisp-mcp.js"
|
|
8
8
|
},
|
|
9
9
|
"main": "src/atlisp-mcp.js",
|
|
10
10
|
"exports": {
|
package/src/atlisp-mcp.js
CHANGED
|
@@ -1,10 +1,52 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { createRequire } from 'module';
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const { version } = require(path.join(__dirname, '..', 'package.json'));
|
|
8
|
+
|
|
9
|
+
if (process.argv[1]?.endsWith('atlisp-mcp.js')) {
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
for (let i = 0; i < args.length; i++) {
|
|
12
|
+
if (args[i] === '--version' || args[i] === '-v') {
|
|
13
|
+
console.log(`atlisp-mcp v${version}`);
|
|
14
|
+
process.exit(0);
|
|
15
|
+
} else if (args[i] === '--help' || args[i] === '-h') {
|
|
16
|
+
console.log(`
|
|
17
|
+
@lisp MCP Server v${version}
|
|
18
|
+
|
|
19
|
+
Usage: atlisp-mcp [options]
|
|
20
|
+
|
|
21
|
+
Options:
|
|
22
|
+
-v, --version Show version number
|
|
23
|
+
--transport <type> Transport type: http or stdio (default: http)
|
|
24
|
+
--port <port> HTTP port (default: 8110)
|
|
25
|
+
--host <host> HTTP host (default: 0.0.0.0)
|
|
26
|
+
--stdio Shorthand for --transport stdio
|
|
27
|
+
-h, --help Show this help message
|
|
28
|
+
|
|
29
|
+
Examples:
|
|
30
|
+
atlisp-mcp # Start HTTP server on port 8110
|
|
31
|
+
atlisp-mcp --port 3000 # Start HTTP server on port 3000
|
|
32
|
+
atlisp-mcp --stdio # Start in stdio mode for MCP clients
|
|
33
|
+
atlisp-mcp --transport stdio # Same as --stdio
|
|
34
|
+
`);
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
1
40
|
import express from 'express';
|
|
2
41
|
import rawBody from 'raw-body';
|
|
3
42
|
import iconv from 'iconv-lite';
|
|
4
43
|
import rateLimit from 'express-rate-limit';
|
|
44
|
+
import { randomUUID } from 'crypto';
|
|
5
45
|
const { decode: charsetDecode, encodingExists } = iconv;
|
|
6
46
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
7
47
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
48
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
49
|
+
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
8
50
|
import {
|
|
9
51
|
ListToolsRequestSchema,
|
|
10
52
|
CallToolRequestSchema,
|
|
@@ -24,8 +66,6 @@ import * as functionHandlers from './handlers/function-handlers.js';
|
|
|
24
66
|
import { listResources, readResource } from './handlers/resource-handlers.js';
|
|
25
67
|
import { listPrompts, getPrompt } from './handlers/prompt-handlers.js';
|
|
26
68
|
import * as subMgr from './subscription-manager.js';
|
|
27
|
-
import { SseSession, SSE_EVENTS, createSseResponseHandler, parseLastEventId } from './sse-session.js';
|
|
28
|
-
import { SseSessionManager } from './sse-session-manager.js';
|
|
29
69
|
import { createError, toMcpError } from './errors.js';
|
|
30
70
|
import config from './config.js';
|
|
31
71
|
|
|
@@ -41,10 +81,9 @@ const SERVER_INFO = {
|
|
|
41
81
|
serverInfo: { name: SERVER_NAME, version: SERVER_VERSION }
|
|
42
82
|
};
|
|
43
83
|
|
|
44
|
-
const { port, host, transport, apiKey,
|
|
84
|
+
const { port, host, transport, apiKey, rateLimitWindow, rateLimitMax } = config;
|
|
45
85
|
|
|
46
86
|
if (apiKey) log('API Key authentication enabled');
|
|
47
|
-
if (enableSse) log('SSE mode enabled');
|
|
48
87
|
|
|
49
88
|
const mcpLimiter = rateLimit({
|
|
50
89
|
windowMs: rateLimitWindow,
|
|
@@ -54,16 +93,6 @@ const mcpLimiter = rateLimit({
|
|
|
54
93
|
message: { error: '请求过于频繁,请稍后再试' }
|
|
55
94
|
});
|
|
56
95
|
|
|
57
|
-
const sseSessionManager = new SseSessionManager();
|
|
58
|
-
|
|
59
|
-
subMgr.setNotify((uri, data) => {
|
|
60
|
-
sseSessionManager.broadcast(SSE_EVENTS.MESSAGE, {
|
|
61
|
-
jsonrpc: '2.0',
|
|
62
|
-
method: 'notifications/resources/updated',
|
|
63
|
-
params: { uri, data }
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
96
|
export { CAD_PLATFORMS, FILE_EXTENSIONS, MOCK_PACKAGES } from './constants.js';
|
|
68
97
|
|
|
69
98
|
const TOOL_HANDLERS = {
|
|
@@ -371,9 +400,15 @@ export async function startServer() {
|
|
|
371
400
|
if (config.transport === 'stdio') {
|
|
372
401
|
await initCadConnection();
|
|
373
402
|
const mcpServer = createMcpServer();
|
|
374
|
-
const transport = new StdioServerTransport();
|
|
403
|
+
const transport = new StdioServerTransport();
|
|
375
404
|
await mcpServer.connect(transport);
|
|
376
405
|
console.error(`${SERVER_NAME} 运行在 stdio 模式`);
|
|
406
|
+
|
|
407
|
+
subMgr.setNotify((uri, data) => {
|
|
408
|
+
mcpServer.sendResourceUpdated({ uri }).catch(err => {
|
|
409
|
+
log(`Failed to send resource update: ${err.message}`);
|
|
410
|
+
});
|
|
411
|
+
});
|
|
377
412
|
} else {
|
|
378
413
|
const app = express();
|
|
379
414
|
|
|
@@ -396,7 +431,7 @@ const transport = new StdioServerTransport();
|
|
|
396
431
|
});
|
|
397
432
|
|
|
398
433
|
app.use((req, res, next) => {
|
|
399
|
-
log(`${req.method} ${req.path}
|
|
434
|
+
log(`${req.method} ${req.path}`);
|
|
400
435
|
next();
|
|
401
436
|
});
|
|
402
437
|
|
|
@@ -414,25 +449,6 @@ const transport = new StdioServerTransport();
|
|
|
414
449
|
res.json({ status: 'ok', cad: cad.connected ? 'connected' : 'disconnected' });
|
|
415
450
|
});
|
|
416
451
|
|
|
417
|
-
app.use((req, res, next) => {
|
|
418
|
-
const path = req.path;
|
|
419
|
-
if (path.startsWith('/%7B') || path.startsWith('/{"')) {
|
|
420
|
-
try {
|
|
421
|
-
const decoded = decodeURIComponent(path.slice(1));
|
|
422
|
-
if (decoded.startsWith('{"path":')) {
|
|
423
|
-
const data = JSON.parse(decoded);
|
|
424
|
-
const endpoint = data.path;
|
|
425
|
-
log(`Client sent SSE endpoint in URL path, extracting: ${endpoint}`);
|
|
426
|
-
req.url = endpoint + ((req._parsedUrl && req._parsedUrl.search) || '');
|
|
427
|
-
try { req.path = endpoint; } catch (_) { /* Express 5: req.path is read-only, req.url is sufficient */ }
|
|
428
|
-
}
|
|
429
|
-
} catch (e) {
|
|
430
|
-
log(`Failed to parse malformed path: ${e.message}`);
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
next();
|
|
434
|
-
});
|
|
435
|
-
|
|
436
452
|
if (config.enableCors) {
|
|
437
453
|
app.use((req, res, next) => {
|
|
438
454
|
res.setHeader('Access-Control-Allow-Origin', config.corsOrigin);
|
|
@@ -446,224 +462,136 @@ const transport = new StdioServerTransport();
|
|
|
446
462
|
});
|
|
447
463
|
}
|
|
448
464
|
|
|
449
|
-
createMcpServer();
|
|
450
|
-
|
|
451
|
-
function setupSseConnection(req, res) {
|
|
452
|
-
log(`SSE connect: ${req.method} ${req.path} - session: ${req.get('mcp-session-id') || 'new'}`);
|
|
453
|
-
const sessionId = req.get('mcp-session-id');
|
|
454
|
-
const lastEventId = parseLastEventId(req);
|
|
455
|
-
const clientId = sessionId || crypto.randomUUID();
|
|
456
|
-
|
|
457
|
-
res.setHeader('mcp-session-id', clientId);
|
|
458
|
-
|
|
459
|
-
let session;
|
|
460
|
-
if (sessionId && sseSessionManager.has(sessionId)) {
|
|
461
|
-
session = sseSessionManager.get(sessionId);
|
|
462
|
-
} else {
|
|
463
|
-
session = new SseSession(res, { clientId, resumeFromId: lastEventId });
|
|
464
|
-
sseSessionManager.add(clientId, session);
|
|
465
|
-
}
|
|
465
|
+
const mcpServer = createMcpServer();
|
|
466
466
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
467
|
+
const transport = new StreamableHTTPServerTransport({
|
|
468
|
+
sessionIdGenerator: () => randomUUID(),
|
|
469
|
+
});
|
|
470
470
|
|
|
471
|
-
|
|
471
|
+
await mcpServer.connect(transport);
|
|
472
|
+
log('MCP Server connected to StreamableHTTPServerTransport');
|
|
472
473
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
474
|
+
subMgr.setNotify((uri, data) => {
|
|
475
|
+
mcpServer.sendResourceUpdated({ uri }).catch(err => {
|
|
476
|
+
log(`Failed to send resource update: ${err.message}`);
|
|
476
477
|
});
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
if (enableSse) {
|
|
480
|
-
app.get('/sse', (req, res) => setupSseConnection(req, res));
|
|
481
|
-
app.get('/mcp/sse', (req, res) => setupSseConnection(req, res));
|
|
482
|
-
|
|
483
|
-
app.post('/mcp/message', mcpLimiter, async (req, res) => {
|
|
484
|
-
const sessionId = req.get('mcp-session-id') || '';
|
|
485
|
-
const accept = req.get('Accept') || '';
|
|
486
|
-
const wantsSse = accept.includes('text/event-stream');
|
|
487
|
-
log(`POST /mcp/message - session: ${sessionId || 'new'} - wantsSSE: ${wantsSse}`);
|
|
488
|
-
|
|
489
|
-
let session;
|
|
490
|
-
if (sessionId && sseSessionManager.has(sessionId)) {
|
|
491
|
-
session = sseSessionManager.get(sessionId);
|
|
492
|
-
} else if (wantsSse) {
|
|
493
|
-
const clientId = sessionId || crypto.randomUUID();
|
|
494
|
-
res.setHeader('mcp-session-id', clientId);
|
|
495
|
-
session = new SseSession(res, { clientId });
|
|
496
|
-
sseSessionManager.add(clientId, session);
|
|
497
|
-
log(`POST /mcp/message - created new session: ${clientId}`);
|
|
498
|
-
res.on('close', () => {
|
|
499
|
-
log(`POST SSE close: session ${clientId}`);
|
|
500
|
-
sseSessionManager.remove(clientId);
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
const body = req.body || {};
|
|
505
|
-
const { method, params, id } = body;
|
|
506
|
-
|
|
507
|
-
if (!id) {
|
|
508
|
-
if (session) res.status(204).end();
|
|
509
|
-
else res.status(202).end();
|
|
510
|
-
return;
|
|
511
|
-
}
|
|
478
|
+
});
|
|
512
479
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
}
|
|
520
|
-
res.status(204).end();
|
|
521
|
-
} else {
|
|
522
|
-
await dispatchMcpMethod(
|
|
523
|
-
(response) => {
|
|
524
|
-
res.setHeader('Content-Type', 'application/json');
|
|
525
|
-
res.status(200).json(response);
|
|
526
|
-
},
|
|
527
|
-
method, params, id
|
|
528
|
-
);
|
|
480
|
+
app.all('/mcp', mcpLimiter, async (req, res) => {
|
|
481
|
+
try {
|
|
482
|
+
await transport.handleRequest(req, res, req.body);
|
|
483
|
+
} catch (error) {
|
|
484
|
+
log(`Transport error: ${error.message}`);
|
|
485
|
+
if (!res.headersSent) {
|
|
486
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
529
487
|
}
|
|
530
|
-
}
|
|
531
|
-
}
|
|
488
|
+
}
|
|
489
|
+
});
|
|
532
490
|
|
|
533
|
-
app.
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
if (wantsSse) {
|
|
542
|
-
if (!enableSse) {
|
|
543
|
-
res.status(400).json({ error: 'SSE mode is disabled' });
|
|
544
|
-
return;
|
|
491
|
+
app.all('/mcp/:path', mcpLimiter, async (req, res) => {
|
|
492
|
+
try {
|
|
493
|
+
await transport.handleRequest(req, res, req.body);
|
|
494
|
+
} catch (error) {
|
|
495
|
+
log(`Transport error: ${error.message}`);
|
|
496
|
+
if (!res.headersSent) {
|
|
497
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
545
498
|
}
|
|
499
|
+
}
|
|
500
|
+
});
|
|
546
501
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
}
|
|
557
|
-
await handleMcpRequest(session, method, params, id);
|
|
558
|
-
res.status(204).end();
|
|
559
|
-
return;
|
|
502
|
+
const sseEndpoint = '/sse';
|
|
503
|
+
app.get(sseEndpoint, async (req, res) => {
|
|
504
|
+
const sseTransport = new SSEServerTransport(sseEndpoint, res);
|
|
505
|
+
try {
|
|
506
|
+
await mcpServer.connect(sseTransport);
|
|
507
|
+
await sseTransport.handleRequest(req, res);
|
|
508
|
+
} catch (error) {
|
|
509
|
+
log(`SSE transport error: ${error.message}`);
|
|
510
|
+
if (!res.headersSent) {
|
|
511
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
560
512
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
app.post(sseEndpoint, mcpLimiter, async (req, res) => {
|
|
516
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
517
|
+
const sseTransport = sessionId ? sseEndpoint + '?sessionId=' + sessionId : sseEndpoint;
|
|
518
|
+
try {
|
|
519
|
+
const transport = new SSEServerTransport(sseEndpoint, res);
|
|
520
|
+
await mcpServer.connect(transport);
|
|
521
|
+
await transport.handleRequest(req, res);
|
|
522
|
+
} catch (error) {
|
|
523
|
+
log(`SSE POST error: ${error.message}`);
|
|
524
|
+
if (!res.headersSent) {
|
|
525
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
567
526
|
}
|
|
568
|
-
await handleMcpRequest(session, method, params, id);
|
|
569
|
-
return;
|
|
570
527
|
}
|
|
571
|
-
|
|
572
|
-
res.setHeader('mcp-session-id', sessionId || crypto.randomUUID());
|
|
573
|
-
const { send } = createSseResponseHandler(res, wantsSse);
|
|
574
|
-
|
|
575
|
-
if (!id) return res.status(204).end();
|
|
576
|
-
|
|
577
|
-
await dispatchMcpMethod(
|
|
578
|
-
(response) => send(response, true),
|
|
579
|
-
method, params, id
|
|
580
|
-
);
|
|
581
528
|
});
|
|
582
529
|
|
|
583
|
-
app.get('/mcp', (req, res) => {
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
530
|
+
app.get('/mcp/sse', async (req, res) => {
|
|
531
|
+
const sseTransport = new SSEServerTransport('/mcp/sse', res);
|
|
532
|
+
try {
|
|
533
|
+
await mcpServer.connect(sseTransport);
|
|
534
|
+
await sseTransport.handleRequest(req, res);
|
|
535
|
+
} catch (error) {
|
|
536
|
+
log(`/mcp/sse transport error: ${error.message}`);
|
|
537
|
+
if (!res.headersSent) {
|
|
538
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
589
539
|
}
|
|
590
|
-
setupSseConnection(req, res);
|
|
591
|
-
return;
|
|
592
540
|
}
|
|
593
|
-
res.status(200).json({
|
|
594
|
-
name: SERVER_NAME,
|
|
595
|
-
version: SERVER_VERSION,
|
|
596
|
-
transport: 'streamable-http',
|
|
597
|
-
sseEndpoint: '/sse',
|
|
598
|
-
messageEndpoint: '/mcp/message'
|
|
599
|
-
});
|
|
600
541
|
});
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
if (wantsSse) {
|
|
611
|
-
if (!enableSse) {
|
|
612
|
-
res.status(400).json({ error: 'SSE mode is disabled' });
|
|
613
|
-
return;
|
|
542
|
+
app.post('/mcp/sse', mcpLimiter, async (req, res) => {
|
|
543
|
+
const sseTransport = new SSEServerTransport('/mcp/sse', res);
|
|
544
|
+
try {
|
|
545
|
+
await mcpServer.connect(sseTransport);
|
|
546
|
+
await sseTransport.handleRequest(req, res);
|
|
547
|
+
} catch (error) {
|
|
548
|
+
log(`/mcp/sse POST error: ${error.message}`);
|
|
549
|
+
if (!res.headersSent) {
|
|
550
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
614
551
|
}
|
|
552
|
+
}
|
|
553
|
+
});
|
|
615
554
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
res.status(204).end();
|
|
624
|
-
return;
|
|
625
|
-
}
|
|
626
|
-
await handleMcpRequest(session, method, params, id);
|
|
627
|
-
res.status(204).end();
|
|
628
|
-
return;
|
|
555
|
+
app.get('/mcp/stream', async (req, res) => {
|
|
556
|
+
try {
|
|
557
|
+
await transport.handleRequest(req, res, req.body);
|
|
558
|
+
} catch (error) {
|
|
559
|
+
log(`/mcp/stream error: ${error.message}`);
|
|
560
|
+
if (!res.headersSent) {
|
|
561
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
629
562
|
}
|
|
563
|
+
}
|
|
564
|
+
});
|
|
630
565
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
566
|
+
app.post('/message', mcpLimiter, async (req, res) => {
|
|
567
|
+
try {
|
|
568
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
569
|
+
const sseTransport = new SSEServerTransport('/message', res);
|
|
570
|
+
await mcpServer.connect(sseTransport);
|
|
571
|
+
await sseTransport.handleRequest(req, res);
|
|
572
|
+
} catch (error) {
|
|
573
|
+
log(`/message error: ${error.message}`);
|
|
574
|
+
if (!res.headersSent) {
|
|
575
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
636
576
|
}
|
|
637
|
-
await handleMcpRequest(session, method, params, id);
|
|
638
|
-
return;
|
|
639
577
|
}
|
|
578
|
+
});
|
|
640
579
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
if (!id) return res.status(204).end();
|
|
645
|
-
|
|
646
|
-
await dispatchMcpMethod(
|
|
647
|
-
(response) => send(response, true),
|
|
648
|
-
method, params, id
|
|
649
|
-
);
|
|
580
|
+
const httpServer = app.listen(config.port, config.host, async () => {
|
|
581
|
+
await initCadConnection();
|
|
582
|
+
console.error(`@lisp MCP Server 启动 - http://${config.host}:${config.port} - Streamable HTTP (SDK)`);
|
|
650
583
|
});
|
|
651
584
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
httpServer.close(() => process.exit(0));
|
|
663
|
-
setTimeout(() => process.exit(1), 5000);
|
|
664
|
-
}
|
|
665
|
-
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
666
|
-
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
585
|
+
async function shutdown(signal) {
|
|
586
|
+
console.error(`\n收到 ${signal},正在优雅关闭...`);
|
|
587
|
+
await transport.close();
|
|
588
|
+
await cad.disconnect();
|
|
589
|
+
closeLog();
|
|
590
|
+
httpServer.close(() => process.exit(0));
|
|
591
|
+
setTimeout(() => process.exit(1), 5000);
|
|
592
|
+
}
|
|
593
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
594
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
667
595
|
}
|
|
668
596
|
}
|
|
669
597
|
|
package/src/cli.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawn } from 'child_process';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import { SERVER_VERSION } from './constants.js';
|
|
6
|
-
|
|
7
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const serverPath = path.join(__dirname, 'atlisp-mcp.js');
|
|
9
|
-
|
|
10
|
-
const args = process.argv.slice(2);
|
|
11
|
-
const env = { ...process.env };
|
|
12
|
-
|
|
13
|
-
for (let i = 0; i < args.length; i++) {
|
|
14
|
-
if (args[i] === '--version' || args[i] === '-v') {
|
|
15
|
-
console.log(`atlisp-mcp v${SERVER_VERSION}`);
|
|
16
|
-
process.exit(0);
|
|
17
|
-
} else if (args[i] === '--transport' && args[i + 1]) {
|
|
18
|
-
env.TRANSPORT = args[i + 1];
|
|
19
|
-
i++;
|
|
20
|
-
} else if (args[i] === '--port' && args[i + 1]) {
|
|
21
|
-
env.PORT = args[i + 1];
|
|
22
|
-
i++;
|
|
23
|
-
} else if (args[i] === '--host' && args[i + 1]) {
|
|
24
|
-
env.HOST = args[i + 1];
|
|
25
|
-
i++;
|
|
26
|
-
} else if (args[i] === '--stdio') {
|
|
27
|
-
env.TRANSPORT = 'stdio';
|
|
28
|
-
} else if (args[i] === '--help' || args[i] === '-h') {
|
|
29
|
-
console.log(`
|
|
30
|
-
@lisp MCP Server v${SERVER_VERSION}
|
|
31
|
-
|
|
32
|
-
Usage: atlisp-mcp [options]
|
|
33
|
-
|
|
34
|
-
Options:
|
|
35
|
-
-v, --version Show version number
|
|
36
|
-
--transport <type> Transport type: http or stdio (default: http)
|
|
37
|
-
--port <port> HTTP port (default: 8110)
|
|
38
|
-
--host <host> HTTP host (default: 0.0.0.0)
|
|
39
|
-
--stdio Shorthand for --transport stdio
|
|
40
|
-
-h, --help Show this help message
|
|
41
|
-
|
|
42
|
-
Examples:
|
|
43
|
-
atlisp-mcp # Start HTTP server on port 8110
|
|
44
|
-
atlisp-mcp --port 3000 # Start HTTP server on port 3000
|
|
45
|
-
atlisp-mcp --stdio # Start in stdio mode for MCP clients
|
|
46
|
-
atlisp-mcp --transport stdio # Same as --stdio
|
|
47
|
-
`);
|
|
48
|
-
process.exit(0);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const child = spawn('node', [serverPath], {
|
|
53
|
-
env,
|
|
54
|
-
stdio: 'inherit'
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
child.on('exit', (code) => {
|
|
58
|
-
process.exit(code);
|
|
59
|
-
});
|