@cnbcool/mcp-server 0.4.5 → 0.5.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.
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.transports = void 0;
4
4
  exports.createStreamableTransport = createStreamableTransport;
5
+ exports.createStatelessStreamableTransport = createStatelessStreamableTransport;
5
6
  const node_crypto_1 = require("node:crypto");
6
7
  const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
7
8
  const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
@@ -17,7 +18,10 @@ async function createStreamableTransport(req) {
17
18
  if (sessionId && exports.transports.streamable[sessionId]) {
18
19
  const transport = exports.transports.streamable[sessionId];
19
20
  if (!(transport instanceof streamableHttp_js_1.StreamableHTTPServerTransport)) {
20
- throw new Error('Bad Request: Session exists but uses a different transport protocol');
21
+ throw {
22
+ status: 400,
23
+ message: 'Session exists but uses a different transport protocol'
24
+ };
21
25
  }
22
26
  return transport;
23
27
  }
@@ -31,8 +35,6 @@ async function createStreamableTransport(req) {
31
35
  });
32
36
  // Clean up transport when closed
33
37
  transport.onclose = () => {
34
- console.log(`Transport closed for session ${transport.sessionId}`);
35
- console.log(Object.keys(exports.transports.streamable));
36
38
  if (transport.sessionId) {
37
39
  delete exports.transports.streamable[transport.sessionId];
38
40
  }
@@ -41,5 +43,30 @@ async function createStreamableTransport(req) {
41
43
  await mcpServer.connect(transport);
42
44
  return transport;
43
45
  }
44
- throw new Error('Bad Request: No valid session ID provided');
46
+ throw {
47
+ status: 400,
48
+ message: 'No valid session ID provided'
49
+ };
50
+ }
51
+ async function createStatelessStreamableTransport(req, res) {
52
+ try {
53
+ const mcpServer = (0, createMcpServer_1.createMcpServer)(req);
54
+ const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
55
+ sessionIdGenerator: undefined
56
+ });
57
+ res.on('close', () => {
58
+ console.log('Request closed');
59
+ void transport.close();
60
+ void mcpServer.close();
61
+ });
62
+ await mcpServer.connect(transport);
63
+ return transport;
64
+ }
65
+ catch (error) {
66
+ console.error('Error handling MCP request:', error);
67
+ if (!res.headersSent) {
68
+ throw new Error('Internal Server Error');
69
+ }
70
+ throw error;
71
+ }
45
72
  }
@@ -1,6 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stopWithError = stopWithError;
3
4
  exports.stopWithBadRequest = stopWithBadRequest;
5
+ exports.stopWithMethodNotAllowed = stopWithMethodNotAllowed;
6
+ exports.stopWithServerError = stopWithServerError;
7
+ function stopWithError(res, status, message) {
8
+ if (status === 400) {
9
+ stopWithBadRequest(res, message);
10
+ return;
11
+ }
12
+ if (status === 405) {
13
+ stopWithMethodNotAllowed(res, message);
14
+ return;
15
+ }
16
+ stopWithServerError(res, message);
17
+ }
4
18
  function stopWithBadRequest(res, message) {
5
19
  res.status(400).json({
6
20
  jsonrpc: '2.0',
@@ -11,3 +25,23 @@ function stopWithBadRequest(res, message) {
11
25
  id: null
12
26
  });
13
27
  }
28
+ function stopWithMethodNotAllowed(res, message) {
29
+ res.writeHead(405).end(JSON.stringify({
30
+ jsonrpc: '2.0',
31
+ error: {
32
+ code: -32000,
33
+ message
34
+ },
35
+ id: null
36
+ }));
37
+ }
38
+ function stopWithServerError(res, message) {
39
+ res.status(500).json({
40
+ jsonrpc: '2.0',
41
+ error: {
42
+ code: -32603,
43
+ message
44
+ },
45
+ id: null
46
+ });
47
+ }
@@ -18,16 +18,27 @@ app.use(express_1.default.json());
18
18
  app.post('/mcp', async (req, res) => {
19
19
  let transport;
20
20
  try {
21
- transport = await (0, createTransport_js_1.createStreamableTransport)(req);
21
+ transport = process.env.MODE_STATELESS
22
+ ? await (0, createTransport_js_1.createStatelessStreamableTransport)(req, res)
23
+ : await (0, createTransport_js_1.createStreamableTransport)(req);
22
24
  }
23
25
  catch (err) {
24
- const message = err instanceof Error ? err.message : 'Unknown error';
25
- (0, sendResponse_js_1.stopWithBadRequest)(res, message);
26
+ if (typeof err === 'object' && err !== null && 'status' in err && 'message' in err) {
27
+ const { status, message } = err;
28
+ (0, sendResponse_js_1.stopWithError)(res, status, message);
29
+ return;
30
+ }
31
+ const message = err instanceof Error ? err.message : String(err);
32
+ (0, sendResponse_js_1.stopWithServerError)(res, message !== null && message !== void 0 ? message : 'Unknown error');
26
33
  return;
27
34
  }
28
35
  await transport.handleRequest(req, res, req.body);
29
36
  });
30
37
  const handleSessionRequest = async (req, res) => {
38
+ if (process.env.MODE_STATELESS) {
39
+ (0, sendResponse_js_1.stopWithMethodNotAllowed)(res, 'Method not allowed');
40
+ return;
41
+ }
31
42
  const sessionId = req.headers['mcp-session-id'];
32
43
  if (!sessionId || !createTransport_js_1.transports.streamable[sessionId]) {
33
44
  res.status(400).send('Invalid or missing session ID');
@@ -36,7 +47,9 @@ const handleSessionRequest = async (req, res) => {
36
47
  const transport = createTransport_js_1.transports.streamable[sessionId];
37
48
  await transport.handleRequest(req, res, req.body);
38
49
  };
50
+ // SSE notifications not supported in stateless mode
39
51
  app.get('/mcp', handleSessionRequest);
52
+ // Session termination not needed in stateless mode
40
53
  app.delete('/mcp', handleSessionRequest);
41
54
  app.get('/sse', async (req, res) => {
42
55
  const transport = new sse_js_1.SSEServerTransport('/messages', res);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cnbcool/mcp-server",
3
3
  "description": "CNB MCP Server. A comprehensive MCP server that provides seamless integration to the CNB's API(https://cnb.cool), offering a wide range of tools for repository management, pipelines operations and collaboration features",
4
- "version": "0.4.5",
4
+ "version": "0.5.0",
5
5
  "main": "./dist/stdio.js",
6
6
  "bin": {
7
7
  "cnb-mcp-stdio": "dist/stdio.js",