cprime-supergateway 3.4.5 → 3.4.7
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.
|
@@ -10,7 +10,11 @@ import { serializeCorsOrigin } from '../lib/serializeCorsOrigin.js';
|
|
|
10
10
|
import { EncryptionService } from '../services/encryptionService.js';
|
|
11
11
|
import { initMongoClient } from '../lib/initMongoClient.js';
|
|
12
12
|
import { McpServerLogRepository } from '../lib/mcpServerLogRepository.js';
|
|
13
|
+
import { LogService } from '../services/logService.js';
|
|
13
14
|
const encryptionService = new EncryptionService('env');
|
|
15
|
+
const mongoClient = initMongoClient();
|
|
16
|
+
const mcpServerLogRepository = new McpServerLogRepository(mongoClient, process.env.MONGO_DB ?? 'localhost', process.env.LOGS_COLLECTION ?? 'mcp_server_logs');
|
|
17
|
+
const logService = new LogService(mcpServerLogRepository);
|
|
14
18
|
let decryptedEnvs = {};
|
|
15
19
|
if (process.env.ENCRYPTED_ENV) {
|
|
16
20
|
const plaintext = await encryptionService.decryptText(process.env.ENCRYPTED_ENV, process.env.AAD_JSON ? JSON.parse(process.env.AAD_JSON) : {});
|
|
@@ -38,8 +42,6 @@ export async function stdioToSse(args) {
|
|
|
38
42
|
logger.info(` - CORS: ${corsOrigin ? `enabled (${serializeCorsOrigin({ corsOrigin })})` : 'disabled'}`);
|
|
39
43
|
logger.info(` - Health endpoints: ${healthEndpoints.length ? healthEndpoints.join(', ') : '(none)'}`);
|
|
40
44
|
onSignals({ logger });
|
|
41
|
-
const mongoClient = initMongoClient();
|
|
42
|
-
const mcpServerLogRepository = new McpServerLogRepository(mongoClient, process.env.MONGO_DB ?? 'localhost', process.env.LOGS_COLLECTION ?? 'mcp_server_logs');
|
|
43
45
|
const child = spawn(stdioCmd, {
|
|
44
46
|
shell: true,
|
|
45
47
|
env: { ...process.env, ...decryptedEnvs },
|
|
@@ -48,7 +50,6 @@ export async function stdioToSse(args) {
|
|
|
48
50
|
logger.error(`Child exited: code=${code}, signal=${signal}`);
|
|
49
51
|
process.exit(code ?? 1);
|
|
50
52
|
});
|
|
51
|
-
const server = new Server({ name: 'supergateway', version: getVersion() }, { capabilities: {} });
|
|
52
53
|
const sessions = {};
|
|
53
54
|
const app = express();
|
|
54
55
|
if (corsOrigin) {
|
|
@@ -74,6 +75,7 @@ export async function stdioToSse(args) {
|
|
|
74
75
|
res,
|
|
75
76
|
headers,
|
|
76
77
|
});
|
|
78
|
+
const server = new Server({ name: 'supergateway', version: getVersion() }, { capabilities: {} });
|
|
77
79
|
const sseTransport = new SSEServerTransport(`${baseUrl}${messagePath}`, res);
|
|
78
80
|
await server.connect(sseTransport);
|
|
79
81
|
const sessionId = sseTransport.sessionId;
|
|
@@ -87,18 +89,9 @@ export async function stdioToSse(args) {
|
|
|
87
89
|
}
|
|
88
90
|
sseTransport.onmessage = (msg) => {
|
|
89
91
|
logger.info(`SSE → Child (session ${sessionId}): ${JSON.stringify(msg)}`);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
ip: req.ip ?? '',
|
|
93
|
-
userId: req.query.userId ?? '',
|
|
92
|
+
logService.log(msg, 'request-rpc', logger, {
|
|
93
|
+
...sessions[sessionId],
|
|
94
94
|
sessionId,
|
|
95
|
-
type: 'rpc',
|
|
96
|
-
data: msg,
|
|
97
|
-
createdAt: new Date(),
|
|
98
|
-
updatedAt: new Date(),
|
|
99
|
-
})
|
|
100
|
-
.catch((err) => {
|
|
101
|
-
logger.error(`Failed to insert log:`, JSON.stringify(err));
|
|
102
95
|
});
|
|
103
96
|
child.stdin.write(JSON.stringify(msg) + '\n');
|
|
104
97
|
};
|
|
@@ -153,18 +146,9 @@ export async function stdioToSse(args) {
|
|
|
153
146
|
for (const [sid, session] of Object.entries(sessions)) {
|
|
154
147
|
try {
|
|
155
148
|
session.transport.send(jsonMsg);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
ip: session.ip,
|
|
159
|
-
userId: session.userId,
|
|
149
|
+
logService.log(jsonMsg, 'response-rpc', logger, {
|
|
150
|
+
...session,
|
|
160
151
|
sessionId: sid,
|
|
161
|
-
type: 'system',
|
|
162
|
-
data: line,
|
|
163
|
-
createdAt: new Date(),
|
|
164
|
-
updatedAt: new Date(),
|
|
165
|
-
})
|
|
166
|
-
.catch((err) => {
|
|
167
|
-
logger.error(`Failed to insert log:`, JSON.stringify(err));
|
|
168
152
|
});
|
|
169
153
|
}
|
|
170
154
|
catch (err) {
|
|
@@ -175,10 +159,22 @@ export async function stdioToSse(args) {
|
|
|
175
159
|
}
|
|
176
160
|
catch {
|
|
177
161
|
logger.error(`Child non-JSON: ${line}`);
|
|
162
|
+
for (const [sid, session] of Object.entries(sessions)) {
|
|
163
|
+
logService.log(line.toString(), 'system', logger, {
|
|
164
|
+
...session,
|
|
165
|
+
sessionId: sid,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
178
168
|
}
|
|
179
169
|
});
|
|
180
170
|
});
|
|
181
171
|
child.stderr.on('data', (chunk) => {
|
|
182
172
|
logger.error(`Child stderr: ${chunk.toString('utf8')}`);
|
|
173
|
+
for (const [sid, session] of Object.entries(sessions)) {
|
|
174
|
+
logService.log(chunk.toString('utf8'), 'system', logger, {
|
|
175
|
+
...session,
|
|
176
|
+
sessionId: sid,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
183
179
|
});
|
|
184
180
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export class LogService {
|
|
2
|
+
repository;
|
|
3
|
+
constructor(repository) {
|
|
4
|
+
this.repository = repository;
|
|
5
|
+
}
|
|
6
|
+
async log(data, type, logger, session) {
|
|
7
|
+
const logDto = {
|
|
8
|
+
ip: session.ip,
|
|
9
|
+
userId: session.userId,
|
|
10
|
+
sessionId: session.sessionId,
|
|
11
|
+
type: type,
|
|
12
|
+
data: data,
|
|
13
|
+
createdAt: new Date(),
|
|
14
|
+
updatedAt: new Date(),
|
|
15
|
+
};
|
|
16
|
+
// Insert to MongoDB with error handling
|
|
17
|
+
try {
|
|
18
|
+
await this.repository.insert(logDto);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
logger.error(`Failed to insert log:`, JSON.stringify(err));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
package/package.json
CHANGED
|
@@ -12,6 +12,7 @@ import { serializeCorsOrigin } from '../lib/serializeCorsOrigin.js'
|
|
|
12
12
|
import { EncryptionService } from '../services/encryptionService.js'
|
|
13
13
|
import { initMongoClient } from '../lib/initMongoClient.js'
|
|
14
14
|
import { McpServerLogRepository } from '../lib/mcpServerLogRepository.js'
|
|
15
|
+
import { ILogService, LogService } from '../services/logService.js'
|
|
15
16
|
|
|
16
17
|
export interface StdioToSseArgs {
|
|
17
18
|
stdioCmd: string
|
|
@@ -26,6 +27,13 @@ export interface StdioToSseArgs {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
const encryptionService = new EncryptionService('env')
|
|
30
|
+
const mongoClient = initMongoClient()
|
|
31
|
+
const mcpServerLogRepository = new McpServerLogRepository(
|
|
32
|
+
mongoClient,
|
|
33
|
+
process.env.MONGO_DB ?? 'localhost',
|
|
34
|
+
process.env.LOGS_COLLECTION ?? 'mcp_server_logs',
|
|
35
|
+
)
|
|
36
|
+
const logService: ILogService = new LogService(mcpServerLogRepository)
|
|
29
37
|
let decryptedEnvs = {}
|
|
30
38
|
if (process.env.ENCRYPTED_ENV) {
|
|
31
39
|
const plaintext = await encryptionService.decryptText(
|
|
@@ -84,13 +92,6 @@ export async function stdioToSse(args: StdioToSseArgs) {
|
|
|
84
92
|
|
|
85
93
|
onSignals({ logger })
|
|
86
94
|
|
|
87
|
-
const mongoClient = initMongoClient()
|
|
88
|
-
const mcpServerLogRepository = new McpServerLogRepository(
|
|
89
|
-
mongoClient,
|
|
90
|
-
process.env.MONGO_DB ?? 'localhost',
|
|
91
|
-
process.env.LOGS_COLLECTION ?? 'mcp_server_logs',
|
|
92
|
-
)
|
|
93
|
-
|
|
94
95
|
const child: ChildProcessWithoutNullStreams = spawn(stdioCmd, {
|
|
95
96
|
shell: true,
|
|
96
97
|
env: { ...process.env, ...decryptedEnvs },
|
|
@@ -100,11 +101,6 @@ export async function stdioToSse(args: StdioToSseArgs) {
|
|
|
100
101
|
process.exit(code ?? 1)
|
|
101
102
|
})
|
|
102
103
|
|
|
103
|
-
const server = new Server(
|
|
104
|
-
{ name: 'supergateway', version: getVersion() },
|
|
105
|
-
{ capabilities: {} },
|
|
106
|
-
)
|
|
107
|
-
|
|
108
104
|
const sessions: Record<
|
|
109
105
|
string,
|
|
110
106
|
{
|
|
@@ -144,6 +140,10 @@ export async function stdioToSse(args: StdioToSseArgs) {
|
|
|
144
140
|
headers,
|
|
145
141
|
})
|
|
146
142
|
|
|
143
|
+
const server = new Server(
|
|
144
|
+
{ name: 'supergateway', version: getVersion() },
|
|
145
|
+
{ capabilities: {} },
|
|
146
|
+
)
|
|
147
147
|
const sseTransport = new SSEServerTransport(`${baseUrl}${messagePath}`, res)
|
|
148
148
|
await server.connect(sseTransport)
|
|
149
149
|
|
|
@@ -159,19 +159,10 @@ export async function stdioToSse(args: StdioToSseArgs) {
|
|
|
159
159
|
|
|
160
160
|
sseTransport.onmessage = (msg: JSONRPCMessage) => {
|
|
161
161
|
logger.info(`SSE → Child (session ${sessionId}): ${JSON.stringify(msg)}`)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
sessionId,
|
|
167
|
-
type: 'rpc',
|
|
168
|
-
data: msg,
|
|
169
|
-
createdAt: new Date(),
|
|
170
|
-
updatedAt: new Date(),
|
|
171
|
-
})
|
|
172
|
-
.catch((err) => {
|
|
173
|
-
logger.error(`Failed to insert log:`, JSON.stringify(err))
|
|
174
|
-
})
|
|
162
|
+
logService.log(msg, 'request-rpc', logger, {
|
|
163
|
+
...sessions[sessionId],
|
|
164
|
+
sessionId,
|
|
165
|
+
})
|
|
175
166
|
child.stdin.write(JSON.stringify(msg) + '\n')
|
|
176
167
|
}
|
|
177
168
|
|
|
@@ -232,19 +223,10 @@ export async function stdioToSse(args: StdioToSseArgs) {
|
|
|
232
223
|
for (const [sid, session] of Object.entries(sessions)) {
|
|
233
224
|
try {
|
|
234
225
|
session.transport.send(jsonMsg)
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
sessionId: sid,
|
|
240
|
-
type: 'system',
|
|
241
|
-
data: line,
|
|
242
|
-
createdAt: new Date(),
|
|
243
|
-
updatedAt: new Date(),
|
|
244
|
-
})
|
|
245
|
-
.catch((err) => {
|
|
246
|
-
logger.error(`Failed to insert log:`, JSON.stringify(err))
|
|
247
|
-
})
|
|
226
|
+
logService.log(jsonMsg, 'response-rpc', logger, {
|
|
227
|
+
...session,
|
|
228
|
+
sessionId: sid,
|
|
229
|
+
})
|
|
248
230
|
} catch (err) {
|
|
249
231
|
logger.error(`Failed to send to session ${sid}:`, err)
|
|
250
232
|
delete sessions[sid]
|
|
@@ -252,11 +234,23 @@ export async function stdioToSse(args: StdioToSseArgs) {
|
|
|
252
234
|
}
|
|
253
235
|
} catch {
|
|
254
236
|
logger.error(`Child non-JSON: ${line}`)
|
|
237
|
+
for (const [sid, session] of Object.entries(sessions)) {
|
|
238
|
+
logService.log(line.toString(), 'system', logger, {
|
|
239
|
+
...session,
|
|
240
|
+
sessionId: sid,
|
|
241
|
+
})
|
|
242
|
+
}
|
|
255
243
|
}
|
|
256
244
|
})
|
|
257
245
|
})
|
|
258
246
|
|
|
259
247
|
child.stderr.on('data', (chunk: Buffer) => {
|
|
260
248
|
logger.error(`Child stderr: ${chunk.toString('utf8')}`)
|
|
249
|
+
for (const [sid, session] of Object.entries(sessions)) {
|
|
250
|
+
logService.log(chunk.toString('utf8'), 'system', logger, {
|
|
251
|
+
...session,
|
|
252
|
+
sessionId: sid,
|
|
253
|
+
})
|
|
254
|
+
}
|
|
261
255
|
})
|
|
262
256
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Logger } from '../types.js'
|
|
2
|
+
import {
|
|
3
|
+
McpServerLogRepository,
|
|
4
|
+
type McpServerLogDto,
|
|
5
|
+
} from '../lib/mcpServerLogRepository.js'
|
|
6
|
+
import { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js'
|
|
7
|
+
|
|
8
|
+
export interface ILogService {
|
|
9
|
+
log(
|
|
10
|
+
data: string | object,
|
|
11
|
+
type: string,
|
|
12
|
+
logger: Logger,
|
|
13
|
+
session: { ip: string; userId: string; sessionId: string },
|
|
14
|
+
): Promise<void>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class LogService implements ILogService {
|
|
18
|
+
constructor(private readonly repository: McpServerLogRepository) {}
|
|
19
|
+
|
|
20
|
+
async log(
|
|
21
|
+
data: string | object,
|
|
22
|
+
type: string,
|
|
23
|
+
logger: Logger,
|
|
24
|
+
session: { ip: string; userId: string; sessionId: string },
|
|
25
|
+
): Promise<void> {
|
|
26
|
+
const logDto: McpServerLogDto = {
|
|
27
|
+
ip: session.ip,
|
|
28
|
+
userId: session.userId,
|
|
29
|
+
sessionId: session.sessionId,
|
|
30
|
+
type: type as McpServerLogDto['type'],
|
|
31
|
+
data: data as JSONRPCMessage | string,
|
|
32
|
+
createdAt: new Date(),
|
|
33
|
+
updatedAt: new Date(),
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Insert to MongoDB with error handling
|
|
37
|
+
try {
|
|
38
|
+
await this.repository.insert(logDto)
|
|
39
|
+
} catch (err) {
|
|
40
|
+
logger.error(`Failed to insert log:`, JSON.stringify(err))
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|