@cnbcool/mcp-server
Version:
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
89 lines (88 loc) • 3.7 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const sse_js_1 = require("@modelcontextprotocol/sdk/server/sse.js");
const dotenv_1 = __importDefault(require("dotenv"));
const createMcpServer_js_1 = require("./helpers/createMcpServer.js");
const sendResponse_js_1 = require("./helpers/sendResponse.js");
const createTransport_js_1 = require("./helpers/createTransport.js");
dotenv_1.default.config();
const DEFAULT_APP_PORT = 3000;
const app = (0, express_1.default)();
app.use(express_1.default.json());
app.post('/mcp', async (req, res) => {
let transport;
try {
transport = process.env.MODE_STATELESS
? await (0, createTransport_js_1.createStatelessStreamableTransport)(req, res)
: await (0, createTransport_js_1.createStreamableTransport)(req);
}
catch (err) {
if (typeof err === 'object' && err !== null && 'status' in err && 'message' in err) {
const { status, message } = err;
(0, sendResponse_js_1.stopWithError)(res, status, message);
return;
}
const message = err instanceof Error ? err.message : String(err);
(0, sendResponse_js_1.stopWithServerError)(res, message !== null && message !== void 0 ? message : 'Unknown error');
return;
}
await transport.handleRequest(req, res, req.body);
});
const handleSessionRequest = async (req, res) => {
if (process.env.MODE_STATELESS) {
(0, sendResponse_js_1.stopWithMethodNotAllowed)(res, 'Method not allowed');
return;
}
const sessionId = req.headers['mcp-session-id'];
if (!sessionId || !createTransport_js_1.transports.streamable[sessionId]) {
res.status(400).send('Invalid or missing session ID');
return;
}
const transport = createTransport_js_1.transports.streamable[sessionId];
await transport.handleRequest(req, res, req.body);
};
// SSE notifications not supported in stateless mode
app.get('/mcp', handleSessionRequest);
// Session termination not needed in stateless mode
app.delete('/mcp', handleSessionRequest);
app.get('/sse', async (req, res) => {
const transport = new sse_js_1.SSEServerTransport('/messages', res);
createTransport_js_1.transports.sse[transport.sessionId] = transport;
res.on('close', () => {
delete createTransport_js_1.transports.sse[transport.sessionId];
});
const mcpServer = (0, createMcpServer_js_1.createMcpServer)(req);
await mcpServer.connect(transport);
});
app.post('/messages', async (req, res) => {
const sessionId = req.query.sessionId;
const transport = createTransport_js_1.transports.sse[sessionId];
if (!transport) {
res.status(400).send('No transport found for sessionId');
return;
}
if (!(transport instanceof sse_js_1.SSEServerTransport)) {
(0, sendResponse_js_1.stopWithBadRequest)(res, 'Bad Request: Session exists but uses a different transport protocol');
return;
}
await transport.handlePostMessage(req, res, req.body);
});
let port = parseInt((_a = process.env.APP_PORT) !== null && _a !== void 0 ? _a : '', 10);
if (isNaN(port)) {
port = DEFAULT_APP_PORT;
}
const server = app.listen(port, () => {
console.log(`MCP Streamable HTTP Server listening on port ${port}`);
});
process.on('SIGTERM', () => {
console.log('SIGTERM signal received: closing HTTP server');
server.close(() => {
console.log('HTTP server closed');
});
});