sychev-lab-mcp-server 1.0.2
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 +173 -0
- package/dist/client.d.ts +111 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +143 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +22 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +312 -0
- package/dist/index.js.map +1 -0
- package/dist/server-http.d.ts +9 -0
- package/dist/server-http.d.ts.map +1 -0
- package/dist/server-http.js +235 -0
- package/dist/server-http.js.map +1 -0
- package/dist/tools.d.ts +184 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +376 -0
- package/dist/tools.js.map +1 -0
- package/package.json +56 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Sychev Lab MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Supports both stdio (for Claude Desktop) and HTTP (for remote clients) transports
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/index.js # Run with stdio transport (default)
|
|
9
|
+
* node dist/index.js --http # Run with HTTP transport
|
|
10
|
+
* node dist/index.js --http 3000 # Run HTTP on port 3000
|
|
11
|
+
*/
|
|
12
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
13
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
14
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
15
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
16
|
+
import { validateConfig, config } from './config.js';
|
|
17
|
+
import { GetProductSchema, SearchProductsSchema, GetArticleSchema, GetTutorialSchema, GetCategoriesSchema, RegisterUserSchema, CreateCheckoutSchema, ListProductsSchema, ListArticlesSchema, ListTutorialsSchema, getProductDetails, searchProductsByCategory, getArticle, getTutorial, getCategories, registerUser, createStripeCheckout, listProducts, listArticles, listTutorials, } from './tools.js';
|
|
18
|
+
// Tool definitions with schemas
|
|
19
|
+
const TOOLS = [
|
|
20
|
+
{
|
|
21
|
+
name: 'list_products',
|
|
22
|
+
description: 'List all available products from the catalog. Optionally filter by featured products only.',
|
|
23
|
+
inputSchema: zodToJsonSchema(ListProductsSchema),
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'get_product_details',
|
|
27
|
+
description: 'Get detailed information about a specific product including price, description, images, and specifications.',
|
|
28
|
+
inputSchema: zodToJsonSchema(GetProductSchema),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'search_products_by_category',
|
|
32
|
+
description: 'Search products within a specific category. Returns matching products with their details.',
|
|
33
|
+
inputSchema: zodToJsonSchema(SearchProductsSchema),
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'get_categories',
|
|
37
|
+
description: 'Get all product categories available in the store.',
|
|
38
|
+
inputSchema: zodToJsonSchema(GetCategoriesSchema),
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'list_articles',
|
|
42
|
+
description: 'List all available articles. Optionally filter by featured articles only.',
|
|
43
|
+
inputSchema: zodToJsonSchema(ListArticlesSchema),
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'get_article',
|
|
47
|
+
description: 'Get full content of a specific article by ID and language.',
|
|
48
|
+
inputSchema: zodToJsonSchema(GetArticleSchema),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'list_tutorials',
|
|
52
|
+
description: 'List all available tutorials. Optionally filter by featured tutorials only.',
|
|
53
|
+
inputSchema: zodToJsonSchema(ListTutorialsSchema),
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'get_tutorial',
|
|
57
|
+
description: 'Get full content of a specific tutorial by ID and language including difficulty and duration.',
|
|
58
|
+
inputSchema: zodToJsonSchema(GetTutorialSchema),
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'register_user',
|
|
62
|
+
description: 'Register a new user account with email and password. Returns user UID on success.',
|
|
63
|
+
inputSchema: zodToJsonSchema(RegisterUserSchema),
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'create_stripe_checkout',
|
|
67
|
+
description: 'Create a Stripe checkout session for purchasing products. Provide product UUIDs and quantities; product details (name, price) are fetched automatically. Returns a URL to redirect the user to complete payment.',
|
|
68
|
+
inputSchema: zodToJsonSchema(CreateCheckoutSchema),
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
// Create MCP server
|
|
72
|
+
const server = new Server({
|
|
73
|
+
name: config.name,
|
|
74
|
+
version: config.version,
|
|
75
|
+
}, {
|
|
76
|
+
capabilities: {
|
|
77
|
+
tools: {},
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
// Handle list tools request
|
|
81
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
82
|
+
return { tools: TOOLS };
|
|
83
|
+
});
|
|
84
|
+
// Handle tool calls
|
|
85
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
86
|
+
const { name, arguments: args } = request.params;
|
|
87
|
+
try {
|
|
88
|
+
switch (name) {
|
|
89
|
+
case 'list_products':
|
|
90
|
+
return await listProducts(ListProductsSchema.parse(args));
|
|
91
|
+
case 'get_product_details':
|
|
92
|
+
return await getProductDetails(GetProductSchema.parse(args));
|
|
93
|
+
case 'search_products_by_category':
|
|
94
|
+
return await searchProductsByCategory(SearchProductsSchema.parse(args));
|
|
95
|
+
case 'get_categories':
|
|
96
|
+
return await getCategories(GetCategoriesSchema.parse(args));
|
|
97
|
+
case 'list_articles':
|
|
98
|
+
return await listArticles(ListArticlesSchema.parse(args));
|
|
99
|
+
case 'get_article':
|
|
100
|
+
return await getArticle(GetArticleSchema.parse(args));
|
|
101
|
+
case 'list_tutorials':
|
|
102
|
+
return await listTutorials(ListTutorialsSchema.parse(args));
|
|
103
|
+
case 'get_tutorial':
|
|
104
|
+
return await getTutorial(GetTutorialSchema.parse(args));
|
|
105
|
+
case 'register_user':
|
|
106
|
+
return await registerUser(RegisterUserSchema.parse(args));
|
|
107
|
+
case 'create_stripe_checkout':
|
|
108
|
+
return await createStripeCheckout(CreateCheckoutSchema.parse(args));
|
|
109
|
+
default:
|
|
110
|
+
return {
|
|
111
|
+
content: [{
|
|
112
|
+
type: 'text',
|
|
113
|
+
text: JSON.stringify({ error: `Unknown tool: ${name}` }),
|
|
114
|
+
}],
|
|
115
|
+
isError: true,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
if (error instanceof Error && error.name === 'ZodError') {
|
|
121
|
+
return {
|
|
122
|
+
content: [{
|
|
123
|
+
type: 'text',
|
|
124
|
+
text: JSON.stringify({
|
|
125
|
+
error: 'Invalid arguments',
|
|
126
|
+
details: error.message,
|
|
127
|
+
}, null, 2),
|
|
128
|
+
}],
|
|
129
|
+
isError: true,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
// Run server with stdio transport
|
|
136
|
+
async function runStdioServer() {
|
|
137
|
+
validateConfig();
|
|
138
|
+
const transport = new StdioServerTransport();
|
|
139
|
+
// Log to stderr so it doesn't interfere with stdio communication
|
|
140
|
+
console.error(`Sychev Lab MCP Server v${config.version}`);
|
|
141
|
+
console.error(`Connected to: ${config.baseUrl}`);
|
|
142
|
+
console.error('Running with stdio transport...');
|
|
143
|
+
await server.connect(transport);
|
|
144
|
+
}
|
|
145
|
+
// Run server with HTTP transport
|
|
146
|
+
async function runHttpServer(port) {
|
|
147
|
+
validateConfig();
|
|
148
|
+
const http = await import('http');
|
|
149
|
+
const url = await import('url');
|
|
150
|
+
// API key is optional - only used if MCP_API_KEY is set
|
|
151
|
+
const API_KEY = process.env.MCP_API_KEY;
|
|
152
|
+
const httpServer = http.createServer(async (req, res) => {
|
|
153
|
+
// CORS headers
|
|
154
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
155
|
+
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
|
156
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
157
|
+
res.setHeader('Content-Type', 'application/json');
|
|
158
|
+
if (req.method === 'OPTIONS') {
|
|
159
|
+
res.writeHead(200);
|
|
160
|
+
res.end();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// Only accept POST requests
|
|
164
|
+
if (req.method !== 'POST') {
|
|
165
|
+
res.writeHead(405);
|
|
166
|
+
res.end(JSON.stringify({ error: 'Method not allowed' }));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
// Check API key only if configured
|
|
170
|
+
if (API_KEY) {
|
|
171
|
+
const authHeader = req.headers['authorization'] || '';
|
|
172
|
+
const apiKey = authHeader.replace('Bearer ', '');
|
|
173
|
+
if (apiKey !== API_KEY) {
|
|
174
|
+
res.writeHead(401);
|
|
175
|
+
res.end(JSON.stringify({ error: 'Unauthorized' }));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// Parse URL
|
|
180
|
+
const parsedUrl = url.parse(req.url || '', true);
|
|
181
|
+
const pathname = parsedUrl.pathname;
|
|
182
|
+
// Read body
|
|
183
|
+
let body = '';
|
|
184
|
+
req.on('data', (chunk) => {
|
|
185
|
+
body += chunk.toString();
|
|
186
|
+
});
|
|
187
|
+
req.on('end', async () => {
|
|
188
|
+
try {
|
|
189
|
+
// Parse body for tool calls, empty body is ok for list
|
|
190
|
+
let requestData = {};
|
|
191
|
+
if (body.trim()) {
|
|
192
|
+
requestData = JSON.parse(body);
|
|
193
|
+
}
|
|
194
|
+
if (pathname === '/mcp/v1/tools/list') {
|
|
195
|
+
// List tools
|
|
196
|
+
res.writeHead(200);
|
|
197
|
+
res.end(JSON.stringify({ tools: TOOLS }));
|
|
198
|
+
}
|
|
199
|
+
else if (pathname === '/mcp/v1/tools/call') {
|
|
200
|
+
// Call tool
|
|
201
|
+
const { name, arguments: args } = requestData;
|
|
202
|
+
let result;
|
|
203
|
+
try {
|
|
204
|
+
switch (name) {
|
|
205
|
+
case 'list_products':
|
|
206
|
+
result = await listProducts(ListProductsSchema.parse(args));
|
|
207
|
+
break;
|
|
208
|
+
case 'get_product_details':
|
|
209
|
+
result = await getProductDetails(GetProductSchema.parse(args));
|
|
210
|
+
break;
|
|
211
|
+
case 'search_products_by_category':
|
|
212
|
+
result = await searchProductsByCategory(SearchProductsSchema.parse(args));
|
|
213
|
+
break;
|
|
214
|
+
case 'get_categories':
|
|
215
|
+
result = await getCategories(GetCategoriesSchema.parse(args));
|
|
216
|
+
break;
|
|
217
|
+
case 'list_articles':
|
|
218
|
+
result = await listArticles(ListArticlesSchema.parse(args));
|
|
219
|
+
break;
|
|
220
|
+
case 'get_article':
|
|
221
|
+
result = await getArticle(GetArticleSchema.parse(args));
|
|
222
|
+
break;
|
|
223
|
+
case 'list_tutorials':
|
|
224
|
+
result = await listTutorials(ListTutorialsSchema.parse(args));
|
|
225
|
+
break;
|
|
226
|
+
case 'get_tutorial':
|
|
227
|
+
result = await getTutorial(GetTutorialSchema.parse(args));
|
|
228
|
+
break;
|
|
229
|
+
case 'register_user':
|
|
230
|
+
result = await registerUser(RegisterUserSchema.parse(args));
|
|
231
|
+
break;
|
|
232
|
+
case 'create_stripe_checkout':
|
|
233
|
+
result = await createStripeCheckout(CreateCheckoutSchema.parse(args));
|
|
234
|
+
break;
|
|
235
|
+
default:
|
|
236
|
+
result = {
|
|
237
|
+
content: [{
|
|
238
|
+
type: 'text',
|
|
239
|
+
text: JSON.stringify({ error: `Unknown tool: ${name}` }),
|
|
240
|
+
}],
|
|
241
|
+
isError: true,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
if (error instanceof Error && error.name === 'ZodError') {
|
|
247
|
+
result = {
|
|
248
|
+
content: [{
|
|
249
|
+
type: 'text',
|
|
250
|
+
text: JSON.stringify({
|
|
251
|
+
error: 'Invalid arguments',
|
|
252
|
+
details: error.message,
|
|
253
|
+
}, null, 2),
|
|
254
|
+
}],
|
|
255
|
+
isError: true,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
res.writeHead(200);
|
|
263
|
+
res.end(JSON.stringify(result));
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
res.writeHead(404);
|
|
267
|
+
res.end(JSON.stringify({ error: 'Not found' }));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
res.writeHead(500);
|
|
272
|
+
res.end(JSON.stringify({
|
|
273
|
+
error: 'Internal server error',
|
|
274
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
275
|
+
}));
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
httpServer.listen(port, () => {
|
|
280
|
+
console.log(`Sychev Lab MCP Server v${config.version}`);
|
|
281
|
+
console.log(`Connected to: ${config.baseUrl}`);
|
|
282
|
+
console.log(`HTTP transport running on port ${port}`);
|
|
283
|
+
console.log(`\nEndpoints:`);
|
|
284
|
+
console.log(` POST http://localhost:${port}/mcp/v1/tools/list`);
|
|
285
|
+
console.log(` POST http://localhost:${port}/mcp/v1/tools/call`);
|
|
286
|
+
console.log(` Content-Type: application/json`);
|
|
287
|
+
if (API_KEY) {
|
|
288
|
+
console.log(`\nAuthentication required:`);
|
|
289
|
+
console.log(` Authorization: Bearer <MCP_API_KEY>`);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
// Parse command line arguments
|
|
294
|
+
const args = process.argv.slice(2);
|
|
295
|
+
const useHttp = args.includes('--http');
|
|
296
|
+
const httpPortIndex = args.indexOf('--http');
|
|
297
|
+
const httpPort = httpPortIndex !== -1 && args[httpPortIndex + 1]
|
|
298
|
+
? parseInt(args[httpPortIndex + 1], 10)
|
|
299
|
+
: 3000;
|
|
300
|
+
if (useHttp) {
|
|
301
|
+
runHttpServer(httpPort).catch((error) => {
|
|
302
|
+
console.error('Fatal error:', error);
|
|
303
|
+
process.exit(1);
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
runStdioServer().catch((error) => {
|
|
308
|
+
console.error('Fatal error:', error);
|
|
309
|
+
process.exit(1);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-http.d.ts","sourceRoot":"","sources":["../src/server-http.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP HTTP Server with Streamable HTTP + SSE Legacy
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* node dist/server-http.js # Run HTTP server on port 3001
|
|
6
|
+
* PORT=3001 node dist/server-http.js
|
|
7
|
+
*/
|
|
8
|
+
import http from "http";
|
|
9
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
10
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
11
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
12
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
13
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
14
|
+
import { validateConfig, config } from "./config.js";
|
|
15
|
+
import { GetProductSchema, SearchProductsSchema, GetArticleSchema, GetTutorialSchema, GetCategoriesSchema, RegisterUserSchema, CreateCheckoutSchema, ListProductsSchema, ListArticlesSchema, ListTutorialsSchema, getProductDetails, searchProductsByCategory, getArticle, getTutorial, getCategories, registerUser, createStripeCheckout, listProducts, listArticles, listTutorials, } from "./tools.js";
|
|
16
|
+
// ── Tool definitions ──────────────────────────────────────────────────
|
|
17
|
+
const TOOLS = [
|
|
18
|
+
{
|
|
19
|
+
name: "list_products",
|
|
20
|
+
description: "List all available products from the catalog. Optionally filter by featured products only.",
|
|
21
|
+
inputSchema: zodToJsonSchema(ListProductsSchema),
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "get_product_details",
|
|
25
|
+
description: "Get detailed information about a specific product including price, description, images, and specifications.",
|
|
26
|
+
inputSchema: zodToJsonSchema(GetProductSchema),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "search_products_by_category",
|
|
30
|
+
description: "Search products within a specific category. Returns matching products with their details.",
|
|
31
|
+
inputSchema: zodToJsonSchema(SearchProductsSchema),
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "get_categories",
|
|
35
|
+
description: "Get all product categories available in the store.",
|
|
36
|
+
inputSchema: zodToJsonSchema(GetCategoriesSchema),
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: "list_articles",
|
|
40
|
+
description: "List all available articles. Optionally filter by featured articles only.",
|
|
41
|
+
inputSchema: zodToJsonSchema(ListArticlesSchema),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "get_article",
|
|
45
|
+
description: "Get full content of a specific article by ID and language.",
|
|
46
|
+
inputSchema: zodToJsonSchema(GetArticleSchema),
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
name: "list_tutorials",
|
|
50
|
+
description: "List all available tutorials. Optionally filter by featured tutorials only.",
|
|
51
|
+
inputSchema: zodToJsonSchema(ListTutorialsSchema),
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "get_tutorial",
|
|
55
|
+
description: "Get full content of a specific tutorial by ID and language including difficulty and duration.",
|
|
56
|
+
inputSchema: zodToJsonSchema(GetTutorialSchema),
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "register_user",
|
|
60
|
+
description: "Register a new user account with email and password. Returns user UID on success.",
|
|
61
|
+
inputSchema: zodToJsonSchema(RegisterUserSchema),
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: "create_stripe_checkout",
|
|
65
|
+
description: "Create a Stripe checkout session for purchasing products. Provide product UUIDs and quantities; product details (name, price) are fetched automatically. Returns a URL to redirect the user to complete payment.",
|
|
66
|
+
inputSchema: zodToJsonSchema(CreateCheckoutSchema),
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
// ── Server factory ────────────────────────────────────────────────────
|
|
70
|
+
function createServer() {
|
|
71
|
+
const server = new Server({ name: config.name, version: config.version }, { capabilities: { tools: {} } });
|
|
72
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
73
|
+
return { tools: TOOLS };
|
|
74
|
+
});
|
|
75
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
76
|
+
const { name, arguments: args } = request.params;
|
|
77
|
+
try {
|
|
78
|
+
switch (name) {
|
|
79
|
+
case "list_products":
|
|
80
|
+
return await listProducts(ListProductsSchema.parse(args));
|
|
81
|
+
case "get_product_details":
|
|
82
|
+
return await getProductDetails(GetProductSchema.parse(args));
|
|
83
|
+
case "search_products_by_category":
|
|
84
|
+
return await searchProductsByCategory(SearchProductsSchema.parse(args));
|
|
85
|
+
case "get_categories":
|
|
86
|
+
return await getCategories(GetCategoriesSchema.parse(args));
|
|
87
|
+
case "list_articles":
|
|
88
|
+
return await listArticles(ListArticlesSchema.parse(args));
|
|
89
|
+
case "get_article":
|
|
90
|
+
return await getArticle(GetArticleSchema.parse(args));
|
|
91
|
+
case "list_tutorials":
|
|
92
|
+
return await listTutorials(ListTutorialsSchema.parse(args));
|
|
93
|
+
case "get_tutorial":
|
|
94
|
+
return await getTutorial(GetTutorialSchema.parse(args));
|
|
95
|
+
case "register_user":
|
|
96
|
+
return await registerUser(RegisterUserSchema.parse(args));
|
|
97
|
+
case "create_stripe_checkout":
|
|
98
|
+
return await createStripeCheckout(CreateCheckoutSchema.parse(args));
|
|
99
|
+
default:
|
|
100
|
+
return {
|
|
101
|
+
content: [{ type: "text", text: JSON.stringify({ error: `Unknown tool: ${name}` }) }],
|
|
102
|
+
isError: true,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (error instanceof Error && error.name === "ZodError") {
|
|
108
|
+
return {
|
|
109
|
+
content: [
|
|
110
|
+
{
|
|
111
|
+
type: "text",
|
|
112
|
+
text: JSON.stringify({ error: "Invalid arguments", details: error.message }, null, 2),
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
isError: true,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return server;
|
|
122
|
+
}
|
|
123
|
+
// ── CORS ──────────────────────────────────────────────────────────────
|
|
124
|
+
function setCorsHeaders(res) {
|
|
125
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
126
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
|
|
127
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Mcp-Session-Id");
|
|
128
|
+
}
|
|
129
|
+
// ── Streamable HTTP ───────────────────────────────────────────────────
|
|
130
|
+
const streamableSessions = new Map();
|
|
131
|
+
async function handleMcp(req, res) {
|
|
132
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
133
|
+
let transport;
|
|
134
|
+
if (sessionId && streamableSessions.has(sessionId)) {
|
|
135
|
+
transport = streamableSessions.get(sessionId);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
transport = new StreamableHTTPServerTransport({
|
|
139
|
+
sessionIdGenerator: () => crypto.randomUUID(),
|
|
140
|
+
onsessioninitialized: (id) => {
|
|
141
|
+
streamableSessions.set(id, transport);
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
transport.onclose = () => {
|
|
145
|
+
if (transport.sessionId)
|
|
146
|
+
streamableSessions.delete(transport.sessionId);
|
|
147
|
+
};
|
|
148
|
+
const server = createServer();
|
|
149
|
+
await server.connect(transport);
|
|
150
|
+
}
|
|
151
|
+
await transport.handleRequest(req, res);
|
|
152
|
+
}
|
|
153
|
+
// ── SSE Legacy ────────────────────────────────────────────────────────
|
|
154
|
+
const sseSessions = new Map();
|
|
155
|
+
async function handleSse(req, res) {
|
|
156
|
+
const transport = new SSEServerTransport("/messages", res, {
|
|
157
|
+
enableDnsRebindingProtection: false,
|
|
158
|
+
});
|
|
159
|
+
sseSessions.set(transport.sessionId, transport);
|
|
160
|
+
const server = createServer();
|
|
161
|
+
await server.connect(transport);
|
|
162
|
+
res.on("close", () => sseSessions.delete(transport.sessionId));
|
|
163
|
+
}
|
|
164
|
+
async function handleMessages(req, res) {
|
|
165
|
+
const url = new URL(req.url || "/messages", `http://${req.headers.host}`);
|
|
166
|
+
const sessionId = url.searchParams.get("sessionId") || undefined;
|
|
167
|
+
if (!sessionId || !sseSessions.has(sessionId)) {
|
|
168
|
+
res.writeHead(404).end(JSON.stringify({ error: "Session not found" }));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const transport = sseSessions.get(sessionId);
|
|
172
|
+
await transport.handlePostMessage(req, res);
|
|
173
|
+
}
|
|
174
|
+
// ── HTTP Server ───────────────────────────────────────────────────────
|
|
175
|
+
validateConfig();
|
|
176
|
+
const PORT = parseInt(process.env.PORT || "3001", 10);
|
|
177
|
+
const httpServer = http.createServer(async (req, res) => {
|
|
178
|
+
setCorsHeaders(res);
|
|
179
|
+
if (req.method === "OPTIONS") {
|
|
180
|
+
res.writeHead(200).end();
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const pathname = new URL(req.url || "/", `http://${req.headers.host}`).pathname;
|
|
184
|
+
try {
|
|
185
|
+
if (pathname === "/mcp") {
|
|
186
|
+
await handleMcp(req, res);
|
|
187
|
+
}
|
|
188
|
+
else if (pathname === "/sse") {
|
|
189
|
+
await handleSse(req, res);
|
|
190
|
+
}
|
|
191
|
+
else if (pathname === "/messages") {
|
|
192
|
+
await handleMessages(req, res);
|
|
193
|
+
}
|
|
194
|
+
else if (pathname === "/health") {
|
|
195
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
196
|
+
res.end(JSON.stringify({ status: "ok", server: config.name, version: config.version }));
|
|
197
|
+
}
|
|
198
|
+
else if (pathname === "/.well-known/mcp") {
|
|
199
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
200
|
+
res.end(JSON.stringify({
|
|
201
|
+
mcp_version: "2025-06-18",
|
|
202
|
+
name: "Sychev Lab MCP Server",
|
|
203
|
+
description: "Accede al catalogo de modelos 3D de Sychev Lab: airsoft, automocion y electronica",
|
|
204
|
+
endpoints: {
|
|
205
|
+
streamable_http: `${config.baseUrl}/mcp`,
|
|
206
|
+
sse: `${config.baseUrl}/sse`,
|
|
207
|
+
},
|
|
208
|
+
capabilities: { tools: {} },
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
213
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
console.error("HTTP error:", error);
|
|
218
|
+
if (!res.headersSent) {
|
|
219
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
220
|
+
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
httpServer.listen(PORT, () => {
|
|
225
|
+
console.log(`Sychev Lab MCP Server v${config.version}`);
|
|
226
|
+
console.log(`Connected to: ${config.baseUrl}`);
|
|
227
|
+
console.log(`HTTP transport running on port ${PORT}`);
|
|
228
|
+
console.log("\nEndpoints:");
|
|
229
|
+
console.log(` POST/DELETE http://localhost:${PORT}/mcp (Streamable HTTP)`);
|
|
230
|
+
console.log(` GET http://localhost:${PORT}/sse (SSE Legacy)`);
|
|
231
|
+
console.log(` POST http://localhost:${PORT}/messages (SSE Messages)`);
|
|
232
|
+
console.log(` GET http://localhost:${PORT}/health (Health Check)`);
|
|
233
|
+
console.log(` GET http://localhost:${PORT}/.well-known/mcp (Discovery)`);
|
|
234
|
+
});
|
|
235
|
+
//# sourceMappingURL=server-http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-http.js","sourceRoot":"","sources":["../src/server-http.ts"],"names":[],"mappings":"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"}
|