@leanmcp/core 0.4.5 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-GTCGBX2K.mjs +279 -0
- package/dist/dynamodb-session-store-G7V5ZRR6.mjs +10 -0
- package/dist/index.d.mts +23 -7
- package/dist/index.d.ts +23 -7
- package/dist/index.js +297 -46
- package/dist/index.mjs +285 -44
- package/package.json +5 -2
package/dist/index.mjs
CHANGED
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
|
|
11
11
|
// src/index.ts
|
|
12
12
|
import "reflect-metadata";
|
|
13
|
-
import
|
|
14
|
-
import
|
|
13
|
+
import fs3 from "fs";
|
|
14
|
+
import path2 from "path";
|
|
15
15
|
import { pathToFileURL } from "url";
|
|
16
16
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
17
17
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -168,6 +168,191 @@ __name(getDecoratedMethods, "getDecoratedMethods");
|
|
|
168
168
|
|
|
169
169
|
// src/schema-generator.ts
|
|
170
170
|
import "reflect-metadata";
|
|
171
|
+
|
|
172
|
+
// src/type-parser.ts
|
|
173
|
+
import fs from "fs";
|
|
174
|
+
import { createRequire } from "module";
|
|
175
|
+
var typeCache = /* @__PURE__ */ new Map();
|
|
176
|
+
var classSourceMap = /* @__PURE__ */ new Map();
|
|
177
|
+
var tsMorphProject = null;
|
|
178
|
+
var tsMorphNode = null;
|
|
179
|
+
var tsMorphLoaded = false;
|
|
180
|
+
function loadTsMorph() {
|
|
181
|
+
if (tsMorphLoaded) {
|
|
182
|
+
return tsMorphProject !== null;
|
|
183
|
+
}
|
|
184
|
+
tsMorphLoaded = true;
|
|
185
|
+
try {
|
|
186
|
+
const customRequire = createRequire(import.meta.url);
|
|
187
|
+
const tsMorph = customRequire("ts-morph");
|
|
188
|
+
tsMorphProject = tsMorph.Project;
|
|
189
|
+
tsMorphNode = tsMorph.Node;
|
|
190
|
+
return true;
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.warn(`[type-parser] ts-morph not available: ${error.message}`);
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
__name(loadTsMorph, "loadTsMorph");
|
|
197
|
+
function registerClassSource(className, sourceFile) {
|
|
198
|
+
classSourceMap.set(className, sourceFile);
|
|
199
|
+
}
|
|
200
|
+
__name(registerClassSource, "registerClassSource");
|
|
201
|
+
function parseClassTypesSync(classConstructor, sourceFilePath) {
|
|
202
|
+
if (!loadTsMorph()) {
|
|
203
|
+
return /* @__PURE__ */ new Map();
|
|
204
|
+
}
|
|
205
|
+
const className = classConstructor.name;
|
|
206
|
+
let filePath = sourceFilePath || classSourceMap.get(className) || findSourceFile();
|
|
207
|
+
if (!filePath) {
|
|
208
|
+
return /* @__PURE__ */ new Map();
|
|
209
|
+
}
|
|
210
|
+
if (filePath.endsWith(".js")) {
|
|
211
|
+
const tsPath = filePath.replace(/\.js$/, ".ts");
|
|
212
|
+
if (fs.existsSync(tsPath)) {
|
|
213
|
+
filePath = tsPath;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const cacheKey = `${filePath}:${className}`;
|
|
217
|
+
if (typeCache.has(cacheKey)) {
|
|
218
|
+
return typeCache.get(cacheKey);
|
|
219
|
+
}
|
|
220
|
+
if (!fs.existsSync(filePath)) {
|
|
221
|
+
return /* @__PURE__ */ new Map();
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
const project = new tsMorphProject({
|
|
225
|
+
skipAddingFilesFromTsConfig: true,
|
|
226
|
+
skipFileDependencyResolution: true,
|
|
227
|
+
useInMemoryFileSystem: false
|
|
228
|
+
});
|
|
229
|
+
const sourceFile = project.addSourceFileAtPath(filePath);
|
|
230
|
+
const classDecl = sourceFile.getClass(className);
|
|
231
|
+
if (!classDecl) {
|
|
232
|
+
return /* @__PURE__ */ new Map();
|
|
233
|
+
}
|
|
234
|
+
const propertyTypes = /* @__PURE__ */ new Map();
|
|
235
|
+
for (const prop of classDecl.getInstanceProperties()) {
|
|
236
|
+
if (tsMorphNode.isPropertyDeclaration(prop)) {
|
|
237
|
+
const propName = prop.getName();
|
|
238
|
+
const typeNode = prop.getTypeNode();
|
|
239
|
+
if (typeNode) {
|
|
240
|
+
const typeText = typeNode.getText();
|
|
241
|
+
const jsonSchemaType = typeTextToJsonSchema(typeText);
|
|
242
|
+
propertyTypes.set(propName, jsonSchemaType);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
typeCache.set(cacheKey, propertyTypes);
|
|
247
|
+
return propertyTypes;
|
|
248
|
+
} catch (error) {
|
|
249
|
+
console.warn(`[type-parser] Failed to parse ${filePath}: ${error.message}`);
|
|
250
|
+
return /* @__PURE__ */ new Map();
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
__name(parseClassTypesSync, "parseClassTypesSync");
|
|
254
|
+
function typeTextToJsonSchema(typeText) {
|
|
255
|
+
const type = typeText.trim().replace(/\?$/, "");
|
|
256
|
+
if (type.endsWith("[]")) {
|
|
257
|
+
const elementType = type.slice(0, -2);
|
|
258
|
+
return {
|
|
259
|
+
type: "array",
|
|
260
|
+
items: typeTextToJsonSchema(elementType)
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
const arrayMatch = type.match(/^Array<(.+)>$/);
|
|
264
|
+
if (arrayMatch) {
|
|
265
|
+
return {
|
|
266
|
+
type: "array",
|
|
267
|
+
items: typeTextToJsonSchema(arrayMatch[1])
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
const lowerType = type.toLowerCase();
|
|
271
|
+
switch (lowerType) {
|
|
272
|
+
case "string":
|
|
273
|
+
return {
|
|
274
|
+
type: "string"
|
|
275
|
+
};
|
|
276
|
+
case "number":
|
|
277
|
+
return {
|
|
278
|
+
type: "number"
|
|
279
|
+
};
|
|
280
|
+
case "integer":
|
|
281
|
+
return {
|
|
282
|
+
type: "integer"
|
|
283
|
+
};
|
|
284
|
+
case "boolean":
|
|
285
|
+
return {
|
|
286
|
+
type: "boolean"
|
|
287
|
+
};
|
|
288
|
+
case "object":
|
|
289
|
+
return {
|
|
290
|
+
type: "object"
|
|
291
|
+
};
|
|
292
|
+
case "any":
|
|
293
|
+
case "unknown":
|
|
294
|
+
return {};
|
|
295
|
+
// No constraints
|
|
296
|
+
case "null":
|
|
297
|
+
return {
|
|
298
|
+
type: "null"
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
if (type.includes("|")) {
|
|
302
|
+
const parts = type.split("|").map((p) => p.trim());
|
|
303
|
+
const nonNullParts = parts.filter((p) => p.toLowerCase() !== "null");
|
|
304
|
+
if (nonNullParts.length === 1) {
|
|
305
|
+
return typeTextToJsonSchema(nonNullParts[0]);
|
|
306
|
+
}
|
|
307
|
+
return {
|
|
308
|
+
anyOf: nonNullParts.map((p) => typeTextToJsonSchema(p))
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
type: "object"
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
__name(typeTextToJsonSchema, "typeTextToJsonSchema");
|
|
316
|
+
function findSourceFile() {
|
|
317
|
+
const originalPrepareStackTrace = Error.prepareStackTrace;
|
|
318
|
+
try {
|
|
319
|
+
Error.prepareStackTrace = (_, stack2) => stack2;
|
|
320
|
+
const err = new Error();
|
|
321
|
+
const stack = err.stack;
|
|
322
|
+
for (const site of stack) {
|
|
323
|
+
const fileName = site.getFileName();
|
|
324
|
+
if (fileName && !fileName.includes("node_modules") && !fileName.includes("type-parser") && !fileName.includes("schema-generator") && (fileName.endsWith(".ts") || fileName.endsWith(".js"))) {
|
|
325
|
+
if (fileName.endsWith(".js")) {
|
|
326
|
+
const tsPath = fileName.replace(/\.js$/, ".ts");
|
|
327
|
+
if (fs.existsSync(tsPath)) {
|
|
328
|
+
return tsPath;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return fileName;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
} finally {
|
|
335
|
+
Error.prepareStackTrace = originalPrepareStackTrace;
|
|
336
|
+
}
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
__name(findSourceFile, "findSourceFile");
|
|
340
|
+
function clearTypeCache() {
|
|
341
|
+
typeCache.clear();
|
|
342
|
+
}
|
|
343
|
+
__name(clearTypeCache, "clearTypeCache");
|
|
344
|
+
|
|
345
|
+
// src/schema-generator.ts
|
|
346
|
+
import path from "path";
|
|
347
|
+
import fs2 from "fs";
|
|
348
|
+
var schemaMetadata = null;
|
|
349
|
+
try {
|
|
350
|
+
const metadataPath = path.join(process.cwd(), "dist", "schema-metadata.json");
|
|
351
|
+
if (fs2.existsSync(metadataPath)) {
|
|
352
|
+
schemaMetadata = JSON.parse(fs2.readFileSync(metadataPath, "utf-8"));
|
|
353
|
+
}
|
|
354
|
+
} catch {
|
|
355
|
+
}
|
|
171
356
|
function classToJsonSchema(classConstructor) {
|
|
172
357
|
const instance = new classConstructor();
|
|
173
358
|
const properties = {};
|
|
@@ -224,20 +409,52 @@ __name(Optional, "Optional");
|
|
|
224
409
|
function SchemaConstraint(constraints) {
|
|
225
410
|
return (target, propertyKey) => {
|
|
226
411
|
Reflect.defineMetadata("schema:constraints", constraints, target, propertyKey);
|
|
412
|
+
const originalPrepareStackTrace = Error.prepareStackTrace;
|
|
413
|
+
try {
|
|
414
|
+
Error.prepareStackTrace = (_, stack2) => stack2;
|
|
415
|
+
const err = new Error();
|
|
416
|
+
const stack = err.stack;
|
|
417
|
+
for (const site of stack) {
|
|
418
|
+
const fileName = site.getFileName();
|
|
419
|
+
if (fileName && !fileName.includes("node_modules") && !fileName.includes("schema-generator") && (fileName.endsWith(".ts") || fileName.endsWith(".js"))) {
|
|
420
|
+
const className = target.constructor.name;
|
|
421
|
+
if (className && className !== "Object") {
|
|
422
|
+
registerClassSource(className, fileName);
|
|
423
|
+
}
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
} finally {
|
|
428
|
+
Error.prepareStackTrace = originalPrepareStackTrace;
|
|
429
|
+
}
|
|
227
430
|
};
|
|
228
431
|
}
|
|
229
432
|
__name(SchemaConstraint, "SchemaConstraint");
|
|
230
|
-
function classToJsonSchemaWithConstraints(classConstructor) {
|
|
433
|
+
function classToJsonSchemaWithConstraints(classConstructor, sourceFilePath) {
|
|
231
434
|
const instance = new classConstructor();
|
|
232
435
|
const properties = {};
|
|
233
436
|
const required = [];
|
|
437
|
+
const className = classConstructor.name;
|
|
438
|
+
const precomputedTypes = schemaMetadata?.[className];
|
|
439
|
+
const parsedTypes = precomputedTypes ? null : parseClassTypesSync(classConstructor, sourceFilePath);
|
|
234
440
|
const propertyNames = Object.keys(instance);
|
|
235
441
|
for (const propertyName of propertyNames) {
|
|
236
442
|
const propertyType = Reflect.getMetadata("design:type", instance, propertyName);
|
|
237
443
|
const constraints = Reflect.getMetadata("schema:constraints", instance, propertyName);
|
|
238
444
|
const isOptional = Reflect.getMetadata("optional", instance, propertyName);
|
|
239
|
-
let
|
|
240
|
-
if (
|
|
445
|
+
let parsedType;
|
|
446
|
+
if (precomputedTypes) {
|
|
447
|
+
parsedType = precomputedTypes[propertyName];
|
|
448
|
+
} else if (parsedTypes) {
|
|
449
|
+
parsedType = parsedTypes.get(propertyName);
|
|
450
|
+
}
|
|
451
|
+
let propertySchema;
|
|
452
|
+
if (parsedType && parsedType.type) {
|
|
453
|
+
propertySchema = {
|
|
454
|
+
...parsedType
|
|
455
|
+
};
|
|
456
|
+
} else if (propertyType) {
|
|
457
|
+
let jsonSchemaType = "string";
|
|
241
458
|
switch (propertyType.name) {
|
|
242
459
|
case "String":
|
|
243
460
|
jsonSchemaType = "string";
|
|
@@ -257,8 +474,16 @@ function classToJsonSchemaWithConstraints(classConstructor) {
|
|
|
257
474
|
default:
|
|
258
475
|
jsonSchemaType = "object";
|
|
259
476
|
}
|
|
477
|
+
propertySchema = {
|
|
478
|
+
type: jsonSchemaType
|
|
479
|
+
};
|
|
260
480
|
} else if (constraints) {
|
|
261
|
-
|
|
481
|
+
let jsonSchemaType = "string";
|
|
482
|
+
if (constraints.type) {
|
|
483
|
+
jsonSchemaType = constraints.type;
|
|
484
|
+
} else if (constraints.items) {
|
|
485
|
+
jsonSchemaType = "array";
|
|
486
|
+
} else if (constraints.minLength !== void 0 || constraints.maxLength !== void 0 || constraints.pattern) {
|
|
262
487
|
jsonSchemaType = "string";
|
|
263
488
|
} else if (constraints.minimum !== void 0 || constraints.maximum !== void 0) {
|
|
264
489
|
jsonSchemaType = "number";
|
|
@@ -272,12 +497,25 @@ function classToJsonSchemaWithConstraints(classConstructor) {
|
|
|
272
497
|
jsonSchemaType = "string";
|
|
273
498
|
}
|
|
274
499
|
}
|
|
500
|
+
propertySchema = {
|
|
501
|
+
type: jsonSchemaType
|
|
502
|
+
};
|
|
503
|
+
} else {
|
|
504
|
+
propertySchema = {
|
|
505
|
+
type: "string"
|
|
506
|
+
};
|
|
275
507
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
508
|
+
if (constraints) {
|
|
509
|
+
const parsedItems = propertySchema.items;
|
|
510
|
+
propertySchema = {
|
|
511
|
+
...propertySchema,
|
|
512
|
+
...constraints
|
|
513
|
+
};
|
|
514
|
+
if (parsedItems && !constraints.items) {
|
|
515
|
+
propertySchema.items = parsedItems;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
if (propertySchema.type === "array" && !propertySchema.items) {
|
|
281
519
|
propertySchema.items = {
|
|
282
520
|
type: "string"
|
|
283
521
|
};
|
|
@@ -305,9 +543,9 @@ function validatePort(port) {
|
|
|
305
543
|
}
|
|
306
544
|
}
|
|
307
545
|
__name(validatePort, "validatePort");
|
|
308
|
-
function validatePath(
|
|
309
|
-
if (
|
|
310
|
-
throw new Error(`Invalid path: ${
|
|
546
|
+
function validatePath(path3) {
|
|
547
|
+
if (path3.includes("..") || path3.includes("~")) {
|
|
548
|
+
throw new Error(`Invalid path: ${path3}. Path traversal patterns are not allowed`);
|
|
311
549
|
}
|
|
312
550
|
}
|
|
313
551
|
__name(validatePath, "validatePath");
|
|
@@ -396,9 +634,9 @@ async function createHTTPServer(serverInput, options) {
|
|
|
396
634
|
if (!serverOptions.mcpDir) {
|
|
397
635
|
const callerFile = getCallerFile();
|
|
398
636
|
if (callerFile) {
|
|
399
|
-
const
|
|
400
|
-
const callerDir =
|
|
401
|
-
resolvedMcpDir =
|
|
637
|
+
const path3 = await import("path");
|
|
638
|
+
const callerDir = path3.dirname(callerFile);
|
|
639
|
+
resolvedMcpDir = path3.join(callerDir, "mcp");
|
|
402
640
|
}
|
|
403
641
|
} else {
|
|
404
642
|
resolvedMcpDir = serverOptions.mcpDir;
|
|
@@ -1328,13 +1566,13 @@ var MCPServer = class {
|
|
|
1328
1566
|
} else {
|
|
1329
1567
|
const callerFile = this.getCallerFile();
|
|
1330
1568
|
if (callerFile) {
|
|
1331
|
-
const callerDir =
|
|
1332
|
-
mcpDir =
|
|
1569
|
+
const callerDir = path2.dirname(callerFile);
|
|
1570
|
+
mcpDir = path2.join(callerDir, "mcp");
|
|
1333
1571
|
} else {
|
|
1334
|
-
mcpDir =
|
|
1572
|
+
mcpDir = path2.join(process.cwd(), "mcp");
|
|
1335
1573
|
}
|
|
1336
1574
|
}
|
|
1337
|
-
if (
|
|
1575
|
+
if (fs3.existsSync(mcpDir)) {
|
|
1338
1576
|
this.logger.debug(`Auto-discovering services from: ${mcpDir}`);
|
|
1339
1577
|
await this.autoRegisterServices(mcpDir, serviceFactories);
|
|
1340
1578
|
} else {
|
|
@@ -1584,7 +1822,7 @@ var MCPServer = class {
|
|
|
1584
1822
|
*/
|
|
1585
1823
|
async autoRegisterServices(mcpDir, serviceFactories) {
|
|
1586
1824
|
this.logger.debug(`Auto-registering services from: ${mcpDir}`);
|
|
1587
|
-
if (!
|
|
1825
|
+
if (!fs3.existsSync(mcpDir)) {
|
|
1588
1826
|
this.logger.warn(`MCP directory not found: ${mcpDir}`);
|
|
1589
1827
|
return;
|
|
1590
1828
|
}
|
|
@@ -1603,11 +1841,11 @@ var MCPServer = class {
|
|
|
1603
1841
|
*/
|
|
1604
1842
|
findServiceFiles(dir) {
|
|
1605
1843
|
const files = [];
|
|
1606
|
-
const entries =
|
|
1844
|
+
const entries = fs3.readdirSync(dir, {
|
|
1607
1845
|
withFileTypes: true
|
|
1608
1846
|
});
|
|
1609
1847
|
for (const entry of entries) {
|
|
1610
|
-
const fullPath =
|
|
1848
|
+
const fullPath = path2.join(dir, entry.name);
|
|
1611
1849
|
if (entry.isDirectory()) {
|
|
1612
1850
|
files.push(...this.findServiceFiles(fullPath));
|
|
1613
1851
|
} else if (entry.isFile()) {
|
|
@@ -1638,7 +1876,7 @@ var MCPServer = class {
|
|
|
1638
1876
|
}
|
|
1639
1877
|
this.registerService(instance);
|
|
1640
1878
|
registeredCount++;
|
|
1641
|
-
this.logger.debug(`Registered service: ${exportName} from ${
|
|
1879
|
+
this.logger.debug(`Registered service: ${exportName} from ${path2.basename(filePath)}`);
|
|
1642
1880
|
} catch (error) {
|
|
1643
1881
|
this.logger.warn(`Skipped ${exportName}: ${error.message}`);
|
|
1644
1882
|
}
|
|
@@ -1737,8 +1975,8 @@ var MCPServer = class {
|
|
|
1737
1975
|
return;
|
|
1738
1976
|
}
|
|
1739
1977
|
try {
|
|
1740
|
-
const manifestPath =
|
|
1741
|
-
if (!
|
|
1978
|
+
const manifestPath = path2.join(process.cwd(), "dist", "ui-manifest.json");
|
|
1979
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
1742
1980
|
return;
|
|
1743
1981
|
}
|
|
1744
1982
|
if (this.logging) {
|
|
@@ -1780,8 +2018,8 @@ var MCPServer = class {
|
|
|
1780
2018
|
*/
|
|
1781
2019
|
async reloadUIManifest() {
|
|
1782
2020
|
try {
|
|
1783
|
-
const manifestPath =
|
|
1784
|
-
if (!
|
|
2021
|
+
const manifestPath = path2.join(process.cwd(), "dist", "ui-manifest.json");
|
|
2022
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
1785
2023
|
const uiResourceUris = Array.from(this.resources.keys()).filter((uri) => uri.startsWith("ui://"));
|
|
1786
2024
|
for (const uri of uiResourceUris) {
|
|
1787
2025
|
this.resources.delete(uri);
|
|
@@ -1791,7 +2029,7 @@ var MCPServer = class {
|
|
|
1791
2029
|
}
|
|
1792
2030
|
return;
|
|
1793
2031
|
}
|
|
1794
|
-
const manifest = JSON.parse(
|
|
2032
|
+
const manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf-8"));
|
|
1795
2033
|
const currentUIUris = new Set(Object.keys(manifest));
|
|
1796
2034
|
const registeredUIUris = Array.from(this.resources.keys()).filter((uri) => uri.startsWith("ui://"));
|
|
1797
2035
|
for (const uri of registeredUIUris) {
|
|
@@ -1807,7 +2045,7 @@ var MCPServer = class {
|
|
|
1807
2045
|
const htmlPath = isString ? entry : entry.htmlPath;
|
|
1808
2046
|
const isGPTApp = !isString && entry.isGPTApp;
|
|
1809
2047
|
const gptMeta = !isString ? entry.gptMeta : void 0;
|
|
1810
|
-
if (!
|
|
2048
|
+
if (!fs3.existsSync(htmlPath)) {
|
|
1811
2049
|
if (this.logging) {
|
|
1812
2050
|
this.logger.warn(`UI HTML file not found: ${htmlPath}`);
|
|
1813
2051
|
}
|
|
@@ -1828,8 +2066,8 @@ var MCPServer = class {
|
|
|
1828
2066
|
mimeType,
|
|
1829
2067
|
inputSchema: void 0,
|
|
1830
2068
|
method: /* @__PURE__ */ __name(async () => {
|
|
1831
|
-
if (
|
|
1832
|
-
const html =
|
|
2069
|
+
if (fs3.existsSync(htmlPath)) {
|
|
2070
|
+
const html = fs3.readFileSync(htmlPath, "utf-8");
|
|
1833
2071
|
return {
|
|
1834
2072
|
text: html,
|
|
1835
2073
|
_meta: Object.keys(_meta).length > 0 ? _meta : void 0
|
|
@@ -1857,11 +2095,11 @@ var MCPServer = class {
|
|
|
1857
2095
|
*/
|
|
1858
2096
|
async loadUIManifest() {
|
|
1859
2097
|
try {
|
|
1860
|
-
const manifestPath =
|
|
1861
|
-
if (!
|
|
2098
|
+
const manifestPath = path2.join(process.cwd(), "dist", "ui-manifest.json");
|
|
2099
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
1862
2100
|
return;
|
|
1863
2101
|
}
|
|
1864
|
-
const manifest = JSON.parse(
|
|
2102
|
+
const manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf-8"));
|
|
1865
2103
|
for (const [uri, entry] of Object.entries(manifest)) {
|
|
1866
2104
|
const isString = typeof entry === "string";
|
|
1867
2105
|
const htmlPath = isString ? entry : entry.htmlPath;
|
|
@@ -1873,13 +2111,13 @@ var MCPServer = class {
|
|
|
1873
2111
|
}
|
|
1874
2112
|
continue;
|
|
1875
2113
|
}
|
|
1876
|
-
if (!
|
|
2114
|
+
if (!fs3.existsSync(htmlPath)) {
|
|
1877
2115
|
if (this.logging) {
|
|
1878
2116
|
this.logger.warn(`UI HTML file not found: ${htmlPath}`);
|
|
1879
2117
|
}
|
|
1880
2118
|
continue;
|
|
1881
2119
|
}
|
|
1882
|
-
const html =
|
|
2120
|
+
const html = fs3.readFileSync(htmlPath, "utf-8");
|
|
1883
2121
|
const mimeType = isGPTApp ? "text/html+skybridge" : "text/html;profile=mcp-app";
|
|
1884
2122
|
const _meta = {};
|
|
1885
2123
|
if (isGPTApp) {
|
|
@@ -2130,19 +2368,19 @@ var MCPServerRuntime = class {
|
|
|
2130
2368
|
});
|
|
2131
2369
|
}
|
|
2132
2370
|
async loadServices() {
|
|
2133
|
-
const absPath =
|
|
2134
|
-
if (!
|
|
2371
|
+
const absPath = path2.resolve(this.options.servicesDir);
|
|
2372
|
+
if (!fs3.existsSync(absPath)) {
|
|
2135
2373
|
this.logger.error(`Services directory not found: ${absPath}`);
|
|
2136
2374
|
return;
|
|
2137
2375
|
}
|
|
2138
|
-
const files =
|
|
2376
|
+
const files = fs3.readdirSync(absPath);
|
|
2139
2377
|
let toolCount = 0;
|
|
2140
2378
|
let promptCount = 0;
|
|
2141
2379
|
let resourceCount = 0;
|
|
2142
2380
|
for (const dir of files) {
|
|
2143
|
-
const modulePath =
|
|
2144
|
-
const modulePathJs =
|
|
2145
|
-
const finalPath =
|
|
2381
|
+
const modulePath = path2.join(absPath, dir, "index.ts");
|
|
2382
|
+
const modulePathJs = path2.join(absPath, dir, "index.js");
|
|
2383
|
+
const finalPath = fs3.existsSync(modulePath) ? modulePath : fs3.existsSync(modulePathJs) ? modulePathJs : null;
|
|
2146
2384
|
if (finalPath) {
|
|
2147
2385
|
try {
|
|
2148
2386
|
const fileUrl = pathToFileURL(finalPath).href;
|
|
@@ -2277,6 +2515,7 @@ export {
|
|
|
2277
2515
|
UserEnvs,
|
|
2278
2516
|
classToJsonSchema,
|
|
2279
2517
|
classToJsonSchemaWithConstraints,
|
|
2518
|
+
clearTypeCache,
|
|
2280
2519
|
createAuthError,
|
|
2281
2520
|
createHTTPServer,
|
|
2282
2521
|
createProtectedResourceMetadata,
|
|
@@ -2285,6 +2524,8 @@ export {
|
|
|
2285
2524
|
getDecoratedMethods,
|
|
2286
2525
|
getMethodMetadata,
|
|
2287
2526
|
isAuthError,
|
|
2527
|
+
parseClassTypesSync,
|
|
2528
|
+
registerClassSource,
|
|
2288
2529
|
startMCPServer,
|
|
2289
2530
|
validateNonEmpty,
|
|
2290
2531
|
validatePath,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leanmcp/core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"description": "Core library implementing decorators, reflection, and MCP runtime server",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
"dotenv": "^16.3.1",
|
|
33
33
|
"reflect-metadata": "^0.2.1"
|
|
34
34
|
},
|
|
35
|
+
"optionalDependencies": {
|
|
36
|
+
"ts-morph": "^24.0.0"
|
|
37
|
+
},
|
|
35
38
|
"peerDependencies": {
|
|
36
39
|
"cors": "^2.8.5",
|
|
37
40
|
"express": "^5.0.0",
|
|
@@ -75,4 +78,4 @@
|
|
|
75
78
|
"publishConfig": {
|
|
76
79
|
"access": "public"
|
|
77
80
|
}
|
|
78
|
-
}
|
|
81
|
+
}
|