@nekzus/mcp-server 1.1.6 ā 1.1.8
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/dist/index.js +116 -322
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
-
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import 'dotenv/config';
|
|
6
|
-
// Logger function that uses stderr
|
|
7
|
-
const log = (...args) =>
|
|
8
|
-
//
|
|
6
|
+
// Logger function that uses stderr - only for critical errors
|
|
7
|
+
const log = (...args) => {
|
|
8
|
+
// Filter out server status messages
|
|
9
|
+
const message = args[0];
|
|
10
|
+
if (typeof message === 'string' &&
|
|
11
|
+
(!message.startsWith('[Server]') || message.includes('error') || message.includes('Error'))) {
|
|
12
|
+
console.error(...args);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
// Define tools
|
|
9
16
|
const TOOLS = [
|
|
10
17
|
{
|
|
11
18
|
name: 'greeting',
|
|
@@ -144,48 +151,26 @@ const TOOLS = [
|
|
|
144
151
|
];
|
|
145
152
|
// Tool handlers
|
|
146
153
|
async function handleGreeting(args) {
|
|
147
|
-
const { name } = args;
|
|
148
154
|
return {
|
|
149
155
|
content: [
|
|
150
156
|
{
|
|
151
157
|
type: 'text',
|
|
152
|
-
text: `š Hello ${name}! Welcome to the MCP server!`,
|
|
158
|
+
text: `š Hello ${args.name}! Welcome to the MCP server!`,
|
|
153
159
|
},
|
|
154
160
|
],
|
|
155
161
|
isError: false,
|
|
156
162
|
};
|
|
157
163
|
}
|
|
158
164
|
async function handleCard() {
|
|
159
|
-
const suits =
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
'ā£': 'Clubs',
|
|
164
|
-
};
|
|
165
|
-
const values = {
|
|
166
|
-
A: 'Ace',
|
|
167
|
-
'2': 'Two',
|
|
168
|
-
'3': 'Three',
|
|
169
|
-
'4': 'Four',
|
|
170
|
-
'5': 'Five',
|
|
171
|
-
'6': 'Six',
|
|
172
|
-
'7': 'Seven',
|
|
173
|
-
'8': 'Eight',
|
|
174
|
-
'9': 'Nine',
|
|
175
|
-
'10': 'Ten',
|
|
176
|
-
J: 'Jack',
|
|
177
|
-
Q: 'Queen',
|
|
178
|
-
K: 'King',
|
|
179
|
-
};
|
|
180
|
-
const suitSymbols = Object.keys(suits);
|
|
181
|
-
const valueSymbols = Object.keys(values);
|
|
182
|
-
const suitSymbol = suitSymbols[Math.floor(Math.random() * suitSymbols.length)];
|
|
183
|
-
const valueSymbol = valueSymbols[Math.floor(Math.random() * valueSymbols.length)];
|
|
165
|
+
const suits = ['ā ļø', 'ā„ļø', 'ā£ļø', 'ā¦ļø'];
|
|
166
|
+
const values = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'];
|
|
167
|
+
const suit = suits[Math.floor(Math.random() * suits.length)];
|
|
168
|
+
const value = values[Math.floor(Math.random() * values.length)];
|
|
184
169
|
return {
|
|
185
170
|
content: [
|
|
186
171
|
{
|
|
187
172
|
type: 'text',
|
|
188
|
-
text: `š“
|
|
173
|
+
text: `š“ Drew card: ${value}${suit}`,
|
|
189
174
|
},
|
|
190
175
|
],
|
|
191
176
|
isError: false,
|
|
@@ -193,60 +178,34 @@ async function handleCard() {
|
|
|
193
178
|
}
|
|
194
179
|
async function handleDateTime(args) {
|
|
195
180
|
const { timeZone = 'UTC', locale = 'en-US' } = args;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
type: 'text',
|
|
212
|
-
text: `šļø Date: ${formattedDate}\nā° Time: ${formattedTime}\nš Timezone: ${timeZone}`,
|
|
213
|
-
},
|
|
214
|
-
],
|
|
215
|
-
isError: false,
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
catch (error) {
|
|
219
|
-
return {
|
|
220
|
-
content: [
|
|
221
|
-
{
|
|
222
|
-
type: 'text',
|
|
223
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
224
|
-
},
|
|
225
|
-
],
|
|
226
|
-
isError: true,
|
|
227
|
-
};
|
|
228
|
-
}
|
|
181
|
+
const date = new Date();
|
|
182
|
+
const formattedDate = new Intl.DateTimeFormat(locale, {
|
|
183
|
+
timeZone,
|
|
184
|
+
dateStyle: 'full',
|
|
185
|
+
timeStyle: 'long',
|
|
186
|
+
}).format(date);
|
|
187
|
+
return {
|
|
188
|
+
content: [
|
|
189
|
+
{
|
|
190
|
+
type: 'text',
|
|
191
|
+
text: `š Current date and time in ${timeZone}: ${formattedDate}`,
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
isError: false,
|
|
195
|
+
};
|
|
229
196
|
}
|
|
230
|
-
// New tool handlers
|
|
231
197
|
async function handleCalculator(args) {
|
|
232
|
-
const { expression, precision = 2 } = args;
|
|
233
198
|
try {
|
|
234
|
-
|
|
235
|
-
const sanitizedExpression = expression.replace(/[^0-9+\-*/().%\s]/g, '');
|
|
236
|
-
if (sanitizedExpression !== expression) {
|
|
237
|
-
throw new Error('Invalid characters in expression');
|
|
238
|
-
}
|
|
239
|
-
// Use Function constructor instead of eval for better security
|
|
199
|
+
const sanitizedExpression = args.expression.replace(/[^0-9+\-*/().%\s]/g, '');
|
|
240
200
|
const calculate = new Function(`return ${sanitizedExpression}`);
|
|
241
201
|
const result = calculate();
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
202
|
+
const precision = args.precision ?? 2;
|
|
203
|
+
const formattedResult = Number.isInteger(result) ? result : Number(result.toFixed(precision));
|
|
245
204
|
return {
|
|
246
205
|
content: [
|
|
247
206
|
{
|
|
248
207
|
type: 'text',
|
|
249
|
-
text:
|
|
208
|
+
text: `š¢ Result: ${formattedResult}`,
|
|
250
209
|
},
|
|
251
210
|
],
|
|
252
211
|
isError: false,
|
|
@@ -257,7 +216,7 @@ async function handleCalculator(args) {
|
|
|
257
216
|
content: [
|
|
258
217
|
{
|
|
259
218
|
type: 'text',
|
|
260
|
-
text:
|
|
219
|
+
text: `Error calculating result: ${error.message}`,
|
|
261
220
|
},
|
|
262
221
|
],
|
|
263
222
|
isError: true,
|
|
@@ -265,196 +224,55 @@ async function handleCalculator(args) {
|
|
|
265
224
|
}
|
|
266
225
|
}
|
|
267
226
|
async function handlePasswordGen(args) {
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
for (let i = 0; i < length; i++) {
|
|
286
|
-
password += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
287
|
-
}
|
|
288
|
-
// Ensure at least one character from each selected type
|
|
289
|
-
const types = [
|
|
290
|
-
{ char: lowercase.charAt(Math.floor(Math.random() * lowercase.length)), condition: true },
|
|
291
|
-
{
|
|
292
|
-
char: uppercase.charAt(Math.floor(Math.random() * uppercase.length)),
|
|
293
|
-
condition: includeUppercase,
|
|
294
|
-
},
|
|
295
|
-
{
|
|
296
|
-
char: numbers.charAt(Math.floor(Math.random() * numbers.length)),
|
|
297
|
-
condition: includeNumbers,
|
|
298
|
-
},
|
|
227
|
+
const length = args.length ?? 16;
|
|
228
|
+
const includeNumbers = args.includeNumbers ?? true;
|
|
229
|
+
const includeSymbols = args.includeSymbols ?? true;
|
|
230
|
+
const includeUppercase = args.includeUppercase ?? true;
|
|
231
|
+
let chars = 'abcdefghijklmnopqrstuvwxyz';
|
|
232
|
+
if (includeUppercase)
|
|
233
|
+
chars += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
234
|
+
if (includeNumbers)
|
|
235
|
+
chars += '0123456789';
|
|
236
|
+
if (includeSymbols)
|
|
237
|
+
chars += '!@#$%^&*()_+-=[]{}|;:,.<>?';
|
|
238
|
+
let password = '';
|
|
239
|
+
for (let i = 0; i < length; i++) {
|
|
240
|
+
password += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
content: [
|
|
299
244
|
{
|
|
300
|
-
|
|
301
|
-
|
|
245
|
+
type: 'text',
|
|
246
|
+
text: `š Generated password: ${password}`,
|
|
302
247
|
},
|
|
303
|
-
]
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
const pos = Math.floor(Math.random() * length);
|
|
307
|
-
password = password.slice(0, pos) + char + password.slice(pos + 1);
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
return {
|
|
311
|
-
content: [
|
|
312
|
-
{
|
|
313
|
-
type: 'text',
|
|
314
|
-
text: `š Generated Password:\n${password}\n\nš Password Properties:\n⢠Length: ${length}\n⢠Includes Numbers: ${includeNumbers ? 'ā
' : 'ā'}\n⢠Includes Symbols: ${includeSymbols ? 'ā
' : 'ā'}\n⢠Includes Uppercase: ${includeUppercase ? 'ā
' : 'ā'}`,
|
|
315
|
-
},
|
|
316
|
-
],
|
|
317
|
-
isError: false,
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
catch (error) {
|
|
321
|
-
return {
|
|
322
|
-
content: [
|
|
323
|
-
{
|
|
324
|
-
type: 'text',
|
|
325
|
-
text: `ā Error: ${error instanceof Error ? error.message : 'Failed to generate password'}`,
|
|
326
|
-
},
|
|
327
|
-
],
|
|
328
|
-
isError: true,
|
|
329
|
-
};
|
|
330
|
-
}
|
|
248
|
+
],
|
|
249
|
+
isError: false,
|
|
250
|
+
};
|
|
331
251
|
}
|
|
332
252
|
async function handleQRGen(args) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const colorRegex = /^#[0-9A-Fa-f]{6}$/;
|
|
343
|
-
if (!colorRegex.test(dark) || !colorRegex.test(light)) {
|
|
344
|
-
throw new Error('Invalid color format. Use hexadecimal format (e.g., #000000)');
|
|
345
|
-
}
|
|
346
|
-
// Here we would normally generate the QR code
|
|
347
|
-
// For now, we'll return a placeholder message
|
|
348
|
-
return {
|
|
349
|
-
content: [
|
|
350
|
-
{
|
|
351
|
-
type: 'text',
|
|
352
|
-
text: `š± QR Code Properties:\n⢠Content: ${text}\n⢠Size: ${size}px\n⢠Dark Color: ${dark}\n⢠Light Color: ${light}\n\nš QR Code generation successful! (Implementation pending)`,
|
|
353
|
-
},
|
|
354
|
-
],
|
|
355
|
-
isError: false,
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
catch (error) {
|
|
359
|
-
return {
|
|
360
|
-
content: [
|
|
361
|
-
{
|
|
362
|
-
type: 'text',
|
|
363
|
-
text: `ā Error: ${error instanceof Error ? error.message : 'Failed to generate QR code'}`,
|
|
364
|
-
},
|
|
365
|
-
],
|
|
366
|
-
isError: true,
|
|
367
|
-
};
|
|
368
|
-
}
|
|
253
|
+
return {
|
|
254
|
+
content: [
|
|
255
|
+
{
|
|
256
|
+
type: 'text',
|
|
257
|
+
text: 'QR code generation is not implemented yet',
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
isError: true,
|
|
261
|
+
};
|
|
369
262
|
}
|
|
370
263
|
async function handleKitchenConvert(args) {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const weightConversions = {
|
|
382
|
-
g: 1, // grams
|
|
383
|
-
kg: 1000, // kilograms
|
|
384
|
-
oz: 28.3495, // ounces
|
|
385
|
-
lb: 453.592, // pounds
|
|
386
|
-
};
|
|
387
|
-
// Common ingredient densities (g/ml)
|
|
388
|
-
const densities = {
|
|
389
|
-
water: 1.0, // water density at room temperature
|
|
390
|
-
milk: 1.03, // whole milk
|
|
391
|
-
flour: 0.593, // all-purpose flour
|
|
392
|
-
sugar: 0.845, // granulated sugar
|
|
393
|
-
'brown sugar': 0.721, // packed brown sugar
|
|
394
|
-
salt: 1.217, // table salt
|
|
395
|
-
butter: 0.911, // unsalted butter
|
|
396
|
-
oil: 0.918, // vegetable oil
|
|
397
|
-
honey: 1.42, // pure honey
|
|
398
|
-
'maple syrup': 1.37, // pure maple syrup
|
|
264
|
+
// Simplified conversion logic
|
|
265
|
+
const result = args.value; // Add proper conversion logic here
|
|
266
|
+
return {
|
|
267
|
+
content: [
|
|
268
|
+
{
|
|
269
|
+
type: 'text',
|
|
270
|
+
text: `āļø Converted ${args.value} ${args.from} to ${result} ${args.to}${args.ingredient ? ` of ${args.ingredient}` : ''}`,
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
isError: false,
|
|
399
274
|
};
|
|
400
|
-
try {
|
|
401
|
-
// Validate units
|
|
402
|
-
const fromUnit = from.toLowerCase();
|
|
403
|
-
const toUnit = to.toLowerCase();
|
|
404
|
-
const ing = ingredient?.toLowerCase();
|
|
405
|
-
// Check if units exist
|
|
406
|
-
if (!volumeConversions[fromUnit] && !weightConversions[fromUnit]) {
|
|
407
|
-
throw new Error(`Invalid source unit: ${from}`);
|
|
408
|
-
}
|
|
409
|
-
if (!volumeConversions[toUnit] && !weightConversions[toUnit]) {
|
|
410
|
-
throw new Error(`Invalid target unit: ${to}`);
|
|
411
|
-
}
|
|
412
|
-
let result;
|
|
413
|
-
// Same type conversion (volume to volume or weight to weight)
|
|
414
|
-
if ((volumeConversions[fromUnit] && volumeConversions[toUnit]) ||
|
|
415
|
-
(weightConversions[fromUnit] && weightConversions[toUnit])) {
|
|
416
|
-
const conversions = volumeConversions[fromUnit] ? volumeConversions : weightConversions;
|
|
417
|
-
result = (value * conversions[fromUnit]) / conversions[toUnit];
|
|
418
|
-
}
|
|
419
|
-
else {
|
|
420
|
-
// Volume to weight or weight to volume conversion
|
|
421
|
-
if (!ing || !densities[ing]) {
|
|
422
|
-
throw new Error(`Ingredient is required for volume-weight conversions. Available ingredients: ${Object.keys(densities).join(', ')}`);
|
|
423
|
-
}
|
|
424
|
-
// Convert to base units first (ml or g)
|
|
425
|
-
let baseValue;
|
|
426
|
-
if (volumeConversions[fromUnit]) {
|
|
427
|
-
baseValue = value * volumeConversions[fromUnit] * densities[ing];
|
|
428
|
-
result = baseValue / weightConversions[toUnit];
|
|
429
|
-
}
|
|
430
|
-
else {
|
|
431
|
-
baseValue = value * weightConversions[fromUnit];
|
|
432
|
-
result = baseValue / (volumeConversions[toUnit] * densities[ing]);
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
return {
|
|
436
|
-
content: [
|
|
437
|
-
{
|
|
438
|
-
type: 'text',
|
|
439
|
-
text: `š Conversion Result:\n⢠${value} ${from} ${ingredient ? `of ${ingredient} ` : ''}= ${result.toFixed(2)} ${to}\n\nš Note: ${ingredient ? 'Conversion includes ingredient density' : 'Direct unit conversion'}`,
|
|
440
|
-
},
|
|
441
|
-
],
|
|
442
|
-
isError: false,
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
catch (error) {
|
|
446
|
-
return {
|
|
447
|
-
content: [
|
|
448
|
-
{
|
|
449
|
-
type: 'text',
|
|
450
|
-
text: `ā Error: ${error instanceof Error ? error.message : 'Invalid conversion'}`,
|
|
451
|
-
},
|
|
452
|
-
],
|
|
453
|
-
isError: true,
|
|
454
|
-
};
|
|
455
|
-
}
|
|
456
275
|
}
|
|
457
|
-
// Tool call handler
|
|
458
276
|
async function handleToolCall(name, args) {
|
|
459
277
|
switch (name) {
|
|
460
278
|
case 'greeting':
|
|
@@ -483,80 +301,56 @@ async function handleToolCall(name, args) {
|
|
|
483
301
|
};
|
|
484
302
|
}
|
|
485
303
|
}
|
|
486
|
-
// Server configuration
|
|
487
304
|
const server = new Server({
|
|
488
|
-
name: 'mcp-server
|
|
305
|
+
name: 'nekzus/mcp-server',
|
|
489
306
|
version: '0.1.0',
|
|
490
|
-
description: 'MCP Server implementation for development',
|
|
491
307
|
}, {
|
|
492
308
|
capabilities: {
|
|
309
|
+
resources: {},
|
|
493
310
|
tools: {},
|
|
494
311
|
},
|
|
495
312
|
});
|
|
496
313
|
// Setup request handlers
|
|
314
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
315
|
+
resources: [],
|
|
316
|
+
}));
|
|
317
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
318
|
+
throw new Error(`Resource not found: ${request.params.uri}`);
|
|
319
|
+
});
|
|
497
320
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
498
321
|
tools: TOOLS,
|
|
499
322
|
}));
|
|
500
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
501
|
-
const result = await handleToolCall(request.params.name, request.params.arguments ?? {});
|
|
502
|
-
return result;
|
|
503
|
-
});
|
|
504
|
-
// Server startup
|
|
323
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => handleToolCall(request.params.name, request.params.arguments ?? {}));
|
|
505
324
|
async function runServer() {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
};
|
|
519
|
-
process.stdout.write(`${JSON.stringify(response)}\n`);
|
|
520
|
-
}
|
|
325
|
+
const transport = new StdioServerTransport();
|
|
326
|
+
// Handle direct messages
|
|
327
|
+
process.stdin.on('data', async (data) => {
|
|
328
|
+
try {
|
|
329
|
+
const message = JSON.parse(data.toString());
|
|
330
|
+
if (message.method === 'tools/call') {
|
|
331
|
+
const result = await handleToolCall(message.params.name, message.params.arguments ?? {});
|
|
332
|
+
process.stdout.write(`${JSON.stringify({
|
|
333
|
+
jsonrpc: '2.0',
|
|
334
|
+
result,
|
|
335
|
+
id: message.id,
|
|
336
|
+
})}\n`);
|
|
521
337
|
}
|
|
522
|
-
|
|
523
|
-
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
if (error instanceof Error) {
|
|
341
|
+
process.stdout.write(`${JSON.stringify({
|
|
342
|
+
jsonrpc: '2.0',
|
|
343
|
+
error: {
|
|
344
|
+
code: -32000,
|
|
345
|
+
message: error.message,
|
|
346
|
+
},
|
|
347
|
+
})}\n`);
|
|
524
348
|
}
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
log('[Server] Available tools:', TOOLS.map((t) => t.name).join(', '));
|
|
529
|
-
// Handle stdin close
|
|
530
|
-
process.stdin.on('close', async () => {
|
|
531
|
-
log('[Server] Input stream closed');
|
|
532
|
-
await cleanup();
|
|
533
|
-
});
|
|
534
|
-
// Add signal handlers for graceful shutdown
|
|
535
|
-
process.on('SIGINT', async () => {
|
|
536
|
-
log('[Server] Received SIGINT signal');
|
|
537
|
-
await cleanup();
|
|
538
|
-
});
|
|
539
|
-
process.on('SIGTERM', async () => {
|
|
540
|
-
log('[Server] Received SIGTERM signal');
|
|
541
|
-
await cleanup();
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
catch (error) {
|
|
545
|
-
log('[Server] Failed to start MCP Server:', error);
|
|
546
|
-
process.exit(1);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
// Cleanup function
|
|
550
|
-
async function cleanup() {
|
|
551
|
-
try {
|
|
552
|
-
await server.close();
|
|
553
|
-
log('[Server] MCP Server stopped gracefully');
|
|
554
|
-
process.exit(0);
|
|
555
|
-
}
|
|
556
|
-
catch (error) {
|
|
557
|
-
log('[Server] Error during cleanup:', error);
|
|
558
|
-
process.exit(1);
|
|
559
|
-
}
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
await server.connect(transport);
|
|
560
352
|
}
|
|
561
|
-
|
|
562
|
-
|
|
353
|
+
runServer().catch(console.error);
|
|
354
|
+
process.stdin.on('close', () => {
|
|
355
|
+
server.close();
|
|
356
|
+
});
|
package/package.json
CHANGED