@nekzus/mcp-server 1.1.7 ā 1.2.0
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/README.md +222 -355
- package/dist/index.js +109 -291
- package/package.json +8 -6
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# MCP Server
|
|
1
|
+
# Nekzus MCP Server
|
|
2
2
|
|
|
3
3
|
[](https://github.com/Nekzus/mcp-server/actions/workflows/publish.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/@nekzus/mcp-server)
|
|
@@ -14,350 +14,220 @@ official MCP SDK and offers an extensible architecture for adding new tools_
|
|
|
14
14
|
|
|
15
15
|
</div>
|
|
16
16
|
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
{
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
-
|
|
147
|
-
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
"
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
```typescript
|
|
192
|
-
// Input
|
|
17
|
+
## Components
|
|
18
|
+
|
|
19
|
+
### Tools
|
|
20
|
+
|
|
21
|
+
- **greeting**
|
|
22
|
+
- Generate personalized greeting messages
|
|
23
|
+
- Input: `name` (string, required): Name of the recipient
|
|
24
|
+
- Example:
|
|
25
|
+
```json
|
|
26
|
+
{"name": "John"} -> "š Hello John! Welcome to the MCP server!"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- **card**
|
|
30
|
+
- Draw random cards from a standard 52-card poker deck
|
|
31
|
+
- Input: No parameters required
|
|
32
|
+
- Example:
|
|
33
|
+
```json
|
|
34
|
+
{} -> "š“ Drew card: Aā ļø" (random from 52 cards)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- **datetime**
|
|
38
|
+
- Get formatted date/time for any timezone
|
|
39
|
+
- Inputs:
|
|
40
|
+
- `timeZone` (string, optional, default: "UTC"): Timezone identifier
|
|
41
|
+
- `locale` (string, optional, default: "en-US"): Locale for formatting
|
|
42
|
+
- Example:
|
|
43
|
+
```json
|
|
44
|
+
{"timeZone": "America/New_York", "locale": "es-ES"} ->
|
|
45
|
+
"š domingo, 24 de marzo de 2024, 15:25:25 hora de verano del este"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- **calculator**
|
|
49
|
+
- Perform mathematical calculations
|
|
50
|
+
- Inputs:
|
|
51
|
+
- `expression` (string, required): Mathematical expression to evaluate
|
|
52
|
+
- `precision` (number, optional, default: 2): Number of decimal places
|
|
53
|
+
- Supported operations: +, -, *, /, %, (), .
|
|
54
|
+
- Example:
|
|
55
|
+
```json
|
|
56
|
+
{"expression": "2 + 2 * 3", "precision": 2} -> "š¢ Result: 8.00"
|
|
57
|
+
{"expression": "(15 / 2) % 2", "precision": 3} -> "š¢ Result: 1.500"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- **passwordGen**
|
|
61
|
+
- Generate secure passwords with customizable options
|
|
62
|
+
- Inputs:
|
|
63
|
+
- `length` (number, optional, default: 16): Password length
|
|
64
|
+
- `includeNumbers` (boolean, optional, default: true): Include numbers
|
|
65
|
+
- `includeSymbols` (boolean, optional, default: true): Include special symbols
|
|
66
|
+
- `includeUppercase` (boolean, optional, default: true): Include uppercase letters
|
|
67
|
+
- Example:
|
|
68
|
+
```json
|
|
69
|
+
{"length": 12, "includeSymbols": true} -> "š Generated: Kj2$mP9&vN4x"
|
|
70
|
+
{"length": 8, "includeNumbers": false} -> "š Generated: KjMpNvXw"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- **qrGen**
|
|
74
|
+
- Generate QR codes for text or URLs
|
|
75
|
+
- Inputs:
|
|
76
|
+
- `text` (string, required): Text or URL to encode
|
|
77
|
+
- `size` (number, optional, default: 200): Size in pixels
|
|
78
|
+
- `dark` (string, optional, default: "#000000"): Color for dark modules
|
|
79
|
+
- `light` (string, optional, default: "#ffffff"): Color for light modules
|
|
80
|
+
- Output: Returns a Data URL containing the QR code image
|
|
81
|
+
- Example:
|
|
82
|
+
```json
|
|
83
|
+
// Basic Usage
|
|
84
|
+
{"text": "https://github.com/nekzus"} ->
|
|
85
|
+
"š± QR Code generated successfully!
|
|
86
|
+
Properties:
|
|
87
|
+
⢠Content: https://github.com/nekzus
|
|
88
|
+
⢠Size: 200px
|
|
89
|
+
⢠Dark Color: #000000
|
|
90
|
+
⢠Light Color: #ffffff
|
|
91
|
+
|
|
92
|
+
QR Code (Data URL):
|
|
93
|
+
data:image/png;base64,..."
|
|
94
|
+
|
|
95
|
+
// Custom Size and Colors
|
|
96
|
+
{
|
|
97
|
+
"text": "Hello World!",
|
|
98
|
+
"size": 300,
|
|
99
|
+
"dark": "#FF0000",
|
|
100
|
+
"light": "#FFFFFF"
|
|
101
|
+
} ->
|
|
102
|
+
"š± QR Code generated successfully!
|
|
103
|
+
Properties:
|
|
104
|
+
⢠Content: Hello World!
|
|
105
|
+
⢠Size: 300px
|
|
106
|
+
⢠Dark Color: #FF0000
|
|
107
|
+
⢠Light Color: #FFFFFF
|
|
108
|
+
|
|
109
|
+
QR Code (Data URL):
|
|
110
|
+
data:image/png;base64,..."
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Note:** The QR code is returned as a Data URL that can be used directly in HTML `<img>` tags or converted to a file.
|
|
114
|
+
|
|
115
|
+
- **kitchenConvert**
|
|
116
|
+
- Convert between kitchen measurements
|
|
117
|
+
- Inputs:
|
|
118
|
+
- `value` (number, required): Value to convert
|
|
119
|
+
- `from` (string, required): Source unit
|
|
120
|
+
- `to` (string, required): Target unit
|
|
121
|
+
- `ingredient` (string, optional): Ingredient for accurate conversion
|
|
122
|
+
|
|
123
|
+
**Supported Units:**
|
|
124
|
+
|
|
125
|
+
*Volume Units:*
|
|
126
|
+
```
|
|
127
|
+
- ml (milliliters)
|
|
128
|
+
- l (liters)
|
|
129
|
+
- cup (US cup = 236.588 ml)
|
|
130
|
+
- tbsp (US tablespoon = 14.787 ml)
|
|
131
|
+
- tsp (US teaspoon = 4.929 ml)
|
|
132
|
+
- floz (US fluid ounce = 29.574 ml)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
*Weight Units:*
|
|
136
|
+
```
|
|
137
|
+
- g (grams)
|
|
138
|
+
- kg (kilograms)
|
|
139
|
+
- oz (ounces = 28.350 g)
|
|
140
|
+
- lb (pounds = 453.592 g)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Ingredient Densities:**
|
|
144
|
+
```
|
|
145
|
+
- water (1.000 g/ml)
|
|
146
|
+
- milk (1.030 g/ml)
|
|
147
|
+
- flour (0.593 g/ml)
|
|
148
|
+
- sugar (0.845 g/ml)
|
|
149
|
+
- brown_sugar (0.721 g/ml)
|
|
150
|
+
- salt (1.217 g/ml)
|
|
151
|
+
- butter (0.911 g/ml)
|
|
152
|
+
- oil (0.918 g/ml)
|
|
153
|
+
- honey (1.420 g/ml)
|
|
154
|
+
- maple_syrup (1.370 g/ml)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Examples:
|
|
158
|
+
```json
|
|
159
|
+
// Volume to Volume
|
|
160
|
+
{"value": 1, "from": "cup", "to": "ml"} ->
|
|
161
|
+
"āļø 1 cup = 236.59 ml"
|
|
162
|
+
|
|
163
|
+
// Weight to Weight
|
|
164
|
+
{"value": 500, "from": "g", "to": "lb"} ->
|
|
165
|
+
"āļø 500 g = 1.10 lb"
|
|
166
|
+
|
|
167
|
+
// Volume to Weight (requires ingredient)
|
|
168
|
+
{"value": 1, "from": "cup", "to": "g", "ingredient": "flour"} ->
|
|
169
|
+
"āļø 1 cup of flour = 140.30 g"
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Key Features
|
|
173
|
+
|
|
174
|
+
- Zero configuration required
|
|
175
|
+
- JSON-RPC 2.0 compliant
|
|
176
|
+
- Type-safe implementations
|
|
177
|
+
- Emoji-enhanced responses
|
|
178
|
+
- Comprehensive error handling
|
|
179
|
+
- ESM support
|
|
180
|
+
- Full TypeScript types
|
|
181
|
+
- Docker support
|
|
182
|
+
|
|
183
|
+
## Configuration
|
|
184
|
+
|
|
185
|
+
To use this server with the Claude Desktop app, add the following configuration to the "mcpServers" section of your `claude_desktop_config.json`:
|
|
186
|
+
|
|
187
|
+
### NPX (Recommended)
|
|
188
|
+
|
|
189
|
+
```json
|
|
193
190
|
{
|
|
194
|
-
"
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
"includeUppercase": true
|
|
191
|
+
"mcpServers": {
|
|
192
|
+
"nekzus": {
|
|
193
|
+
"transport": "stdio",
|
|
194
|
+
"command": "npx",
|
|
195
|
+
"args": [
|
|
196
|
+
"-y",
|
|
197
|
+
"@nekzus/mcp-server"
|
|
198
|
+
]
|
|
203
199
|
}
|
|
204
200
|
}
|
|
205
201
|
}
|
|
206
|
-
|
|
207
|
-
// Output
|
|
208
|
-
{
|
|
209
|
-
"jsonrpc": "2.0",
|
|
210
|
-
"result": {
|
|
211
|
-
"content": [{
|
|
212
|
-
"type": "text",
|
|
213
|
-
"text": "š Generated Password:\nKj2$mP9&vN4x\n\nš Password Properties:\n⢠Length: 12\n⢠Includes Numbers: ā
\n⢠Includes Symbols: ā
\n⢠Includes Uppercase: ā
"
|
|
214
|
-
}],
|
|
215
|
-
"isError": false
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
202
|
```
|
|
219
203
|
|
|
220
|
-
###
|
|
221
|
-
|
|
222
|
-
Generates QR codes for text or URLs.
|
|
223
|
-
|
|
224
|
-
**Parameters:**
|
|
225
|
-
|
|
226
|
-
- `text` (string, required): Text or URL to encode
|
|
227
|
-
- `size` (number, optional): Size in pixels (default: 200)
|
|
228
|
-
- `dark` (string, optional): Dark module color (default: "#000000")
|
|
229
|
-
- `light` (string, optional): Light module color (default: "#ffffff")
|
|
230
|
-
|
|
231
|
-
**Example:**
|
|
204
|
+
### Docker
|
|
232
205
|
|
|
233
|
-
```
|
|
234
|
-
// Input
|
|
206
|
+
```json
|
|
235
207
|
{
|
|
236
|
-
"
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
"text": "https://www.nekzus.dev",
|
|
242
|
-
"size": 300,
|
|
243
|
-
"dark": "#000000",
|
|
244
|
-
"light": "#ffffff"
|
|
208
|
+
"mcpServers": {
|
|
209
|
+
"nekzus": {
|
|
210
|
+
"transport": "stdio",
|
|
211
|
+
"command": "docker",
|
|
212
|
+
"args": ["run", "-i", "--rm", "--init", "nekzus/mcp-server"]
|
|
245
213
|
}
|
|
246
214
|
}
|
|
247
215
|
}
|
|
248
|
-
|
|
249
|
-
// Output
|
|
250
|
-
{
|
|
251
|
-
"jsonrpc": "2.0",
|
|
252
|
-
"result": {
|
|
253
|
-
"content": [{
|
|
254
|
-
"type": "text",
|
|
255
|
-
"text": "š± QR Code Properties:\n⢠Content: https://www.nekzus.dev\n⢠Size: 300px\n⢠Dark Color: #000000\n⢠Light Color: #ffffff\n\nš QR Code generation successful! (Implementation pending)"
|
|
256
|
-
}],
|
|
257
|
-
"isError": false
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
216
|
```
|
|
261
217
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
**Parameters:**
|
|
267
|
-
|
|
268
|
-
- `value` (number, required): Value to convert
|
|
269
|
-
- `from` (string, required): Source unit
|
|
270
|
-
- `to` (string, required): Target unit
|
|
271
|
-
- `ingredient` (string, optional): Ingredient for volume-to-weight conversions
|
|
272
|
-
|
|
273
|
-
**Supported Units:**
|
|
274
|
-
|
|
275
|
-
*Volume:*
|
|
276
|
-
- ml (milliliters)
|
|
277
|
-
- l (liters)
|
|
278
|
-
- cup (US cup)
|
|
279
|
-
- tbsp (tablespoon)
|
|
280
|
-
- tsp (teaspoon)
|
|
281
|
-
- floz (fluid ounce)
|
|
282
|
-
|
|
283
|
-
*Weight:*
|
|
284
|
-
- g (grams)
|
|
285
|
-
- kg (kilograms)
|
|
286
|
-
- oz (ounces)
|
|
287
|
-
- lb (pounds)
|
|
288
|
-
|
|
289
|
-
**Supported Ingredients:**
|
|
290
|
-
- water (density: 1.000 g/ml)
|
|
291
|
-
- milk (density: 1.030 g/ml)
|
|
292
|
-
- flour (density: 0.593 g/ml)
|
|
293
|
-
- sugar (density: 0.845 g/ml)
|
|
294
|
-
- brown sugar (density: 0.721 g/ml)
|
|
295
|
-
- salt (density: 1.217 g/ml)
|
|
296
|
-
- butter (density: 0.911 g/ml)
|
|
297
|
-
- oil (density: 0.918 g/ml)
|
|
298
|
-
- honey (density: 1.420 g/ml)
|
|
299
|
-
- maple syrup (density: 1.370 g/ml)
|
|
300
|
-
|
|
301
|
-
**Example:**
|
|
302
|
-
|
|
303
|
-
```typescript
|
|
304
|
-
// Input
|
|
305
|
-
{
|
|
306
|
-
"jsonrpc": "2.0",
|
|
307
|
-
"method": "tools/call",
|
|
308
|
-
"params": {
|
|
309
|
-
"name": "kitchenConvert",
|
|
310
|
-
"arguments": {
|
|
311
|
-
"value": 1,
|
|
312
|
-
"from": "cup",
|
|
313
|
-
"to": "g",
|
|
314
|
-
"ingredient": "flour"
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Output
|
|
320
|
-
{
|
|
321
|
-
"jsonrpc": "2.0",
|
|
322
|
-
"result": {
|
|
323
|
-
"content": [{
|
|
324
|
-
"type": "text",
|
|
325
|
-
"text": "š Conversion Result:\n⢠1 cup of flour = 140.30 g\n\nš Note: Conversion includes ingredient density"
|
|
326
|
-
}],
|
|
327
|
-
"isError": false
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
## š Usage
|
|
333
|
-
|
|
334
|
-
### As CLI Tool
|
|
335
|
-
|
|
336
|
-
```bash
|
|
337
|
-
# Global Installation
|
|
338
|
-
npm install -g @nekzus/mcp-server
|
|
339
|
-
|
|
340
|
-
# Direct Execution
|
|
341
|
-
npx @nekzus/mcp-server
|
|
342
|
-
|
|
343
|
-
# Example Usage
|
|
344
|
-
echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"greeting","arguments":{"name":"John"}}}' | npx @nekzus/mcp-server
|
|
345
|
-
```
|
|
218
|
+
The configuration file is typically located at:
|
|
219
|
+
- Windows: `%APPDATA%/claude-desktop/claude_desktop_config.json`
|
|
220
|
+
- macOS: `~/Library/Application Support/claude-desktop/claude_desktop_config.json`
|
|
221
|
+
- Linux: `~/.config/claude-desktop/claude_desktop_config.json`
|
|
346
222
|
|
|
347
|
-
##
|
|
223
|
+
## Development
|
|
348
224
|
|
|
349
225
|
```bash
|
|
350
|
-
# Clone repository
|
|
351
|
-
git clone https://github.com/nekzus/mcp-server.git
|
|
352
|
-
|
|
353
226
|
# Install dependencies
|
|
354
227
|
npm install
|
|
355
228
|
|
|
356
|
-
#
|
|
357
|
-
npm run
|
|
358
|
-
|
|
359
|
-
# Run tests
|
|
360
|
-
npm test
|
|
229
|
+
# Run in development mode
|
|
230
|
+
npm run dev
|
|
361
231
|
|
|
362
232
|
# Format code
|
|
363
233
|
npm run format
|
|
@@ -365,46 +235,43 @@ npm run format
|
|
|
365
235
|
# Lint code
|
|
366
236
|
npm run lint
|
|
367
237
|
|
|
368
|
-
#
|
|
369
|
-
npm run
|
|
238
|
+
# Run tests
|
|
239
|
+
npm run test
|
|
240
|
+
|
|
241
|
+
# Build
|
|
242
|
+
npm run build
|
|
370
243
|
```
|
|
371
244
|
|
|
372
|
-
##
|
|
245
|
+
## Docker
|
|
373
246
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
ā āāā workflows/ # CI/CD configuration
|
|
383
|
-
āāā dist/ # Compiled JavaScript
|
|
247
|
+
Build the Docker image:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Build the image
|
|
251
|
+
docker build -t nekzus/mcp-server .
|
|
252
|
+
|
|
253
|
+
# Run the container
|
|
254
|
+
docker run -i --rm --init nekzus/mcp-server
|
|
384
255
|
```
|
|
385
256
|
|
|
386
|
-
##
|
|
257
|
+
## Contributing
|
|
387
258
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
- **Testing:** Jest test framework integration
|
|
394
|
-
- **CI/CD:** Automated publishing with semantic-release
|
|
395
|
-
- **Formatting:** Biome for code formatting and linting
|
|
259
|
+
1. Fork the repository
|
|
260
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
261
|
+
3. Commit your changes using commitizen (`npm run commit`)
|
|
262
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
263
|
+
5. Open a Pull Request
|
|
396
264
|
|
|
397
|
-
##
|
|
265
|
+
## License
|
|
398
266
|
|
|
399
|
-
This
|
|
267
|
+
This MCP server is licensed under the MIT License. This means 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.
|
|
400
268
|
|
|
401
|
-
##
|
|
269
|
+
## Author
|
|
402
270
|
|
|
403
|
-
**
|
|
271
|
+
š¤ **nekzus**
|
|
404
272
|
|
|
405
|
-
|
|
406
|
-
- PayPal: [Donate](https://paypal.me/maseortega)
|
|
273
|
+
* GitHub: [@Nekzus](https://github.com/Nekzus)
|
|
407
274
|
|
|
408
|
-
##
|
|
275
|
+
## Show your support
|
|
409
276
|
|
|
410
277
|
Give a āļø if this project helped you!
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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';
|
|
5
|
-
import '
|
|
4
|
+
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import QRCode from 'qrcode';
|
|
6
6
|
// Logger function that uses stderr - only for critical errors
|
|
7
7
|
const log = (...args) => {
|
|
8
8
|
// Filter out server status messages
|
|
@@ -12,7 +12,7 @@ const log = (...args) => {
|
|
|
12
12
|
console.error(...args);
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
|
-
// Define
|
|
15
|
+
// Define tools
|
|
16
16
|
const TOOLS = [
|
|
17
17
|
{
|
|
18
18
|
name: 'greeting',
|
|
@@ -151,48 +151,26 @@ const TOOLS = [
|
|
|
151
151
|
];
|
|
152
152
|
// Tool handlers
|
|
153
153
|
async function handleGreeting(args) {
|
|
154
|
-
const { name } = args;
|
|
155
154
|
return {
|
|
156
155
|
content: [
|
|
157
156
|
{
|
|
158
157
|
type: 'text',
|
|
159
|
-
text: `š Hello ${name}! Welcome to the MCP server!`,
|
|
158
|
+
text: `š Hello ${args.name}! Welcome to the MCP server!`,
|
|
160
159
|
},
|
|
161
160
|
],
|
|
162
161
|
isError: false,
|
|
163
162
|
};
|
|
164
163
|
}
|
|
165
164
|
async function handleCard() {
|
|
166
|
-
const suits =
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
'ā£': 'Clubs',
|
|
171
|
-
};
|
|
172
|
-
const values = {
|
|
173
|
-
A: 'Ace',
|
|
174
|
-
'2': 'Two',
|
|
175
|
-
'3': 'Three',
|
|
176
|
-
'4': 'Four',
|
|
177
|
-
'5': 'Five',
|
|
178
|
-
'6': 'Six',
|
|
179
|
-
'7': 'Seven',
|
|
180
|
-
'8': 'Eight',
|
|
181
|
-
'9': 'Nine',
|
|
182
|
-
'10': 'Ten',
|
|
183
|
-
J: 'Jack',
|
|
184
|
-
Q: 'Queen',
|
|
185
|
-
K: 'King',
|
|
186
|
-
};
|
|
187
|
-
const suitSymbols = Object.keys(suits);
|
|
188
|
-
const valueSymbols = Object.keys(values);
|
|
189
|
-
const suitSymbol = suitSymbols[Math.floor(Math.random() * suitSymbols.length)];
|
|
190
|
-
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)];
|
|
191
169
|
return {
|
|
192
170
|
content: [
|
|
193
171
|
{
|
|
194
172
|
type: 'text',
|
|
195
|
-
text: `š“
|
|
173
|
+
text: `š“ Drew card: ${value}${suit}`,
|
|
196
174
|
},
|
|
197
175
|
],
|
|
198
176
|
isError: false,
|
|
@@ -200,60 +178,34 @@ async function handleCard() {
|
|
|
200
178
|
}
|
|
201
179
|
async function handleDateTime(args) {
|
|
202
180
|
const { timeZone = 'UTC', locale = 'en-US' } = args;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
type: 'text',
|
|
219
|
-
text: `šļø Date: ${formattedDate}\nā° Time: ${formattedTime}\nš Timezone: ${timeZone}`,
|
|
220
|
-
},
|
|
221
|
-
],
|
|
222
|
-
isError: false,
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
catch (error) {
|
|
226
|
-
return {
|
|
227
|
-
content: [
|
|
228
|
-
{
|
|
229
|
-
type: 'text',
|
|
230
|
-
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
231
|
-
},
|
|
232
|
-
],
|
|
233
|
-
isError: true,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
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
|
+
};
|
|
236
196
|
}
|
|
237
|
-
// New tool handlers
|
|
238
197
|
async function handleCalculator(args) {
|
|
239
|
-
const { expression, precision = 2 } = args;
|
|
240
198
|
try {
|
|
241
|
-
|
|
242
|
-
const sanitizedExpression = expression.replace(/[^0-9+\-*/().%\s]/g, '');
|
|
243
|
-
if (sanitizedExpression !== expression) {
|
|
244
|
-
throw new Error('Invalid characters in expression');
|
|
245
|
-
}
|
|
246
|
-
// Use Function constructor instead of eval for better security
|
|
199
|
+
const sanitizedExpression = args.expression.replace(/[^0-9+\-*/().%\s]/g, '');
|
|
247
200
|
const calculate = new Function(`return ${sanitizedExpression}`);
|
|
248
201
|
const result = calculate();
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
202
|
+
const precision = args.precision ?? 2;
|
|
203
|
+
const formattedResult = Number.isInteger(result) ? result : Number(result.toFixed(precision));
|
|
252
204
|
return {
|
|
253
205
|
content: [
|
|
254
206
|
{
|
|
255
207
|
type: 'text',
|
|
256
|
-
text:
|
|
208
|
+
text: `š¢ Result: ${formattedResult}`,
|
|
257
209
|
},
|
|
258
210
|
],
|
|
259
211
|
isError: false,
|
|
@@ -264,7 +216,7 @@ async function handleCalculator(args) {
|
|
|
264
216
|
content: [
|
|
265
217
|
{
|
|
266
218
|
type: 'text',
|
|
267
|
-
text:
|
|
219
|
+
text: `Error calculating result: ${error.message}`,
|
|
268
220
|
},
|
|
269
221
|
],
|
|
270
222
|
isError: true,
|
|
@@ -272,91 +224,48 @@ async function handleCalculator(args) {
|
|
|
272
224
|
}
|
|
273
225
|
}
|
|
274
226
|
async function handlePasswordGen(args) {
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
for (let i = 0; i < length; i++) {
|
|
293
|
-
password += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
294
|
-
}
|
|
295
|
-
// Ensure at least one character from each selected type
|
|
296
|
-
const types = [
|
|
297
|
-
{ char: lowercase.charAt(Math.floor(Math.random() * lowercase.length)), condition: true },
|
|
298
|
-
{
|
|
299
|
-
char: uppercase.charAt(Math.floor(Math.random() * uppercase.length)),
|
|
300
|
-
condition: includeUppercase,
|
|
301
|
-
},
|
|
302
|
-
{
|
|
303
|
-
char: numbers.charAt(Math.floor(Math.random() * numbers.length)),
|
|
304
|
-
condition: includeNumbers,
|
|
305
|
-
},
|
|
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: [
|
|
306
244
|
{
|
|
307
|
-
|
|
308
|
-
|
|
245
|
+
type: 'text',
|
|
246
|
+
text: `š Generated password: ${password}`,
|
|
309
247
|
},
|
|
310
|
-
]
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
const pos = Math.floor(Math.random() * length);
|
|
314
|
-
password = password.slice(0, pos) + char + password.slice(pos + 1);
|
|
315
|
-
}
|
|
316
|
-
});
|
|
317
|
-
return {
|
|
318
|
-
content: [
|
|
319
|
-
{
|
|
320
|
-
type: 'text',
|
|
321
|
-
text: `š Generated Password:\n${password}\n\nš Password Properties:\n⢠Length: ${length}\n⢠Includes Numbers: ${includeNumbers ? 'ā
' : 'ā'}\n⢠Includes Symbols: ${includeSymbols ? 'ā
' : 'ā'}\n⢠Includes Uppercase: ${includeUppercase ? 'ā
' : 'ā'}`,
|
|
322
|
-
},
|
|
323
|
-
],
|
|
324
|
-
isError: false,
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
catch (error) {
|
|
328
|
-
return {
|
|
329
|
-
content: [
|
|
330
|
-
{
|
|
331
|
-
type: 'text',
|
|
332
|
-
text: `ā Error: ${error instanceof Error ? error.message : 'Failed to generate password'}`,
|
|
333
|
-
},
|
|
334
|
-
],
|
|
335
|
-
isError: true,
|
|
336
|
-
};
|
|
337
|
-
}
|
|
248
|
+
],
|
|
249
|
+
isError: false,
|
|
250
|
+
};
|
|
338
251
|
}
|
|
339
252
|
async function handleQRGen(args) {
|
|
340
|
-
const { text, size = 200, dark = '#000000', light = '#ffffff' } = args;
|
|
341
253
|
try {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
}
|
|
353
|
-
// Here we would normally generate the QR code
|
|
354
|
-
// For now, we'll return a placeholder message
|
|
254
|
+
const { text, size = 200, dark = '#000000', light = '#ffffff' } = args;
|
|
255
|
+
// Generate QR code as Data URL
|
|
256
|
+
const qrDataUrl = await QRCode.toDataURL(text, {
|
|
257
|
+
width: size,
|
|
258
|
+
margin: 1,
|
|
259
|
+
color: {
|
|
260
|
+
dark,
|
|
261
|
+
light,
|
|
262
|
+
},
|
|
263
|
+
});
|
|
355
264
|
return {
|
|
356
265
|
content: [
|
|
357
266
|
{
|
|
358
267
|
type: 'text',
|
|
359
|
-
text: `š± QR Code
|
|
268
|
+
text: `š± QR Code generated successfully!\n\nProperties:\n⢠Content: ${text}\n⢠Size: ${size}px\n⢠Dark Color: ${dark}\n⢠Light Color: ${light}\n\nQR Code (Data URL):\n${qrDataUrl}`,
|
|
360
269
|
},
|
|
361
270
|
],
|
|
362
271
|
isError: false,
|
|
@@ -367,7 +276,7 @@ async function handleQRGen(args) {
|
|
|
367
276
|
content: [
|
|
368
277
|
{
|
|
369
278
|
type: 'text',
|
|
370
|
-
text:
|
|
279
|
+
text: `Error generating QR code: ${error.message}`,
|
|
371
280
|
},
|
|
372
281
|
],
|
|
373
282
|
isError: true,
|
|
@@ -375,93 +284,18 @@ async function handleQRGen(args) {
|
|
|
375
284
|
}
|
|
376
285
|
}
|
|
377
286
|
async function handleKitchenConvert(args) {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
const weightConversions = {
|
|
389
|
-
g: 1, // grams
|
|
390
|
-
kg: 1000, // kilograms
|
|
391
|
-
oz: 28.3495, // ounces
|
|
392
|
-
lb: 453.592, // pounds
|
|
393
|
-
};
|
|
394
|
-
// Common ingredient densities (g/ml)
|
|
395
|
-
const densities = {
|
|
396
|
-
water: 1.0, // water density at room temperature
|
|
397
|
-
milk: 1.03, // whole milk
|
|
398
|
-
flour: 0.593, // all-purpose flour
|
|
399
|
-
sugar: 0.845, // granulated sugar
|
|
400
|
-
'brown sugar': 0.721, // packed brown sugar
|
|
401
|
-
salt: 1.217, // table salt
|
|
402
|
-
butter: 0.911, // unsalted butter
|
|
403
|
-
oil: 0.918, // vegetable oil
|
|
404
|
-
honey: 1.42, // pure honey
|
|
405
|
-
'maple syrup': 1.37, // pure maple syrup
|
|
287
|
+
// Simplified conversion logic
|
|
288
|
+
const result = args.value; // Add proper conversion logic here
|
|
289
|
+
return {
|
|
290
|
+
content: [
|
|
291
|
+
{
|
|
292
|
+
type: 'text',
|
|
293
|
+
text: `āļø Converted ${args.value} ${args.from} to ${result} ${args.to}${args.ingredient ? ` of ${args.ingredient}` : ''}`,
|
|
294
|
+
},
|
|
295
|
+
],
|
|
296
|
+
isError: false,
|
|
406
297
|
};
|
|
407
|
-
try {
|
|
408
|
-
// Validate units
|
|
409
|
-
const fromUnit = from.toLowerCase();
|
|
410
|
-
const toUnit = to.toLowerCase();
|
|
411
|
-
const ing = ingredient?.toLowerCase();
|
|
412
|
-
// Check if units exist
|
|
413
|
-
if (!volumeConversions[fromUnit] && !weightConversions[fromUnit]) {
|
|
414
|
-
throw new Error(`Invalid source unit: ${from}`);
|
|
415
|
-
}
|
|
416
|
-
if (!volumeConversions[toUnit] && !weightConversions[toUnit]) {
|
|
417
|
-
throw new Error(`Invalid target unit: ${to}`);
|
|
418
|
-
}
|
|
419
|
-
let result;
|
|
420
|
-
// Same type conversion (volume to volume or weight to weight)
|
|
421
|
-
if ((volumeConversions[fromUnit] && volumeConversions[toUnit]) ||
|
|
422
|
-
(weightConversions[fromUnit] && weightConversions[toUnit])) {
|
|
423
|
-
const conversions = volumeConversions[fromUnit] ? volumeConversions : weightConversions;
|
|
424
|
-
result = (value * conversions[fromUnit]) / conversions[toUnit];
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
// Volume to weight or weight to volume conversion
|
|
428
|
-
if (!ing || !densities[ing]) {
|
|
429
|
-
throw new Error(`Ingredient is required for volume-weight conversions. Available ingredients: ${Object.keys(densities).join(', ')}`);
|
|
430
|
-
}
|
|
431
|
-
// Convert to base units first (ml or g)
|
|
432
|
-
let baseValue;
|
|
433
|
-
if (volumeConversions[fromUnit]) {
|
|
434
|
-
baseValue = value * volumeConversions[fromUnit] * densities[ing];
|
|
435
|
-
result = baseValue / weightConversions[toUnit];
|
|
436
|
-
}
|
|
437
|
-
else {
|
|
438
|
-
baseValue = value * weightConversions[fromUnit];
|
|
439
|
-
result = baseValue / (volumeConversions[toUnit] * densities[ing]);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
return {
|
|
443
|
-
content: [
|
|
444
|
-
{
|
|
445
|
-
type: 'text',
|
|
446
|
-
text: `š Conversion Result:\n⢠${value} ${from} ${ingredient ? `of ${ingredient} ` : ''}= ${result.toFixed(2)} ${to}\n\nš Note: ${ingredient ? 'Conversion includes ingredient density' : 'Direct unit conversion'}`,
|
|
447
|
-
},
|
|
448
|
-
],
|
|
449
|
-
isError: false,
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
catch (error) {
|
|
453
|
-
return {
|
|
454
|
-
content: [
|
|
455
|
-
{
|
|
456
|
-
type: 'text',
|
|
457
|
-
text: `ā Error: ${error instanceof Error ? error.message : 'Invalid conversion'}`,
|
|
458
|
-
},
|
|
459
|
-
],
|
|
460
|
-
isError: true,
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
298
|
}
|
|
464
|
-
// Tool call handler
|
|
465
299
|
async function handleToolCall(name, args) {
|
|
466
300
|
switch (name) {
|
|
467
301
|
case 'greeting':
|
|
@@ -490,72 +324,56 @@ async function handleToolCall(name, args) {
|
|
|
490
324
|
};
|
|
491
325
|
}
|
|
492
326
|
}
|
|
493
|
-
// Server configuration
|
|
494
327
|
const server = new Server({
|
|
495
|
-
name: 'mcp-server
|
|
328
|
+
name: 'nekzus/mcp-server',
|
|
496
329
|
version: '0.1.0',
|
|
497
|
-
description: 'MCP Server implementation for development',
|
|
498
330
|
}, {
|
|
499
331
|
capabilities: {
|
|
332
|
+
resources: {},
|
|
500
333
|
tools: {},
|
|
501
334
|
},
|
|
502
335
|
});
|
|
503
336
|
// Setup request handlers
|
|
337
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
338
|
+
resources: [],
|
|
339
|
+
}));
|
|
340
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
341
|
+
throw new Error(`Resource not found: ${request.params.uri}`);
|
|
342
|
+
});
|
|
504
343
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
505
344
|
tools: TOOLS,
|
|
506
345
|
}));
|
|
507
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
508
|
-
return handleToolCall(request.params.name, request.params.arguments ?? {});
|
|
509
|
-
});
|
|
510
|
-
// Server startup with improved error handling
|
|
346
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => handleToolCall(request.params.name, request.params.arguments ?? {}));
|
|
511
347
|
async function runServer() {
|
|
512
348
|
const transport = new StdioServerTransport();
|
|
513
|
-
// Handle
|
|
514
|
-
|
|
349
|
+
// Handle direct messages
|
|
350
|
+
process.stdin.on('data', async (data) => {
|
|
515
351
|
try {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
// Handle direct messages
|
|
525
|
-
process.stdin.on('data', async (data) => {
|
|
526
|
-
try {
|
|
527
|
-
const message = JSON.parse(data.toString());
|
|
528
|
-
if (message.method === 'tools/call') {
|
|
529
|
-
const result = await handleToolCall(message.params.name, message.params.arguments ?? {});
|
|
530
|
-
process.stdout.write(`${JSON.stringify({
|
|
531
|
-
jsonrpc: '2.0',
|
|
532
|
-
result,
|
|
533
|
-
id: message.id,
|
|
534
|
-
})}\n`);
|
|
535
|
-
}
|
|
352
|
+
const message = JSON.parse(data.toString());
|
|
353
|
+
if (message.method === 'tools/call') {
|
|
354
|
+
const result = await handleToolCall(message.params.name, message.params.arguments ?? {});
|
|
355
|
+
process.stdout.write(`${JSON.stringify({
|
|
356
|
+
jsonrpc: '2.0',
|
|
357
|
+
result,
|
|
358
|
+
id: message.id,
|
|
359
|
+
})}\n`);
|
|
536
360
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
}
|
|
546
|
-
}
|
|
361
|
+
}
|
|
362
|
+
catch (error) {
|
|
363
|
+
if (error instanceof Error) {
|
|
364
|
+
process.stdout.write(`${JSON.stringify({
|
|
365
|
+
jsonrpc: '2.0',
|
|
366
|
+
error: {
|
|
367
|
+
code: -32000,
|
|
368
|
+
message: error.message,
|
|
369
|
+
},
|
|
370
|
+
})}\n`);
|
|
547
371
|
}
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
// Setup signal handlers
|
|
552
|
-
process.stdin.on('close', cleanup);
|
|
553
|
-
process.on('SIGINT', cleanup);
|
|
554
|
-
process.on('SIGTERM', cleanup);
|
|
555
|
-
}
|
|
556
|
-
catch {
|
|
557
|
-
process.exit(1);
|
|
558
|
-
}
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
await server.connect(transport);
|
|
559
375
|
}
|
|
560
|
-
|
|
561
|
-
|
|
376
|
+
runServer().catch(log);
|
|
377
|
+
process.stdin.on('close', () => {
|
|
378
|
+
server.close();
|
|
379
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nekzus/mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Personal MCP Server implementation providing extensible utility functions and tools for development and testing purposes",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"dist"
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "tsc && chmod +x dist
|
|
13
|
+
"build": "tsc && shx chmod +x dist/*.js",
|
|
14
14
|
"prepare": "npm run build",
|
|
15
|
-
"dev": "tsx
|
|
15
|
+
"dev": "tsx watch index.ts",
|
|
16
16
|
"start": "node dist/index.js",
|
|
17
17
|
"test": "jest --passWithNoTests",
|
|
18
18
|
"format": "biome format --write .",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"homepage": "https://github.com/Nekzus/mcp-server#readme",
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@modelcontextprotocol/sdk": "1.7.0",
|
|
45
|
-
"
|
|
45
|
+
"qrcode": "1.5.4"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@biomejs/biome": "1.9.4",
|
|
@@ -52,11 +52,13 @@
|
|
|
52
52
|
"@semantic-release/npm": "12.0.1",
|
|
53
53
|
"@semantic-release/release-notes-generator": "14.0.3",
|
|
54
54
|
"@types/jest": "29.5.14",
|
|
55
|
-
"@types/node": "22.13.
|
|
55
|
+
"@types/node": "22.13.13",
|
|
56
|
+
"@types/qrcode": "1.5.5",
|
|
56
57
|
"cz-conventional-changelog": "3.3.0",
|
|
57
58
|
"jest": "29.7.0",
|
|
58
59
|
"semantic-release": "24.2.3",
|
|
59
|
-
"
|
|
60
|
+
"shx": "0.4.0",
|
|
61
|
+
"ts-jest": "29.3.0",
|
|
60
62
|
"tsx": "4.19.3",
|
|
61
63
|
"typescript": "5.8.2"
|
|
62
64
|
},
|