forked from Nutlope/logocreator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmcp-test-server.mjs
167 lines (146 loc) · 4.71 KB
/
mcp-test-server.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
#!/usr/bin/env node
// STDIO-based MCP server
process.stdin.setEncoding('utf8');
let buffer = '';
// Handle incoming data from stdin
process.stdin.on('data', (chunk) => {
buffer += chunk;
// Try to process complete JSON-RPC messages
let newlineIndex;
while ((newlineIndex = buffer.indexOf('\n')) !== -1) {
const line = buffer.slice(0, newlineIndex);
buffer = buffer.slice(newlineIndex + 1);
if (line.trim()) {
try {
const request = JSON.parse(line);
console.error('Received request:', request);
// Handle the request
handleRequest(request);
} catch (error) {
console.error('Error parsing JSON:', error);
sendError(null, -32700, 'Parse error', error.message);
}
}
}
});
// Handle process termination
process.on('SIGINT', () => {
console.error('Received SIGINT. Shutting down...');
process.exit(0);
});
process.on('SIGTERM', () => {
console.error('Received SIGTERM. Shutting down...');
process.exit(0);
});
// Send a message to stdout
function sendMessage(message) {
process.stdout.write(JSON.stringify(message) + '\n');
}
// Send an error response
function sendError(id, code, message, data) {
const error = {
jsonrpc: '2.0',
id,
error: {
code,
message,
data
}
};
sendMessage(error);
}
// Send a notification
function sendNotification(method, params) {
const notification = {
jsonrpc: '2.0',
method,
params
};
sendMessage(notification);
}
// Handle incoming requests
function handleRequest(request) {
if (!request.jsonrpc || request.jsonrpc !== '2.0') {
return sendError(request.id, -32600, 'Invalid Request', 'Invalid JSON-RPC version');
}
// Handle method calls
switch (request.method) {
case 'initialize':
// Send proper MCP initialization response
sendMessage({
jsonrpc: '2.0',
id: request.id,
result: {
protocolVersion: request.params.protocolVersion,
capabilities: {
completions: {
maxTokens: 2048,
streaming: true,
models: ['test-model']
},
notifications: {
supported: true
}
},
serverInfo: {
name: 'test-mcp-server',
version: '1.0.0'
}
}
});
// Send ready notification after initialization
sendNotification('server/ready', {
status: 'ready'
});
break;
case 'complete':
// Send a streaming completion response
const messageId = request.id;
// Send start of stream
sendMessage({
jsonrpc: '2.0',
id: messageId,
result: {
choices: [{
index: 0,
message: {
role: 'assistant',
content: ''
}
}]
}
});
// Stream some content
let content = 'This is a test response from the MCP server.';
for (let i = 0; i < content.length; i++) {
setTimeout(() => {
sendNotification('completion/chunk', {
id: messageId,
choices: [{
index: 0,
delta: {
content: content[i]
}
}]
});
// If this is the last character, send end of stream
if (i === content.length - 1) {
sendNotification('completion/done', {
id: messageId
});
}
}, i * 100); // Stream each character with 100ms delay
}
break;
default:
sendError(request.id, -32601, 'Method not found', `Method ${request.method} not supported`);
}
}
// Send periodic heartbeat notifications
setInterval(() => {
sendNotification('server/heartbeat', {
timestamp: new Date().toISOString()
});
}, 30000);
// Log startup
console.error('MCP test server running (STDIO mode)');