@leanmcp/core 0.2.0 → 0.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/dist/index.js CHANGED
@@ -6,6 +6,9 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
9
12
  var __export = (target, all) => {
10
13
  for (var name in all)
11
14
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -28,48 +31,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
31
  ));
29
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
33
 
31
- // src/index.ts
32
- var index_exports = {};
33
- __export(index_exports, {
34
- Auth: () => Auth,
35
- Deprecated: () => Deprecated,
36
- LogLevel: () => LogLevel,
37
- Logger: () => Logger,
38
- MCPServer: () => MCPServer,
39
- MCPServerRuntime: () => MCPServerRuntime,
40
- Optional: () => Optional,
41
- Prompt: () => Prompt,
42
- Render: () => Render,
43
- Resource: () => Resource,
44
- SchemaConstraint: () => SchemaConstraint,
45
- Tool: () => Tool,
46
- UI: () => UI,
47
- UserEnvs: () => UserEnvs,
48
- classToJsonSchema: () => classToJsonSchema,
49
- classToJsonSchemaWithConstraints: () => classToJsonSchemaWithConstraints,
50
- createHTTPServer: () => createHTTPServer,
51
- defaultLogger: () => defaultLogger,
52
- getDecoratedMethods: () => getDecoratedMethods,
53
- getMethodMetadata: () => getMethodMetadata,
54
- startMCPServer: () => startMCPServer,
55
- validateNonEmpty: () => validateNonEmpty,
56
- validatePath: () => validatePath,
57
- validatePort: () => validatePort,
58
- validateServiceName: () => validateServiceName,
59
- validateUrl: () => validateUrl
60
- });
61
- module.exports = __toCommonJS(index_exports);
62
- var import_reflect_metadata3 = require("reflect-metadata");
63
- var import_fs = __toESM(require("fs"));
64
- var import_path = __toESM(require("path"));
65
- var import_url = require("url");
66
- var import_server = require("@modelcontextprotocol/sdk/server/index.js");
67
- var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
68
- var import_types = require("@modelcontextprotocol/sdk/types.js");
69
- var import_ajv = __toESM(require("ajv"));
70
-
71
34
  // src/decorators.ts
72
- var import_reflect_metadata = require("reflect-metadata");
73
35
  function Tool(options = {}) {
74
36
  return (target, propertyKey, descriptor) => {
75
37
  const toolName = String(propertyKey);
@@ -81,7 +43,6 @@ function Tool(options = {}) {
81
43
  }
82
44
  };
83
45
  }
84
- __name(Tool, "Tool");
85
46
  function Prompt(options = {}) {
86
47
  return (target, propertyKey, descriptor) => {
87
48
  const promptName = String(propertyKey);
@@ -98,7 +59,6 @@ function Prompt(options = {}) {
98
59
  }
99
60
  };
100
61
  }
101
- __name(Prompt, "Prompt");
102
62
  function Resource(options = {}) {
103
63
  return (target, propertyKey, descriptor) => {
104
64
  const resourceName = String(propertyKey);
@@ -114,7 +74,6 @@ function Resource(options = {}) {
114
74
  }
115
75
  };
116
76
  }
117
- __name(Resource, "Resource");
118
77
  function Auth(options) {
119
78
  return (target, propertyKey, descriptor) => {
120
79
  if (propertyKey && descriptor) {
@@ -126,14 +85,12 @@ function Auth(options) {
126
85
  }
127
86
  };
128
87
  }
129
- __name(Auth, "Auth");
130
88
  function UserEnvs() {
131
89
  return (target, propertyKey) => {
132
90
  const constructor = target.constructor;
133
91
  Reflect.defineMetadata("userenvs:propertyKey", propertyKey, constructor);
134
92
  };
135
93
  }
136
- __name(UserEnvs, "UserEnvs");
137
94
  function UI(component) {
138
95
  return (target, propertyKey, descriptor) => {
139
96
  if (propertyKey && descriptor) {
@@ -143,13 +100,11 @@ function UI(component) {
143
100
  }
144
101
  };
145
102
  }
146
- __name(UI, "UI");
147
103
  function Render(format) {
148
104
  return (target, propertyKey, descriptor) => {
149
105
  Reflect.defineMetadata("render:format", format, descriptor.value);
150
106
  };
151
107
  }
152
- __name(Render, "Render");
153
108
  function Deprecated(message) {
154
109
  return (target, propertyKey, descriptor) => {
155
110
  const deprecationMessage = message || "This feature is deprecated";
@@ -168,7 +123,6 @@ function Deprecated(message) {
168
123
  }
169
124
  };
170
125
  }
171
- __name(Deprecated, "Deprecated");
172
126
  function getMethodMetadata(method) {
173
127
  return {
174
128
  // Tool metadata
@@ -192,7 +146,6 @@ function getMethodMetadata(method) {
192
146
  deprecationMessage: Reflect.getMetadata("deprecated:message", method)
193
147
  };
194
148
  }
195
- __name(getMethodMetadata, "getMethodMetadata");
196
149
  function getDecoratedMethods(target, metadataKey) {
197
150
  const methods = [];
198
151
  const prototype = target.prototype || target;
@@ -211,10 +164,25 @@ function getDecoratedMethods(target, metadataKey) {
211
164
  }
212
165
  return methods;
213
166
  }
214
- __name(getDecoratedMethods, "getDecoratedMethods");
167
+ var import_reflect_metadata;
168
+ var init_decorators = __esm({
169
+ "src/decorators.ts"() {
170
+ "use strict";
171
+ import_reflect_metadata = require("reflect-metadata");
172
+ __name(Tool, "Tool");
173
+ __name(Prompt, "Prompt");
174
+ __name(Resource, "Resource");
175
+ __name(Auth, "Auth");
176
+ __name(UserEnvs, "UserEnvs");
177
+ __name(UI, "UI");
178
+ __name(Render, "Render");
179
+ __name(Deprecated, "Deprecated");
180
+ __name(getMethodMetadata, "getMethodMetadata");
181
+ __name(getDecoratedMethods, "getDecoratedMethods");
182
+ }
183
+ });
215
184
 
216
185
  // src/schema-generator.ts
217
- var import_reflect_metadata2 = require("reflect-metadata");
218
186
  function classToJsonSchema(classConstructor) {
219
187
  const instance = new classConstructor();
220
188
  const properties = {};
@@ -261,19 +229,16 @@ function classToJsonSchema(classConstructor) {
261
229
  required: required.length > 0 ? required : void 0
262
230
  };
263
231
  }
264
- __name(classToJsonSchema, "classToJsonSchema");
265
232
  function Optional() {
266
233
  return (target, propertyKey) => {
267
234
  Reflect.defineMetadata("optional", true, target, propertyKey);
268
235
  };
269
236
  }
270
- __name(Optional, "Optional");
271
237
  function SchemaConstraint(constraints) {
272
238
  return (target, propertyKey) => {
273
239
  Reflect.defineMetadata("schema:constraints", constraints, target, propertyKey);
274
240
  };
275
241
  }
276
- __name(SchemaConstraint, "SchemaConstraint");
277
242
  function classToJsonSchemaWithConstraints(classConstructor) {
278
243
  const instance = new classConstructor();
279
244
  const properties = {};
@@ -334,70 +299,83 @@ function classToJsonSchemaWithConstraints(classConstructor) {
334
299
  required: required.length > 0 ? required : void 0
335
300
  };
336
301
  }
337
- __name(classToJsonSchemaWithConstraints, "classToJsonSchemaWithConstraints");
338
-
339
- // src/http-server.ts
340
- var import_node_crypto = require("crypto");
302
+ var import_reflect_metadata2;
303
+ var init_schema_generator = __esm({
304
+ "src/schema-generator.ts"() {
305
+ "use strict";
306
+ import_reflect_metadata2 = require("reflect-metadata");
307
+ __name(classToJsonSchema, "classToJsonSchema");
308
+ __name(Optional, "Optional");
309
+ __name(SchemaConstraint, "SchemaConstraint");
310
+ __name(classToJsonSchemaWithConstraints, "classToJsonSchemaWithConstraints");
311
+ }
312
+ });
341
313
 
342
314
  // src/logger.ts
343
- var LogLevel = /* @__PURE__ */ (function(LogLevel2) {
344
- LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
345
- LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
346
- LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
347
- LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
348
- LogLevel2[LogLevel2["NONE"] = 4] = "NONE";
349
- return LogLevel2;
350
- })({});
351
- var Logger = class {
352
- static {
353
- __name(this, "Logger");
354
- }
355
- level;
356
- prefix;
357
- timestamps;
358
- constructor(options = {}) {
359
- this.level = options.level ?? 1;
360
- this.prefix = options.prefix ?? "";
361
- this.timestamps = options.timestamps ?? true;
362
- }
363
- format(level, message, ...args) {
364
- const timestamp = this.timestamps ? `[${(/* @__PURE__ */ new Date()).toISOString()}]` : "";
365
- const prefix = this.prefix ? `[${this.prefix}]` : "";
366
- return `${timestamp}${prefix}[${level}] ${message}`;
367
- }
368
- shouldLog(level) {
369
- return level >= this.level;
370
- }
371
- debug(message, ...args) {
372
- if (this.shouldLog(0)) {
373
- console.debug(this.format("DEBUG", message), ...args);
374
- }
375
- }
376
- info(message, ...args) {
377
- if (this.shouldLog(1)) {
378
- console.info(this.format("INFO", message), ...args);
379
- }
380
- }
381
- warn(message, ...args) {
382
- if (this.shouldLog(2)) {
383
- console.warn(this.format("WARN", message), ...args);
384
- }
385
- }
386
- error(message, ...args) {
387
- if (this.shouldLog(3)) {
388
- console.error(this.format("ERROR", message), ...args);
389
- }
390
- }
391
- setLevel(level) {
392
- this.level = level;
393
- }
394
- getLevel() {
395
- return this.level;
315
+ var LogLevel, Logger, defaultLogger;
316
+ var init_logger = __esm({
317
+ "src/logger.ts"() {
318
+ "use strict";
319
+ LogLevel = /* @__PURE__ */ (function(LogLevel2) {
320
+ LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
321
+ LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
322
+ LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
323
+ LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
324
+ LogLevel2[LogLevel2["NONE"] = 4] = "NONE";
325
+ return LogLevel2;
326
+ })({});
327
+ Logger = class {
328
+ static {
329
+ __name(this, "Logger");
330
+ }
331
+ level;
332
+ prefix;
333
+ timestamps;
334
+ constructor(options = {}) {
335
+ this.level = options.level ?? 1;
336
+ this.prefix = options.prefix ?? "";
337
+ this.timestamps = options.timestamps ?? true;
338
+ }
339
+ format(level, message, ...args) {
340
+ const timestamp = this.timestamps ? `[${(/* @__PURE__ */ new Date()).toISOString()}]` : "";
341
+ const prefix = this.prefix ? `[${this.prefix}]` : "";
342
+ return `${timestamp}${prefix}[${level}] ${message}`;
343
+ }
344
+ shouldLog(level) {
345
+ return level >= this.level;
346
+ }
347
+ debug(message, ...args) {
348
+ if (this.shouldLog(0)) {
349
+ console.debug(this.format("DEBUG", message), ...args);
350
+ }
351
+ }
352
+ info(message, ...args) {
353
+ if (this.shouldLog(1)) {
354
+ console.info(this.format("INFO", message), ...args);
355
+ }
356
+ }
357
+ warn(message, ...args) {
358
+ if (this.shouldLog(2)) {
359
+ console.warn(this.format("WARN", message), ...args);
360
+ }
361
+ }
362
+ error(message, ...args) {
363
+ if (this.shouldLog(3)) {
364
+ console.error(this.format("ERROR", message), ...args);
365
+ }
366
+ }
367
+ setLevel(level) {
368
+ this.level = level;
369
+ }
370
+ getLevel() {
371
+ return this.level;
372
+ }
373
+ };
374
+ defaultLogger = new Logger({
375
+ level: 1,
376
+ prefix: "LeanMCP"
377
+ });
396
378
  }
397
- };
398
- var defaultLogger = new Logger({
399
- level: 1,
400
- prefix: "LeanMCP"
401
379
  });
402
380
 
403
381
  // src/validation.ts
@@ -406,26 +384,22 @@ function validatePort(port) {
406
384
  throw new Error(`Invalid port: ${port}. Must be an integer between 1-65535`);
407
385
  }
408
386
  }
409
- __name(validatePort, "validatePort");
410
387
  function validatePath(path2) {
411
388
  if (path2.includes("..") || path2.includes("~")) {
412
389
  throw new Error(`Invalid path: ${path2}. Path traversal patterns are not allowed`);
413
390
  }
414
391
  }
415
- __name(validatePath, "validatePath");
416
392
  function validateServiceName(name) {
417
393
  const validNamePattern = /^[a-zA-Z0-9_-]+$/;
418
394
  if (!validNamePattern.test(name)) {
419
395
  throw new Error(`Invalid service name: ${name}. Service names must contain only alphanumeric characters, hyphens, and underscores`);
420
396
  }
421
397
  }
422
- __name(validateServiceName, "validateServiceName");
423
398
  function validateNonEmpty(value, fieldName) {
424
399
  if (!value || value.trim().length === 0) {
425
400
  throw new Error(`${fieldName} cannot be empty`);
426
401
  }
427
402
  }
428
- __name(validateNonEmpty, "validateNonEmpty");
429
403
  function validateUrl(url, allowedProtocols = [
430
404
  "http:",
431
405
  "https:"
@@ -442,14 +416,41 @@ function validateUrl(url, allowedProtocols = [
442
416
  throw error;
443
417
  }
444
418
  }
445
- __name(validateUrl, "validateUrl");
419
+ var init_validation = __esm({
420
+ "src/validation.ts"() {
421
+ "use strict";
422
+ __name(validatePort, "validatePort");
423
+ __name(validatePath, "validatePath");
424
+ __name(validateServiceName, "validateServiceName");
425
+ __name(validateNonEmpty, "validateNonEmpty");
426
+ __name(validateUrl, "validateUrl");
427
+ }
428
+ });
446
429
 
447
430
  // src/http-server.ts
448
431
  function isInitializeRequest(body) {
449
432
  return body && body.method === "initialize";
450
433
  }
451
- __name(isInitializeRequest, "isInitializeRequest");
452
- async function createHTTPServer(serverFactory, options = {}) {
434
+ async function createHTTPServer(serverInput, options) {
435
+ let serverFactory;
436
+ let httpOptions;
437
+ if (typeof serverInput === "function") {
438
+ serverFactory = serverInput;
439
+ httpOptions = options || {};
440
+ } else {
441
+ const serverOptions = serverInput;
442
+ const { MCPServer: MCPServer2 } = await Promise.resolve().then(() => (init_index(), index_exports));
443
+ serverFactory = /* @__PURE__ */ __name(async () => {
444
+ const mcpServer2 = new MCPServer2(serverOptions);
445
+ return mcpServer2.getServer();
446
+ }, "serverFactory");
447
+ httpOptions = {
448
+ port: serverOptions.port,
449
+ cors: serverOptions.cors,
450
+ logging: serverOptions.logging,
451
+ sessionTimeout: serverOptions.sessionTimeout
452
+ };
453
+ }
453
454
  const [express, { StreamableHTTPServerTransport }, cors] = await Promise.all([
454
455
  // @ts-ignore
455
456
  import("express").catch(() => {
@@ -460,20 +461,20 @@ async function createHTTPServer(serverFactory, options = {}) {
460
461
  throw new Error("MCP SDK not found. Install with: npm install @modelcontextprotocol/sdk");
461
462
  }),
462
463
  // @ts-ignore
463
- options.cors ? import("cors").catch(() => null) : Promise.resolve(null)
464
+ httpOptions.cors ? import("cors").catch(() => null) : Promise.resolve(null)
464
465
  ]);
465
466
  const app = express.default();
466
- const port = options.port || 3001;
467
+ const port = httpOptions.port || 3001;
467
468
  validatePort(port);
468
469
  const transports = {};
469
470
  let mcpServer = null;
470
- const logger = options.logger || new Logger({
471
- level: options.logging ? LogLevel.INFO : LogLevel.NONE,
471
+ const logger = httpOptions.logger || new Logger({
472
+ level: httpOptions.logging ? LogLevel.INFO : LogLevel.NONE,
472
473
  prefix: "HTTP"
473
474
  });
474
- if (cors && options.cors) {
475
- const corsOptions = typeof options.cors === "object" ? {
476
- origin: options.cors.origin || false,
475
+ if (cors && httpOptions.cors) {
476
+ const corsOptions = typeof httpOptions.cors === "object" ? {
477
+ origin: httpOptions.cors.origin || false,
477
478
  methods: [
478
479
  "GET",
479
480
  "POST",
@@ -489,7 +490,7 @@ async function createHTTPServer(serverFactory, options = {}) {
489
490
  exposedHeaders: [
490
491
  "mcp-session-id"
491
492
  ],
492
- credentials: options.cors.credentials ?? false,
493
+ credentials: httpOptions.cors.credentials ?? false,
493
494
  maxAge: 86400
494
495
  } : false;
495
496
  if (corsOptions) {
@@ -606,736 +607,806 @@ async function createHTTPServer(serverFactory, options = {}) {
606
607
  }
607
608
  });
608
609
  }
609
- __name(createHTTPServer, "createHTTPServer");
610
+ var import_node_crypto;
611
+ var init_http_server = __esm({
612
+ "src/http-server.ts"() {
613
+ "use strict";
614
+ import_node_crypto = require("crypto");
615
+ init_logger();
616
+ init_validation();
617
+ __name(isInitializeRequest, "isInitializeRequest");
618
+ __name(createHTTPServer, "createHTTPServer");
619
+ }
620
+ });
610
621
 
611
622
  // src/index.ts
612
- var ajv = new import_ajv.default();
613
- var MCPServer = class {
614
- static {
615
- __name(this, "MCPServer");
616
- }
617
- server;
618
- tools = /* @__PURE__ */ new Map();
619
- prompts = /* @__PURE__ */ new Map();
620
- resources = /* @__PURE__ */ new Map();
621
- logging;
622
- logger;
623
- options;
624
- initPromise;
625
- autoDiscovered = false;
626
- constructor(options) {
627
- this.options = options;
628
- this.logging = options.logging || false;
629
- let logLevel = LogLevel.NONE;
630
- if (options.logging) {
631
- logLevel = options.debug ? LogLevel.DEBUG : LogLevel.INFO;
632
- }
633
- this.logger = new Logger({
634
- level: logLevel,
635
- prefix: "MCPServer"
636
- });
637
- this.server = new import_server.Server({
638
- name: options.name,
639
- version: options.version
640
- }, {
641
- capabilities: {
642
- tools: {},
643
- prompts: {},
644
- resources: {}
623
+ var index_exports = {};
624
+ __export(index_exports, {
625
+ Auth: () => Auth,
626
+ Deprecated: () => Deprecated,
627
+ LogLevel: () => LogLevel,
628
+ Logger: () => Logger,
629
+ MCPServer: () => MCPServer,
630
+ MCPServerRuntime: () => MCPServerRuntime,
631
+ Optional: () => Optional,
632
+ Prompt: () => Prompt,
633
+ Render: () => Render,
634
+ Resource: () => Resource,
635
+ SchemaConstraint: () => SchemaConstraint,
636
+ Tool: () => Tool,
637
+ UI: () => UI,
638
+ UserEnvs: () => UserEnvs,
639
+ classToJsonSchema: () => classToJsonSchema,
640
+ classToJsonSchemaWithConstraints: () => classToJsonSchemaWithConstraints,
641
+ createHTTPServer: () => createHTTPServer,
642
+ defaultLogger: () => defaultLogger,
643
+ getDecoratedMethods: () => getDecoratedMethods,
644
+ getMethodMetadata: () => getMethodMetadata,
645
+ startMCPServer: () => startMCPServer,
646
+ validateNonEmpty: () => validateNonEmpty,
647
+ validatePath: () => validatePath,
648
+ validatePort: () => validatePort,
649
+ validateServiceName: () => validateServiceName,
650
+ validateUrl: () => validateUrl
651
+ });
652
+ module.exports = __toCommonJS(index_exports);
653
+ async function startMCPServer(options) {
654
+ const runtime = new MCPServerRuntime(options);
655
+ await runtime.start();
656
+ return runtime;
657
+ }
658
+ var import_reflect_metadata3, import_fs, import_path, import_url, import_server, import_stdio, import_types, import_ajv, ajv, MCPServer, MCPServerRuntime;
659
+ var init_index = __esm({
660
+ "src/index.ts"() {
661
+ import_reflect_metadata3 = require("reflect-metadata");
662
+ import_fs = __toESM(require("fs"));
663
+ import_path = __toESM(require("path"));
664
+ import_url = require("url");
665
+ import_server = require("@modelcontextprotocol/sdk/server/index.js");
666
+ import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
667
+ import_types = require("@modelcontextprotocol/sdk/types.js");
668
+ import_ajv = __toESM(require("ajv"));
669
+ init_decorators();
670
+ init_schema_generator();
671
+ init_http_server();
672
+ init_logger();
673
+ init_validation();
674
+ init_decorators();
675
+ init_schema_generator();
676
+ init_logger();
677
+ ajv = new import_ajv.default();
678
+ MCPServer = class {
679
+ static {
680
+ __name(this, "MCPServer");
645
681
  }
646
- });
647
- this.setupHandlers();
648
- this.initPromise = this.autoInit();
649
- }
650
- /**
651
- * Internal initialization - runs automatically in constructor
652
- */
653
- async autoInit() {
654
- const options = this.options;
655
- if (options.autoDiscover !== false) {
656
- await this.autoDiscoverServices(options.mcpDir, options.serviceFactories);
657
- }
658
- }
659
- /**
660
- * Wait for initialization to complete
661
- * This is called internally by createHTTPServer
662
- */
663
- async waitForInit() {
664
- await this.initPromise;
665
- }
666
- /**
667
- * Automatically discover and register services from the mcp directory
668
- * Called by init() unless autoDiscover is set to false
669
- */
670
- async autoDiscoverServices(customMcpDir, serviceFactories) {
671
- if (this.autoDiscovered) return;
672
- this.autoDiscovered = true;
673
- try {
674
- let mcpDir;
675
- if (customMcpDir) {
676
- mcpDir = customMcpDir;
677
- } else {
678
- const callerFile = this.getCallerFile();
679
- if (callerFile) {
680
- const callerDir = import_path.default.dirname(callerFile);
681
- mcpDir = import_path.default.join(callerDir, "mcp");
682
- } else {
683
- mcpDir = import_path.default.join(process.cwd(), "mcp");
682
+ server;
683
+ tools = /* @__PURE__ */ new Map();
684
+ prompts = /* @__PURE__ */ new Map();
685
+ resources = /* @__PURE__ */ new Map();
686
+ logging;
687
+ logger;
688
+ options;
689
+ initPromise;
690
+ autoDiscovered = false;
691
+ constructor(options) {
692
+ this.options = options;
693
+ this.logging = options.logging || false;
694
+ let logLevel = LogLevel.NONE;
695
+ if (options.logging) {
696
+ logLevel = options.debug ? LogLevel.DEBUG : LogLevel.INFO;
684
697
  }
698
+ this.logger = new Logger({
699
+ level: logLevel,
700
+ prefix: "MCPServer"
701
+ });
702
+ this.server = new import_server.Server({
703
+ name: options.name,
704
+ version: options.version
705
+ }, {
706
+ capabilities: {
707
+ tools: {},
708
+ prompts: {},
709
+ resources: {}
710
+ }
711
+ });
712
+ this.setupHandlers();
713
+ this.initPromise = this.autoInit();
685
714
  }
686
- if (import_fs.default.existsSync(mcpDir)) {
687
- this.logger.debug(`Auto-discovering services from: ${mcpDir}`);
688
- await this.autoRegisterServices(mcpDir, serviceFactories);
689
- } else {
690
- this.logger.debug(`MCP directory not found at ${mcpDir}, skipping auto-discovery`);
715
+ /**
716
+ * Internal initialization - runs automatically in constructor
717
+ */
718
+ async autoInit() {
719
+ const options = this.options;
720
+ if (options.autoDiscover !== false) {
721
+ await this.autoDiscoverServices(options.mcpDir, options.serviceFactories);
722
+ }
691
723
  }
692
- } catch (error) {
693
- this.logger.warn(`Auto-discovery failed: ${error.message}`);
694
- }
695
- }
696
- /**
697
- * Get the file path of the caller (the file that instantiated MCPServer)
698
- */
699
- getCallerFile() {
700
- const originalPrepareStackTrace = Error.prepareStackTrace;
701
- try {
702
- const err = new Error();
703
- Error.prepareStackTrace = (_, stack2) => stack2;
704
- const stack = err.stack;
705
- for (let i = 0; i < stack.length; i++) {
706
- let fileName = stack[i].getFileName();
707
- if (fileName && !fileName.includes("@leanmcp") && !fileName.includes("leanmcp-sdk\\packages\\core") && !fileName.includes("leanmcp-sdk/packages/core") && (fileName.endsWith(".ts") || fileName.endsWith(".js") || fileName.endsWith(".mjs"))) {
708
- if (fileName.startsWith("file://")) {
709
- fileName = fileName.replace("file:///", "").replace("file://", "");
710
- if (process.platform === "win32" && fileName.startsWith("/")) {
711
- fileName = fileName.substring(1);
724
+ /**
725
+ * Wait for initialization to complete
726
+ * This is called internally by createHTTPServer
727
+ */
728
+ async waitForInit() {
729
+ await this.initPromise;
730
+ }
731
+ /**
732
+ * Automatically discover and register services from the mcp directory
733
+ * Called by init() unless autoDiscover is set to false
734
+ */
735
+ async autoDiscoverServices(customMcpDir, serviceFactories) {
736
+ if (this.autoDiscovered) return;
737
+ this.autoDiscovered = true;
738
+ try {
739
+ let mcpDir;
740
+ if (customMcpDir) {
741
+ mcpDir = customMcpDir;
742
+ } else {
743
+ const callerFile = this.getCallerFile();
744
+ if (callerFile) {
745
+ const callerDir = import_path.default.dirname(callerFile);
746
+ mcpDir = import_path.default.join(callerDir, "mcp");
747
+ } else {
748
+ mcpDir = import_path.default.join(process.cwd(), "mcp");
712
749
  }
713
750
  }
714
- return fileName;
751
+ if (import_fs.default.existsSync(mcpDir)) {
752
+ this.logger.debug(`Auto-discovering services from: ${mcpDir}`);
753
+ await this.autoRegisterServices(mcpDir, serviceFactories);
754
+ } else {
755
+ this.logger.debug(`MCP directory not found at ${mcpDir}, skipping auto-discovery`);
756
+ }
757
+ } catch (error) {
758
+ this.logger.warn(`Auto-discovery failed: ${error.message}`);
715
759
  }
716
760
  }
717
- return null;
718
- } finally {
719
- Error.prepareStackTrace = originalPrepareStackTrace;
720
- }
721
- }
722
- setupHandlers() {
723
- this.server.setRequestHandler(import_types.ListToolsRequestSchema, async () => {
724
- const tools = [];
725
- for (const [name, tool] of this.tools.entries()) {
726
- tools.push({
727
- name,
728
- description: tool.description,
729
- inputSchema: tool.inputSchema || {
730
- type: "object",
731
- properties: {}
761
+ /**
762
+ * Get the file path of the caller (the file that instantiated MCPServer)
763
+ */
764
+ getCallerFile() {
765
+ const originalPrepareStackTrace = Error.prepareStackTrace;
766
+ try {
767
+ const err = new Error();
768
+ Error.prepareStackTrace = (_, stack2) => stack2;
769
+ const stack = err.stack;
770
+ for (let i = 0; i < stack.length; i++) {
771
+ let fileName = stack[i].getFileName();
772
+ if (fileName && !fileName.includes("@leanmcp") && !fileName.includes("leanmcp-sdk\\packages\\core") && !fileName.includes("leanmcp-sdk/packages/core") && (fileName.endsWith(".ts") || fileName.endsWith(".js") || fileName.endsWith(".mjs"))) {
773
+ if (fileName.startsWith("file://")) {
774
+ try {
775
+ const url = new URL(fileName);
776
+ fileName = decodeURIComponent(url.pathname);
777
+ if (process.platform === "win32" && fileName.startsWith("/")) {
778
+ fileName = fileName.substring(1);
779
+ }
780
+ } catch (e) {
781
+ fileName = fileName.replace("file://", "");
782
+ if (process.platform === "win32" && fileName.startsWith("/")) {
783
+ fileName = fileName.substring(1);
784
+ }
785
+ }
786
+ }
787
+ return fileName;
788
+ }
732
789
  }
733
- });
734
- }
735
- return {
736
- tools
737
- };
738
- });
739
- this.server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
740
- const toolName = request.params.name;
741
- const tool = this.tools.get(toolName);
742
- if (!tool) {
743
- throw new Error(`Tool ${toolName} not found`);
744
- }
745
- const methodMeta = getMethodMetadata(tool.method);
746
- if (methodMeta.inputSchema) {
747
- const validate = ajv.compile(methodMeta.inputSchema);
748
- const valid = validate(request.params.arguments || {});
749
- if (!valid) {
750
- throw new Error(`Input validation failed: ${JSON.stringify(validate.errors)}`);
790
+ return null;
791
+ } finally {
792
+ Error.prepareStackTrace = originalPrepareStackTrace;
751
793
  }
752
794
  }
753
- try {
754
- const meta = request.params._meta;
755
- const result = await tool.method.call(tool.instance, request.params.arguments, meta);
756
- let formattedResult = result;
757
- if (methodMeta.renderFormat === "markdown" && typeof result === "string") {
758
- formattedResult = result;
759
- } else if (methodMeta.renderFormat === "json" || typeof result === "object") {
760
- formattedResult = JSON.stringify(result, null, 2);
761
- } else {
762
- formattedResult = String(result);
763
- }
764
- return {
765
- content: [
766
- {
767
- type: "text",
768
- text: formattedResult
795
+ setupHandlers() {
796
+ this.server.setRequestHandler(import_types.ListToolsRequestSchema, async () => {
797
+ const tools = [];
798
+ for (const [name, tool] of this.tools.entries()) {
799
+ tools.push({
800
+ name,
801
+ description: tool.description,
802
+ inputSchema: tool.inputSchema || {
803
+ type: "object",
804
+ properties: {}
805
+ }
806
+ });
807
+ }
808
+ return {
809
+ tools
810
+ };
811
+ });
812
+ this.server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
813
+ const toolName = request.params.name;
814
+ const tool = this.tools.get(toolName);
815
+ if (!tool) {
816
+ throw new Error(`Tool ${toolName} not found`);
817
+ }
818
+ const methodMeta = getMethodMetadata(tool.method);
819
+ if (methodMeta.inputSchema) {
820
+ const validate = ajv.compile(methodMeta.inputSchema);
821
+ const valid = validate(request.params.arguments || {});
822
+ if (!valid) {
823
+ throw new Error(`Input validation failed: ${JSON.stringify(validate.errors)}`);
769
824
  }
770
- ]
771
- };
772
- } catch (error) {
773
- return {
774
- content: [
775
- {
776
- type: "text",
777
- text: `Error: ${error.message}`
825
+ }
826
+ try {
827
+ const meta = request.params._meta;
828
+ const result = await tool.method.call(tool.instance, request.params.arguments, meta);
829
+ let formattedResult = result;
830
+ if (methodMeta.renderFormat === "markdown" && typeof result === "string") {
831
+ formattedResult = result;
832
+ } else if (methodMeta.renderFormat === "json" || typeof result === "object") {
833
+ formattedResult = JSON.stringify(result, null, 2);
834
+ } else {
835
+ formattedResult = String(result);
778
836
  }
779
- ],
780
- isError: true
781
- };
782
- }
783
- });
784
- this.server.setRequestHandler(import_types.ListResourcesRequestSchema, async () => {
785
- const resources = [];
786
- for (const [uri, resource] of this.resources.entries()) {
787
- const resourceInfo = {
788
- uri: resource.uri,
789
- name: resource.name,
790
- description: resource.description,
791
- mimeType: resource.mimeType
792
- };
793
- if (resource.inputSchema) {
794
- resourceInfo.inputSchema = resource.inputSchema;
795
- }
796
- resources.push(resourceInfo);
797
- }
798
- return {
799
- resources
800
- };
801
- });
802
- this.server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
803
- const uri = request.params.uri;
804
- const resource = this.resources.get(uri);
805
- if (!resource) {
806
- throw new Error(`Resource ${uri} not found`);
807
- }
808
- try {
809
- const result = await resource.method.call(resource.instance);
810
- return {
811
- contents: [
812
- {
813
- uri,
814
- mimeType: resource.mimeType,
815
- text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
837
+ return {
838
+ content: [
839
+ {
840
+ type: "text",
841
+ text: formattedResult
842
+ }
843
+ ]
844
+ };
845
+ } catch (error) {
846
+ return {
847
+ content: [
848
+ {
849
+ type: "text",
850
+ text: `Error: ${error.message}`
851
+ }
852
+ ],
853
+ isError: true
854
+ };
855
+ }
856
+ });
857
+ this.server.setRequestHandler(import_types.ListResourcesRequestSchema, async () => {
858
+ const resources = [];
859
+ for (const [uri, resource] of this.resources.entries()) {
860
+ const resourceInfo = {
861
+ uri: resource.uri,
862
+ name: resource.name,
863
+ description: resource.description,
864
+ mimeType: resource.mimeType
865
+ };
866
+ if (resource.inputSchema) {
867
+ resourceInfo.inputSchema = resource.inputSchema;
816
868
  }
817
- ]
818
- };
819
- } catch (error) {
820
- throw new Error(`Failed to read resource ${uri}: ${error.message}`);
821
- }
822
- });
823
- this.server.setRequestHandler(import_types.ListPromptsRequestSchema, async () => {
824
- const prompts = [];
825
- for (const [name, prompt] of this.prompts.entries()) {
826
- prompts.push({
827
- name,
828
- description: prompt.description,
829
- arguments: prompt.arguments
869
+ resources.push(resourceInfo);
870
+ }
871
+ return {
872
+ resources
873
+ };
874
+ });
875
+ this.server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
876
+ const uri = request.params.uri;
877
+ const resource = this.resources.get(uri);
878
+ if (!resource) {
879
+ throw new Error(`Resource ${uri} not found`);
880
+ }
881
+ try {
882
+ const result = await resource.method.call(resource.instance);
883
+ return {
884
+ contents: [
885
+ {
886
+ uri,
887
+ mimeType: resource.mimeType,
888
+ text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
889
+ }
890
+ ]
891
+ };
892
+ } catch (error) {
893
+ throw new Error(`Failed to read resource ${uri}: ${error.message}`);
894
+ }
895
+ });
896
+ this.server.setRequestHandler(import_types.ListPromptsRequestSchema, async () => {
897
+ const prompts = [];
898
+ for (const [name, prompt] of this.prompts.entries()) {
899
+ prompts.push({
900
+ name,
901
+ description: prompt.description,
902
+ arguments: prompt.arguments
903
+ });
904
+ }
905
+ return {
906
+ prompts
907
+ };
908
+ });
909
+ this.server.setRequestHandler(import_types.GetPromptRequestSchema, async (request) => {
910
+ const promptName = request.params.name;
911
+ const prompt = this.prompts.get(promptName);
912
+ if (!prompt) {
913
+ throw new Error(`Prompt ${promptName} not found`);
914
+ }
915
+ try {
916
+ const result = await prompt.method.call(prompt.instance, request.params.arguments || {});
917
+ if (result && result.messages) {
918
+ return result;
919
+ }
920
+ return {
921
+ description: prompt.description,
922
+ messages: [
923
+ {
924
+ role: "user",
925
+ content: {
926
+ type: "text",
927
+ text: typeof result === "string" ? result : JSON.stringify(result)
928
+ }
929
+ }
930
+ ]
931
+ };
932
+ } catch (error) {
933
+ throw new Error(`Failed to get prompt ${promptName}: ${error.message}`);
934
+ }
830
935
  });
831
936
  }
832
- return {
833
- prompts
834
- };
835
- });
836
- this.server.setRequestHandler(import_types.GetPromptRequestSchema, async (request) => {
837
- const promptName = request.params.name;
838
- const prompt = this.prompts.get(promptName);
839
- if (!prompt) {
840
- throw new Error(`Prompt ${promptName} not found`);
937
+ /**
938
+ * Auto-register all services from the mcp directory
939
+ * Scans the directory recursively and registers all exported classes
940
+ *
941
+ * @param mcpDir - Path to the mcp directory containing service files
942
+ * @param serviceFactories - Optional map of service class names to factory functions for dependency injection
943
+ *
944
+ * @example
945
+ * // Auto-register services with no dependencies
946
+ * await server.autoRegisterServices('./mcp');
947
+ *
948
+ * @example
949
+ * // Auto-register with dependency injection
950
+ * await server.autoRegisterServices('./mcp', {
951
+ * SlackService: () => new SlackService(process.env.SLACK_TOKEN),
952
+ * AuthService: () => new AuthService(authProvider)
953
+ * });
954
+ */
955
+ async autoRegisterServices(mcpDir, serviceFactories) {
956
+ this.logger.debug(`Auto-registering services from: ${mcpDir}`);
957
+ if (!import_fs.default.existsSync(mcpDir)) {
958
+ this.logger.warn(`MCP directory not found: ${mcpDir}`);
959
+ return;
960
+ }
961
+ const serviceFiles = this.findServiceFiles(mcpDir);
962
+ this.logger.debug(`Found ${serviceFiles.length} service file(s)`);
963
+ for (const filePath of serviceFiles) {
964
+ try {
965
+ await this.loadAndRegisterService(filePath, serviceFactories);
966
+ } catch (error) {
967
+ this.logger.error(`Failed to load service from ${filePath}: ${error.message}`);
968
+ }
969
+ }
841
970
  }
842
- try {
843
- const result = await prompt.method.call(prompt.instance, request.params.arguments || {});
844
- if (result && result.messages) {
845
- return result;
971
+ /**
972
+ * Recursively find all index.ts/index.js files in the mcp directory
973
+ */
974
+ findServiceFiles(dir) {
975
+ const files = [];
976
+ const entries = import_fs.default.readdirSync(dir, {
977
+ withFileTypes: true
978
+ });
979
+ for (const entry of entries) {
980
+ const fullPath = import_path.default.join(dir, entry.name);
981
+ if (entry.isDirectory()) {
982
+ files.push(...this.findServiceFiles(fullPath));
983
+ } else if (entry.isFile()) {
984
+ if (entry.name === "index.ts" || entry.name === "index.js") {
985
+ files.push(fullPath);
986
+ }
987
+ }
846
988
  }
847
- return {
848
- description: prompt.description,
849
- messages: [
850
- {
851
- role: "user",
852
- content: {
853
- type: "text",
854
- text: typeof result === "string" ? result : JSON.stringify(result)
989
+ return files;
990
+ }
991
+ /**
992
+ * Load a service file and register all exported classes
993
+ */
994
+ async loadAndRegisterService(filePath, serviceFactories) {
995
+ this.logger.debug(`Loading service from: ${filePath}`);
996
+ const fileUrl = (0, import_url.pathToFileURL)(filePath).href;
997
+ const module2 = await import(fileUrl);
998
+ let registeredCount = 0;
999
+ for (const [exportName, exportValue] of Object.entries(module2)) {
1000
+ if (typeof exportValue === "function" && exportValue.prototype) {
1001
+ try {
1002
+ let instance;
1003
+ if (serviceFactories && serviceFactories[exportName]) {
1004
+ instance = serviceFactories[exportName]();
1005
+ this.logger.info(`Using factory for service: ${exportName}`);
1006
+ } else {
1007
+ instance = new exportValue();
855
1008
  }
1009
+ this.registerService(instance);
1010
+ registeredCount++;
1011
+ this.logger.debug(`Registered service: ${exportName} from ${import_path.default.basename(filePath)}`);
1012
+ } catch (error) {
1013
+ this.logger.warn(`Skipped ${exportName}: ${error.message}`);
856
1014
  }
857
- ]
858
- };
859
- } catch (error) {
860
- throw new Error(`Failed to get prompt ${promptName}: ${error.message}`);
861
- }
862
- });
863
- }
864
- /**
865
- * Auto-register all services from the mcp directory
866
- * Scans the directory recursively and registers all exported classes
867
- *
868
- * @param mcpDir - Path to the mcp directory containing service files
869
- * @param serviceFactories - Optional map of service class names to factory functions for dependency injection
870
- *
871
- * @example
872
- * // Auto-register services with no dependencies
873
- * await server.autoRegisterServices('./mcp');
874
- *
875
- * @example
876
- * // Auto-register with dependency injection
877
- * await server.autoRegisterServices('./mcp', {
878
- * SlackService: () => new SlackService(process.env.SLACK_TOKEN),
879
- * AuthService: () => new AuthService(authProvider)
880
- * });
881
- */
882
- async autoRegisterServices(mcpDir, serviceFactories) {
883
- this.logger.debug(`Auto-registering services from: ${mcpDir}`);
884
- if (!import_fs.default.existsSync(mcpDir)) {
885
- this.logger.warn(`MCP directory not found: ${mcpDir}`);
886
- return;
887
- }
888
- const serviceFiles = this.findServiceFiles(mcpDir);
889
- this.logger.debug(`Found ${serviceFiles.length} service file(s)`);
890
- for (const filePath of serviceFiles) {
891
- try {
892
- await this.loadAndRegisterService(filePath, serviceFactories);
893
- } catch (error) {
894
- this.logger.error(`Failed to load service from ${filePath}: ${error.message}`);
895
- }
896
- }
897
- }
898
- /**
899
- * Recursively find all index.ts/index.js files in the mcp directory
900
- */
901
- findServiceFiles(dir) {
902
- const files = [];
903
- const entries = import_fs.default.readdirSync(dir, {
904
- withFileTypes: true
905
- });
906
- for (const entry of entries) {
907
- const fullPath = import_path.default.join(dir, entry.name);
908
- if (entry.isDirectory()) {
909
- files.push(...this.findServiceFiles(fullPath));
910
- } else if (entry.isFile()) {
911
- if (entry.name === "index.ts" || entry.name === "index.js") {
912
- files.push(fullPath);
1015
+ }
1016
+ }
1017
+ if (registeredCount === 0) {
1018
+ this.logger.warn(`No services registered from ${filePath}`);
913
1019
  }
914
1020
  }
915
- }
916
- return files;
917
- }
918
- /**
919
- * Load a service file and register all exported classes
920
- */
921
- async loadAndRegisterService(filePath, serviceFactories) {
922
- this.logger.debug(`Loading service from: ${filePath}`);
923
- const fileUrl = (0, import_url.pathToFileURL)(filePath).href;
924
- const module2 = await import(fileUrl);
925
- let registeredCount = 0;
926
- for (const [exportName, exportValue] of Object.entries(module2)) {
927
- if (typeof exportValue === "function" && exportValue.prototype) {
928
- try {
929
- let instance;
930
- if (serviceFactories && serviceFactories[exportName]) {
931
- instance = serviceFactories[exportName]();
932
- this.logger.info(`Using factory for service: ${exportName}`);
933
- } else {
934
- instance = new exportValue();
1021
+ /**
1022
+ * Register a service instance with decorated methods
1023
+ */
1024
+ registerService(instance) {
1025
+ const cls = instance.constructor;
1026
+ const toolMethods = getDecoratedMethods(cls, "tool:name");
1027
+ for (const { method, propertyKey } of toolMethods) {
1028
+ const methodMeta = getMethodMetadata(method);
1029
+ const inputClass = Reflect.getMetadata?.("tool:inputClass", method);
1030
+ let inputSchema = methodMeta.inputSchema;
1031
+ if (inputClass) {
1032
+ inputSchema = classToJsonSchemaWithConstraints(inputClass);
1033
+ }
1034
+ this.tools.set(methodMeta.toolName, {
1035
+ name: methodMeta.toolName,
1036
+ description: methodMeta.toolDescription || "",
1037
+ inputSchema,
1038
+ method,
1039
+ instance,
1040
+ propertyKey
1041
+ });
1042
+ if (this.logging) {
1043
+ this.logger.debug(`Registered tool: ${methodMeta.toolName}${inputClass ? " (class-based schema)" : ""}`);
1044
+ }
1045
+ }
1046
+ const promptMethods = getDecoratedMethods(cls, "prompt:name");
1047
+ for (const { method, propertyKey } of promptMethods) {
1048
+ const methodMeta = getMethodMetadata(method);
1049
+ const inputClass = Reflect.getMetadata?.("prompt:inputClass", method);
1050
+ let inputSchema = methodMeta.inputSchema;
1051
+ if (inputClass) {
1052
+ inputSchema = classToJsonSchemaWithConstraints(inputClass);
1053
+ }
1054
+ const promptArgs = inputSchema?.properties ? Object.keys(inputSchema.properties).map((key) => ({
1055
+ name: key,
1056
+ description: inputSchema?.properties?.[key]?.description || "",
1057
+ required: inputSchema?.required?.includes(key) || false
1058
+ })) : [];
1059
+ this.prompts.set(methodMeta.promptName, {
1060
+ name: methodMeta.promptName,
1061
+ description: methodMeta.promptDescription || "",
1062
+ arguments: promptArgs,
1063
+ method,
1064
+ instance,
1065
+ propertyKey
1066
+ });
1067
+ if (this.logging) {
1068
+ this.logger.debug(`Registered prompt: ${methodMeta.promptName}`);
1069
+ }
1070
+ }
1071
+ const resourceMethods = getDecoratedMethods(cls, "resource:uri");
1072
+ for (const { method, propertyKey } of resourceMethods) {
1073
+ const methodMeta = getMethodMetadata(method);
1074
+ const inputClass = Reflect.getMetadata?.("resource:inputClass", method);
1075
+ let inputSchema = methodMeta.inputSchema;
1076
+ if (inputClass) {
1077
+ inputSchema = classToJsonSchemaWithConstraints(inputClass);
1078
+ }
1079
+ const mimeType = Reflect.getMetadata?.("resource:mimeType", method) || "application/json";
1080
+ this.resources.set(methodMeta.resourceUri, {
1081
+ uri: methodMeta.resourceUri,
1082
+ name: methodMeta.resourceName || methodMeta.resourceUri,
1083
+ description: methodMeta.resourceDescription || "",
1084
+ mimeType,
1085
+ inputSchema,
1086
+ method,
1087
+ instance,
1088
+ propertyKey
1089
+ });
1090
+ if (this.logging) {
1091
+ this.logger.debug(`Registered resource: ${methodMeta.resourceUri}`);
935
1092
  }
936
- this.registerService(instance);
937
- registeredCount++;
938
- this.logger.debug(`Registered service: ${exportName} from ${import_path.default.basename(filePath)}`);
939
- } catch (error) {
940
- this.logger.warn(`Skipped ${exportName}: ${error.message}`);
941
1093
  }
942
1094
  }
943
- }
944
- if (registeredCount === 0) {
945
- this.logger.warn(`No services registered from ${filePath}`);
946
- }
947
- }
948
- /**
949
- * Register a service instance with decorated methods
950
- */
951
- registerService(instance) {
952
- const cls = instance.constructor;
953
- const toolMethods = getDecoratedMethods(cls, "tool:name");
954
- for (const { method, propertyKey } of toolMethods) {
955
- const methodMeta = getMethodMetadata(method);
956
- const inputClass = Reflect.getMetadata?.("tool:inputClass", method);
957
- let inputSchema = methodMeta.inputSchema;
958
- if (inputClass) {
959
- inputSchema = classToJsonSchemaWithConstraints(inputClass);
960
- }
961
- this.tools.set(methodMeta.toolName, {
962
- name: methodMeta.toolName,
963
- description: methodMeta.toolDescription || "",
964
- inputSchema,
965
- method,
966
- instance,
967
- propertyKey
968
- });
969
- if (this.logging) {
970
- this.logger.debug(`Registered tool: ${methodMeta.toolName}${inputClass ? " (class-based schema)" : ""}`);
971
- }
972
- }
973
- const promptMethods = getDecoratedMethods(cls, "prompt:name");
974
- for (const { method, propertyKey } of promptMethods) {
975
- const methodMeta = getMethodMetadata(method);
976
- const inputClass = Reflect.getMetadata?.("prompt:inputClass", method);
977
- let inputSchema = methodMeta.inputSchema;
978
- if (inputClass) {
979
- inputSchema = classToJsonSchemaWithConstraints(inputClass);
980
- }
981
- const promptArgs = inputSchema?.properties ? Object.keys(inputSchema.properties).map((key) => ({
982
- name: key,
983
- description: inputSchema?.properties?.[key]?.description || "",
984
- required: inputSchema?.required?.includes(key) || false
985
- })) : [];
986
- this.prompts.set(methodMeta.promptName, {
987
- name: methodMeta.promptName,
988
- description: methodMeta.promptDescription || "",
989
- arguments: promptArgs,
990
- method,
991
- instance,
992
- propertyKey
993
- });
994
- if (this.logging) {
995
- this.logger.debug(`Registered prompt: ${methodMeta.promptName}`);
996
- }
997
- }
998
- const resourceMethods = getDecoratedMethods(cls, "resource:uri");
999
- for (const { method, propertyKey } of resourceMethods) {
1000
- const methodMeta = getMethodMetadata(method);
1001
- const inputClass = Reflect.getMetadata?.("resource:inputClass", method);
1002
- let inputSchema = methodMeta.inputSchema;
1003
- if (inputClass) {
1004
- inputSchema = classToJsonSchemaWithConstraints(inputClass);
1005
- }
1006
- const mimeType = Reflect.getMetadata?.("resource:mimeType", method) || "application/json";
1007
- this.resources.set(methodMeta.resourceUri, {
1008
- uri: methodMeta.resourceUri,
1009
- name: methodMeta.resourceName || methodMeta.resourceUri,
1010
- description: methodMeta.resourceDescription || "",
1011
- mimeType,
1012
- inputSchema,
1013
- method,
1014
- instance,
1015
- propertyKey
1016
- });
1017
- if (this.logging) {
1018
- this.logger.debug(`Registered resource: ${methodMeta.resourceUri}`);
1095
+ /**
1096
+ * Get the underlying MCP SDK Server instance
1097
+ * Attaches waitForInit method for HTTP server initialization
1098
+ */
1099
+ getServer() {
1100
+ this.server.waitForInit = () => this.waitForInit();
1101
+ return this.server;
1019
1102
  }
1020
- }
1021
- }
1022
- /**
1023
- * Get the underlying MCP SDK Server instance
1024
- * Attaches waitForInit method for HTTP server initialization
1025
- */
1026
- getServer() {
1027
- this.server.waitForInit = () => this.waitForInit();
1028
- return this.server;
1029
- }
1030
- };
1031
- var MCPServerRuntime = class {
1032
- static {
1033
- __name(this, "MCPServerRuntime");
1034
- }
1035
- server;
1036
- tools = /* @__PURE__ */ new Map();
1037
- prompts = /* @__PURE__ */ new Map();
1038
- resources = /* @__PURE__ */ new Map();
1039
- options;
1040
- logger;
1041
- constructor(options) {
1042
- this.options = options;
1043
- this.logger = new Logger({
1044
- level: this.options.logging ? LogLevel.INFO : LogLevel.NONE,
1045
- prefix: "MCPServerRuntime"
1046
- });
1047
- this.server = new import_server.Server({
1048
- name: "leanmcp-server",
1049
- version: "0.1.0"
1050
- }, {
1051
- capabilities: {
1052
- tools: {},
1053
- resources: {},
1054
- prompts: {}
1103
+ };
1104
+ MCPServerRuntime = class {
1105
+ static {
1106
+ __name(this, "MCPServerRuntime");
1055
1107
  }
1056
- });
1057
- this.setupHandlers();
1058
- }
1059
- setupHandlers() {
1060
- this.server.setRequestHandler(import_types.ListToolsRequestSchema, async () => {
1061
- const tools = [];
1062
- for (const [name, tool] of this.tools.entries()) {
1063
- tools.push({
1064
- name,
1065
- description: tool.description,
1066
- inputSchema: tool.inputSchema || {
1067
- type: "object",
1068
- properties: {}
1108
+ server;
1109
+ tools = /* @__PURE__ */ new Map();
1110
+ prompts = /* @__PURE__ */ new Map();
1111
+ resources = /* @__PURE__ */ new Map();
1112
+ options;
1113
+ logger;
1114
+ constructor(options) {
1115
+ this.options = options;
1116
+ this.logger = new Logger({
1117
+ level: this.options.logging ? LogLevel.INFO : LogLevel.NONE,
1118
+ prefix: "MCPServerRuntime"
1119
+ });
1120
+ this.server = new import_server.Server({
1121
+ name: "leanmcp-server",
1122
+ version: "0.1.0"
1123
+ }, {
1124
+ capabilities: {
1125
+ tools: {},
1126
+ resources: {},
1127
+ prompts: {}
1069
1128
  }
1070
1129
  });
1130
+ this.setupHandlers();
1071
1131
  }
1072
- return {
1073
- tools
1074
- };
1075
- });
1076
- this.server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
1077
- const toolName = request.params.name;
1078
- const tool = this.tools.get(toolName);
1079
- if (!tool) {
1080
- throw new Error(`Tool ${toolName} not found`);
1081
- }
1082
- const methodMeta = getMethodMetadata(tool.method);
1083
- if (methodMeta.inputSchema) {
1084
- const validate = ajv.compile(methodMeta.inputSchema);
1085
- const valid = validate(request.params.arguments || {});
1086
- if (!valid) {
1087
- throw new Error(`Input validation failed: ${JSON.stringify(validate.errors)}`);
1088
- }
1089
- }
1090
- if (methodMeta.authRequired) {
1091
- if (this.options.logging) {
1092
- this.logger.info(`Auth required for ${toolName} (provider: ${methodMeta.authProvider})`);
1093
- }
1094
- }
1095
- try {
1096
- const meta = request.params._meta;
1097
- const result = await tool.method.call(tool.instance, request.params.arguments, meta);
1098
- if (result && typeof result === "object" && result.type === "elicitation") {
1099
- return {
1100
- content: [
1101
- {
1102
- type: "text",
1103
- text: JSON.stringify(result, null, 2)
1132
+ setupHandlers() {
1133
+ this.server.setRequestHandler(import_types.ListToolsRequestSchema, async () => {
1134
+ const tools = [];
1135
+ for (const [name, tool] of this.tools.entries()) {
1136
+ tools.push({
1137
+ name,
1138
+ description: tool.description,
1139
+ inputSchema: tool.inputSchema || {
1140
+ type: "object",
1141
+ properties: {}
1104
1142
  }
1105
- ],
1106
- isError: false
1143
+ });
1144
+ }
1145
+ return {
1146
+ tools
1107
1147
  };
1108
- }
1109
- let formattedResult = result;
1110
- if (methodMeta.renderFormat === "markdown" && typeof result === "string") {
1111
- formattedResult = result;
1112
- } else if (methodMeta.renderFormat === "json" || typeof result === "object") {
1113
- formattedResult = JSON.stringify(result, null, 2);
1114
- } else {
1115
- formattedResult = String(result);
1116
- }
1117
- return {
1118
- content: [
1119
- {
1120
- type: "text",
1121
- text: formattedResult
1148
+ });
1149
+ this.server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
1150
+ const toolName = request.params.name;
1151
+ const tool = this.tools.get(toolName);
1152
+ if (!tool) {
1153
+ throw new Error(`Tool ${toolName} not found`);
1154
+ }
1155
+ const methodMeta = getMethodMetadata(tool.method);
1156
+ if (methodMeta.inputSchema) {
1157
+ const validate = ajv.compile(methodMeta.inputSchema);
1158
+ const valid = validate(request.params.arguments || {});
1159
+ if (!valid) {
1160
+ throw new Error(`Input validation failed: ${JSON.stringify(validate.errors)}`);
1122
1161
  }
1123
- ]
1124
- };
1125
- } catch (error) {
1126
- return {
1127
- content: [
1128
- {
1129
- type: "text",
1130
- text: `Error: ${error.message}`
1162
+ }
1163
+ if (methodMeta.authRequired) {
1164
+ if (this.options.logging) {
1165
+ this.logger.info(`Auth required for ${toolName} (provider: ${methodMeta.authProvider})`);
1131
1166
  }
1132
- ],
1133
- isError: true
1134
- };
1135
- }
1136
- });
1137
- this.server.setRequestHandler(import_types.ListResourcesRequestSchema, async () => {
1138
- const resources = [];
1139
- for (const [uri, resource] of this.resources.entries()) {
1140
- resources.push({
1141
- uri: resource.uri,
1142
- name: resource.name,
1143
- description: resource.description,
1144
- mimeType: resource.mimeType
1167
+ }
1168
+ try {
1169
+ const meta = request.params._meta;
1170
+ const result = await tool.method.call(tool.instance, request.params.arguments, meta);
1171
+ if (result && typeof result === "object" && result.type === "elicitation") {
1172
+ return {
1173
+ content: [
1174
+ {
1175
+ type: "text",
1176
+ text: JSON.stringify(result, null, 2)
1177
+ }
1178
+ ],
1179
+ isError: false
1180
+ };
1181
+ }
1182
+ let formattedResult = result;
1183
+ if (methodMeta.renderFormat === "markdown" && typeof result === "string") {
1184
+ formattedResult = result;
1185
+ } else if (methodMeta.renderFormat === "json" || typeof result === "object") {
1186
+ formattedResult = JSON.stringify(result, null, 2);
1187
+ } else {
1188
+ formattedResult = String(result);
1189
+ }
1190
+ return {
1191
+ content: [
1192
+ {
1193
+ type: "text",
1194
+ text: formattedResult
1195
+ }
1196
+ ]
1197
+ };
1198
+ } catch (error) {
1199
+ return {
1200
+ content: [
1201
+ {
1202
+ type: "text",
1203
+ text: `Error: ${error.message}`
1204
+ }
1205
+ ],
1206
+ isError: true
1207
+ };
1208
+ }
1145
1209
  });
1146
- }
1147
- return {
1148
- resources
1149
- };
1150
- });
1151
- this.server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
1152
- const uri = request.params.uri;
1153
- const resource = this.resources.get(uri);
1154
- if (!resource) {
1155
- throw new Error(`Resource ${uri} not found`);
1156
- }
1157
- try {
1158
- const result = await resource.method.call(resource.instance);
1159
- return {
1160
- contents: [
1161
- {
1162
- uri,
1163
- mimeType: resource.mimeType,
1164
- text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
1210
+ this.server.setRequestHandler(import_types.ListResourcesRequestSchema, async () => {
1211
+ const resources = [];
1212
+ for (const [uri, resource] of this.resources.entries()) {
1213
+ resources.push({
1214
+ uri: resource.uri,
1215
+ name: resource.name,
1216
+ description: resource.description,
1217
+ mimeType: resource.mimeType
1218
+ });
1219
+ }
1220
+ return {
1221
+ resources
1222
+ };
1223
+ });
1224
+ this.server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
1225
+ const uri = request.params.uri;
1226
+ const resource = this.resources.get(uri);
1227
+ if (!resource) {
1228
+ throw new Error(`Resource ${uri} not found`);
1229
+ }
1230
+ try {
1231
+ const result = await resource.method.call(resource.instance);
1232
+ return {
1233
+ contents: [
1234
+ {
1235
+ uri,
1236
+ mimeType: resource.mimeType,
1237
+ text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
1238
+ }
1239
+ ]
1240
+ };
1241
+ } catch (error) {
1242
+ throw new Error(`Failed to read resource ${uri}: ${error.message}`);
1243
+ }
1244
+ });
1245
+ this.server.setRequestHandler(import_types.ListPromptsRequestSchema, async () => {
1246
+ const prompts = [];
1247
+ for (const [name, prompt] of this.prompts.entries()) {
1248
+ prompts.push({
1249
+ name,
1250
+ description: prompt.description,
1251
+ arguments: prompt.arguments
1252
+ });
1253
+ }
1254
+ return {
1255
+ prompts
1256
+ };
1257
+ });
1258
+ this.server.setRequestHandler(import_types.GetPromptRequestSchema, async (request) => {
1259
+ const promptName = request.params.name;
1260
+ const prompt = this.prompts.get(promptName);
1261
+ if (!prompt) {
1262
+ throw new Error(`Prompt ${promptName} not found`);
1263
+ }
1264
+ try {
1265
+ const result = await prompt.method.call(prompt.instance, request.params.arguments || {});
1266
+ if (result && result.messages) {
1267
+ return result;
1165
1268
  }
1166
- ]
1167
- };
1168
- } catch (error) {
1169
- throw new Error(`Failed to read resource ${uri}: ${error.message}`);
1170
- }
1171
- });
1172
- this.server.setRequestHandler(import_types.ListPromptsRequestSchema, async () => {
1173
- const prompts = [];
1174
- for (const [name, prompt] of this.prompts.entries()) {
1175
- prompts.push({
1176
- name,
1177
- description: prompt.description,
1178
- arguments: prompt.arguments
1269
+ return {
1270
+ description: prompt.description,
1271
+ messages: [
1272
+ {
1273
+ role: "user",
1274
+ content: {
1275
+ type: "text",
1276
+ text: typeof result === "string" ? result : JSON.stringify(result)
1277
+ }
1278
+ }
1279
+ ]
1280
+ };
1281
+ } catch (error) {
1282
+ throw new Error(`Failed to get prompt ${promptName}: ${error.message}`);
1283
+ }
1179
1284
  });
1180
1285
  }
1181
- return {
1182
- prompts
1183
- };
1184
- });
1185
- this.server.setRequestHandler(import_types.GetPromptRequestSchema, async (request) => {
1186
- const promptName = request.params.name;
1187
- const prompt = this.prompts.get(promptName);
1188
- if (!prompt) {
1189
- throw new Error(`Prompt ${promptName} not found`);
1190
- }
1191
- try {
1192
- const result = await prompt.method.call(prompt.instance, request.params.arguments || {});
1193
- if (result && result.messages) {
1194
- return result;
1286
+ async loadServices() {
1287
+ const absPath = import_path.default.resolve(this.options.servicesDir);
1288
+ if (!import_fs.default.existsSync(absPath)) {
1289
+ this.logger.error(`Services directory not found: ${absPath}`);
1290
+ return;
1195
1291
  }
1196
- return {
1197
- description: prompt.description,
1198
- messages: [
1199
- {
1200
- role: "user",
1201
- content: {
1202
- type: "text",
1203
- text: typeof result === "string" ? result : JSON.stringify(result)
1204
- }
1205
- }
1206
- ]
1207
- };
1208
- } catch (error) {
1209
- throw new Error(`Failed to get prompt ${promptName}: ${error.message}`);
1210
- }
1211
- });
1212
- }
1213
- async loadServices() {
1214
- const absPath = import_path.default.resolve(this.options.servicesDir);
1215
- if (!import_fs.default.existsSync(absPath)) {
1216
- this.logger.error(`Services directory not found: ${absPath}`);
1217
- return;
1218
- }
1219
- const files = import_fs.default.readdirSync(absPath);
1220
- let toolCount = 0;
1221
- let promptCount = 0;
1222
- let resourceCount = 0;
1223
- for (const dir of files) {
1224
- const modulePath = import_path.default.join(absPath, dir, "index.ts");
1225
- const modulePathJs = import_path.default.join(absPath, dir, "index.js");
1226
- const finalPath = import_fs.default.existsSync(modulePath) ? modulePath : import_fs.default.existsSync(modulePathJs) ? modulePathJs : null;
1227
- if (finalPath) {
1228
- try {
1229
- const fileUrl = (0, import_url.pathToFileURL)(finalPath).href;
1230
- const mod = await import(fileUrl);
1231
- const exportedClasses = Object.values(mod).filter((val) => typeof val === "function" && val.prototype);
1232
- for (const cls of exportedClasses) {
1233
- const instance = new cls();
1234
- const envsPropKey = Reflect.getMetadata?.("userenvs:propertyKey", cls);
1235
- if (envsPropKey) {
1236
- instance[envsPropKey] = process.env;
1237
- }
1238
- const toolMethods = getDecoratedMethods(cls, "tool:name");
1239
- for (const { method, propertyKey, metadata } of toolMethods) {
1240
- const methodMeta = getMethodMetadata(method);
1241
- const inputClass = Reflect.getMetadata?.("tool:inputClass", method);
1242
- const outputClass = Reflect.getMetadata?.("tool:outputClass", method);
1243
- let inputSchema = methodMeta.inputSchema;
1244
- if (inputClass) {
1245
- inputSchema = classToJsonSchemaWithConstraints(inputClass);
1292
+ const files = import_fs.default.readdirSync(absPath);
1293
+ let toolCount = 0;
1294
+ let promptCount = 0;
1295
+ let resourceCount = 0;
1296
+ for (const dir of files) {
1297
+ const modulePath = import_path.default.join(absPath, dir, "index.ts");
1298
+ const modulePathJs = import_path.default.join(absPath, dir, "index.js");
1299
+ const finalPath = import_fs.default.existsSync(modulePath) ? modulePath : import_fs.default.existsSync(modulePathJs) ? modulePathJs : null;
1300
+ if (finalPath) {
1301
+ try {
1302
+ const fileUrl = (0, import_url.pathToFileURL)(finalPath).href;
1303
+ const mod = await import(fileUrl);
1304
+ const exportedClasses = Object.values(mod).filter((val) => typeof val === "function" && val.prototype);
1305
+ for (const cls of exportedClasses) {
1306
+ const instance = new cls();
1307
+ const envsPropKey = Reflect.getMetadata?.("userenvs:propertyKey", cls);
1308
+ if (envsPropKey) {
1309
+ instance[envsPropKey] = process.env;
1310
+ }
1311
+ const toolMethods = getDecoratedMethods(cls, "tool:name");
1312
+ for (const { method, propertyKey, metadata } of toolMethods) {
1313
+ const methodMeta = getMethodMetadata(method);
1314
+ const inputClass = Reflect.getMetadata?.("tool:inputClass", method);
1315
+ const outputClass = Reflect.getMetadata?.("tool:outputClass", method);
1316
+ let inputSchema = methodMeta.inputSchema;
1317
+ if (inputClass) {
1318
+ inputSchema = classToJsonSchemaWithConstraints(inputClass);
1319
+ }
1320
+ this.tools.set(methodMeta.toolName, {
1321
+ name: methodMeta.toolName,
1322
+ description: methodMeta.toolDescription || "",
1323
+ inputSchema,
1324
+ method,
1325
+ instance,
1326
+ propertyKey
1327
+ });
1328
+ toolCount++;
1329
+ if (this.options.logging) {
1330
+ this.logger.info(`Loaded tool: ${methodMeta.toolName}${inputClass ? " (class-based schema)" : ""}`);
1331
+ }
1332
+ }
1333
+ const promptMethods = getDecoratedMethods(cls, "prompt:name");
1334
+ for (const { method, propertyKey, metadata } of promptMethods) {
1335
+ const methodMeta = getMethodMetadata(method);
1336
+ const promptArgs = methodMeta.inputSchema?.properties ? Object.keys(methodMeta.inputSchema.properties).map((key) => ({
1337
+ name: key,
1338
+ description: methodMeta.inputSchema?.properties?.[key]?.description || "",
1339
+ required: methodMeta.inputSchema?.required?.includes(key) || false
1340
+ })) : [];
1341
+ this.prompts.set(methodMeta.promptName, {
1342
+ name: methodMeta.promptName,
1343
+ description: methodMeta.promptDescription || "",
1344
+ arguments: promptArgs,
1345
+ method,
1346
+ instance,
1347
+ propertyKey
1348
+ });
1349
+ promptCount++;
1350
+ if (this.options.logging) {
1351
+ this.logger.info(`Loaded prompt: ${methodMeta.promptName}`);
1352
+ }
1353
+ }
1354
+ const resourceMethods = getDecoratedMethods(cls, "resource:uri");
1355
+ for (const { method, propertyKey, metadata } of resourceMethods) {
1356
+ const methodMeta = getMethodMetadata(method);
1357
+ this.resources.set(methodMeta.resourceUri, {
1358
+ uri: methodMeta.resourceUri,
1359
+ name: methodMeta.resourceName || methodMeta.resourceUri,
1360
+ description: methodMeta.resourceDescription || "",
1361
+ mimeType: "application/json",
1362
+ method,
1363
+ instance,
1364
+ propertyKey
1365
+ });
1366
+ resourceCount++;
1367
+ if (this.options.logging) {
1368
+ this.logger.info(`Loaded resource: ${methodMeta.resourceUri}`);
1369
+ }
1370
+ }
1246
1371
  }
1247
- this.tools.set(methodMeta.toolName, {
1248
- name: methodMeta.toolName,
1249
- description: methodMeta.toolDescription || "",
1250
- inputSchema,
1251
- method,
1252
- instance,
1253
- propertyKey
1254
- });
1255
- toolCount++;
1372
+ } catch (error) {
1373
+ this.logger.error(`Failed to load from ${dir}:`, error.message || error);
1256
1374
  if (this.options.logging) {
1257
- this.logger.info(`Loaded tool: ${methodMeta.toolName}${inputClass ? " (class-based schema)" : ""}`);
1375
+ this.logger.error("Full error:", error);
1258
1376
  }
1259
1377
  }
1260
- const promptMethods = getDecoratedMethods(cls, "prompt:name");
1261
- for (const { method, propertyKey, metadata } of promptMethods) {
1262
- const methodMeta = getMethodMetadata(method);
1263
- const promptArgs = methodMeta.inputSchema?.properties ? Object.keys(methodMeta.inputSchema.properties).map((key) => ({
1264
- name: key,
1265
- description: methodMeta.inputSchema?.properties?.[key]?.description || "",
1266
- required: methodMeta.inputSchema?.required?.includes(key) || false
1267
- })) : [];
1268
- this.prompts.set(methodMeta.promptName, {
1269
- name: methodMeta.promptName,
1270
- description: methodMeta.promptDescription || "",
1271
- arguments: promptArgs,
1272
- method,
1273
- instance,
1274
- propertyKey
1275
- });
1276
- promptCount++;
1277
- if (this.options.logging) {
1278
- this.logger.info(`Loaded prompt: ${methodMeta.promptName}`);
1279
- }
1280
- }
1281
- const resourceMethods = getDecoratedMethods(cls, "resource:uri");
1282
- for (const { method, propertyKey, metadata } of resourceMethods) {
1283
- const methodMeta = getMethodMetadata(method);
1284
- this.resources.set(methodMeta.resourceUri, {
1285
- uri: methodMeta.resourceUri,
1286
- name: methodMeta.resourceName || methodMeta.resourceUri,
1287
- description: methodMeta.resourceDescription || "",
1288
- mimeType: "application/json",
1289
- method,
1290
- instance,
1291
- propertyKey
1292
- });
1293
- resourceCount++;
1294
- if (this.options.logging) {
1295
- this.logger.info(`Loaded resource: ${methodMeta.resourceUri}`);
1296
- }
1297
- }
1298
- }
1299
- } catch (error) {
1300
- this.logger.error(`Failed to load from ${dir}:`, error.message || error);
1301
- if (this.options.logging) {
1302
- this.logger.error("Full error:", error);
1303
1378
  }
1304
1379
  }
1305
- }
1306
- }
1307
- if (this.options.logging) {
1308
- this.logger.info(`
1380
+ if (this.options.logging) {
1381
+ this.logger.info(`
1309
1382
  Loaded ${toolCount} tools, ${promptCount} prompts, ${resourceCount} resources`);
1310
- }
1311
- }
1312
- async start() {
1313
- await this.loadServices();
1314
- const transport = new import_stdio.StdioServerTransport();
1315
- await this.server.connect(transport);
1316
- if (this.options.logging) {
1317
- this.logger.info("LeanMCP server running on stdio");
1318
- }
1319
- }
1320
- getServer() {
1321
- return this.server;
1322
- }
1323
- getTools() {
1324
- return Array.from(this.tools.values());
1325
- }
1326
- getPrompts() {
1327
- return Array.from(this.prompts.values());
1328
- }
1329
- getResources() {
1330
- return Array.from(this.resources.values());
1383
+ }
1384
+ }
1385
+ async start() {
1386
+ await this.loadServices();
1387
+ const transport = new import_stdio.StdioServerTransport();
1388
+ await this.server.connect(transport);
1389
+ if (this.options.logging) {
1390
+ this.logger.info("LeanMCP server running on stdio");
1391
+ }
1392
+ }
1393
+ getServer() {
1394
+ return this.server;
1395
+ }
1396
+ getTools() {
1397
+ return Array.from(this.tools.values());
1398
+ }
1399
+ getPrompts() {
1400
+ return Array.from(this.prompts.values());
1401
+ }
1402
+ getResources() {
1403
+ return Array.from(this.resources.values());
1404
+ }
1405
+ };
1406
+ __name(startMCPServer, "startMCPServer");
1331
1407
  }
1332
- };
1333
- async function startMCPServer(options) {
1334
- const runtime = new MCPServerRuntime(options);
1335
- await runtime.start();
1336
- return runtime;
1337
- }
1338
- __name(startMCPServer, "startMCPServer");
1408
+ });
1409
+ init_index();
1339
1410
  // Annotate the CommonJS export names for ESM import in node:
1340
1411
  0 && (module.exports = {
1341
1412
  Auth,