mcp-server-db2i 1.2.1 → 1.3.1
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 +90 -308
- package/dist/auth/authMiddleware.d.ts +66 -0
- package/dist/auth/authMiddleware.d.ts.map +1 -0
- package/dist/auth/authMiddleware.js +217 -0
- package/dist/auth/authMiddleware.js.map +1 -0
- package/dist/auth/index.d.ts +9 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +10 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/tokenManager.d.ts +114 -0
- package/dist/auth/tokenManager.d.ts.map +1 -0
- package/dist/auth/tokenManager.js +255 -0
- package/dist/auth/tokenManager.js.map +1 -0
- package/dist/auth/types.d.ts +103 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +10 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/config.d.ts +128 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +185 -0
- package/dist/config.js.map +1 -1
- package/dist/db/connection.d.ts +53 -3
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +154 -15
- package/dist/db/connection.js.map +1 -1
- package/dist/db/queries.d.ts +29 -6
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +35 -12
- package/dist/db/queries.js.map +1 -1
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +97 -42
- package/dist/index.js.map +1 -1
- package/dist/openapi.d.ts +49 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +634 -0
- package/dist/openapi.js.map +1 -0
- package/dist/server.d.ts +26 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +68 -22
- package/dist/server.js.map +1 -1
- package/dist/tools/metadata.d.ts +10 -0
- package/dist/tools/metadata.d.ts.map +1 -1
- package/dist/tools/metadata.js +10 -6
- package/dist/tools/metadata.js.map +1 -1
- package/dist/tools/query.d.ts +4 -0
- package/dist/tools/query.d.ts.map +1 -1
- package/dist/tools/query.js +5 -3
- package/dist/tools/query.js.map +1 -1
- package/dist/transports/http.d.ts +26 -0
- package/dist/transports/http.d.ts.map +1 -0
- package/dist/transports/http.js +552 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/index.d.ts +8 -0
- package/dist/transports/index.d.ts.map +1 -0
- package/dist/transports/index.js +8 -0
- package/dist/transports/index.js.map +1 -0
- package/dist/transports/sessionManager.d.ts +106 -0
- package/dist/transports/sessionManager.d.ts.map +1 -0
- package/dist/transports/sessionManager.js +260 -0
- package/dist/transports/sessionManager.js.map +1 -0
- package/package.json +9 -5
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Transport for MCP Server
|
|
3
|
+
*
|
|
4
|
+
* Express-based HTTP server with:
|
|
5
|
+
* - OAuth-style token authentication (/auth)
|
|
6
|
+
* - MCP protocol endpoints (/mcp)
|
|
7
|
+
* - Health check endpoint (/health)
|
|
8
|
+
* - Stateful and stateless session modes
|
|
9
|
+
* - Optional TLS support
|
|
10
|
+
*/
|
|
11
|
+
import express from 'express';
|
|
12
|
+
import https from 'node:https';
|
|
13
|
+
import http from 'node:http';
|
|
14
|
+
import crypto from 'node:crypto';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
17
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
18
|
+
import { getHttpConfig, loadConfig, loadPartialConfig, } from '../config.js';
|
|
19
|
+
import { createChildLogger } from '../utils/logger.js';
|
|
20
|
+
import { getTokenManager, authMiddleware, authRateLimitMiddleware, recordFailedAuthAttempt, clearAuthRateLimit, } from '../auth/index.js';
|
|
21
|
+
import { getSessionManager } from './sessionManager.js';
|
|
22
|
+
import { createServer as createMcpServer, SERVER_NAME, SERVER_VERSION } from '../server.js';
|
|
23
|
+
import { getOpenApiSpec } from '../openapi.js';
|
|
24
|
+
import { initializeSessionPool, testSessionConnection, closeSessionPool, closeAllSessionPools } from '../db/connection.js';
|
|
25
|
+
const log = createChildLogger({ component: 'http-transport' });
|
|
26
|
+
/**
|
|
27
|
+
* Validate auth request body
|
|
28
|
+
*/
|
|
29
|
+
function validateAuthRequest(body) {
|
|
30
|
+
if (!body || typeof body !== 'object') {
|
|
31
|
+
return { valid: false, error: 'Request body must be a JSON object' };
|
|
32
|
+
}
|
|
33
|
+
const req = body;
|
|
34
|
+
// Validate required fields
|
|
35
|
+
if (!req.username || typeof req.username !== 'string' || req.username.trim() === '') {
|
|
36
|
+
return { valid: false, error: 'username is required and must be a non-empty string' };
|
|
37
|
+
}
|
|
38
|
+
if (!req.password || typeof req.password !== 'string') {
|
|
39
|
+
return { valid: false, error: 'password is required and must be a string' };
|
|
40
|
+
}
|
|
41
|
+
// Validate optional fields
|
|
42
|
+
if (req.host !== undefined && (typeof req.host !== 'string' || req.host.trim() === '')) {
|
|
43
|
+
return { valid: false, error: 'host must be a non-empty string if provided' };
|
|
44
|
+
}
|
|
45
|
+
if (req.port !== undefined && (typeof req.port !== 'number' || req.port < 1 || req.port > 65535)) {
|
|
46
|
+
return { valid: false, error: 'port must be a number between 1 and 65535' };
|
|
47
|
+
}
|
|
48
|
+
if (req.database !== undefined && typeof req.database !== 'string') {
|
|
49
|
+
return { valid: false, error: 'database must be a string if provided' };
|
|
50
|
+
}
|
|
51
|
+
if (req.schema !== undefined && typeof req.schema !== 'string') {
|
|
52
|
+
return { valid: false, error: 'schema must be a string if provided' };
|
|
53
|
+
}
|
|
54
|
+
if (req.duration !== undefined) {
|
|
55
|
+
if (typeof req.duration !== 'number' || req.duration < 1 || req.duration > 86400) {
|
|
56
|
+
return { valid: false, error: 'duration must be a number between 1 and 86400 seconds' };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
valid: true,
|
|
61
|
+
request: {
|
|
62
|
+
username: req.username.trim(),
|
|
63
|
+
password: req.password,
|
|
64
|
+
host: typeof req.host === 'string' ? req.host.trim() : undefined,
|
|
65
|
+
port: typeof req.port === 'number' ? req.port : undefined,
|
|
66
|
+
database: typeof req.database === 'string' ? req.database : undefined,
|
|
67
|
+
schema: typeof req.schema === 'string' ? req.schema : undefined,
|
|
68
|
+
duration: typeof req.duration === 'number' ? req.duration : undefined,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create the Express application
|
|
74
|
+
*/
|
|
75
|
+
export function createHttpApp() {
|
|
76
|
+
const app = express();
|
|
77
|
+
const httpConfig = getHttpConfig();
|
|
78
|
+
// Middleware
|
|
79
|
+
app.use(express.json());
|
|
80
|
+
// Security headers
|
|
81
|
+
app.use((req, res, next) => {
|
|
82
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
83
|
+
res.setHeader('X-Frame-Options', 'DENY');
|
|
84
|
+
res.setHeader('X-XSS-Protection', '1; mode=block');
|
|
85
|
+
next();
|
|
86
|
+
});
|
|
87
|
+
// CORS - validate against allowed origins list
|
|
88
|
+
// By default (MCP_CORS_ORIGINS not set), no CORS headers are sent = same-origin only
|
|
89
|
+
// Set MCP_CORS_ORIGINS='*' to allow all origins, or comma-separated list for specific origins
|
|
90
|
+
app.use((req, res, next) => {
|
|
91
|
+
const origin = req.headers.origin;
|
|
92
|
+
const allowedOrigins = httpConfig.corsOrigins;
|
|
93
|
+
if (origin && allowedOrigins.length > 0) {
|
|
94
|
+
// CORS is explicitly configured - check if origin is allowed
|
|
95
|
+
const isAllowed = allowedOrigins.includes('*') || // Wildcard = allow all
|
|
96
|
+
allowedOrigins.includes(origin); // Specific origin match
|
|
97
|
+
if (isAllowed) {
|
|
98
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
99
|
+
// Only set credentials when origin is explicitly allowed (not wildcard)
|
|
100
|
+
if (!allowedOrigins.includes('*')) {
|
|
101
|
+
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
102
|
+
}
|
|
103
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
|
|
104
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Mcp-Session-Id, Accept');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// When allowedOrigins is empty (default), no CORS headers are set.
|
|
108
|
+
// Browser will enforce same-origin policy, blocking cross-origin requests.
|
|
109
|
+
if (req.method === 'OPTIONS') {
|
|
110
|
+
res.status(204).end();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
next();
|
|
114
|
+
});
|
|
115
|
+
// OpenAPI specification endpoint
|
|
116
|
+
app.get('/openapi.json', (req, res) => {
|
|
117
|
+
const protocol = httpConfig.tls.enabled ? 'https' : 'http';
|
|
118
|
+
const host = req.get('host') || `${httpConfig.host}:${httpConfig.port}`;
|
|
119
|
+
const baseUrl = `${protocol}://${host}`;
|
|
120
|
+
res.setHeader('Content-Type', 'application/json');
|
|
121
|
+
res.json(getOpenApiSpec(baseUrl));
|
|
122
|
+
});
|
|
123
|
+
// Health check endpoint
|
|
124
|
+
app.get('/health', (req, res) => {
|
|
125
|
+
const tokenManager = getTokenManager();
|
|
126
|
+
const sessionManager = getSessionManager();
|
|
127
|
+
res.json({
|
|
128
|
+
status: 'ok',
|
|
129
|
+
timestamp: new Date().toISOString(),
|
|
130
|
+
server: {
|
|
131
|
+
name: SERVER_NAME,
|
|
132
|
+
version: SERVER_VERSION,
|
|
133
|
+
},
|
|
134
|
+
config: {
|
|
135
|
+
authMode: httpConfig.authMode,
|
|
136
|
+
sessionMode: httpConfig.sessionMode,
|
|
137
|
+
tlsEnabled: httpConfig.tls.enabled,
|
|
138
|
+
},
|
|
139
|
+
sessions: {
|
|
140
|
+
tokens: httpConfig.authMode === 'required' ? tokenManager.getStats() : undefined,
|
|
141
|
+
mcp: sessionManager.getStats(),
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
// Authentication endpoint (only active in 'required' auth mode)
|
|
146
|
+
app.post('/auth', authRateLimitMiddleware, async (req, res) => {
|
|
147
|
+
try {
|
|
148
|
+
// Check if /auth endpoint is needed for current auth mode
|
|
149
|
+
if (httpConfig.authMode !== 'required') {
|
|
150
|
+
res.status(404).json({
|
|
151
|
+
error: 'not_found',
|
|
152
|
+
error_description: httpConfig.authMode === 'none'
|
|
153
|
+
? 'Authentication is disabled. Access /mcp directly.'
|
|
154
|
+
: 'Using token authentication mode. Use the pre-configured token.',
|
|
155
|
+
});
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
// Validate request
|
|
159
|
+
const validation = validateAuthRequest(req.body);
|
|
160
|
+
if (!validation.valid || !validation.request) {
|
|
161
|
+
recordFailedAuthAttempt(req);
|
|
162
|
+
res.status(400).json({
|
|
163
|
+
error: 'invalid_request',
|
|
164
|
+
error_description: validation.error,
|
|
165
|
+
});
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const authReq = validation.request;
|
|
169
|
+
// Build DB config with env fallbacks
|
|
170
|
+
let dbConfig;
|
|
171
|
+
try {
|
|
172
|
+
dbConfig = loadPartialConfig({
|
|
173
|
+
hostname: authReq.host,
|
|
174
|
+
port: authReq.port,
|
|
175
|
+
username: authReq.username,
|
|
176
|
+
password: authReq.password,
|
|
177
|
+
database: authReq.database,
|
|
178
|
+
schema: authReq.schema,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
recordFailedAuthAttempt(req);
|
|
183
|
+
const message = err instanceof Error ? err.message : 'Configuration error';
|
|
184
|
+
res.status(400).json({
|
|
185
|
+
error: 'invalid_request',
|
|
186
|
+
error_description: message,
|
|
187
|
+
});
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
// Test connection to validate credentials
|
|
191
|
+
log.debug({ host: dbConfig.hostname, user: dbConfig.username }, 'Testing credentials');
|
|
192
|
+
// Use crypto random bytes for unique test pool ID (avoids collision with concurrent requests)
|
|
193
|
+
const testPoolId = `auth-test-${crypto.randomBytes(16).toString('hex')}`;
|
|
194
|
+
try {
|
|
195
|
+
initializeSessionPool(testPoolId, dbConfig);
|
|
196
|
+
const connected = await testSessionConnection(testPoolId);
|
|
197
|
+
await closeSessionPool(testPoolId);
|
|
198
|
+
if (!connected) {
|
|
199
|
+
recordFailedAuthAttempt(req);
|
|
200
|
+
res.status(401).json({
|
|
201
|
+
error: 'invalid_credentials',
|
|
202
|
+
error_description: 'Authentication failed: unable to connect to database',
|
|
203
|
+
});
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
await closeSessionPool(testPoolId);
|
|
209
|
+
recordFailedAuthAttempt(req);
|
|
210
|
+
const message = err instanceof Error ? err.message : 'Connection failed';
|
|
211
|
+
res.status(401).json({
|
|
212
|
+
error: 'invalid_credentials',
|
|
213
|
+
error_description: `Authentication failed: ${message}`,
|
|
214
|
+
});
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
// Create token session
|
|
218
|
+
const tokenManager = getTokenManager();
|
|
219
|
+
// Advisory check - the hard limit is enforced in createSession()
|
|
220
|
+
if (!tokenManager.canCreateSession()) {
|
|
221
|
+
res.status(503).json({
|
|
222
|
+
error: 'service_unavailable',
|
|
223
|
+
error_description: 'Maximum concurrent sessions reached. Please try again later.',
|
|
224
|
+
});
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// Create session with proper error handling for race condition
|
|
228
|
+
// (another request could fill the limit between canCreateSession and createSession)
|
|
229
|
+
let token;
|
|
230
|
+
let expiresAt;
|
|
231
|
+
let expiresIn;
|
|
232
|
+
try {
|
|
233
|
+
const result = tokenManager.createSession(dbConfig, authReq.duration);
|
|
234
|
+
token = result.token;
|
|
235
|
+
expiresAt = result.expiresAt;
|
|
236
|
+
expiresIn = result.expiresIn;
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
// Check if this is a max sessions error (race condition)
|
|
240
|
+
if (err instanceof Error && err.message.includes('Maximum concurrent sessions')) {
|
|
241
|
+
res.status(503).json({
|
|
242
|
+
error: 'service_unavailable',
|
|
243
|
+
error_description: err.message,
|
|
244
|
+
});
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
throw err; // Re-throw other errors
|
|
248
|
+
}
|
|
249
|
+
// Clear rate limit on successful auth
|
|
250
|
+
clearAuthRateLimit(req);
|
|
251
|
+
const response = {
|
|
252
|
+
access_token: token,
|
|
253
|
+
token_type: 'Bearer',
|
|
254
|
+
expires_in: expiresIn,
|
|
255
|
+
expires_at: expiresAt.toISOString(),
|
|
256
|
+
};
|
|
257
|
+
log.info({ host: dbConfig.hostname, user: dbConfig.username, expiresIn }, 'Authentication successful');
|
|
258
|
+
res.status(201).json(response);
|
|
259
|
+
}
|
|
260
|
+
catch (err) {
|
|
261
|
+
log.error({ err }, 'Unexpected error in auth handler');
|
|
262
|
+
res.status(500).json({
|
|
263
|
+
error: 'server_error',
|
|
264
|
+
error_description: 'An unexpected error occurred',
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
// MCP endpoint - POST (main request handler)
|
|
269
|
+
app.post('/mcp', authMiddleware, async (req, res) => {
|
|
270
|
+
const authReq = req;
|
|
271
|
+
try {
|
|
272
|
+
// Determine DB config and session key based on auth mode
|
|
273
|
+
let dbConfig;
|
|
274
|
+
let sessionKey;
|
|
275
|
+
if (httpConfig.authMode === 'none' || httpConfig.authMode === 'token') {
|
|
276
|
+
// Use env-based config (like stdio mode)
|
|
277
|
+
try {
|
|
278
|
+
dbConfig = loadConfig();
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
const message = err instanceof Error ? err.message : 'Configuration error';
|
|
282
|
+
log.error({ err }, 'Failed to load DB config from environment');
|
|
283
|
+
res.status(500).json({
|
|
284
|
+
jsonrpc: '2.0',
|
|
285
|
+
error: { code: -32603, message: `DB configuration error: ${message}` },
|
|
286
|
+
id: null,
|
|
287
|
+
});
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
// Use a single shared pool for none/token modes (similar to stdio mode).
|
|
291
|
+
// This pool persists for the server's lifetime and is cleaned up on shutdown
|
|
292
|
+
// via closeAllSessionPools(). This is intentional connection reuse, not a leak.
|
|
293
|
+
sessionKey = 'global';
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
// Required mode - use per-user config from token
|
|
297
|
+
if (!authReq.tokenSession || !authReq.authToken) {
|
|
298
|
+
log.error('Token session or auth token missing in required mode');
|
|
299
|
+
res.status(401).json({
|
|
300
|
+
jsonrpc: '2.0',
|
|
301
|
+
error: { code: -32001, message: 'Token session not found' },
|
|
302
|
+
id: null,
|
|
303
|
+
});
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const session = authReq.tokenSession;
|
|
307
|
+
const authToken = authReq.authToken;
|
|
308
|
+
dbConfig = session.config;
|
|
309
|
+
sessionKey = authToken;
|
|
310
|
+
}
|
|
311
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
312
|
+
const sessionManager = getSessionManager();
|
|
313
|
+
if (httpConfig.sessionMode === 'stateful') {
|
|
314
|
+
// Stateful mode - reuse or create sessions
|
|
315
|
+
if (sessionId) {
|
|
316
|
+
// Existing session
|
|
317
|
+
const mcpSession = sessionManager.getSession(sessionId);
|
|
318
|
+
if (!mcpSession) {
|
|
319
|
+
res.status(404).json({
|
|
320
|
+
jsonrpc: '2.0',
|
|
321
|
+
error: { code: -32001, message: 'Session not found or expired' },
|
|
322
|
+
id: null,
|
|
323
|
+
});
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
sessionManager.incrementActiveRequests(sessionId);
|
|
327
|
+
try {
|
|
328
|
+
await mcpSession.transport.handleRequest(req, res, req.body);
|
|
329
|
+
}
|
|
330
|
+
finally {
|
|
331
|
+
sessionManager.decrementActiveRequests(sessionId);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
else if (isInitializeRequest(req.body)) {
|
|
335
|
+
// New session initialization
|
|
336
|
+
// Initialize DB pool for this session key
|
|
337
|
+
initializeSessionPool(sessionKey, dbConfig);
|
|
338
|
+
// Create MCP server and session with proper cleanup on failure
|
|
339
|
+
let mcpServer;
|
|
340
|
+
let transport;
|
|
341
|
+
let newSessionId;
|
|
342
|
+
try {
|
|
343
|
+
mcpServer = createMcpServer(dbConfig, sessionKey);
|
|
344
|
+
const result = await sessionManager.createSession(mcpServer, sessionKey);
|
|
345
|
+
transport = result.transport;
|
|
346
|
+
newSessionId = result.sessionId;
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
// Clean up resources if server or session creation fails
|
|
350
|
+
if (mcpServer) {
|
|
351
|
+
await mcpServer.close().catch(() => { });
|
|
352
|
+
}
|
|
353
|
+
// Only close the pool if it's a per-user pool (required auth mode).
|
|
354
|
+
// For 'none'/'token' modes, sessionKey='global' and the pool is shared
|
|
355
|
+
// across all sessions - closing it would break other active sessions.
|
|
356
|
+
// The global pool is only closed on server shutdown.
|
|
357
|
+
if (sessionKey !== 'global') {
|
|
358
|
+
await closeSessionPool(sessionKey);
|
|
359
|
+
}
|
|
360
|
+
throw err;
|
|
361
|
+
}
|
|
362
|
+
// Associate MCP session with token (only in required mode)
|
|
363
|
+
if (httpConfig.authMode === 'required') {
|
|
364
|
+
const tokenManager = getTokenManager();
|
|
365
|
+
tokenManager.setMcpSessionId(sessionKey, newSessionId);
|
|
366
|
+
}
|
|
367
|
+
// Handle the initial request
|
|
368
|
+
// Note: errors here are handled by the outer try-catch, and the session
|
|
369
|
+
// will be cleaned up via normal session management (not here)
|
|
370
|
+
await transport.handleRequest(req, res, req.body);
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
res.status(400).json({
|
|
374
|
+
jsonrpc: '2.0',
|
|
375
|
+
error: { code: -32000, message: 'Session ID required for non-initialize requests' },
|
|
376
|
+
id: null,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
// Stateless mode - new server per request
|
|
382
|
+
const transport = new StreamableHTTPServerTransport({
|
|
383
|
+
sessionIdGenerator: undefined,
|
|
384
|
+
});
|
|
385
|
+
// Initialize or reuse pool for this session key.
|
|
386
|
+
// In 'required' auth mode, sessionKey = authToken, so the pool is shared
|
|
387
|
+
// across all requests with the same token. This is intentional for efficiency.
|
|
388
|
+
// Pool cleanup is handled by TokenManager when the token expires or is revoked
|
|
389
|
+
// (see setCleanupCallback in startHttpServer).
|
|
390
|
+
initializeSessionPool(sessionKey, dbConfig);
|
|
391
|
+
const mcpServer = createMcpServer(dbConfig, sessionKey);
|
|
392
|
+
// Clean up MCP server and transport on response close.
|
|
393
|
+
// Note: The database connection pool is NOT closed here - it's reused across
|
|
394
|
+
// requests with the same auth token and cleaned up on token expiration.
|
|
395
|
+
res.on('close', () => {
|
|
396
|
+
mcpServer.close().catch(() => { });
|
|
397
|
+
transport.close().catch(() => { });
|
|
398
|
+
});
|
|
399
|
+
await mcpServer.connect(transport);
|
|
400
|
+
await transport.handleRequest(req, res, req.body);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
catch (err) {
|
|
404
|
+
log.error({ err }, 'Error handling MCP request');
|
|
405
|
+
if (!res.headersSent) {
|
|
406
|
+
res.status(500).json({
|
|
407
|
+
jsonrpc: '2.0',
|
|
408
|
+
error: { code: -32603, message: 'Internal server error' },
|
|
409
|
+
id: null,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
// MCP endpoint - GET (SSE for stateful mode)
|
|
415
|
+
app.get('/mcp', authMiddleware, async (req, res) => {
|
|
416
|
+
const httpConfig = getHttpConfig();
|
|
417
|
+
if (httpConfig.sessionMode !== 'stateful') {
|
|
418
|
+
res.status(405).json({
|
|
419
|
+
error: 'method_not_allowed',
|
|
420
|
+
error_description: 'GET requests only supported in stateful mode',
|
|
421
|
+
});
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
425
|
+
if (!sessionId) {
|
|
426
|
+
res.status(400).json({
|
|
427
|
+
error: 'invalid_request',
|
|
428
|
+
error_description: 'Mcp-Session-Id header required',
|
|
429
|
+
});
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
const sessionManager = getSessionManager();
|
|
433
|
+
const mcpSession = sessionManager.getSession(sessionId);
|
|
434
|
+
if (!mcpSession) {
|
|
435
|
+
res.status(404).json({
|
|
436
|
+
error: 'not_found',
|
|
437
|
+
error_description: 'Session not found or expired',
|
|
438
|
+
});
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
await mcpSession.transport.handleRequest(req, res);
|
|
442
|
+
});
|
|
443
|
+
// MCP endpoint - DELETE (close session)
|
|
444
|
+
app.delete('/mcp', authMiddleware, async (req, res) => {
|
|
445
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
446
|
+
if (!sessionId) {
|
|
447
|
+
res.status(400).json({
|
|
448
|
+
error: 'invalid_request',
|
|
449
|
+
error_description: 'Mcp-Session-Id header required',
|
|
450
|
+
});
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const sessionManager = getSessionManager();
|
|
454
|
+
const closed = await sessionManager.closeSession(sessionId);
|
|
455
|
+
if (closed) {
|
|
456
|
+
res.json({ status: 'session_closed', sessionId });
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
res.status(404).json({
|
|
460
|
+
error: 'not_found',
|
|
461
|
+
error_description: 'Session not found',
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
return app;
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Start the HTTP server
|
|
469
|
+
*/
|
|
470
|
+
export async function startHttpServer() {
|
|
471
|
+
const httpConfig = getHttpConfig();
|
|
472
|
+
const app = createHttpApp();
|
|
473
|
+
// Register cleanup callback to close session pools when tokens expire or are revoked.
|
|
474
|
+
// This handles cleanup for both stateful and stateless modes in 'required' auth:
|
|
475
|
+
// - sessionKey = authToken, so pools are keyed by token
|
|
476
|
+
// - Pools are intentionally reused across requests for the same token (efficiency)
|
|
477
|
+
// - When token expires/revokes, this callback closes the associated pool
|
|
478
|
+
if (httpConfig.authMode === 'required') {
|
|
479
|
+
const tokenManager = getTokenManager();
|
|
480
|
+
tokenManager.setCleanupCallback(async (token) => {
|
|
481
|
+
await closeSessionPool(token);
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
let server;
|
|
485
|
+
if (httpConfig.tls.enabled && httpConfig.tls.certPath && httpConfig.tls.keyPath) {
|
|
486
|
+
const cert = readFileSync(httpConfig.tls.certPath);
|
|
487
|
+
const key = readFileSync(httpConfig.tls.keyPath);
|
|
488
|
+
server = https.createServer({ cert, key }, app);
|
|
489
|
+
log.info('TLS enabled');
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
server = http.createServer(app);
|
|
493
|
+
if (httpConfig.host !== '127.0.0.1' && httpConfig.host !== 'localhost') {
|
|
494
|
+
log.warn('TLS is disabled. For production use, enable TLS or run behind a reverse proxy with TLS.');
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return new Promise((resolve, reject) => {
|
|
498
|
+
server.on('error', (err) => {
|
|
499
|
+
log.error({ err }, 'HTTP server error');
|
|
500
|
+
reject(err);
|
|
501
|
+
});
|
|
502
|
+
server.listen(httpConfig.port, httpConfig.host, () => {
|
|
503
|
+
const protocol = httpConfig.tls.enabled ? 'https' : 'http';
|
|
504
|
+
const address = `${protocol}://${httpConfig.host}:${httpConfig.port}`;
|
|
505
|
+
log.info({
|
|
506
|
+
address,
|
|
507
|
+
sessionMode: httpConfig.sessionMode,
|
|
508
|
+
authMode: httpConfig.authMode,
|
|
509
|
+
tlsEnabled: httpConfig.tls.enabled,
|
|
510
|
+
}, `HTTP server listening at ${address}`);
|
|
511
|
+
// Log security warnings based on auth mode
|
|
512
|
+
if (httpConfig.authMode === 'none') {
|
|
513
|
+
log.warn('AUTH MODE IS DISABLED (MCP_AUTH_MODE=none). ' +
|
|
514
|
+
'The /mcp endpoint is accessible without authentication. ' +
|
|
515
|
+
'Only use this on trusted networks or localhost.');
|
|
516
|
+
}
|
|
517
|
+
else if (httpConfig.authMode === 'token' && !httpConfig.tls.enabled) {
|
|
518
|
+
log.warn('Using static token auth without TLS. ' +
|
|
519
|
+
'Enable TLS (MCP_TLS_ENABLED=true) or run behind a TLS-terminating proxy.');
|
|
520
|
+
}
|
|
521
|
+
resolve(server);
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Gracefully shutdown the HTTP server
|
|
527
|
+
*/
|
|
528
|
+
export async function shutdownHttpServer(server) {
|
|
529
|
+
log.info('Shutting down HTTP server...');
|
|
530
|
+
// Close session manager (closes MCP sessions)
|
|
531
|
+
const sessionManager = getSessionManager();
|
|
532
|
+
await sessionManager.shutdown();
|
|
533
|
+
// Close token manager (clears auth tokens and triggers pool cleanup via callback)
|
|
534
|
+
const tokenManager = getTokenManager();
|
|
535
|
+
await tokenManager.shutdown();
|
|
536
|
+
// Close all database connection pools
|
|
537
|
+
await closeAllSessionPools();
|
|
538
|
+
// Close HTTP server
|
|
539
|
+
return new Promise((resolve, reject) => {
|
|
540
|
+
server.close((err) => {
|
|
541
|
+
if (err) {
|
|
542
|
+
log.error({ err }, 'Error closing HTTP server');
|
|
543
|
+
reject(err);
|
|
544
|
+
}
|
|
545
|
+
else {
|
|
546
|
+
log.info('HTTP server closed');
|
|
547
|
+
resolve();
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport modules for MCP server
|
|
3
|
+
*
|
|
4
|
+
* Exports HTTP transport and session management utilities.
|
|
5
|
+
*/
|
|
6
|
+
export { createHttpApp, startHttpServer, shutdownHttpServer, } from './http.js';
|
|
7
|
+
export { getSessionManager, SessionManager, type McpSession, } from './sessionManager.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transports/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,aAAa,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,KAAK,UAAU,GAChB,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport modules for MCP server
|
|
3
|
+
*
|
|
4
|
+
* Exports HTTP transport and session management utilities.
|
|
5
|
+
*/
|
|
6
|
+
export { createHttpApp, startHttpServer, shutdownHttpServer, } from './http.js';
|
|
7
|
+
export { getSessionManager, SessionManager, } from './sessionManager.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transports/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,aAAa,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,iBAAiB,EACjB,cAAc,GAEf,MAAM,qBAAqB,CAAC"}
|