@cnbcool/mcp-server 0.3.1 → 0.4.0-beta.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 CHANGED
@@ -17,7 +17,7 @@ https://cnb.cool/examples/ecosystem/cnb-mcp-client-with-ollama
17
17
  2. `npx openapi-typescript@5.4.2 https://api.cnb.cool/swagger.json -o src/schema.d.ts`
18
18
  3. Rename `.env.example` to `.env` and fill in the values
19
19
  4. `npm build`
20
- 5. `npx @modelcontextprotocol/inspector -e API_TOKEN=xxxxxxxxxx node dist/index.js`
20
+ 5. `npx @modelcontextprotocol/inspector -e API_TOKEN=xxxxxxxxxx node dist/stdio.js`
21
21
 
22
22
  > @modelcontextprotocol/inspector requires Node.js: ^22.7.5
23
23
 
@@ -32,7 +32,7 @@ https://cnb.cool/examples/ecosystem/cnb-mcp-client-with-ollama
32
32
  "mcpServers": {
33
33
  "cnb": {
34
34
  "command": "node",
35
- "args": ["/path/to/cnbcool/mcp-server/dist/index.js"],
35
+ "args": ["/path/to/cnbcool/mcp-server/dist/stdio.js"],
36
36
  "env": {
37
37
  "API_BASE_URL": "<BASE_URL>", // optional, defualt vaule: https://api.cnb.cool
38
38
  "API_TOKEN": "<YOUR_TOKEN>"
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+ import express from 'express';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
6
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
7
+ import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
8
+ import dotenv from 'dotenv';
9
+ import { registerTools } from './tools/index.js';
10
+ // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html#import-attributes
11
+ import packageJSON from '../package.json' with { type: 'json' };
12
+ dotenv.config();
13
+ // Store transports for each session type
14
+ const transports = {
15
+ streamable: {},
16
+ sse: {}
17
+ };
18
+ const app = express();
19
+ app.use((req, res, next) => {
20
+ const token = req.headers['authorization'];
21
+ if (!token) {
22
+ res.status(401).json({ error: 'Unauthorized' });
23
+ return;
24
+ }
25
+ next();
26
+ });
27
+ app.use(express.json());
28
+ app.post('/mcp', async (req, res) => {
29
+ const sessionId = req.headers['mcp-session-id'];
30
+ let transport;
31
+ // Reuse existing transport
32
+ if (sessionId && transports.streamable[sessionId]) {
33
+ transport = transports.streamable[sessionId];
34
+ await transport.handleRequest(req, res, req.body);
35
+ return;
36
+ }
37
+ // New initialization request
38
+ if (!sessionId && isInitializeRequest(req.body)) {
39
+ transport = new StreamableHTTPServerTransport({
40
+ sessionIdGenerator: () => randomUUID(),
41
+ onsessioninitialized: (sessionId) => {
42
+ transports.streamable[sessionId] = transport;
43
+ }
44
+ });
45
+ // Clean up transport when closed
46
+ transport.onclose = () => {
47
+ if (transport.sessionId) {
48
+ delete transports.streamable[transport.sessionId];
49
+ }
50
+ };
51
+ const mcpServer = new McpServer({
52
+ name: 'cnb-mcp-server',
53
+ version: packageJSON.version
54
+ });
55
+ const token = req.headers['authorization'].split(' ')[1];
56
+ registerTools(mcpServer, token);
57
+ await mcpServer.connect(transport);
58
+ await transport.handleRequest(req, res, req.body);
59
+ return;
60
+ }
61
+ // Invalid request
62
+ res.status(400).json({
63
+ jsonrpc: '2.0',
64
+ error: {
65
+ code: -32000,
66
+ message: 'Bad Request: No valid session ID provided'
67
+ },
68
+ id: null
69
+ });
70
+ });
71
+ const handleSessionRequest = async (req, res) => {
72
+ const sessionId = req.headers['mcp-session-id'];
73
+ if (!sessionId || !transports.streamable[sessionId]) {
74
+ res.status(400).send('Invalid or missing session ID');
75
+ return;
76
+ }
77
+ const transport = transports.streamable[sessionId];
78
+ await transport.handleRequest(req, res);
79
+ };
80
+ app.get('/mcp', handleSessionRequest);
81
+ app.delete('/mcp', handleSessionRequest);
82
+ const mcpServer = new McpServer({
83
+ name: 'cnb-mcp-server',
84
+ version: packageJSON.version
85
+ });
86
+ app.get('/sse', async (req, res) => {
87
+ const transport = new SSEServerTransport('/messages', res);
88
+ transports.sse[transport.sessionId] = transport;
89
+ res.on('close', () => {
90
+ delete transports.sse[transport.sessionId];
91
+ });
92
+ const token = req.headers['authorization'].split(' ')[1];
93
+ registerTools(mcpServer, token);
94
+ await mcpServer.connect(transport);
95
+ });
96
+ app.post('/messages', async (req, res) => {
97
+ const sessionId = req.query.sessionId;
98
+ const transport = transports.sse[sessionId];
99
+ if (transport) {
100
+ await transport.handlePostMessage(req, res);
101
+ }
102
+ else {
103
+ res.status(400).send('No transport found for sessionId');
104
+ }
105
+ });
106
+ const server = app.listen(3000, () => {
107
+ console.log('MCP Streamable HTTP Server listening on port 3000');
108
+ });
109
+ process.on('SIGTERM', () => {
110
+ console.log('SIGTERM signal received: closing HTTP server');
111
+ server.close(() => {
112
+ console.log('HTTP server closed');
113
+ });
114
+ });
package/package.json CHANGED
@@ -1,16 +1,17 @@
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.3.1",
5
- "main": "./dist/index.js",
4
+ "version": "0.4.0-beta.0",
5
+ "main": "./dist/stdio.js",
6
6
  "bin": {
7
- "cnb-mcp-server": "dist/index.js"
7
+ "cnb-mcp-stdio": "dist/stdio.js",
8
+ "cnb-mcp-streamable": "dist/streamable.js"
8
9
  },
9
10
  "type": "module",
10
11
  "scripts": {
11
12
  "build": "tsc",
12
13
  "watch": "tsc --watch",
13
- "start": "node dist/index.js",
14
+ "start": "node dist/stdio.js",
14
15
  "prepare": "husky",
15
16
  "lint": "eslint src",
16
17
  "format": "prettier --check src"
@@ -39,12 +40,14 @@
39
40
  "dependencies": {
40
41
  "@modelcontextprotocol/sdk": "1.10.2",
41
42
  "dotenv": "16.5.0",
43
+ "express": "5.1.0",
42
44
  "zod": "3.24.3"
43
45
  },
44
46
  "devDependencies": {
45
47
  "@commitlint/cli": "19.8.0",
46
48
  "@commitlint/config-conventional": "19.8.0",
47
49
  "@eslint/js": "9.24.0",
50
+ "@types/express": "5.0.1",
48
51
  "@types/node": "22.13.9",
49
52
  "eslint": "9.24.0",
50
53
  "eslint-config-prettier": "10.1.2",
File without changes