@leanmcp/core 0.4.6 → 0.4.7-alpha.29.3837d4c
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/LICENSE +21 -21
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +56 -39
- package/dist/index.mjs +54 -37
- package/package.json +5 -3
- package/dist/chunk-GTCGBX2K.mjs +0 -279
- package/dist/chunk-LPEX4YW6.mjs +0 -13
- package/dist/dynamodb-session-store-G7V5ZRR6.mjs +0 -10
- package/dist/server-BEQUIEE2.mjs +0 -25808
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 LeanMCP Contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 LeanMCP Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.mts
CHANGED
|
@@ -386,8 +386,8 @@ declare function SchemaConstraint(constraints: {
|
|
|
386
386
|
}): PropertyDecorator;
|
|
387
387
|
/**
|
|
388
388
|
* Enhanced schema generator that includes constraints.
|
|
389
|
-
*
|
|
390
|
-
*
|
|
389
|
+
* Uses pre-computed metadata (from leanmcp build) when available for fast startup.
|
|
390
|
+
* Falls back to ts-morph parsing in dev mode.
|
|
391
391
|
*/
|
|
392
392
|
declare function classToJsonSchemaWithConstraints(classConstructor: new () => any, sourceFilePath?: string): any;
|
|
393
393
|
|
package/dist/index.d.ts
CHANGED
|
@@ -386,8 +386,8 @@ declare function SchemaConstraint(constraints: {
|
|
|
386
386
|
}): PropertyDecorator;
|
|
387
387
|
/**
|
|
388
388
|
* Enhanced schema generator that includes constraints.
|
|
389
|
-
*
|
|
390
|
-
*
|
|
389
|
+
* Uses pre-computed metadata (from leanmcp build) when available for fast startup.
|
|
390
|
+
* Falls back to ts-morph parsing in dev mode.
|
|
391
391
|
*/
|
|
392
392
|
declare function classToJsonSchemaWithConstraints(classConstructor: new () => any, sourceFilePath?: string): any;
|
|
393
393
|
|
package/dist/index.js
CHANGED
|
@@ -444,13 +444,20 @@ function classToJsonSchemaWithConstraints(classConstructor, sourceFilePath) {
|
|
|
444
444
|
const instance = new classConstructor();
|
|
445
445
|
const properties = {};
|
|
446
446
|
const required = [];
|
|
447
|
-
const
|
|
447
|
+
const className = classConstructor.name;
|
|
448
|
+
const precomputedTypes = schemaMetadata?.[className];
|
|
449
|
+
const parsedTypes = precomputedTypes ? null : parseClassTypesSync(classConstructor, sourceFilePath);
|
|
448
450
|
const propertyNames = Object.keys(instance);
|
|
449
451
|
for (const propertyName of propertyNames) {
|
|
450
452
|
const propertyType = Reflect.getMetadata("design:type", instance, propertyName);
|
|
451
453
|
const constraints = Reflect.getMetadata("schema:constraints", instance, propertyName);
|
|
452
454
|
const isOptional = Reflect.getMetadata("optional", instance, propertyName);
|
|
453
|
-
|
|
455
|
+
let parsedType;
|
|
456
|
+
if (precomputedTypes) {
|
|
457
|
+
parsedType = precomputedTypes[propertyName];
|
|
458
|
+
} else if (parsedTypes) {
|
|
459
|
+
parsedType = parsedTypes.get(propertyName);
|
|
460
|
+
}
|
|
454
461
|
let propertySchema;
|
|
455
462
|
if (parsedType && parsedType.type) {
|
|
456
463
|
propertySchema = {
|
|
@@ -534,12 +541,22 @@ function classToJsonSchemaWithConstraints(classConstructor, sourceFilePath) {
|
|
|
534
541
|
required: required.length > 0 ? required : void 0
|
|
535
542
|
};
|
|
536
543
|
}
|
|
537
|
-
var import_reflect_metadata2;
|
|
544
|
+
var import_reflect_metadata2, import_path, import_fs2, schemaMetadata;
|
|
538
545
|
var init_schema_generator = __esm({
|
|
539
546
|
"src/schema-generator.ts"() {
|
|
540
547
|
"use strict";
|
|
541
548
|
import_reflect_metadata2 = require("reflect-metadata");
|
|
542
549
|
init_type_parser();
|
|
550
|
+
import_path = __toESM(require("path"));
|
|
551
|
+
import_fs2 = __toESM(require("fs"));
|
|
552
|
+
schemaMetadata = null;
|
|
553
|
+
try {
|
|
554
|
+
const metadataPath = import_path.default.join(process.cwd(), "dist", "schema-metadata.json");
|
|
555
|
+
if (import_fs2.default.existsSync(metadataPath)) {
|
|
556
|
+
schemaMetadata = JSON.parse(import_fs2.default.readFileSync(metadataPath, "utf-8"));
|
|
557
|
+
}
|
|
558
|
+
} catch {
|
|
559
|
+
}
|
|
543
560
|
__name(classToJsonSchema, "classToJsonSchema");
|
|
544
561
|
__name(Optional, "Optional");
|
|
545
562
|
__name(SchemaConstraint, "SchemaConstraint");
|
|
@@ -672,9 +689,9 @@ function validatePort(port) {
|
|
|
672
689
|
throw new Error(`Invalid port: ${port}. Must be an integer between 1-65535`);
|
|
673
690
|
}
|
|
674
691
|
}
|
|
675
|
-
function validatePath(
|
|
676
|
-
if (
|
|
677
|
-
throw new Error(`Invalid path: ${
|
|
692
|
+
function validatePath(path3) {
|
|
693
|
+
if (path3.includes("..") || path3.includes("~")) {
|
|
694
|
+
throw new Error(`Invalid path: ${path3}. Path traversal patterns are not allowed`);
|
|
678
695
|
}
|
|
679
696
|
}
|
|
680
697
|
function validateServiceName(name) {
|
|
@@ -925,9 +942,9 @@ async function createHTTPServer(serverInput, options) {
|
|
|
925
942
|
if (!serverOptions.mcpDir) {
|
|
926
943
|
const callerFile = getCallerFile();
|
|
927
944
|
if (callerFile) {
|
|
928
|
-
const
|
|
929
|
-
const callerDir =
|
|
930
|
-
resolvedMcpDir =
|
|
945
|
+
const path3 = await import("path");
|
|
946
|
+
const callerDir = path3.dirname(callerFile);
|
|
947
|
+
resolvedMcpDir = path3.join(callerDir, "mcp");
|
|
931
948
|
}
|
|
932
949
|
} else {
|
|
933
950
|
resolvedMcpDir = serverOptions.mcpDir;
|
|
@@ -1868,12 +1885,12 @@ async function startMCPServer(options) {
|
|
|
1868
1885
|
await runtime.start();
|
|
1869
1886
|
return runtime;
|
|
1870
1887
|
}
|
|
1871
|
-
var import_reflect_metadata3,
|
|
1888
|
+
var import_reflect_metadata3, import_fs3, import_path2, import_url, import_server, import_stdio, import_types, import_ajv, ajv, MCPServer, MCPServerRuntime;
|
|
1872
1889
|
var init_index = __esm({
|
|
1873
1890
|
"src/index.ts"() {
|
|
1874
1891
|
import_reflect_metadata3 = require("reflect-metadata");
|
|
1875
|
-
|
|
1876
|
-
|
|
1892
|
+
import_fs3 = __toESM(require("fs"));
|
|
1893
|
+
import_path2 = __toESM(require("path"));
|
|
1877
1894
|
import_url = require("url");
|
|
1878
1895
|
import_server = require("@modelcontextprotocol/sdk/server/index.js");
|
|
1879
1896
|
import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
@@ -1964,13 +1981,13 @@ var init_index = __esm({
|
|
|
1964
1981
|
} else {
|
|
1965
1982
|
const callerFile = this.getCallerFile();
|
|
1966
1983
|
if (callerFile) {
|
|
1967
|
-
const callerDir =
|
|
1968
|
-
mcpDir =
|
|
1984
|
+
const callerDir = import_path2.default.dirname(callerFile);
|
|
1985
|
+
mcpDir = import_path2.default.join(callerDir, "mcp");
|
|
1969
1986
|
} else {
|
|
1970
|
-
mcpDir =
|
|
1987
|
+
mcpDir = import_path2.default.join(process.cwd(), "mcp");
|
|
1971
1988
|
}
|
|
1972
1989
|
}
|
|
1973
|
-
if (
|
|
1990
|
+
if (import_fs3.default.existsSync(mcpDir)) {
|
|
1974
1991
|
this.logger.debug(`Auto-discovering services from: ${mcpDir}`);
|
|
1975
1992
|
await this.autoRegisterServices(mcpDir, serviceFactories);
|
|
1976
1993
|
} else {
|
|
@@ -2220,7 +2237,7 @@ var init_index = __esm({
|
|
|
2220
2237
|
*/
|
|
2221
2238
|
async autoRegisterServices(mcpDir, serviceFactories) {
|
|
2222
2239
|
this.logger.debug(`Auto-registering services from: ${mcpDir}`);
|
|
2223
|
-
if (!
|
|
2240
|
+
if (!import_fs3.default.existsSync(mcpDir)) {
|
|
2224
2241
|
this.logger.warn(`MCP directory not found: ${mcpDir}`);
|
|
2225
2242
|
return;
|
|
2226
2243
|
}
|
|
@@ -2239,11 +2256,11 @@ var init_index = __esm({
|
|
|
2239
2256
|
*/
|
|
2240
2257
|
findServiceFiles(dir) {
|
|
2241
2258
|
const files = [];
|
|
2242
|
-
const entries =
|
|
2259
|
+
const entries = import_fs3.default.readdirSync(dir, {
|
|
2243
2260
|
withFileTypes: true
|
|
2244
2261
|
});
|
|
2245
2262
|
for (const entry of entries) {
|
|
2246
|
-
const fullPath =
|
|
2263
|
+
const fullPath = import_path2.default.join(dir, entry.name);
|
|
2247
2264
|
if (entry.isDirectory()) {
|
|
2248
2265
|
files.push(...this.findServiceFiles(fullPath));
|
|
2249
2266
|
} else if (entry.isFile()) {
|
|
@@ -2274,7 +2291,7 @@ var init_index = __esm({
|
|
|
2274
2291
|
}
|
|
2275
2292
|
this.registerService(instance);
|
|
2276
2293
|
registeredCount++;
|
|
2277
|
-
this.logger.debug(`Registered service: ${exportName} from ${
|
|
2294
|
+
this.logger.debug(`Registered service: ${exportName} from ${import_path2.default.basename(filePath)}`);
|
|
2278
2295
|
} catch (error) {
|
|
2279
2296
|
this.logger.warn(`Skipped ${exportName}: ${error.message}`);
|
|
2280
2297
|
}
|
|
@@ -2373,8 +2390,8 @@ var init_index = __esm({
|
|
|
2373
2390
|
return;
|
|
2374
2391
|
}
|
|
2375
2392
|
try {
|
|
2376
|
-
const manifestPath =
|
|
2377
|
-
if (!
|
|
2393
|
+
const manifestPath = import_path2.default.join(process.cwd(), "dist", "ui-manifest.json");
|
|
2394
|
+
if (!import_fs3.default.existsSync(manifestPath)) {
|
|
2378
2395
|
return;
|
|
2379
2396
|
}
|
|
2380
2397
|
if (this.logging) {
|
|
@@ -2416,8 +2433,8 @@ var init_index = __esm({
|
|
|
2416
2433
|
*/
|
|
2417
2434
|
async reloadUIManifest() {
|
|
2418
2435
|
try {
|
|
2419
|
-
const manifestPath =
|
|
2420
|
-
if (!
|
|
2436
|
+
const manifestPath = import_path2.default.join(process.cwd(), "dist", "ui-manifest.json");
|
|
2437
|
+
if (!import_fs3.default.existsSync(manifestPath)) {
|
|
2421
2438
|
const uiResourceUris = Array.from(this.resources.keys()).filter((uri) => uri.startsWith("ui://"));
|
|
2422
2439
|
for (const uri of uiResourceUris) {
|
|
2423
2440
|
this.resources.delete(uri);
|
|
@@ -2427,7 +2444,7 @@ var init_index = __esm({
|
|
|
2427
2444
|
}
|
|
2428
2445
|
return;
|
|
2429
2446
|
}
|
|
2430
|
-
const manifest = JSON.parse(
|
|
2447
|
+
const manifest = JSON.parse(import_fs3.default.readFileSync(manifestPath, "utf-8"));
|
|
2431
2448
|
const currentUIUris = new Set(Object.keys(manifest));
|
|
2432
2449
|
const registeredUIUris = Array.from(this.resources.keys()).filter((uri) => uri.startsWith("ui://"));
|
|
2433
2450
|
for (const uri of registeredUIUris) {
|
|
@@ -2443,7 +2460,7 @@ var init_index = __esm({
|
|
|
2443
2460
|
const htmlPath = isString ? entry : entry.htmlPath;
|
|
2444
2461
|
const isGPTApp = !isString && entry.isGPTApp;
|
|
2445
2462
|
const gptMeta = !isString ? entry.gptMeta : void 0;
|
|
2446
|
-
if (!
|
|
2463
|
+
if (!import_fs3.default.existsSync(htmlPath)) {
|
|
2447
2464
|
if (this.logging) {
|
|
2448
2465
|
this.logger.warn(`UI HTML file not found: ${htmlPath}`);
|
|
2449
2466
|
}
|
|
@@ -2464,8 +2481,8 @@ var init_index = __esm({
|
|
|
2464
2481
|
mimeType,
|
|
2465
2482
|
inputSchema: void 0,
|
|
2466
2483
|
method: /* @__PURE__ */ __name(async () => {
|
|
2467
|
-
if (
|
|
2468
|
-
const html =
|
|
2484
|
+
if (import_fs3.default.existsSync(htmlPath)) {
|
|
2485
|
+
const html = import_fs3.default.readFileSync(htmlPath, "utf-8");
|
|
2469
2486
|
return {
|
|
2470
2487
|
text: html,
|
|
2471
2488
|
_meta: Object.keys(_meta).length > 0 ? _meta : void 0
|
|
@@ -2493,11 +2510,11 @@ var init_index = __esm({
|
|
|
2493
2510
|
*/
|
|
2494
2511
|
async loadUIManifest() {
|
|
2495
2512
|
try {
|
|
2496
|
-
const manifestPath =
|
|
2497
|
-
if (!
|
|
2513
|
+
const manifestPath = import_path2.default.join(process.cwd(), "dist", "ui-manifest.json");
|
|
2514
|
+
if (!import_fs3.default.existsSync(manifestPath)) {
|
|
2498
2515
|
return;
|
|
2499
2516
|
}
|
|
2500
|
-
const manifest = JSON.parse(
|
|
2517
|
+
const manifest = JSON.parse(import_fs3.default.readFileSync(manifestPath, "utf-8"));
|
|
2501
2518
|
for (const [uri, entry] of Object.entries(manifest)) {
|
|
2502
2519
|
const isString = typeof entry === "string";
|
|
2503
2520
|
const htmlPath = isString ? entry : entry.htmlPath;
|
|
@@ -2509,13 +2526,13 @@ var init_index = __esm({
|
|
|
2509
2526
|
}
|
|
2510
2527
|
continue;
|
|
2511
2528
|
}
|
|
2512
|
-
if (!
|
|
2529
|
+
if (!import_fs3.default.existsSync(htmlPath)) {
|
|
2513
2530
|
if (this.logging) {
|
|
2514
2531
|
this.logger.warn(`UI HTML file not found: ${htmlPath}`);
|
|
2515
2532
|
}
|
|
2516
2533
|
continue;
|
|
2517
2534
|
}
|
|
2518
|
-
const html =
|
|
2535
|
+
const html = import_fs3.default.readFileSync(htmlPath, "utf-8");
|
|
2519
2536
|
const mimeType = isGPTApp ? "text/html+skybridge" : "text/html;profile=mcp-app";
|
|
2520
2537
|
const _meta = {};
|
|
2521
2538
|
if (isGPTApp) {
|
|
@@ -2766,19 +2783,19 @@ var init_index = __esm({
|
|
|
2766
2783
|
});
|
|
2767
2784
|
}
|
|
2768
2785
|
async loadServices() {
|
|
2769
|
-
const absPath =
|
|
2770
|
-
if (!
|
|
2786
|
+
const absPath = import_path2.default.resolve(this.options.servicesDir);
|
|
2787
|
+
if (!import_fs3.default.existsSync(absPath)) {
|
|
2771
2788
|
this.logger.error(`Services directory not found: ${absPath}`);
|
|
2772
2789
|
return;
|
|
2773
2790
|
}
|
|
2774
|
-
const files =
|
|
2791
|
+
const files = import_fs3.default.readdirSync(absPath);
|
|
2775
2792
|
let toolCount = 0;
|
|
2776
2793
|
let promptCount = 0;
|
|
2777
2794
|
let resourceCount = 0;
|
|
2778
2795
|
for (const dir of files) {
|
|
2779
|
-
const modulePath =
|
|
2780
|
-
const modulePathJs =
|
|
2781
|
-
const finalPath =
|
|
2796
|
+
const modulePath = import_path2.default.join(absPath, dir, "index.ts");
|
|
2797
|
+
const modulePathJs = import_path2.default.join(absPath, dir, "index.js");
|
|
2798
|
+
const finalPath = import_fs3.default.existsSync(modulePath) ? modulePath : import_fs3.default.existsSync(modulePathJs) ? modulePathJs : null;
|
|
2782
2799
|
if (finalPath) {
|
|
2783
2800
|
try {
|
|
2784
2801
|
const fileUrl = (0, import_url.pathToFileURL)(finalPath).href;
|
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";
|
|
@@ -343,6 +343,16 @@ function clearTypeCache() {
|
|
|
343
343
|
__name(clearTypeCache, "clearTypeCache");
|
|
344
344
|
|
|
345
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
|
+
}
|
|
346
356
|
function classToJsonSchema(classConstructor) {
|
|
347
357
|
const instance = new classConstructor();
|
|
348
358
|
const properties = {};
|
|
@@ -424,13 +434,20 @@ function classToJsonSchemaWithConstraints(classConstructor, sourceFilePath) {
|
|
|
424
434
|
const instance = new classConstructor();
|
|
425
435
|
const properties = {};
|
|
426
436
|
const required = [];
|
|
427
|
-
const
|
|
437
|
+
const className = classConstructor.name;
|
|
438
|
+
const precomputedTypes = schemaMetadata?.[className];
|
|
439
|
+
const parsedTypes = precomputedTypes ? null : parseClassTypesSync(classConstructor, sourceFilePath);
|
|
428
440
|
const propertyNames = Object.keys(instance);
|
|
429
441
|
for (const propertyName of propertyNames) {
|
|
430
442
|
const propertyType = Reflect.getMetadata("design:type", instance, propertyName);
|
|
431
443
|
const constraints = Reflect.getMetadata("schema:constraints", instance, propertyName);
|
|
432
444
|
const isOptional = Reflect.getMetadata("optional", instance, propertyName);
|
|
433
|
-
|
|
445
|
+
let parsedType;
|
|
446
|
+
if (precomputedTypes) {
|
|
447
|
+
parsedType = precomputedTypes[propertyName];
|
|
448
|
+
} else if (parsedTypes) {
|
|
449
|
+
parsedType = parsedTypes.get(propertyName);
|
|
450
|
+
}
|
|
434
451
|
let propertySchema;
|
|
435
452
|
if (parsedType && parsedType.type) {
|
|
436
453
|
propertySchema = {
|
|
@@ -526,9 +543,9 @@ function validatePort(port) {
|
|
|
526
543
|
}
|
|
527
544
|
}
|
|
528
545
|
__name(validatePort, "validatePort");
|
|
529
|
-
function validatePath(
|
|
530
|
-
if (
|
|
531
|
-
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`);
|
|
532
549
|
}
|
|
533
550
|
}
|
|
534
551
|
__name(validatePath, "validatePath");
|
|
@@ -617,9 +634,9 @@ async function createHTTPServer(serverInput, options) {
|
|
|
617
634
|
if (!serverOptions.mcpDir) {
|
|
618
635
|
const callerFile = getCallerFile();
|
|
619
636
|
if (callerFile) {
|
|
620
|
-
const
|
|
621
|
-
const callerDir =
|
|
622
|
-
resolvedMcpDir =
|
|
637
|
+
const path3 = await import("path");
|
|
638
|
+
const callerDir = path3.dirname(callerFile);
|
|
639
|
+
resolvedMcpDir = path3.join(callerDir, "mcp");
|
|
623
640
|
}
|
|
624
641
|
} else {
|
|
625
642
|
resolvedMcpDir = serverOptions.mcpDir;
|
|
@@ -1549,13 +1566,13 @@ var MCPServer = class {
|
|
|
1549
1566
|
} else {
|
|
1550
1567
|
const callerFile = this.getCallerFile();
|
|
1551
1568
|
if (callerFile) {
|
|
1552
|
-
const callerDir =
|
|
1553
|
-
mcpDir =
|
|
1569
|
+
const callerDir = path2.dirname(callerFile);
|
|
1570
|
+
mcpDir = path2.join(callerDir, "mcp");
|
|
1554
1571
|
} else {
|
|
1555
|
-
mcpDir =
|
|
1572
|
+
mcpDir = path2.join(process.cwd(), "mcp");
|
|
1556
1573
|
}
|
|
1557
1574
|
}
|
|
1558
|
-
if (
|
|
1575
|
+
if (fs3.existsSync(mcpDir)) {
|
|
1559
1576
|
this.logger.debug(`Auto-discovering services from: ${mcpDir}`);
|
|
1560
1577
|
await this.autoRegisterServices(mcpDir, serviceFactories);
|
|
1561
1578
|
} else {
|
|
@@ -1805,7 +1822,7 @@ var MCPServer = class {
|
|
|
1805
1822
|
*/
|
|
1806
1823
|
async autoRegisterServices(mcpDir, serviceFactories) {
|
|
1807
1824
|
this.logger.debug(`Auto-registering services from: ${mcpDir}`);
|
|
1808
|
-
if (!
|
|
1825
|
+
if (!fs3.existsSync(mcpDir)) {
|
|
1809
1826
|
this.logger.warn(`MCP directory not found: ${mcpDir}`);
|
|
1810
1827
|
return;
|
|
1811
1828
|
}
|
|
@@ -1824,11 +1841,11 @@ var MCPServer = class {
|
|
|
1824
1841
|
*/
|
|
1825
1842
|
findServiceFiles(dir) {
|
|
1826
1843
|
const files = [];
|
|
1827
|
-
const entries =
|
|
1844
|
+
const entries = fs3.readdirSync(dir, {
|
|
1828
1845
|
withFileTypes: true
|
|
1829
1846
|
});
|
|
1830
1847
|
for (const entry of entries) {
|
|
1831
|
-
const fullPath =
|
|
1848
|
+
const fullPath = path2.join(dir, entry.name);
|
|
1832
1849
|
if (entry.isDirectory()) {
|
|
1833
1850
|
files.push(...this.findServiceFiles(fullPath));
|
|
1834
1851
|
} else if (entry.isFile()) {
|
|
@@ -1859,7 +1876,7 @@ var MCPServer = class {
|
|
|
1859
1876
|
}
|
|
1860
1877
|
this.registerService(instance);
|
|
1861
1878
|
registeredCount++;
|
|
1862
|
-
this.logger.debug(`Registered service: ${exportName} from ${
|
|
1879
|
+
this.logger.debug(`Registered service: ${exportName} from ${path2.basename(filePath)}`);
|
|
1863
1880
|
} catch (error) {
|
|
1864
1881
|
this.logger.warn(`Skipped ${exportName}: ${error.message}`);
|
|
1865
1882
|
}
|
|
@@ -1958,8 +1975,8 @@ var MCPServer = class {
|
|
|
1958
1975
|
return;
|
|
1959
1976
|
}
|
|
1960
1977
|
try {
|
|
1961
|
-
const manifestPath =
|
|
1962
|
-
if (!
|
|
1978
|
+
const manifestPath = path2.join(process.cwd(), "dist", "ui-manifest.json");
|
|
1979
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
1963
1980
|
return;
|
|
1964
1981
|
}
|
|
1965
1982
|
if (this.logging) {
|
|
@@ -2001,8 +2018,8 @@ var MCPServer = class {
|
|
|
2001
2018
|
*/
|
|
2002
2019
|
async reloadUIManifest() {
|
|
2003
2020
|
try {
|
|
2004
|
-
const manifestPath =
|
|
2005
|
-
if (!
|
|
2021
|
+
const manifestPath = path2.join(process.cwd(), "dist", "ui-manifest.json");
|
|
2022
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
2006
2023
|
const uiResourceUris = Array.from(this.resources.keys()).filter((uri) => uri.startsWith("ui://"));
|
|
2007
2024
|
for (const uri of uiResourceUris) {
|
|
2008
2025
|
this.resources.delete(uri);
|
|
@@ -2012,7 +2029,7 @@ var MCPServer = class {
|
|
|
2012
2029
|
}
|
|
2013
2030
|
return;
|
|
2014
2031
|
}
|
|
2015
|
-
const manifest = JSON.parse(
|
|
2032
|
+
const manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf-8"));
|
|
2016
2033
|
const currentUIUris = new Set(Object.keys(manifest));
|
|
2017
2034
|
const registeredUIUris = Array.from(this.resources.keys()).filter((uri) => uri.startsWith("ui://"));
|
|
2018
2035
|
for (const uri of registeredUIUris) {
|
|
@@ -2028,7 +2045,7 @@ var MCPServer = class {
|
|
|
2028
2045
|
const htmlPath = isString ? entry : entry.htmlPath;
|
|
2029
2046
|
const isGPTApp = !isString && entry.isGPTApp;
|
|
2030
2047
|
const gptMeta = !isString ? entry.gptMeta : void 0;
|
|
2031
|
-
if (!
|
|
2048
|
+
if (!fs3.existsSync(htmlPath)) {
|
|
2032
2049
|
if (this.logging) {
|
|
2033
2050
|
this.logger.warn(`UI HTML file not found: ${htmlPath}`);
|
|
2034
2051
|
}
|
|
@@ -2049,8 +2066,8 @@ var MCPServer = class {
|
|
|
2049
2066
|
mimeType,
|
|
2050
2067
|
inputSchema: void 0,
|
|
2051
2068
|
method: /* @__PURE__ */ __name(async () => {
|
|
2052
|
-
if (
|
|
2053
|
-
const html =
|
|
2069
|
+
if (fs3.existsSync(htmlPath)) {
|
|
2070
|
+
const html = fs3.readFileSync(htmlPath, "utf-8");
|
|
2054
2071
|
return {
|
|
2055
2072
|
text: html,
|
|
2056
2073
|
_meta: Object.keys(_meta).length > 0 ? _meta : void 0
|
|
@@ -2078,11 +2095,11 @@ var MCPServer = class {
|
|
|
2078
2095
|
*/
|
|
2079
2096
|
async loadUIManifest() {
|
|
2080
2097
|
try {
|
|
2081
|
-
const manifestPath =
|
|
2082
|
-
if (!
|
|
2098
|
+
const manifestPath = path2.join(process.cwd(), "dist", "ui-manifest.json");
|
|
2099
|
+
if (!fs3.existsSync(manifestPath)) {
|
|
2083
2100
|
return;
|
|
2084
2101
|
}
|
|
2085
|
-
const manifest = JSON.parse(
|
|
2102
|
+
const manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf-8"));
|
|
2086
2103
|
for (const [uri, entry] of Object.entries(manifest)) {
|
|
2087
2104
|
const isString = typeof entry === "string";
|
|
2088
2105
|
const htmlPath = isString ? entry : entry.htmlPath;
|
|
@@ -2094,13 +2111,13 @@ var MCPServer = class {
|
|
|
2094
2111
|
}
|
|
2095
2112
|
continue;
|
|
2096
2113
|
}
|
|
2097
|
-
if (!
|
|
2114
|
+
if (!fs3.existsSync(htmlPath)) {
|
|
2098
2115
|
if (this.logging) {
|
|
2099
2116
|
this.logger.warn(`UI HTML file not found: ${htmlPath}`);
|
|
2100
2117
|
}
|
|
2101
2118
|
continue;
|
|
2102
2119
|
}
|
|
2103
|
-
const html =
|
|
2120
|
+
const html = fs3.readFileSync(htmlPath, "utf-8");
|
|
2104
2121
|
const mimeType = isGPTApp ? "text/html+skybridge" : "text/html;profile=mcp-app";
|
|
2105
2122
|
const _meta = {};
|
|
2106
2123
|
if (isGPTApp) {
|
|
@@ -2351,19 +2368,19 @@ var MCPServerRuntime = class {
|
|
|
2351
2368
|
});
|
|
2352
2369
|
}
|
|
2353
2370
|
async loadServices() {
|
|
2354
|
-
const absPath =
|
|
2355
|
-
if (!
|
|
2371
|
+
const absPath = path2.resolve(this.options.servicesDir);
|
|
2372
|
+
if (!fs3.existsSync(absPath)) {
|
|
2356
2373
|
this.logger.error(`Services directory not found: ${absPath}`);
|
|
2357
2374
|
return;
|
|
2358
2375
|
}
|
|
2359
|
-
const files =
|
|
2376
|
+
const files = fs3.readdirSync(absPath);
|
|
2360
2377
|
let toolCount = 0;
|
|
2361
2378
|
let promptCount = 0;
|
|
2362
2379
|
let resourceCount = 0;
|
|
2363
2380
|
for (const dir of files) {
|
|
2364
|
-
const modulePath =
|
|
2365
|
-
const modulePathJs =
|
|
2366
|
-
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;
|
|
2367
2384
|
if (finalPath) {
|
|
2368
2385
|
try {
|
|
2369
2386
|
const fileUrl = pathToFileURL(finalPath).href;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leanmcp/core",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7-alpha.29.3837d4c",
|
|
4
4
|
"description": "Core library implementing decorators, reflection, and MCP runtime server",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -30,7 +30,9 @@
|
|
|
30
30
|
"ajv": "^8.12.0",
|
|
31
31
|
"chokidar": "^4.0.0",
|
|
32
32
|
"dotenv": "^16.3.1",
|
|
33
|
-
"reflect-metadata": "^0.2.1"
|
|
33
|
+
"reflect-metadata": "^0.2.1"
|
|
34
|
+
},
|
|
35
|
+
"optionalDependencies": {
|
|
34
36
|
"ts-morph": "^24.0.0"
|
|
35
37
|
},
|
|
36
38
|
"peerDependencies": {
|
|
@@ -76,4 +78,4 @@
|
|
|
76
78
|
"publishConfig": {
|
|
77
79
|
"access": "public"
|
|
78
80
|
}
|
|
79
|
-
}
|
|
81
|
+
}
|