smart-thinking-mcp 11.0.5 → 12.0.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.
Files changed (45) hide show
  1. package/README.md +18 -2
  2. package/build/cli.d.ts +2 -0
  3. package/build/cli.js +650 -0
  4. package/build/cli.js.map +1 -0
  5. package/build/index.d.ts +24 -2
  6. package/build/index.js +35 -462
  7. package/build/index.js.map +1 -1
  8. package/build/memory-manager.d.ts +6 -0
  9. package/build/memory-manager.js +38 -6
  10. package/build/memory-manager.js.map +1 -1
  11. package/build/server/contracts.d.ts +221 -0
  12. package/build/server/contracts.js +93 -0
  13. package/build/server/contracts.js.map +1 -0
  14. package/build/server/registrations/prompt-registrations.d.ts +2 -0
  15. package/build/server/registrations/prompt-registrations.js +60 -0
  16. package/build/server/registrations/prompt-registrations.js.map +1 -0
  17. package/build/server/registrations/resource-registrations.d.ts +3 -0
  18. package/build/server/registrations/resource-registrations.js +99 -0
  19. package/build/server/registrations/resource-registrations.js.map +1 -0
  20. package/build/server/registrations/tool-registrations.d.ts +7 -0
  21. package/build/server/registrations/tool-registrations.js +202 -0
  22. package/build/server/registrations/tool-registrations.js.map +1 -0
  23. package/build/server/server-metadata.d.ts +6 -0
  24. package/build/server/server-metadata.js +36 -0
  25. package/build/server/server-metadata.js.map +1 -0
  26. package/build/server/smart-thinking-server.d.ts +11 -344
  27. package/build/server/smart-thinking-server.js +19 -275
  28. package/build/server/smart-thinking-server.js.map +1 -1
  29. package/build/services/service-container.d.ts +17 -49
  30. package/build/services/service-container.js +12 -57
  31. package/build/services/service-container.js.map +1 -1
  32. package/build/services/verification-service.js +1 -1
  33. package/build/services/verification-service.js.map +1 -1
  34. package/build/test-utils/logger-setup.js +1 -1
  35. package/build/test-utils/logger-setup.js.map +1 -1
  36. package/build/tool-integrator.d.ts +11 -1
  37. package/build/tool-integrator.js +43 -11
  38. package/build/tool-integrator.js.map +1 -1
  39. package/build/utils/logger.js +4 -1
  40. package/build/utils/logger.js.map +1 -1
  41. package/build/verification-memory.d.ts +5 -0
  42. package/build/verification-memory.js +35 -5
  43. package/build/verification-memory.js.map +1 -1
  44. package/package.json +12 -12
  45. package/scripts/make-executable.js +28 -29
package/README.md CHANGED
@@ -80,11 +80,27 @@ Smart-Thinking is validated across the most popular MCP clients and operating sy
80
80
 
81
81
  > Need a minimal deployment footprint? Combine `--transport=http --mode=connector` with a reverse proxy (ngrok, fly.io, render, etc.) so remote clients can consume the server without exposing the full toolset.
82
82
 
83
+ For registry scanners and fallback metadata extraction, Smart-Thinking also exposes:
84
+
85
+ - `GET /.well-known/mcp/server-card.json`
86
+
83
87
  ## Configuration & Feature Flags
84
88
  - `feature-flags.ts` toggles advanced behaviours such as external integrations (disabled by default) and verbose tracing.
85
89
  - `config.ts` aligns platform-specific paths and verification thresholds.
86
90
  - `memory-manager.ts` and `verification-memory.ts` store session graphs, metrics, and calculation results using deterministic JSON snapshots.
87
91
 
92
+ ## Zero-API-Key Mode (Default)
93
+ - Smart-Thinking runs fully in local deterministic mode without any API key.
94
+ - External verification/search connectors are disabled by default in `ToolIntegrator`.
95
+ - To explicitly enable external connectors, set:
96
+
97
+ ```bash
98
+ export SMART_THINKING_ENABLE_EXTERNAL_TOOLS=true
99
+ ```
100
+
101
+ - If external connectors are disabled (default), verification suggestions stay local (`executePython`, `executeJavaScript`) and external tool calls return a local fallback result.
102
+ - `FeatureFlags.externalLlmEnabled` and `FeatureFlags.externalEmbeddingEnabled` remain disabled by default, so no remote LLM/embedding provider is required.
103
+
88
104
  ## Development Workflow
89
105
  ```bash
90
106
  npm run build # Compile TypeScript sources
@@ -94,11 +110,11 @@ npm run test:coverage # Jest coverage report
94
110
  npm run watch # Incremental TypeScript compilation
95
111
  ```
96
112
 
97
- See `TRANSFORMATION_PLAN.md` for the full transformation history and the checklist that drives ongoing hardening.
113
+ See `docs/modernisation-smart-thinking-v12-plan.md` for the modernization checklist and rollout tracking.
98
114
 
99
115
  ## Quality & Support
100
116
  - Deterministic heuristics and verification eliminate dependency on remote LLMs.
101
- - Coverage targets: 80 % on persistence modules, ≥60 % branch coverage across orchestrator logic.
117
+ - Latest validation (February 6, 2026): `80.47%` statements, `81.59%` lines, `84.34%` functions, `63.48%` branches.
102
118
  - CI recommendations: run `npm run lint` and `npm run test:coverage` before each release candidate.
103
119
 
104
120
  ## Contributing
package/build/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import './utils/logger';
package/build/cli.js ADDED
@@ -0,0 +1,650 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /* istanbul ignore file -- Point d'entrée CLI difficile à tester automatiquement */
4
+ var __importDefault = (this && this.__importDefault) || function (mod) {
5
+ return (mod && mod.__esModule) ? mod : { "default": mod };
6
+ };
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ require("./utils/logger");
9
+ const express_1 = __importDefault(require("express"));
10
+ const crypto_1 = require("crypto");
11
+ const fs_1 = require("fs");
12
+ const path_1 = __importDefault(require("path"));
13
+ const sse_js_1 = require("@modelcontextprotocol/sdk/server/sse.js");
14
+ const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
15
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
16
+ const platform_stdio_1 = require("./utils/platform-stdio");
17
+ const path_utils_1 = require("./utils/path-utils");
18
+ const config_1 = require("./config");
19
+ const smart_thinking_server_1 = require("./server/smart-thinking-server");
20
+ const PROJECT_HOMEPAGE = 'https://github.com/Leghis/Smart-Thinking';
21
+ const PROJECT_ICON = 'https://raw.githubusercontent.com/Leghis/Smart-Thinking/main/logoSmart-thinking.png';
22
+ function parseCsvEnv(name) {
23
+ const raw = process.env[name];
24
+ if (!raw) {
25
+ return [];
26
+ }
27
+ return raw.split(',').map(item => item.trim()).filter(Boolean);
28
+ }
29
+ function resolveDefaultAllowedHosts(host, port) {
30
+ const hosts = new Set([
31
+ 'localhost',
32
+ `localhost:${port}`,
33
+ '127.0.0.1',
34
+ `127.0.0.1:${port}`
35
+ ]);
36
+ if (host && host !== '0.0.0.0' && host !== '::') {
37
+ hosts.add(host);
38
+ hosts.add(`${host}:${port}`);
39
+ }
40
+ return Array.from(hosts);
41
+ }
42
+ function resolveDefaultAllowedOrigins(host, port) {
43
+ const origins = new Set([
44
+ `http://localhost:${port}`,
45
+ `http://127.0.0.1:${port}`,
46
+ `https://localhost:${port}`,
47
+ `https://127.0.0.1:${port}`
48
+ ]);
49
+ if (host && host !== '0.0.0.0' && host !== '::') {
50
+ origins.add(`http://${host}:${port}`);
51
+ origins.add(`https://${host}:${port}`);
52
+ }
53
+ return Array.from(origins);
54
+ }
55
+ function loadPackageVersion() {
56
+ try {
57
+ const packageJsonPath = path_1.default.join(__dirname, '..', 'package.json');
58
+ const raw = (0, fs_1.readFileSync)(packageJsonPath, 'utf8');
59
+ const parsed = JSON.parse(raw);
60
+ return parsed.version ?? '0.0.0';
61
+ }
62
+ catch {
63
+ return '0.0.0';
64
+ }
65
+ }
66
+ function buildServerCard(options) {
67
+ const version = loadPackageVersion();
68
+ const tools = [
69
+ {
70
+ name: 'search',
71
+ description: 'Recherche semantique dans les memoires locales Smart-Thinking.',
72
+ inputSchema: {
73
+ type: 'object',
74
+ properties: {
75
+ query: { type: 'string', description: 'Requete de recherche.' },
76
+ limit: { type: 'integer', minimum: 1, maximum: 20, default: 5, description: 'Nombre maximal de resultats.' },
77
+ sessionId: { type: 'string', description: 'Session cible optionnelle.' },
78
+ },
79
+ required: ['query'],
80
+ },
81
+ },
82
+ {
83
+ name: 'fetch',
84
+ description: 'Recupere une memoire complete par identifiant.',
85
+ inputSchema: {
86
+ type: 'object',
87
+ properties: {
88
+ id: { type: 'string', description: 'Identifiant de la memoire.' },
89
+ sessionId: { type: 'string', description: 'Session cible optionnelle.' },
90
+ },
91
+ required: ['id'],
92
+ },
93
+ },
94
+ ];
95
+ if (options.mode !== 'connector') {
96
+ tools.unshift({
97
+ name: 'smartthinking',
98
+ description: 'Pipeline de raisonnement graphe local, deterministe et persistant.',
99
+ inputSchema: {
100
+ type: 'object',
101
+ properties: {
102
+ thought: { type: 'string', description: 'Pensee a analyser.' },
103
+ thoughtType: {
104
+ type: 'string',
105
+ enum: ['regular', 'revision', 'meta', 'hypothesis', 'conclusion'],
106
+ default: 'regular',
107
+ description: 'Type de pensee.',
108
+ },
109
+ sessionId: { type: 'string', description: 'Identifiant de session optionnel.' },
110
+ requestSuggestions: { type: 'boolean', default: false, description: 'Demande des suggestions d amelioration.' },
111
+ requestVerification: { type: 'boolean', default: false, description: 'Active la verification explicite.' },
112
+ containsCalculations: { type: 'boolean', default: false, description: 'Indique la presence de calculs.' },
113
+ generateVisualization: { type: 'boolean', default: false, description: 'Active la visualisation.' },
114
+ help: { type: 'boolean', default: false, description: 'Retourne le guide d utilisation.' },
115
+ },
116
+ },
117
+ });
118
+ }
119
+ return {
120
+ serverInfo: {
121
+ name: 'smart-thinking-mcp',
122
+ title: 'Smart-Thinking',
123
+ version,
124
+ websiteUrl: PROJECT_HOMEPAGE,
125
+ icons: [
126
+ {
127
+ src: PROJECT_ICON,
128
+ mimeType: 'image/png',
129
+ sizes: ['512x512'],
130
+ },
131
+ ],
132
+ },
133
+ tools,
134
+ prompts: [
135
+ {
136
+ name: 'smartthinking-reasoning-plan',
137
+ description: 'Construit un plan de raisonnement testable avant execution.',
138
+ arguments: [
139
+ { name: 'objective', required: true, description: 'Objectif principal.' },
140
+ { name: 'constraints', required: false, description: 'Contraintes.' },
141
+ { name: 'depth', required: false, description: 'Niveau de profondeur (fast|balanced|deep).' },
142
+ ],
143
+ },
144
+ {
145
+ name: 'smartthinking-verify-claim',
146
+ description: 'Genere une checklist de verification factuelle.',
147
+ arguments: [
148
+ { name: 'claim', required: true, description: 'Affirmation a verifier.' },
149
+ ],
150
+ },
151
+ ],
152
+ resources: [
153
+ {
154
+ uri: 'smart-thinking://docs/about',
155
+ name: 'smartthinking-about',
156
+ description: 'Documentation du serveur.',
157
+ },
158
+ {
159
+ uri: 'smart-thinking://runtime/status',
160
+ name: 'smartthinking-runtime-status',
161
+ description: 'Etat runtime du serveur.',
162
+ },
163
+ {
164
+ uriTemplate: 'smart-thinking://sessions/{sessionId}/recent',
165
+ name: 'smartthinking-session-recent',
166
+ description: 'Memoires recentes par session.',
167
+ },
168
+ {
169
+ uriTemplate: 'smart-thinking://memories/{memoryId}',
170
+ name: 'smartthinking-memory-by-id',
171
+ description: 'Memoire complete par identifiant.',
172
+ },
173
+ ],
174
+ };
175
+ }
176
+ (async () => {
177
+ const options = parseArgs(process.argv.slice(2));
178
+ try {
179
+ await ensureDataDirExists();
180
+ if (options.transport === 'stdio') {
181
+ await startStdIoServer(options);
182
+ }
183
+ else {
184
+ await startHttpServer(options);
185
+ }
186
+ }
187
+ catch (error) {
188
+ console.error('Smart-Thinking: échec du démarrage du serveur', error);
189
+ process.exit(1);
190
+ }
191
+ })();
192
+ function parseArgs(argv) {
193
+ const envMode = (process.env.SMART_THINKING_MODE ?? '').toLowerCase();
194
+ const defaultMode = envMode === 'connector' ? 'connector' : 'full';
195
+ const options = {
196
+ transport: 'stdio',
197
+ port: process.env.PORT ? Number(process.env.PORT) : 3000,
198
+ host: process.env.HOST ?? '127.0.0.1',
199
+ allowOrigins: parseCsvEnv('SMART_THINKING_ALLOWED_ORIGINS'),
200
+ allowHosts: parseCsvEnv('SMART_THINKING_ALLOWED_HOSTS'),
201
+ enableSse: true,
202
+ enableStream: true,
203
+ mode: defaultMode
204
+ };
205
+ for (let i = 0; i < argv.length; i += 1) {
206
+ const arg = argv[i];
207
+ const [flag, inlineValue] = arg.includes('=') ? arg.split('=', 2) : [arg, undefined];
208
+ const readValue = () => {
209
+ if (inlineValue !== undefined) {
210
+ return inlineValue;
211
+ }
212
+ const nextArg = argv[i + 1];
213
+ if (nextArg && !nextArg.startsWith('--')) {
214
+ i += 1;
215
+ return nextArg;
216
+ }
217
+ return undefined;
218
+ };
219
+ switch (flag) {
220
+ case '--transport': {
221
+ const value = readValue();
222
+ if (value === 'stdio' || value === 'http' || value === 'sse' || value === 'stream') {
223
+ options.transport = value;
224
+ }
225
+ break;
226
+ }
227
+ case '--port': {
228
+ const value = readValue();
229
+ const port = value ? Number(value) : NaN;
230
+ if (!Number.isNaN(port)) {
231
+ options.port = port;
232
+ }
233
+ break;
234
+ }
235
+ case '--host': {
236
+ const value = readValue();
237
+ if (value) {
238
+ options.host = value;
239
+ }
240
+ break;
241
+ }
242
+ case '--allow-origin': {
243
+ const value = readValue();
244
+ if (value) {
245
+ options.allowOrigins.push(value);
246
+ }
247
+ break;
248
+ }
249
+ case '--allow-host': {
250
+ const value = readValue();
251
+ if (value) {
252
+ options.allowHosts.push(value);
253
+ }
254
+ break;
255
+ }
256
+ case '--disable-sse':
257
+ options.enableSse = false;
258
+ break;
259
+ case '--disable-stream':
260
+ options.enableStream = false;
261
+ break;
262
+ case '--mode': {
263
+ const value = readValue();
264
+ if (value === 'full' || value === 'connector') {
265
+ options.mode = value;
266
+ }
267
+ break;
268
+ }
269
+ default:
270
+ break;
271
+ }
272
+ }
273
+ if (options.transport === 'sse') {
274
+ options.enableSse = true;
275
+ options.enableStream = false;
276
+ }
277
+ else if (options.transport === 'stream') {
278
+ options.enableSse = false;
279
+ options.enableStream = true;
280
+ }
281
+ else if (options.transport === 'http') {
282
+ options.enableSse = options.enableSse !== false;
283
+ options.enableStream = options.enableStream !== false;
284
+ }
285
+ if (options.transport !== 'stdio' && !options.enableSse && !options.enableStream) {
286
+ options.enableStream = true;
287
+ }
288
+ if (options.allowHosts.length === 0) {
289
+ options.allowHosts = resolveDefaultAllowedHosts(options.host, options.port);
290
+ }
291
+ if (options.allowOrigins.length === 0) {
292
+ options.allowOrigins = resolveDefaultAllowedOrigins(options.host, options.port);
293
+ }
294
+ return options;
295
+ }
296
+ async function startStdIoServer(options) {
297
+ configureStdoutFiltering();
298
+ if (options.mode === 'connector') {
299
+ console.info('Smart-Thinking: mode connecteur actif (outils search & fetch uniquement)');
300
+ }
301
+ const { server } = (0, smart_thinking_server_1.createSmartThinkingServer)(undefined, {
302
+ includeSmartThinkingTool: options.mode !== 'connector'
303
+ });
304
+ const transport = new platform_stdio_1.EnhancedStdioServerTransport();
305
+ try {
306
+ await server.connect(transport);
307
+ }
308
+ catch (error) {
309
+ console.error('Smart-Thinking: échec de la connexion STDIO', error);
310
+ throw error;
311
+ }
312
+ }
313
+ async function startHttpServer(options) {
314
+ const app = (0, express_1.default)();
315
+ app.use(express_1.default.json({ limit: '4mb' }));
316
+ app.use(createHostValidationMiddleware(options));
317
+ app.use(createCorsMiddleware(options));
318
+ app.get('/.well-known/mcp/server-card.json', (_req, res) => {
319
+ res.json(buildServerCard(options));
320
+ });
321
+ if (options.mode === 'connector') {
322
+ console.info('Smart-Thinking: mode connecteur actif (outils search & fetch uniquement)');
323
+ }
324
+ const sessions = new Map();
325
+ const dnsProtectionEnabled = true;
326
+ if (options.enableStream) {
327
+ app.all('/mcp', async (req, res) => {
328
+ try {
329
+ const sessionHeader = req.headers['mcp-session-id'];
330
+ const sessionId = Array.isArray(sessionHeader) ? sessionHeader[0] : sessionHeader;
331
+ if (sessionId) {
332
+ const state = sessions.get(sessionId);
333
+ if (!state || state.type !== 'stream') {
334
+ res.status(404).json({
335
+ jsonrpc: '2.0',
336
+ error: {
337
+ code: -32000,
338
+ message: 'Session inconnue pour le transport streamable HTTP'
339
+ },
340
+ id: null
341
+ });
342
+ return;
343
+ }
344
+ await state.transport.handleRequest(req, res, req.body);
345
+ return;
346
+ }
347
+ if (req.method !== 'POST' || !(0, types_js_1.isInitializeRequest)(req.body)) {
348
+ res.status(400).json({
349
+ jsonrpc: '2.0',
350
+ error: {
351
+ code: -32000,
352
+ message: 'Initialisation manquante ou requête invalide'
353
+ },
354
+ id: null
355
+ });
356
+ return;
357
+ }
358
+ const { server } = (0, smart_thinking_server_1.createSmartThinkingServer)(undefined, {
359
+ includeSmartThinkingTool: options.mode !== 'connector'
360
+ });
361
+ const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
362
+ sessionIdGenerator: () => (0, crypto_1.randomUUID)(),
363
+ enableDnsRebindingProtection: dnsProtectionEnabled,
364
+ allowedHosts: options.allowHosts.length ? options.allowHosts : undefined,
365
+ allowedOrigins: options.allowOrigins.length ? options.allowOrigins : undefined,
366
+ onsessioninitialized: (id) => {
367
+ sessions.set(id, {
368
+ transport,
369
+ serverClose: () => server.close().catch(() => undefined),
370
+ type: 'stream'
371
+ });
372
+ },
373
+ onsessionclosed: (id) => {
374
+ void cleanupSession(sessions, id, true);
375
+ }
376
+ });
377
+ transport.onerror = (error) => {
378
+ console.error('Smart-Thinking: erreur transport streamable', error);
379
+ };
380
+ transport.onclose = () => {
381
+ void cleanupSession(sessions, transport.sessionId, true);
382
+ };
383
+ await server.connect(transport);
384
+ await transport.handleRequest(req, res, req.body);
385
+ }
386
+ catch (error) {
387
+ if (!res.headersSent) {
388
+ res.status(500).json({
389
+ jsonrpc: '2.0',
390
+ error: {
391
+ code: -32603,
392
+ message: 'Erreur interne du serveur'
393
+ },
394
+ id: null
395
+ });
396
+ }
397
+ console.error('Smart-Thinking: erreur lors du traitement streamable HTTP', error);
398
+ }
399
+ });
400
+ }
401
+ else {
402
+ app.all('/mcp', (_req, res) => {
403
+ res.status(404).json({
404
+ jsonrpc: '2.0',
405
+ error: {
406
+ code: -32000,
407
+ message: 'Transport streamable HTTP désactivé sur ce serveur'
408
+ },
409
+ id: null
410
+ });
411
+ });
412
+ }
413
+ if (options.enableSse) {
414
+ app.get('/sse', async (req, res) => {
415
+ try {
416
+ const { server } = (0, smart_thinking_server_1.createSmartThinkingServer)(undefined, {
417
+ includeSmartThinkingTool: options.mode !== 'connector'
418
+ });
419
+ const transport = new sse_js_1.SSEServerTransport('/messages', res, {
420
+ enableDnsRebindingProtection: dnsProtectionEnabled,
421
+ allowedHosts: options.allowHosts.length ? options.allowHosts : undefined,
422
+ allowedOrigins: options.allowOrigins.length ? options.allowOrigins : undefined
423
+ });
424
+ const sessionId = transport.sessionId;
425
+ sessions.set(sessionId, {
426
+ transport,
427
+ serverClose: () => server.close().catch(() => undefined),
428
+ type: 'sse'
429
+ });
430
+ transport.onclose = () => {
431
+ void cleanupSession(sessions, sessionId, true);
432
+ };
433
+ transport.onerror = (error) => {
434
+ console.error('Smart-Thinking: erreur transport SSE', error);
435
+ };
436
+ await server.connect(transport);
437
+ }
438
+ catch (error) {
439
+ if (!res.headersSent) {
440
+ res.status(500).send('Erreur lors de l\'établissement du flux SSE');
441
+ }
442
+ console.error('Smart-Thinking: échec d\'initialisation SSE', error);
443
+ }
444
+ });
445
+ app.post('/messages', async (req, res) => {
446
+ try {
447
+ const queryParam = req.query.sessionId;
448
+ const sessionId = typeof queryParam === 'string'
449
+ ? queryParam
450
+ : Array.isArray(queryParam)
451
+ ? queryParam.find((value) => typeof value === 'string')
452
+ : undefined;
453
+ if (!sessionId) {
454
+ res.status(400).send('Paramètre sessionId manquant');
455
+ return;
456
+ }
457
+ const state = sessions.get(sessionId);
458
+ if (!state || state.type !== 'sse') {
459
+ res.status(404).send('Session SSE introuvable');
460
+ return;
461
+ }
462
+ await state.transport.handlePostMessage(req, res, req.body);
463
+ }
464
+ catch (error) {
465
+ if (!res.headersSent) {
466
+ res.status(500).send('Erreur traitement message SSE');
467
+ }
468
+ console.error('Smart-Thinking: erreur sur /messages', error);
469
+ }
470
+ });
471
+ }
472
+ else {
473
+ app.get('/sse', (_req, res) => {
474
+ res.status(404).send('Transport SSE désactivé');
475
+ });
476
+ app.post('/messages', (_req, res) => {
477
+ res.status(404).send('Transport SSE désactivé');
478
+ });
479
+ }
480
+ app.use((error, _req, res, _next) => {
481
+ if (!res.headersSent) {
482
+ res.status(500).json({ error: 'Erreur interne du serveur MCP' });
483
+ }
484
+ console.error('Smart-Thinking: middleware erreur', error);
485
+ });
486
+ await new Promise((resolve, reject) => {
487
+ const httpServer = app.listen(options.port, options.host, () => {
488
+ console.info(`Smart-Thinking: serveur MCP HTTP lance sur http://${options.host}:${options.port}`);
489
+ if (options.enableStream) {
490
+ console.info(' • Endpoint streamable HTTP : /mcp');
491
+ }
492
+ if (options.enableSse) {
493
+ console.info(' • Endpoint SSE (legacy) : /sse + /messages');
494
+ }
495
+ });
496
+ httpServer.on('error', reject);
497
+ const shutdown = async () => {
498
+ console.info('Smart-Thinking: arret du serveur HTTP en cours...');
499
+ for (const [sessionId] of sessions) {
500
+ await cleanupSession(sessions, sessionId);
501
+ }
502
+ await new Promise((resolveClose) => {
503
+ httpServer.close(() => resolveClose());
504
+ });
505
+ resolve();
506
+ };
507
+ process.once('SIGINT', shutdown);
508
+ process.once('SIGTERM', shutdown);
509
+ });
510
+ }
511
+ function createCorsMiddleware(options) {
512
+ return (req, res, next) => {
513
+ const originHeader = Array.isArray(req.headers.origin) ? req.headers.origin[0] : req.headers.origin;
514
+ res.header('Vary', 'Origin');
515
+ if (originHeader) {
516
+ if (!options.allowOrigins.includes(originHeader)) {
517
+ res.status(403).json({ error: 'Origin non autorisee' });
518
+ return;
519
+ }
520
+ res.header('Access-Control-Allow-Origin', originHeader);
521
+ }
522
+ res.header('Access-Control-Allow-Headers', 'Content-Type, MCP-Session-Id');
523
+ res.header('Access-Control-Expose-Headers', 'Mcp-Session-Id');
524
+ res.header('Access-Control-Allow-Methods', 'GET,POST,DELETE,OPTIONS');
525
+ if (req.method === 'OPTIONS') {
526
+ res.status(204).end();
527
+ return;
528
+ }
529
+ next();
530
+ };
531
+ }
532
+ function createHostValidationMiddleware(options) {
533
+ const allowedHosts = new Set(options.allowHosts.map(host => host.toLowerCase()));
534
+ return (req, res, next) => {
535
+ const hostHeader = Array.isArray(req.headers.host) ? req.headers.host[0] : req.headers.host;
536
+ if (!hostHeader) {
537
+ next();
538
+ return;
539
+ }
540
+ const normalizedHost = hostHeader.toLowerCase();
541
+ const hostOnly = normalizedHost.split(':')[0];
542
+ if (!allowedHosts.has(normalizedHost) && !allowedHosts.has(hostOnly)) {
543
+ res.status(403).json({ error: 'Host non autorise' });
544
+ return;
545
+ }
546
+ next();
547
+ };
548
+ }
549
+ async function cleanupSession(sessions, sessionId, skipTransportClose = false) {
550
+ if (!sessionId) {
551
+ return;
552
+ }
553
+ const state = sessions.get(sessionId);
554
+ if (!state) {
555
+ return;
556
+ }
557
+ sessions.delete(sessionId);
558
+ try {
559
+ if (!skipTransportClose) {
560
+ await state.transport.close();
561
+ }
562
+ }
563
+ catch (error) {
564
+ console.error(`Smart-Thinking: erreur fermeture transport ${sessionId}`, error);
565
+ }
566
+ try {
567
+ await state.serverClose();
568
+ }
569
+ catch (error) {
570
+ console.error(`Smart-Thinking: erreur fermeture serveur ${sessionId}`, error);
571
+ }
572
+ }
573
+ function configureStdoutFiltering() {
574
+ const originalStdoutWrite = process.stdout.write.bind(process.stdout);
575
+ function isValidJSON(str) {
576
+ if (typeof str !== 'string')
577
+ return false;
578
+ const trimmed = str.trim();
579
+ if (!trimmed)
580
+ return false;
581
+ if (!(trimmed.startsWith('{') && trimmed.endsWith('}')) &&
582
+ !(trimmed.startsWith('[') && trimmed.endsWith(']'))) {
583
+ return false;
584
+ }
585
+ try {
586
+ JSON.parse(trimmed);
587
+ return true;
588
+ }
589
+ catch {
590
+ return false;
591
+ }
592
+ }
593
+ process.stdout.write = function stdoutFilter(chunk, encoding, cb) {
594
+ if (typeof chunk === 'string') {
595
+ const trimmed = chunk.trim();
596
+ if ((trimmed.startsWith('{') || trimmed.startsWith('[')) && !isValidJSON(trimmed)) {
597
+ console.error('[ERREUR] JSON invalide détecté:', chunk);
598
+ try {
599
+ const safeMessage = JSON.stringify({
600
+ jsonrpc: '2.0',
601
+ result: {
602
+ content: [{ type: 'text', text: chunk }]
603
+ }
604
+ }) + (config_1.PlatformConfig.IS_WINDOWS ? '\n' : '');
605
+ return originalStdoutWrite(safeMessage, encoding, cb);
606
+ }
607
+ catch (error) {
608
+ console.error('[ERREUR] Impossible de corriger le JSON:', error);
609
+ process.stderr.write(chunk, encoding);
610
+ if (cb)
611
+ cb();
612
+ return true;
613
+ }
614
+ }
615
+ if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {
616
+ process.stderr.write(chunk, encoding);
617
+ if (cb)
618
+ cb();
619
+ return true;
620
+ }
621
+ }
622
+ return originalStdoutWrite(chunk, encoding, cb);
623
+ };
624
+ }
625
+ async function ensureDataDirExists() {
626
+ const dataDir = path_utils_1.PathUtils.getDataDirectory();
627
+ try {
628
+ await fs_1.promises.mkdir(dataDir, { recursive: true });
629
+ if (config_1.PlatformConfig.IS_WINDOWS) {
630
+ try {
631
+ await fs_1.promises.access(dataDir, fs_1.constants.W_OK);
632
+ }
633
+ catch {
634
+ console.warn('Smart-Thinking: permissions limitées sur le répertoire data, utilisation possible d\'un fallback.');
635
+ }
636
+ }
637
+ }
638
+ catch {
639
+ if (config_1.PlatformConfig.IS_WINDOWS) {
640
+ const altDataDir = path_1.default.join(process.env.USERPROFILE || '', 'Documents', 'Smart-Thinking', 'data');
641
+ try {
642
+ await fs_1.promises.mkdir(altDataDir, { recursive: true });
643
+ }
644
+ catch {
645
+ // Ignorer l'erreur, le gestionnaire de mémoire basculera en mémoire vive uniquement
646
+ }
647
+ }
648
+ }
649
+ }
650
+ //# sourceMappingURL=cli.js.map