@loop_ouroboros/mcp-hub-lite 1.3.0 → 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.
Files changed (120) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +405 -331
  3. package/dist/client/assets/{HomeView-Bi2bkUKf.js → HomeView-DplI3V-h.js} +1 -1
  4. package/dist/client/assets/{ResourceDetailView-DyuSovH9.js → ResourceDetailView-CeHPn99Y.js} +1 -1
  5. package/dist/client/assets/ResourcesView-C1ObRhYS.js +1 -0
  6. package/dist/client/assets/{ServerDashboard-BGyyZAti.js → ServerDashboard-D7wG4Gvt.js} +1 -1
  7. package/dist/client/assets/ServerDetail-G23phOcJ.js +2 -0
  8. package/dist/client/assets/{ServerListView-yQPVJFHG.js → ServerListView-BFiZLtPO.js} +1 -1
  9. package/dist/client/assets/{ServerStatusTags.vue_vue_type_script_setup_true_lang-C8gQlxGE.js → ServerStatusTags.vue_vue_type_script_setup_true_lang-Deb_SbFw.js} +1 -1
  10. package/dist/client/assets/SettingsView-QBFLZ6fP.js +1 -0
  11. package/dist/client/assets/ToolCallDialog-DYS-ADCL.js +1 -0
  12. package/dist/client/assets/ToolsView-DYwgtm7W.js +1 -0
  13. package/dist/client/assets/_baseClone-DQno9YO3.js +1 -0
  14. package/dist/client/assets/{el-form-item-DfWq_kSy.js → el-form-item-DF0zzQdH.js} +2 -2
  15. package/dist/client/assets/el-input-C_p2Qw42.js +1 -0
  16. package/dist/client/assets/el-loading-BaenpNzU.js +1 -0
  17. package/dist/client/assets/el-overlay-MbIUXSQ7.js +1 -0
  18. package/dist/client/assets/el-radio-group-COnCjCcz.js +1 -0
  19. package/dist/client/assets/el-skeleton-item-qj0eQP4s.js +1 -0
  20. package/dist/client/assets/el-switch-BZbXqB3_.js +1 -0
  21. package/dist/client/assets/el-tab-pane-w7RltRLd.js +1 -0
  22. package/dist/client/assets/el-table-column-OD8zhFcD.js +1 -0
  23. package/dist/client/assets/index-DwhULJXZ.js +2 -0
  24. package/dist/client/assets/{index-Bzz3tYbS.css → index-UtsV0Cvh.css} +1 -1
  25. package/dist/client/assets/{omit-BIIebEYo.js → omit-BAJQlviJ.js} +1 -1
  26. package/dist/client/assets/raf-B1Ry7ruA.js +1 -0
  27. package/dist/client/assets/{vue-vendor-Dwcr0jep.js → vue-vendor-ClSvefnQ.js} +1 -1
  28. package/dist/client/index.html +3 -3
  29. package/dist/server/shared/models/constants.d.ts +5 -0
  30. package/dist/server/shared/models/constants.d.ts.map +1 -1
  31. package/dist/server/shared/models/constants.js +4 -0
  32. package/dist/server/shared/models/server.model.d.ts +14 -0
  33. package/dist/server/shared/models/server.model.d.ts.map +1 -1
  34. package/dist/server/shared/models/server.model.js +27 -4
  35. package/dist/server/src/api/mcp/gateway.d.ts +10 -6
  36. package/dist/server/src/api/mcp/gateway.d.ts.map +1 -1
  37. package/dist/server/src/api/mcp/gateway.js +235 -69
  38. package/dist/server/src/api/web/sessions.d.ts +1 -27
  39. package/dist/server/src/api/web/sessions.d.ts.map +1 -1
  40. package/dist/server/src/api/web/sessions.js +8 -97
  41. package/dist/server/src/app.d.ts.map +1 -1
  42. package/dist/server/src/app.js +5 -0
  43. package/dist/server/src/cli/commands/status.js +39 -1
  44. package/dist/server/src/cli/commands/use-guide.d.ts +0 -8
  45. package/dist/server/src/cli/commands/use-guide.d.ts.map +1 -1
  46. package/dist/server/src/cli/commands/use-guide.js +28 -170
  47. package/dist/server/src/cli/server.d.ts +10 -0
  48. package/dist/server/src/cli/server.d.ts.map +1 -1
  49. package/dist/server/src/cli/server.js +31 -1
  50. package/dist/server/src/server/dev-server.js +2 -0
  51. package/dist/server/src/server/runner.d.ts.map +1 -1
  52. package/dist/server/src/server/runner.js +2 -0
  53. package/dist/server/src/services/connection/connection-manager.d.ts +2 -0
  54. package/dist/server/src/services/connection/connection-manager.d.ts.map +1 -1
  55. package/dist/server/src/services/connection/connection-manager.js +14 -7
  56. package/dist/server/src/services/gateway/gateway.service.d.ts +13 -0
  57. package/dist/server/src/services/gateway/gateway.service.d.ts.map +1 -1
  58. package/dist/server/src/services/gateway/gateway.service.js +72 -0
  59. package/dist/server/src/services/gateway/global-transport.d.ts +20 -10
  60. package/dist/server/src/services/gateway/global-transport.d.ts.map +1 -1
  61. package/dist/server/src/services/gateway/global-transport.js +50 -34
  62. package/dist/server/src/services/gateway/request-handlers/initialize-handler.d.ts.map +1 -1
  63. package/dist/server/src/services/gateway/request-handlers/initialize-handler.js +22 -6
  64. package/dist/server/src/services/gateway/request-handlers/resources-handler.d.ts.map +1 -1
  65. package/dist/server/src/services/gateway/request-handlers/resources-handler.js +5 -1
  66. package/dist/server/src/services/gateway/session-manager.d.ts +101 -0
  67. package/dist/server/src/services/gateway/session-manager.d.ts.map +1 -0
  68. package/dist/server/src/services/gateway/session-manager.js +256 -0
  69. package/dist/server/src/services/hub-tools/resource-generator.d.ts +1 -1
  70. package/dist/server/src/services/hub-tools/resource-generator.d.ts.map +1 -1
  71. package/dist/server/src/services/hub-tools/resource-generator.js +11 -9
  72. package/dist/server/src/services/hub-tools.service.d.ts.map +1 -1
  73. package/dist/server/src/services/hub-tools.service.js +3 -1
  74. package/dist/server/src/utils/json-utils.d.ts +9 -0
  75. package/dist/server/src/utils/json-utils.d.ts.map +1 -1
  76. package/dist/server/src/utils/json-utils.js +19 -0
  77. package/dist/server/src/utils/logger/index.d.ts +1 -1
  78. package/dist/server/src/utils/logger/index.d.ts.map +1 -1
  79. package/dist/server/src/utils/logger/index.js +1 -1
  80. package/dist/server/src/utils/logger/log-context.d.ts +1 -0
  81. package/dist/server/src/utils/logger/log-context.d.ts.map +1 -1
  82. package/dist/server/src/utils/logger/log-formatter.d.ts.map +1 -1
  83. package/dist/server/src/utils/logger/log-formatter.js +25 -11
  84. package/dist/server/src/utils/logger/log-output.d.ts +17 -1
  85. package/dist/server/src/utils/logger/log-output.d.ts.map +1 -1
  86. package/dist/server/src/utils/logger/log-output.js +46 -40
  87. package/dist/server/src/utils/logger/logger.d.ts.map +1 -1
  88. package/dist/server/src/utils/logger/logger.js +18 -2
  89. package/dist/server/src/utils/request-context.d.ts +8 -70
  90. package/dist/server/src/utils/request-context.d.ts.map +1 -1
  91. package/dist/server/src/utils/request-context.js +11 -70
  92. package/dist/server/tests/unit/config/config.schema.test.js +2 -1
  93. package/dist/server/tests/unit/server/runner.test.js +14 -7
  94. package/dist/server/tests/unit/services/gateway-session-mode.test.d.ts +2 -0
  95. package/dist/server/tests/unit/services/gateway-session-mode.test.d.ts.map +1 -0
  96. package/dist/server/tests/unit/services/gateway-session-mode.test.js +174 -0
  97. package/dist/server/tests/unit/services/hub-tools.service.test.js +4 -4
  98. package/dist/server/tests/unit/utils/config.test.js +14 -7
  99. package/dist/server/tests/unit/utils/log-output.test.d.ts +2 -0
  100. package/dist/server/tests/unit/utils/log-output.test.d.ts.map +1 -0
  101. package/dist/server/tests/unit/utils/log-output.test.js +198 -0
  102. package/dist/server/vitest.config.d.ts.map +1 -1
  103. package/dist/server/vitest.config.js +0 -2
  104. package/package.json +1 -1
  105. package/dist/client/assets/ResourcesView-CU0VbNy5.js +0 -1
  106. package/dist/client/assets/ServerDetail-bcQ8BVXR.js +0 -2
  107. package/dist/client/assets/SettingsView-B1DxbFP3.js +0 -1
  108. package/dist/client/assets/ToolCallDialog-DEapCO06.js +0 -1
  109. package/dist/client/assets/ToolsView-DA0u_bCw.js +0 -1
  110. package/dist/client/assets/_baseClone-B991Lvrt.js +0 -1
  111. package/dist/client/assets/el-input-5YzZrwir.js +0 -1
  112. package/dist/client/assets/el-loading-DE3FcxNH.js +0 -1
  113. package/dist/client/assets/el-overlay-BTeTueuN.js +0 -1
  114. package/dist/client/assets/el-radio-group-Y1E2bxIW.js +0 -1
  115. package/dist/client/assets/el-skeleton-item-DhgR50Jx.js +0 -1
  116. package/dist/client/assets/el-switch-fF--nMSD.js +0 -1
  117. package/dist/client/assets/el-tab-pane-rvS_KTwP.js +0 -1
  118. package/dist/client/assets/el-table-column-B1O8mY47.js +0 -1
  119. package/dist/client/assets/index-DkqV9kH4.js +0 -2
  120. package/dist/client/assets/raf-Cj-gATZv.js +0 -1
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Session Manager for stateful Streamable HTTP MCP transport.
3
+ *
4
+ * Each client session owns a StreamableHTTPServerTransport + McpServer pair.
5
+ * Sessions are identified by mcp-session-id header (generated by the SDK).
6
+ * Notifications are broadcast to all active sessions via their McpServer instances.
7
+ */
8
+ import { logger, LOG_MODULES } from '../../utils/logger/index.js';
9
+ import { getGatewayDebugSetting } from '../../utils/json-utils.js';
10
+ import { configManager } from '../../config/config-manager.js';
11
+ const CLEANUP_INTERVAL_MS = 60 * 1000; // every minute
12
+ const PING_COOLDOWN_MS = 30 * 1000; // min interval between pings
13
+ const PING_TIMEOUT_MS = 10 * 1000; // per-ping timeout
14
+ export class SessionManager {
15
+ sessions = new Map();
16
+ cleanupTimer = null;
17
+ pendingClientMetadata = new WeakMap();
18
+ /**
19
+ * Registers a newly created session.
20
+ */
21
+ addSession(sessionId, transport, server) {
22
+ const pendingMeta = this.pendingClientMetadata.get(server);
23
+ this.pendingClientMetadata.delete(server);
24
+ this.sessions.set(sessionId, {
25
+ sessionId,
26
+ transport,
27
+ server,
28
+ createdAt: Date.now(),
29
+ lastAccessedAt: Date.now(),
30
+ isClosing: false,
31
+ activeSseCount: 0,
32
+ lastPingedAt: 0,
33
+ pingPending: false,
34
+ clientName: pendingMeta?.clientName,
35
+ clientVersion: pendingMeta?.clientVersion,
36
+ protocolVersion: pendingMeta?.protocolVersion,
37
+ createdByMethod: 'POST',
38
+ lastMethod: 'POST'
39
+ });
40
+ if (getGatewayDebugSetting()) {
41
+ logger.debug(`Session registered: ${sessionId} (total: ${this.sessions.size}, activeSseCount: 0)`, LOG_MODULES.GATEWAY);
42
+ }
43
+ this.ensureCleanupTimer();
44
+ }
45
+ /**
46
+ * Looks up an existing session by ID and updates lastAccessedAt.
47
+ */
48
+ getSession(sessionId) {
49
+ const session = this.sessions.get(sessionId);
50
+ if (session && !session.isClosing) {
51
+ session.lastAccessedAt = Date.now();
52
+ return session;
53
+ }
54
+ return undefined;
55
+ }
56
+ /**
57
+ * Marks an SSE stream as opened for the given session.
58
+ * Prevents the session from being cleaned up while the stream is active.
59
+ */
60
+ markSseOpened(sessionId) {
61
+ const session = this.sessions.get(sessionId);
62
+ if (session && !session.isClosing) {
63
+ session.activeSseCount++;
64
+ if (getGatewayDebugSetting()) {
65
+ logger.debug(`Session ${sessionId} SSE opened (activeSseCount: ${session.activeSseCount})`, LOG_MODULES.GATEWAY);
66
+ }
67
+ }
68
+ }
69
+ /**
70
+ * Marks an SSE stream as closed for the given session.
71
+ */
72
+ markSseClosed(sessionId) {
73
+ const session = this.sessions.get(sessionId);
74
+ if (session) {
75
+ session.activeSseCount = Math.max(0, session.activeSseCount - 1);
76
+ if (getGatewayDebugSetting()) {
77
+ logger.debug(`Session ${sessionId} SSE closed (activeSseCount: ${session.activeSseCount})`, LOG_MODULES.GATEWAY);
78
+ }
79
+ }
80
+ }
81
+ /**
82
+ * Removes a session (called on DELETE or onsessionclosed).
83
+ */
84
+ removeSession(sessionId) {
85
+ const session = this.sessions.get(sessionId);
86
+ if (!session || session.isClosing)
87
+ return;
88
+ session.isClosing = true;
89
+ try {
90
+ session.transport.close().catch((err) => {
91
+ logger.debug(`Error closing transport for session ${sessionId}: ${err}`, LOG_MODULES.GATEWAY);
92
+ });
93
+ }
94
+ catch {
95
+ // transport may already be closed
96
+ }
97
+ this.sessions.delete(sessionId);
98
+ if (getGatewayDebugSetting()) {
99
+ logger.debug(`Session removed: ${sessionId} (total: ${this.sessions.size}, age: ${Date.now() - session.createdAt}ms, activeSseCount: ${session.activeSseCount})`, LOG_MODULES.GATEWAY);
100
+ }
101
+ }
102
+ pendingBroadcasts = new Map();
103
+ BROADCAST_DEBOUNCE_MS = 3000;
104
+ /**
105
+ * Broadcasts a notification to all active sessions.
106
+ * Debounced: same-type notifications within BROADCAST_DEBOUNCE_MS are coalesced.
107
+ * @param method - 'tools' for sendToolListChanged, 'resources' for sendResourceListChanged
108
+ */
109
+ broadcastNotification(method) {
110
+ // Skip if a debounce timer for this method type is already pending
111
+ if (this.pendingBroadcasts.has(method))
112
+ return;
113
+ this.pendingBroadcasts.set(method, setTimeout(() => {
114
+ this.pendingBroadcasts.delete(method);
115
+ if (this.sessions.size === 0)
116
+ return;
117
+ for (const [sessionId, state] of this.sessions) {
118
+ if (state.isClosing)
119
+ continue;
120
+ try {
121
+ if (method === 'tools') {
122
+ state.server.sendToolListChanged();
123
+ }
124
+ else {
125
+ state.server.sendResourceListChanged();
126
+ }
127
+ }
128
+ catch (error) {
129
+ logger.debug(`Failed to broadcast ${method} notification to session ${sessionId}: ${error}`, LOG_MODULES.GATEWAY);
130
+ }
131
+ }
132
+ }, this.BROADCAST_DEBOUNCE_MS));
133
+ }
134
+ /**
135
+ * Removes sessions that have been idle longer than SESSION_TIMEOUT_MS.
136
+ */
137
+ cleanupStaleSessions() {
138
+ const now = Date.now();
139
+ const staleIds = [];
140
+ let skippedClosing = 0;
141
+ let skippedSse = 0;
142
+ let pingFailed = 0;
143
+ for (const [id, state] of this.sessions) {
144
+ if (state.isClosing) {
145
+ skippedClosing++;
146
+ continue;
147
+ }
148
+ // Ping from last cycle timed out — session is dead
149
+ if (state.pingPending) {
150
+ state.pingPending = false;
151
+ pingFailed++;
152
+ staleIds.push(id);
153
+ continue;
154
+ }
155
+ if (state.activeSseCount > 0) {
156
+ if (now - state.lastPingedAt < PING_COOLDOWN_MS) {
157
+ skippedSse++;
158
+ continue;
159
+ }
160
+ state.lastPingedAt = now;
161
+ state.pingPending = true;
162
+ // Fire-and-forget concurrent ping with timeout
163
+ const pingWithTimeout = Promise.race([
164
+ state.server.server.ping(),
165
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Ping timeout')), PING_TIMEOUT_MS))
166
+ ]);
167
+ pingWithTimeout.then(() => {
168
+ const s = this.sessions.get(id);
169
+ if (s) {
170
+ s.pingPending = false;
171
+ s.lastAccessedAt = Date.now();
172
+ }
173
+ }, () => {
174
+ // Keep pingPending=true so the next cycle cleans up this dead session
175
+ });
176
+ skippedSse++;
177
+ continue;
178
+ }
179
+ if (now - state.lastAccessedAt > configManager.getConfig().security.idleConnectionTimeout) {
180
+ staleIds.push(id);
181
+ }
182
+ }
183
+ if (getGatewayDebugSetting() && (staleIds.length > 0 || skippedSse > 0 || pingFailed > 0)) {
184
+ logger.debug(`Stale cleanup: total=${this.sessions.size} stale=${staleIds.length} skippedClosing=${skippedClosing} skippedSse=${skippedSse} pingFailed=${pingFailed}`, LOG_MODULES.GATEWAY);
185
+ }
186
+ for (const id of staleIds) {
187
+ logger.info(`Removing stale session: ${id}`, LOG_MODULES.GATEWAY);
188
+ this.removeSession(id);
189
+ }
190
+ }
191
+ ensureCleanupTimer() {
192
+ if (this.cleanupTimer)
193
+ return;
194
+ this.cleanupTimer = setInterval(() => this.cleanupStaleSessions(), CLEANUP_INTERVAL_MS);
195
+ this.cleanupTimer.unref();
196
+ }
197
+ /**
198
+ * Shuts down all sessions. Called on server shutdown.
199
+ */
200
+ shutdownAll() {
201
+ if (this.cleanupTimer) {
202
+ clearInterval(this.cleanupTimer);
203
+ this.cleanupTimer = null;
204
+ }
205
+ for (const timer of this.pendingBroadcasts.values()) {
206
+ clearTimeout(timer);
207
+ }
208
+ this.pendingBroadcasts.clear();
209
+ for (const [id] of this.sessions) {
210
+ this.removeSession(id);
211
+ }
212
+ logger.info('All sessions shut down', LOG_MODULES.GATEWAY);
213
+ }
214
+ /** Returns the current session count (for diagnostics). */
215
+ get sessionCount() {
216
+ return this.sessions.size;
217
+ }
218
+ /**
219
+ * Stores client metadata against a McpServer instance so that
220
+ * addSession() can consume it when the session is registered later.
221
+ */
222
+ storePendingClientMetadata(server, metadata) {
223
+ this.pendingClientMetadata.set(server, metadata);
224
+ }
225
+ /**
226
+ * Returns metadata for all active sessions. Does not expose internal
227
+ * transport or server references.
228
+ */
229
+ getAllSessions() {
230
+ const result = [];
231
+ for (const state of this.sessions.values()) {
232
+ result.push({
233
+ sessionId: state.sessionId,
234
+ clientName: state.clientName,
235
+ clientVersion: state.clientVersion,
236
+ protocolVersion: state.protocolVersion,
237
+ createdByMethod: state.createdByMethod,
238
+ lastMethod: state.lastMethod,
239
+ createdAt: new Date(state.createdAt).toLocaleString(),
240
+ lastAccessedAt: new Date(state.lastAccessedAt).toLocaleString(),
241
+ isClosing: state.isClosing,
242
+ activeSseCount: state.activeSseCount
243
+ });
244
+ }
245
+ return result;
246
+ }
247
+ /** Updates the last HTTP method seen for a session. */
248
+ updateSessionMethod(sessionId, method) {
249
+ const session = this.sessions.get(sessionId);
250
+ if (session) {
251
+ session.lastMethod = method;
252
+ }
253
+ }
254
+ }
255
+ /** Singleton instance. */
256
+ export const sessionManager = new SessionManager();
@@ -58,5 +58,5 @@ export declare function generateDynamicResources(): Resource[];
58
58
  * const tools = await readResource('hub://servers/my-mcp-server/tools');
59
59
  * ```
60
60
  */
61
- export declare function readResource(uri: string): Promise<ServerMetadata | Resource[] | string | unknown>;
61
+ export declare function readResource(uri: string, language?: string): Promise<ServerMetadata | Resource[] | string | unknown>;
62
62
  //# sourceMappingURL=resource-generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resource-generator.d.ts","sourceRoot":"","sources":["../../../../../src/services/hub-tools/resource-generator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAiLlE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,IAAI,QAAQ,EAAE,CAqErD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,cAAc,GAAG,QAAQ,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,CAyGzD"}
1
+ {"version":3,"file":"resource-generator.d.ts","sourceRoot":"","sources":["../../../../../src/services/hub-tools/resource-generator.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAmLlE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,IAAI,QAAQ,EAAE,CAqErD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,cAAc,GAAG,QAAQ,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,CAyGzD"}
@@ -104,27 +104,29 @@ function parseHubUri(uri) {
104
104
  */
105
105
  const __filename = fileURLToPath(import.meta.url);
106
106
  const __dirname = dirname(__filename);
107
- const USE_GUIDE_PATH = join(__dirname, 'use-guide.md');
107
+ const USE_GUIDE_PATH_ZH = join(__dirname, 'use-guide-zh.md');
108
+ const USE_GUIDE_PATH_EN = join(__dirname, 'use-guide-en.md');
108
109
  /**
109
110
  * Loads the use guide content from the Markdown file.
110
111
  *
111
- * @returns {string} Markdown formatted use guide content
112
+ * @param language - Language code ('zh' for Chinese, defaults to 'en')
113
+ * @returns Markdown formatted use guide content
112
114
  */
113
- function loadUseGuideContent() {
115
+ function loadUseGuideContent(language) {
116
+ const path = language === 'zh' ? USE_GUIDE_PATH_ZH : USE_GUIDE_PATH_EN;
114
117
  try {
115
- return fs.readFileSync(USE_GUIDE_PATH, 'utf-8');
118
+ return fs.readFileSync(path, 'utf-8');
116
119
  }
117
120
  catch {
118
- // Fallback in case the file can't be read
119
121
  return `# MCP Hub Lite Use Guide
120
122
 
121
123
  ## Overview
122
124
 
123
125
  MCP Hub Lite is a lightweight MCP (Model Context Protocol) gateway that acts as a unified interface between AI assistants and multiple backend MCP servers.
124
126
 
125
- ## Note
127
+ Use \`resources/list\` to discover servers, then \`list_tools\` / \`get_tool\` / \`call_tool\` to interact with them.
126
128
 
127
- The complete use guide is currently unavailable. Please check the MCP Hub Lite documentation at https://github.com/your-org/mcp-hub-lite for more information.
129
+ The complete use guide is currently unavailable. Please check the documentation for more information.
128
130
  `;
129
131
  }
130
132
  }
@@ -248,14 +250,14 @@ export function generateDynamicResources() {
248
250
  * const tools = await readResource('hub://servers/my-mcp-server/tools');
249
251
  * ```
250
252
  */
251
- export async function readResource(uri) {
253
+ export async function readResource(uri, language) {
252
254
  // Validate URI format
253
255
  if (!uri.startsWith('hub://')) {
254
256
  throw new Error(`Invalid Hub resource URI: ${uri}. Must start with 'hub://'`);
255
257
  }
256
258
  // Check for use-guide resource first
257
259
  if (uri === USE_GUIDE_URI) {
258
- return loadUseGuideContent();
260
+ return loadUseGuideContent(language);
259
261
  }
260
262
  // Parse URI
261
263
  const parsed = parseHubUri(uri);
@@ -1 +1 @@
1
- {"version":3,"file":"hub-tools.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-tools.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hub-tools.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-tools.service.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { hubManager } from './hub-manager.service.js';
2
2
  import { mcpConnectionManager } from './connection/index.js';
3
+ import { configManager } from '../config/config-manager.js';
3
4
  import { eventBus, EventTypes } from './event-bus.service.js';
4
5
  import { generateGatewayToolsList } from './gateway/tool-list-generator.js';
5
6
  import { logger, LOG_MODULES } from '../utils/logger/index.js';
@@ -668,7 +669,8 @@ export class HubToolsService {
668
669
  * @throws {Error} If URI format is invalid, server not found, or resource type unknown
669
670
  */
670
671
  async readResource(uri) {
671
- return readResourceUtil(uri);
672
+ const language = configManager.getConfig().system.language;
673
+ return readResourceUtil(uri, language);
672
674
  }
673
675
  }
674
676
  export const hubToolsService = new HubToolsService();
@@ -25,6 +25,7 @@ type ConfigGetter = () => {
25
25
  mcpCommDebug: boolean;
26
26
  apiDebug: boolean;
27
27
  gatewayDebug: boolean;
28
+ showTraceContext?: boolean;
28
29
  };
29
30
  };
30
31
  };
@@ -72,6 +73,14 @@ export declare function getApiDebugSetting(): boolean;
72
73
  * @returns boolean indicating whether to enable Gateway debug logging
73
74
  */
74
75
  export declare function getGatewayDebugSetting(): boolean;
76
+ /**
77
+ * Get the showTraceContext configuration value.
78
+ * Controls whether [SSN]/[TID]/[SID] trace context markers appear in log output.
79
+ * Defaults to true.
80
+ *
81
+ * @returns boolean indicating whether to show trace context in logs
82
+ */
83
+ export declare function getShowTraceContextSetting(): boolean;
75
84
  /**
76
85
  * Stringify object for logging with dynamic pretty formatting based on LOG_JSON_PRETTY environment variable
77
86
  * @param obj Object to stringify
@@ -1 +1 @@
1
- {"version":3,"file":"json-utils.d.ts","sourceRoot":"","sources":["../../../../src/utils/json-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAiED;;GAEG;AACH,KAAK,YAAY,GAAG,MAAM;IACxB,MAAM,EAAE;QACN,OAAO,EAAE;YACP,UAAU,EAAE,OAAO,CAAC;YACpB,YAAY,EAAE,OAAO,CAAC;YACtB,QAAQ,EAAE,OAAO,CAAC;YAClB,YAAY,EAAE,OAAO,CAAC;SACvB,CAAC;KACH,CAAC;CACH,CAAC;AAQF;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAE3E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU/E;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAG1E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAiB9C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAUhD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAU5C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAUhD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAOxD;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE,OAAO,EACZ,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,GAClD,MAAM,CAOR"}
1
+ {"version":3,"file":"json-utils.d.ts","sourceRoot":"","sources":["../../../../src/utils/json-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAiED;;GAEG;AACH,KAAK,YAAY,GAAG,MAAM;IACxB,MAAM,EAAE;QACN,OAAO,EAAE;YACP,UAAU,EAAE,OAAO,CAAC;YACpB,YAAY,EAAE,OAAO,CAAC;YACtB,QAAQ,EAAE,OAAO,CAAC;YAClB,YAAY,EAAE,OAAO,CAAC;YACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;SAC5B,CAAC;KACH,CAAC;CACH,CAAC;AAQF;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAE3E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU/E;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAG1E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAiB9C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAUhD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAU5C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAUhD;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAUpD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAOxD;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE,OAAO,EACZ,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,GAClD,MAAM,CAOR"}
@@ -198,6 +198,25 @@ export function getGatewayDebugSetting() {
198
198
  }
199
199
  return getDefaultForDevMode(false);
200
200
  }
201
+ /**
202
+ * Get the showTraceContext configuration value.
203
+ * Controls whether [SSN]/[TID]/[SID] trace context markers appear in log output.
204
+ * Defaults to true.
205
+ *
206
+ * @returns boolean indicating whether to show trace context in logs
207
+ */
208
+ export function getShowTraceContextSetting() {
209
+ if (_configGetter) {
210
+ try {
211
+ const config = _configGetter();
212
+ return config.system.logging.showTraceContext ?? true;
213
+ }
214
+ catch {
215
+ // Fall through to default if config getter fails
216
+ }
217
+ }
218
+ return true; // default enabled
219
+ }
201
220
  /**
202
221
  * Stringify object for logging with dynamic pretty formatting based on LOG_JSON_PRETTY environment variable
203
222
  * @param obj Object to stringify
@@ -7,7 +7,7 @@ export { LOG_MODULES } from './log-modules.js';
7
7
  export type { LogModuleKey, LogModule } from './log-modules.js';
8
8
  export { COLORS, getColorCodeForLevel, getResetColor } from './log-colors.js';
9
9
  export { formatTimestamp, formatLogLevel, formatPid, createColoredLogMessage, createLogMessage, formatError } from './log-formatter.js';
10
- export { isToolsListResponse, simplifyToolsListResponse, hasImageContent, simplifyImageContent, formatMcpMessageForLogging, isNotificationMessage, logNotificationMessage } from './log-output.js';
10
+ export { isToolsListResponse, simplifyToolsListResponse, hasImageContent, simplifyImageContent, hasDataUriImage, simplifyDataUriImages, formatMcpMessageForLogging, isNotificationMessage, logNotificationMessage } from './log-output.js';
11
11
  export { Logger } from './logger.js';
12
12
  import { Logger } from './logger.js';
13
13
  export declare const logger: Logger;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/utils/logger/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG/D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGhE,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG9E,OAAO,EACL,eAAe,EACf,cAAc,EACd,SAAS,EACT,uBAAuB,EACvB,gBAAgB,EAChB,WAAW,EACZ,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,eAAe,EACf,oBAAoB,EACpB,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,eAAO,MAAM,MAAM,QAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/utils/logger/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG/D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGhE,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAG9E,OAAO,EACL,eAAe,EACf,cAAc,EACd,SAAS,EACT,uBAAuB,EACvB,gBAAgB,EAChB,WAAW,EACZ,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,eAAO,MAAM,MAAM,QAAe,CAAC"}
@@ -9,7 +9,7 @@ export { COLORS, getColorCodeForLevel, getResetColor } from './log-colors.js';
9
9
  // Re-export formatter utilities
10
10
  export { formatTimestamp, formatLogLevel, formatPid, createColoredLogMessage, createLogMessage, formatError } from './log-formatter.js';
11
11
  // Re-export output utilities
12
- export { isToolsListResponse, simplifyToolsListResponse, hasImageContent, simplifyImageContent, formatMcpMessageForLogging, isNotificationMessage, logNotificationMessage } from './log-output.js';
12
+ export { isToolsListResponse, simplifyToolsListResponse, hasImageContent, simplifyImageContent, hasDataUriImage, simplifyDataUriImages, formatMcpMessageForLogging, isNotificationMessage, logNotificationMessage } from './log-output.js';
13
13
  // Re-export main Logger class
14
14
  export { Logger } from './logger.js';
15
15
  // Create and export the default logger instance
@@ -6,6 +6,7 @@ export interface LogContext {
6
6
  pid?: number;
7
7
  serverName?: string;
8
8
  module?: string;
9
+ sessionId?: string;
9
10
  traceId?: string;
10
11
  spanId?: string;
11
12
  caller?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"log-context.d.ts","sourceRoot":"","sources":["../../../../../src/utils/logger/log-context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,GAAG,YAAY,CAAC,CAAC"}
1
+ {"version":3,"file":"log-context.d.ts","sourceRoot":"","sources":["../../../../../src/utils/logger/log-context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,GAAG,YAAY,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"log-formatter.d.ts","sourceRoot":"","sources":["../../../../../src/utils/logger/log-formatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMnD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAsED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,UAAU,SAAI,GAAG,UAAU,GAAG,IAAI,CAQ/D;AA2HD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAK/D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CASlD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAatD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM7C;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,QAAQ,EACf,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,UAAU,GACnB,MAAM,CAsCR;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,MAAM,CA6B/F;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAyHlD"}
1
+ {"version":3,"file":"log-formatter.d.ts","sourceRoot":"","sources":["../../../../../src/utils/logger/log-formatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAOnD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAsED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,UAAU,SAAI,GAAG,UAAU,GAAG,IAAI,CAQ/D;AA2HD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAK/D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CASlD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAatD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM7C;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,QAAQ,EACf,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,UAAU,GACnB,MAAM,CA2CR;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,MAAM,CAkC/F;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CA4HlD"}
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { stringifyForLogging } from '../json-utils.js';
6
6
  import { getColorCodeForLevel, getResetColor, COLORS } from './log-colors.js';
7
+ import { getShowTraceContextSetting } from '../json-utils.js';
7
8
  // PID formatting configuration
8
9
  const PID_WIDTH = 8;
9
10
  /**
@@ -272,11 +273,16 @@ export function createColoredLogMessage(level, message, context) {
272
273
  const callerColor = COLORS.brightBlue;
273
274
  const resetColor = getResetColor();
274
275
  let result = `${timestampColor}[${timestamp}]${resetColor} ${levelColor}[${formattedLevel}]${resetColor} ${pidColor}[${formattedPid}]${resetColor}`;
275
- if (context?.traceId) {
276
- result += ` ${traceColor}[TID:${context.traceId}]${resetColor}`;
277
- }
278
- if (context?.spanId) {
279
- result += ` ${traceColor}[SID:${context.spanId}]${resetColor}`;
276
+ if (getShowTraceContextSetting()) {
277
+ if (context?.sessionId) {
278
+ result += ` ${traceColor}[SSN:${context.sessionId}]${resetColor}`;
279
+ }
280
+ if (context?.traceId) {
281
+ result += ` ${traceColor}[TID:${context.traceId}]${resetColor}`;
282
+ }
283
+ if (context?.spanId) {
284
+ result += ` ${traceColor}[SID:${context.spanId}]${resetColor}`;
285
+ }
280
286
  }
281
287
  result += ` ${serverColor}[${actualServerName}]${resetColor}`;
282
288
  if (context?.module) {
@@ -302,11 +308,16 @@ export function createLogMessage(level, message, context) {
302
308
  const pidStr = processPid.toString().padStart(PID_WIDTH, ' ');
303
309
  const serverIdentifier = context?.serverName || 'mcp-hub';
304
310
  let result = `[${timestamp}] [${formattedLevel}] [PID:${pidStr}]`;
305
- if (context?.traceId) {
306
- result += ` [TID:${context.traceId}]`;
307
- }
308
- if (context?.spanId) {
309
- result += ` [SID:${context.spanId}]`;
311
+ if (getShowTraceContextSetting()) {
312
+ if (context?.sessionId) {
313
+ result += ` [SSN:${context.sessionId}]`;
314
+ }
315
+ if (context?.traceId) {
316
+ result += ` [TID:${context.traceId}]`;
317
+ }
318
+ if (context?.spanId) {
319
+ result += ` [SID:${context.spanId}]`;
320
+ }
310
321
  }
311
322
  result += ` [${serverIdentifier}]`;
312
323
  if (context?.module) {
@@ -336,7 +347,10 @@ export function formatError(error) {
336
347
  if (typeof element === 'object' &&
337
348
  element !== null &&
338
349
  !Array.isArray(element) &&
339
- ('module' in element || 'traceId' in element || 'spanId' in element)) {
350
+ ('module' in element ||
351
+ 'traceId' in element ||
352
+ 'spanId' in element ||
353
+ 'sessionId' in element)) {
340
354
  return '';
341
355
  }
342
356
  // Otherwise format the single element
@@ -32,9 +32,25 @@ export declare function isNotificationMessage(message: unknown): message is Noti
32
32
  * @param serverId - Optional server ID for log storage (for frontend display)
33
33
  */
34
34
  export declare function logNotificationMessage(message: unknown, context: string, serverId?: string): void;
35
+ /**
36
+ * Check if JSON string contains data:image/*;base64 data URIs.
37
+ * These commonly appear in serverInfo.icons[].src and other metadata fields.
38
+ *
39
+ * @param data - JSON string to check
40
+ * @returns true if it contains data:image data URIs
41
+ */
42
+ export declare function hasDataUriImage(data: string): boolean;
43
+ /**
44
+ * Simplify data URI images by replacing base64 payload with placeholder.
45
+ * Matches all data:image/*;base64,... patterns and truncates the payload.
46
+ *
47
+ * @param data - JSON string containing data URIs
48
+ * @returns JSON string with base64 payloads replaced
49
+ */
50
+ export declare function simplifyDataUriImages(data: string): string;
35
51
  /**
36
52
  * Format an MCP message for logging, with simplification for tools/list,
37
- * resources/list, capabilities responses, and image content.
53
+ * resources/list, capabilities responses, image content, and data URI images.
38
54
  *
39
55
  * @param message - The MCP message object to format
40
56
  * @returns Formatted log message string
@@ -1 +1 @@
1
- {"version":3,"file":"log-output.d.ts","sourceRoot":"","sources":["../../../../../src/utils/logger/log-output.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;GAEG;AACH,UAAU,yBAAyB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,UAAU,mBAAmB;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,yBAAyB,CAAC;CACpC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,mBAAmB,CAMtF;AAqBD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAiDjG;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CA4BnE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAgCrD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqDzD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAyCzD;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuFrE"}
1
+ {"version":3,"file":"log-output.d.ts","sourceRoot":"","sources":["../../../../../src/utils/logger/log-output.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;GAEG;AACH,UAAU,yBAAyB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,UAAU,mBAAmB;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,yBAAyB,CAAC;CACpC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,mBAAmB,CAMtF;AAqBD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAiDjG;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CA8CnE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAgCrD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqDzD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CA+BzD;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiDrE"}