@nekzus/mcp-server 1.0.29 → 1.0.31
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 +166 -94
- package/package.json +11 -11
- package/dist/tools/index.js +0 -111
- package/dist/types/index.js +0 -1
- package/dist/utils/cards.js +0 -10
- package/dist/utils/datetime.js +0 -28
- package/dist/utils/schema.js +0 -35
package/dist/index.js
CHANGED
|
@@ -1,106 +1,178 @@
|
|
|
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
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import 'dotenv/config';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
const TOOLS = [
|
|
7
|
+
{
|
|
8
|
+
name: 'greeting',
|
|
9
|
+
description: 'Generate a personalized greeting message for the specified person',
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
name: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
description: 'Name of the recipient for the greeting',
|
|
16
|
+
},
|
|
17
17
|
},
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
required: ['name'],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: 'card',
|
|
23
|
+
description: 'Draw a random card from a standard 52-card poker deck',
|
|
24
|
+
inputSchema: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
random_string: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
description: 'Dummy parameter for no-parameter tools',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
required: ['random_string'],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'datetime',
|
|
37
|
+
description: 'Get the current date and time for a specific timezone',
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: 'object',
|
|
40
|
+
properties: {
|
|
41
|
+
timeZone: {
|
|
42
|
+
type: 'string',
|
|
43
|
+
description: 'Timezone identifier (e.g., "America/New_York")',
|
|
44
|
+
},
|
|
45
|
+
locale: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
description: 'Locale identifier (e.g., "en-US")',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
async function handleGreeting(args) {
|
|
54
|
+
const { name } = args;
|
|
55
|
+
return {
|
|
56
|
+
content: [
|
|
57
|
+
{
|
|
58
|
+
type: 'text',
|
|
59
|
+
text: `¡Hola ${name}! ¿Cómo estás?`,
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
isError: false,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
async function handleCard() {
|
|
66
|
+
const suits = ['♠', '♥', '♦', '♣'];
|
|
67
|
+
const values = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'];
|
|
68
|
+
const suit = suits[Math.floor(Math.random() * suits.length)];
|
|
69
|
+
const value = values[Math.floor(Math.random() * values.length)];
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: 'text',
|
|
74
|
+
text: `${value}${suit}`,
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
isError: false,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async function handleDateTime(args) {
|
|
81
|
+
const { timeZone = 'UTC', locale = 'en-US' } = args;
|
|
82
|
+
try {
|
|
83
|
+
const date = new Date();
|
|
84
|
+
const formattedDate = new Intl.DateTimeFormat(locale, {
|
|
85
|
+
timeZone,
|
|
86
|
+
dateStyle: 'full',
|
|
87
|
+
timeStyle: 'long',
|
|
88
|
+
}).format(date);
|
|
89
|
+
return {
|
|
90
|
+
content: [
|
|
91
|
+
{
|
|
92
|
+
type: 'text',
|
|
93
|
+
text: formattedDate,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
isError: false,
|
|
97
|
+
};
|
|
23
98
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (!tool) {
|
|
35
|
-
throw new Error(`Tool not found: ${name}`);
|
|
36
|
-
}
|
|
37
|
-
const handler = tool.handler;
|
|
38
|
-
const result = await handler(args);
|
|
39
|
-
return {
|
|
40
|
-
content: result.content.map((content) => {
|
|
41
|
-
const mappedContent = {
|
|
42
|
-
type: content.type,
|
|
43
|
-
text: typeof content.text === 'string'
|
|
44
|
-
? content.text
|
|
45
|
-
: JSON.stringify(content.text, null, 2),
|
|
46
|
-
};
|
|
47
|
-
if (content.data !== undefined) {
|
|
48
|
-
return { ...mappedContent, data: content.data };
|
|
49
|
-
}
|
|
50
|
-
return mappedContent;
|
|
51
|
-
}),
|
|
52
|
-
isError: result.isError,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
catch (error) {
|
|
56
|
-
return {
|
|
57
|
-
content: [
|
|
58
|
-
{
|
|
59
|
-
type: 'text',
|
|
60
|
-
text: error instanceof Error ? error.message : String(error),
|
|
61
|
-
},
|
|
62
|
-
],
|
|
63
|
-
isError: true,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
});
|
|
99
|
+
catch (error) {
|
|
100
|
+
return {
|
|
101
|
+
content: [
|
|
102
|
+
{
|
|
103
|
+
type: 'text',
|
|
104
|
+
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
isError: true,
|
|
108
|
+
};
|
|
67
109
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
110
|
+
}
|
|
111
|
+
async function handleToolCall(name, args) {
|
|
112
|
+
switch (name) {
|
|
113
|
+
case 'greeting':
|
|
114
|
+
return handleGreeting(args);
|
|
115
|
+
case 'card':
|
|
116
|
+
return handleCard();
|
|
117
|
+
case 'datetime':
|
|
118
|
+
return handleDateTime(args);
|
|
119
|
+
default:
|
|
120
|
+
return {
|
|
121
|
+
content: [
|
|
122
|
+
{
|
|
123
|
+
type: 'text',
|
|
124
|
+
text: `Error: Unknown tool '${name}'`,
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
isError: true,
|
|
128
|
+
};
|
|
86
129
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
130
|
+
}
|
|
131
|
+
const server = new Server({
|
|
132
|
+
name: '@nekzus/mcp-server',
|
|
133
|
+
version: '0.1.0',
|
|
134
|
+
description: 'MCP Server implementation for development',
|
|
135
|
+
}, {
|
|
136
|
+
capabilities: {
|
|
137
|
+
tools: {},
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
141
|
+
return {
|
|
142
|
+
tools: TOOLS,
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
146
|
+
const { name, arguments: args } = request.params;
|
|
147
|
+
return handleToolCall(name, args ?? {});
|
|
148
|
+
});
|
|
149
|
+
async function runServer() {
|
|
150
|
+
try {
|
|
151
|
+
const transport = new StdioServerTransport();
|
|
152
|
+
await server.connect(transport);
|
|
153
|
+
console.log('[Server] MCP Server is running');
|
|
154
|
+
console.log('[Server] Available tools:', TOOLS.map((t) => t.name).join(', '));
|
|
155
|
+
process.on('SIGTERM', () => cleanup());
|
|
156
|
+
process.on('SIGINT', () => cleanup());
|
|
157
|
+
process.stdin.on('close', () => {
|
|
158
|
+
console.log('[Server] Input stream closed');
|
|
159
|
+
cleanup();
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
console.error('[Server] Failed to start MCP Server:', error);
|
|
164
|
+
process.exit(1);
|
|
97
165
|
}
|
|
98
166
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
167
|
+
async function cleanup() {
|
|
168
|
+
try {
|
|
169
|
+
await server.close();
|
|
170
|
+
console.log('[Server] MCP Server stopped gracefully');
|
|
171
|
+
process.exit(0);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
console.error('[Server] Error during cleanup:', error);
|
|
104
175
|
process.exit(1);
|
|
105
|
-
}
|
|
176
|
+
}
|
|
106
177
|
}
|
|
178
|
+
runServer();
|
package/package.json
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nekzus/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.31",
|
|
4
4
|
"description": "Personal MCP Server implementation providing extensible utility functions and tools for development and testing purposes",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "dist/index.js",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
|
-
"bin":
|
|
9
|
-
"mcp-server": "./dist/index.js"
|
|
10
|
-
},
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"bin": "./dist/index.js",
|
|
11
9
|
"files": [
|
|
12
|
-
"dist"
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
|
-
"build": "tsc && shx chmod +x dist
|
|
15
|
+
"build": "tsc && shx chmod +x dist/index.js",
|
|
16
16
|
"dev": "tsx src/index.ts",
|
|
17
17
|
"start": "node dist/index.js",
|
|
18
18
|
"test": "jest --passWithNoTests",
|
|
19
|
-
"format": "biome format --write
|
|
20
|
-
"lint": "biome lint --write
|
|
21
|
-
"check": "biome check --apply
|
|
19
|
+
"format": "biome format --write .",
|
|
20
|
+
"lint": "biome lint --write .",
|
|
21
|
+
"check": "biome check --apply .",
|
|
22
22
|
"commit": "git-cz",
|
|
23
23
|
"semantic-release": "semantic-release --branches main",
|
|
24
24
|
"prepare": "npm run build",
|
package/dist/tools/index.js
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { getRandomCard } from '../utils/cards.js';
|
|
2
|
-
import { getCurrentDateTime } from '../utils/datetime.js';
|
|
3
|
-
export const greetingTool = {
|
|
4
|
-
name: 'greeting',
|
|
5
|
-
description: 'Generate a personalized greeting message for the specified person',
|
|
6
|
-
inputSchema: {
|
|
7
|
-
type: 'object',
|
|
8
|
-
properties: {
|
|
9
|
-
name: { type: 'string', description: 'Name of the recipient for the greeting' },
|
|
10
|
-
},
|
|
11
|
-
required: ['name'],
|
|
12
|
-
},
|
|
13
|
-
handler: async (args) => {
|
|
14
|
-
try {
|
|
15
|
-
return {
|
|
16
|
-
content: [
|
|
17
|
-
{
|
|
18
|
-
type: 'text',
|
|
19
|
-
text: `👋 Hello ${args.name}! Welcome to the MCP server!`,
|
|
20
|
-
},
|
|
21
|
-
],
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
catch (err) {
|
|
25
|
-
return {
|
|
26
|
-
content: [
|
|
27
|
-
{
|
|
28
|
-
type: 'text',
|
|
29
|
-
text: `Error generating greeting for ${args.name}`,
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
isError: true,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
export const cardTool = {
|
|
38
|
-
name: 'card',
|
|
39
|
-
description: 'Draw a random card from a standard 52-card poker deck',
|
|
40
|
-
inputSchema: {
|
|
41
|
-
type: 'object',
|
|
42
|
-
properties: {},
|
|
43
|
-
required: [],
|
|
44
|
-
},
|
|
45
|
-
handler: async () => {
|
|
46
|
-
try {
|
|
47
|
-
const card = getRandomCard();
|
|
48
|
-
return {
|
|
49
|
-
content: [
|
|
50
|
-
{
|
|
51
|
-
type: 'text',
|
|
52
|
-
text: `🎴 You drew: ${card.value} of ${card.suit}`,
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
catch (err) {
|
|
58
|
-
return {
|
|
59
|
-
content: [
|
|
60
|
-
{
|
|
61
|
-
type: 'text',
|
|
62
|
-
text: 'Error drawing card from deck',
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
isError: true,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
export const dateTimeTool = {
|
|
71
|
-
name: 'datetime',
|
|
72
|
-
description: 'Get the current date and time for a specific timezone',
|
|
73
|
-
inputSchema: {
|
|
74
|
-
type: 'object',
|
|
75
|
-
properties: {
|
|
76
|
-
timeZone: {
|
|
77
|
-
type: 'string',
|
|
78
|
-
description: 'Timezone identifier (e.g., "America/New_York")',
|
|
79
|
-
},
|
|
80
|
-
locale: {
|
|
81
|
-
type: 'string',
|
|
82
|
-
description: 'Locale identifier (e.g., "en-US")',
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
handler: async (args) => {
|
|
87
|
-
try {
|
|
88
|
-
const { date, time, timezone } = getCurrentDateTime(args.timeZone, args.locale);
|
|
89
|
-
return {
|
|
90
|
-
content: [
|
|
91
|
-
{
|
|
92
|
-
type: 'text',
|
|
93
|
-
text: `🗓️ Date: ${date}\n⏰ Time: ${time}\n🌍 Timezone: ${timezone}`,
|
|
94
|
-
},
|
|
95
|
-
],
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
catch (err) {
|
|
99
|
-
return {
|
|
100
|
-
content: [
|
|
101
|
-
{
|
|
102
|
-
type: 'text',
|
|
103
|
-
text: 'Error getting date and time',
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
isError: true,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
};
|
|
111
|
-
export default [greetingTool, cardTool, dateTimeTool];
|
package/dist/types/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/utils/cards.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export const SUITS = ['♠️ Spades', '♥️ Hearts', '♦️ Diamonds', '♣️ Clubs'];
|
|
2
|
-
export const VALUES = ['Ace', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'];
|
|
3
|
-
export function getRandomCard() {
|
|
4
|
-
const randomSuit = SUITS[Math.floor(Math.random() * SUITS.length)];
|
|
5
|
-
const randomValue = VALUES[Math.floor(Math.random() * VALUES.length)];
|
|
6
|
-
return {
|
|
7
|
-
suit: randomSuit,
|
|
8
|
-
value: randomValue,
|
|
9
|
-
};
|
|
10
|
-
}
|
package/dist/utils/datetime.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export function getCurrentDateTime(timeZone, locale) {
|
|
2
|
-
try {
|
|
3
|
-
const now = new Date();
|
|
4
|
-
const defaultTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
5
|
-
const options = {
|
|
6
|
-
timeZone: timeZone || defaultTimeZone,
|
|
7
|
-
dateStyle: 'full',
|
|
8
|
-
timeStyle: 'medium',
|
|
9
|
-
};
|
|
10
|
-
const formatter = new Intl.DateTimeFormat(locale || 'en-US', options);
|
|
11
|
-
const [datePart, timePart] = formatter.format(now).split(' at ');
|
|
12
|
-
return {
|
|
13
|
-
date: datePart,
|
|
14
|
-
time: timePart,
|
|
15
|
-
timezone: timeZone || defaultTimeZone,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
catch (error) {
|
|
19
|
-
console.error('[DateTime] Error formatting date and time:', error);
|
|
20
|
-
const now = new Date();
|
|
21
|
-
const defaultTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
22
|
-
return {
|
|
23
|
-
date: now.toLocaleDateString(),
|
|
24
|
-
time: now.toLocaleTimeString(),
|
|
25
|
-
timezone: defaultTimeZone,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
}
|
package/dist/utils/schema.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
function convertProperty(prop) {
|
|
3
|
-
switch (prop.type) {
|
|
4
|
-
case 'string':
|
|
5
|
-
return z.string();
|
|
6
|
-
case 'number':
|
|
7
|
-
return z.number();
|
|
8
|
-
case 'boolean':
|
|
9
|
-
return z.boolean();
|
|
10
|
-
case 'array':
|
|
11
|
-
if (!prop.items) {
|
|
12
|
-
throw new Error('Array schema must have items property');
|
|
13
|
-
}
|
|
14
|
-
return z.array(convertProperty(prop.items));
|
|
15
|
-
case 'object':
|
|
16
|
-
return z.record(z.string(), z.unknown());
|
|
17
|
-
default:
|
|
18
|
-
return z.unknown();
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
export const schemaConverter = {
|
|
22
|
-
toZod: (schema) => {
|
|
23
|
-
if (schema.type !== 'object') {
|
|
24
|
-
throw new Error('Only object schemas are supported');
|
|
25
|
-
}
|
|
26
|
-
const shape = {};
|
|
27
|
-
if (schema.properties) {
|
|
28
|
-
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
29
|
-
shape[key] = convertProperty(prop);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
const zodSchema = z.object(shape);
|
|
33
|
-
return schema.required?.length ? zodSchema.required() : zodSchema;
|
|
34
|
-
},
|
|
35
|
-
};
|