easy-mcp-nest 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +166 -8
- package/dist/adapters/express/express-adapter.d.ts +3 -0
- package/dist/adapters/express/express-adapter.js +125 -0
- package/dist/adapters/express/express-adapter.js.map +1 -0
- package/dist/adapters/express/http-gateway.service.d.ts +13 -0
- package/dist/adapters/express/http-gateway.service.js +102 -0
- package/dist/adapters/express/http-gateway.service.js.map +1 -0
- package/dist/adapters/express/index.d.ts +3 -0
- package/dist/adapters/express/index.js +8 -0
- package/dist/adapters/express/index.js.map +1 -0
- package/dist/adapters/express/types.d.ts +15 -0
- package/dist/adapters/express/types.js +3 -0
- package/dist/adapters/express/types.js.map +1 -0
- package/dist/app.module.js +2 -0
- package/dist/app.module.js.map +1 -1
- package/dist/auth/oauth/index.d.ts +3 -0
- package/dist/auth/oauth/index.js +8 -0
- package/dist/auth/oauth/index.js.map +1 -0
- package/dist/auth/oauth/oauth-config.interface.d.ts +12 -0
- package/dist/auth/oauth/oauth-config.interface.js +3 -0
- package/dist/auth/oauth/oauth-config.interface.js.map +1 -0
- package/dist/auth/oauth/oauth-middleware.d.ts +3 -0
- package/dist/auth/oauth/oauth-middleware.js +54 -0
- package/dist/auth/oauth/oauth-middleware.js.map +1 -0
- package/dist/auth/oauth/oauth-provider.service.d.ts +8 -0
- package/dist/auth/oauth/oauth-provider.service.js +63 -0
- package/dist/auth/oauth/oauth-provider.service.js.map +1 -0
- package/dist/config/mcp-config.interface.d.ts +1 -1
- package/dist/core/context/context-provider.service.d.ts +8 -0
- package/dist/core/context/context-provider.service.js +55 -0
- package/dist/core/context/context-provider.service.js.map +1 -0
- package/dist/core/context/mcp-context.interface.d.ts +12 -0
- package/dist/core/context/mcp-context.interface.js +3 -0
- package/dist/core/context/mcp-context.interface.js.map +1 -0
- package/dist/core/mcp-server/mcp-server.service.d.ts +3 -1
- package/dist/core/mcp-server/mcp-server.service.js +8 -3
- package/dist/core/mcp-server/mcp-server.service.js.map +1 -1
- package/dist/core/utils/sanitize.util.d.ts +1 -0
- package/dist/core/utils/sanitize.util.js +29 -0
- package/dist/core/utils/sanitize.util.js.map +1 -1
- package/dist/decorators/factory-provider.d.ts +2 -0
- package/dist/decorators/factory-provider.js +20 -0
- package/dist/decorators/factory-provider.js.map +1 -0
- package/dist/decorators/index.d.ts +4 -0
- package/dist/decorators/index.js +17 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/mcp-context.decorator.d.ts +3 -0
- package/dist/decorators/mcp-context.decorator.js +20 -0
- package/dist/decorators/mcp-context.decorator.js.map +1 -0
- package/dist/decorators/mcp-param.decorator.d.ts +10 -0
- package/dist/decorators/mcp-param.decorator.js +41 -0
- package/dist/decorators/mcp-param.decorator.js.map +1 -0
- package/dist/decorators/mcp-service.decorator.d.ts +6 -0
- package/dist/decorators/mcp-service.decorator.js +27 -0
- package/dist/decorators/mcp-service.decorator.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +27 -1
- package/dist/index.js.map +1 -1
- package/dist/interface/jsonrpc.interface.d.ts +8 -0
- package/dist/interface/jsonrpc.interface.js.map +1 -1
- package/dist/standalone/core-services.d.ts +29 -0
- package/dist/standalone/core-services.js +94 -0
- package/dist/standalone/core-services.js.map +1 -0
- package/dist/standalone/index.d.ts +3 -0
- package/dist/standalone/index.js +11 -0
- package/dist/standalone/index.js.map +1 -0
- package/dist/standalone/standalone-server.d.ts +23 -0
- package/dist/standalone/standalone-server.js +366 -0
- package/dist/standalone/standalone-server.js.map +1 -0
- package/dist/standalone/types.d.ts +14 -0
- package/dist/standalone/types.js +3 -0
- package/dist/standalone/types.js.map +1 -0
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.js +14 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/mock-context.d.ts +2 -0
- package/dist/testing/mock-context.js +17 -0
- package/dist/testing/mock-context.js.map +1 -0
- package/dist/testing/test-app.factory.d.ts +15 -0
- package/dist/testing/test-app.factory.js +37 -0
- package/dist/testing/test-app.factory.js.map +1 -0
- package/dist/testing/test-helpers.d.ts +10 -0
- package/dist/testing/test-helpers.js +46 -0
- package/dist/testing/test-helpers.js.map +1 -0
- package/dist/tooling/tool-registry/tool-registry.service.d.ts +1 -1
- package/dist/tooling/tool-registry/tool-registry.service.js +2 -2
- package/dist/tooling/tool-registry/tool-registry.service.js.map +1 -1
- package/dist/tooling/tool.interface.d.ts +3 -2
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/validation/index.d.ts +1 -0
- package/dist/validation/index.js +8 -0
- package/dist/validation/index.js.map +1 -0
- package/dist/validation/zod-integration.d.ts +11 -0
- package/dist/validation/zod-integration.js +148 -0
- package/dist/validation/zod-integration.js.map +1 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -29,12 +29,26 @@ EasyMCP requires the following peer dependencies to be installed:
|
|
|
29
29
|
- `@nestjs/core` ^11.0.1
|
|
30
30
|
- `@nestjs/platform-express` ^11.0.1
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
**Optional peer dependencies** (for specific features):
|
|
33
|
+
- `express` ^4.18.0 (for Express adapter)
|
|
34
|
+
- `zod` ^3.22.0 (for TypeScript-first validation)
|
|
35
|
+
|
|
36
|
+
Install required dependencies with:
|
|
33
37
|
|
|
34
38
|
```bash
|
|
35
39
|
npm install @nestjs/common@^11.0.1 @nestjs/core@^11.0.1 @nestjs/platform-express@^11.0.1
|
|
36
40
|
```
|
|
37
41
|
|
|
42
|
+
Install optional dependencies as needed:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# For Express adapter
|
|
46
|
+
npm install express@^4.18.0
|
|
47
|
+
|
|
48
|
+
# For Zod validation
|
|
49
|
+
npm install zod@^3.22.0
|
|
50
|
+
```
|
|
51
|
+
|
|
38
52
|
## Quick Start
|
|
39
53
|
|
|
40
54
|
```typescript
|
|
@@ -193,6 +207,7 @@ process.on('SIGINT', async () => {
|
|
|
193
207
|
|
|
194
208
|
### Types
|
|
195
209
|
|
|
210
|
+
**Core Types:**
|
|
196
211
|
- `McpConfig` - Main configuration interface
|
|
197
212
|
- `ToolRegistrationInput` - Tool definition interface
|
|
198
213
|
- `ServerInfo` - Optional server information
|
|
@@ -207,6 +222,13 @@ process.on('SIGINT', async () => {
|
|
|
207
222
|
- `VERSION`, `PACKAGE_NAME`, `getVersion()`, `getPackageName()` - Version information utilities
|
|
208
223
|
- `INTERFACE_LAYER_TOKEN` - Token for accessing the interface layer (advanced use cases)
|
|
209
224
|
|
|
225
|
+
**New Feature Types:**
|
|
226
|
+
- `McpContext` - Context interface for user information
|
|
227
|
+
- `CreateMcpExpressRouterOptions` - Express adapter options
|
|
228
|
+
- `OAuthProviderConfig`, `OAuthConfig` - OAuth configuration
|
|
229
|
+
- `CreateMcpServerOptions` - Standalone server options
|
|
230
|
+
- `StandaloneTransport` - Transport type ('stdio' | 'http')
|
|
231
|
+
|
|
210
232
|
## Architecture
|
|
211
233
|
|
|
212
234
|
EasyMCP uses a simplified architecture for standard MCP servers:
|
|
@@ -245,11 +267,11 @@ EasyMCP implements the following MCP protocol methods:
|
|
|
245
267
|
- Validates client protocol version
|
|
246
268
|
- Returns server capabilities (currently supports tools)
|
|
247
269
|
- Returns server information (name and version)
|
|
248
|
-
|
|
270
|
+
|
|
249
271
|
- **`tools/list`** - Returns all registered tools with their JSON Schema 2020-12 definitions
|
|
250
272
|
- Returns array of tool definitions in MCP format
|
|
251
273
|
- Each tool includes name, description, inputSchema, and optional icon
|
|
252
|
-
|
|
274
|
+
|
|
253
275
|
- **`tools/call`** - Executes a tool with provided arguments and returns the result
|
|
254
276
|
- Validates tool arguments against JSON Schema 2020-12
|
|
255
277
|
- Executes tool function
|
|
@@ -310,7 +332,7 @@ This enables the MCP-specified Content-Length header format, which some clients
|
|
|
310
332
|
|
|
311
333
|
### Limitations
|
|
312
334
|
|
|
313
|
-
- **Transport**:
|
|
335
|
+
- **Transport**: stdio transport is fully supported. HTTP transport is available via Express adapter. WebSocket transport is not available.
|
|
314
336
|
- **Protocol Version**: Only protocol version 2025-11-25 is supported. Older or newer versions will be rejected.
|
|
315
337
|
- **Resources Subscribe/Unsubscribe**: Basic resource subscription is not yet implemented (resources/list and resources/read are supported)
|
|
316
338
|
|
|
@@ -330,10 +352,10 @@ EasyMCP provides comprehensive error handling with custom error classes and clea
|
|
|
330
352
|
### Error Handling Examples
|
|
331
353
|
|
|
332
354
|
```typescript
|
|
333
|
-
import {
|
|
334
|
-
EasyMCP,
|
|
335
|
-
ConfigurationError,
|
|
336
|
-
ToolExecutionError,
|
|
355
|
+
import {
|
|
356
|
+
EasyMCP,
|
|
357
|
+
ConfigurationError,
|
|
358
|
+
ToolExecutionError,
|
|
337
359
|
ToolNotFoundError
|
|
338
360
|
} from 'easy-mcp-nest';
|
|
339
361
|
|
|
@@ -438,6 +460,142 @@ Debug mode provides detailed information about:
|
|
|
438
460
|
|
|
439
461
|
**Note**: The `DEBUG` environment variable accepts either `'1'` or `'true'` (case-sensitive) to enable debug logging.
|
|
440
462
|
|
|
463
|
+
## New Features
|
|
464
|
+
|
|
465
|
+
### Express Adapter
|
|
466
|
+
|
|
467
|
+
Use EasyMCP in Express applications without requiring NestJS for the HTTP layer:
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
import express from 'express';
|
|
471
|
+
import { createMcpExpressRouter } from 'easy-mcp-nest';
|
|
472
|
+
|
|
473
|
+
const app = express();
|
|
474
|
+
app.use(express.json());
|
|
475
|
+
|
|
476
|
+
const mcpRouter = createMcpExpressRouter({
|
|
477
|
+
tools: [BuildingTools, PaymentTools],
|
|
478
|
+
resources: [BuildingResources],
|
|
479
|
+
auth: mcpAuthMiddleware, // Optional
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
app.use('/mcp', mcpRouter);
|
|
483
|
+
app.listen(3000);
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### Context Injection
|
|
487
|
+
|
|
488
|
+
Inject user context into tools using the `@McpContext()` decorator:
|
|
489
|
+
|
|
490
|
+
```typescript
|
|
491
|
+
import { McpContext, McpContextDecorator } from 'easy-mcp-nest';
|
|
492
|
+
|
|
493
|
+
@McpTool({ name: 'create_building' })
|
|
494
|
+
async createBuilding(
|
|
495
|
+
@McpParam() params: CreateBuildingDto,
|
|
496
|
+
@McpContextDecorator() context: McpContext
|
|
497
|
+
) {
|
|
498
|
+
return this.service.createBuilding(context.userId, params);
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### Factory Pattern Support
|
|
503
|
+
|
|
504
|
+
Use factory functions instead of dependency injection:
|
|
505
|
+
|
|
506
|
+
```typescript
|
|
507
|
+
import { McpService } from 'easy-mcp-nest';
|
|
508
|
+
|
|
509
|
+
@McpTool({ name: 'create_building' })
|
|
510
|
+
export class BuildingTools {
|
|
511
|
+
constructor(
|
|
512
|
+
@McpService(() => getBuildingService())
|
|
513
|
+
private buildingService: BuildingService
|
|
514
|
+
) {}
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### OAuth Integration
|
|
519
|
+
|
|
520
|
+
Standardize OAuth integration across MCP servers:
|
|
521
|
+
|
|
522
|
+
```typescript
|
|
523
|
+
import { createOAuthMiddleware, OAuthProviderConfig } from 'easy-mcp-nest';
|
|
524
|
+
|
|
525
|
+
const oauthConfig: OAuthProviderConfig = {
|
|
526
|
+
provider: 'custom',
|
|
527
|
+
validateToken: async (token) => {
|
|
528
|
+
// Validate token and return payload
|
|
529
|
+
return jwt.verify(token, secret);
|
|
530
|
+
},
|
|
531
|
+
extractContext: (payload) => ({
|
|
532
|
+
userId: payload.sub,
|
|
533
|
+
scopes: payload.scopes,
|
|
534
|
+
buildingIds: payload.buildingIds,
|
|
535
|
+
}),
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
const oauthMiddleware = createOAuthMiddleware(oauthProviderService);
|
|
539
|
+
app.use('/mcp', oauthMiddleware, mcpRouter);
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### TypeScript-First Validation with Zod
|
|
543
|
+
|
|
544
|
+
Use Zod schemas for type-safe validation:
|
|
545
|
+
|
|
546
|
+
```typescript
|
|
547
|
+
import { z } from 'zod';
|
|
548
|
+
import { McpParam } from 'easy-mcp-nest';
|
|
549
|
+
|
|
550
|
+
const CreateBuildingSchema = z.object({
|
|
551
|
+
name: z.string(),
|
|
552
|
+
address: z.string(),
|
|
553
|
+
floors: z.number().int().min(1).max(100),
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
@McpTool({ name: 'create_building' })
|
|
557
|
+
async createBuilding(
|
|
558
|
+
@McpParam(CreateBuildingSchema) params: z.infer<typeof CreateBuildingSchema>
|
|
559
|
+
) {
|
|
560
|
+
// params is fully typed and validated
|
|
561
|
+
return this.service.createBuilding(params);
|
|
562
|
+
}
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### Standalone Mode
|
|
566
|
+
|
|
567
|
+
Use EasyMCP without NestJS:
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
import { createMcpServer } from 'easy-mcp-nest';
|
|
571
|
+
|
|
572
|
+
const server = createMcpServer({
|
|
573
|
+
tools: [BuildingTools, PaymentTools],
|
|
574
|
+
resources: [BuildingResources],
|
|
575
|
+
transport: 'http', // or 'stdio'
|
|
576
|
+
auth: validateMcpToken, // Optional
|
|
577
|
+
port: 3000,
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
await server.start();
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### Testing Utilities
|
|
584
|
+
|
|
585
|
+
Test MCP tools easily:
|
|
586
|
+
|
|
587
|
+
```typescript
|
|
588
|
+
import { createMcpTestApp, mockMcpContext } from 'easy-mcp-nest';
|
|
589
|
+
|
|
590
|
+
const app = await createMcpTestApp([BuildingTools]);
|
|
591
|
+
const context = mockMcpContext({
|
|
592
|
+
userId: '123',
|
|
593
|
+
scopes: ['read', 'write'],
|
|
594
|
+
});
|
|
595
|
+
const result = await app.callTool('create_building', params, context);
|
|
596
|
+
await app.close();
|
|
597
|
+
```
|
|
598
|
+
|
|
441
599
|
## Examples
|
|
442
600
|
|
|
443
601
|
See the `examples/` directory for complete working examples.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createMcpExpressRouter = createMcpExpressRouter;
|
|
4
|
+
const express_1 = require("express");
|
|
5
|
+
const constants_1 = require("../../config/constants");
|
|
6
|
+
const EasyMCP_1 = require("../../EasyMCP");
|
|
7
|
+
const http_gateway_service_1 = require("./http-gateway.service");
|
|
8
|
+
const logger_util_1 = require("../../core/utils/logger.util");
|
|
9
|
+
const sanitize_util_1 = require("../../core/utils/sanitize.util");
|
|
10
|
+
const mcp_server_service_1 = require("../../core/mcp-server/mcp-server.service");
|
|
11
|
+
const oauth_provider_service_1 = require("../../auth/oauth/oauth-provider.service");
|
|
12
|
+
const oauth_middleware_1 = require("../../auth/oauth/oauth-middleware");
|
|
13
|
+
function createMcpExpressRouter(options) {
|
|
14
|
+
const router = (0, express_1.Router)();
|
|
15
|
+
const pathPrefix = options.pathPrefix || "/mcp";
|
|
16
|
+
const tools = (options.tools || []).map((tool) => {
|
|
17
|
+
if (tool && typeof tool === "object" && "name" in tool && "function" in tool) {
|
|
18
|
+
return tool;
|
|
19
|
+
}
|
|
20
|
+
if (typeof tool === "function") {
|
|
21
|
+
throw new Error("Class-based tools are not directly supported in createMcpExpressRouter. Please convert them to ToolRegistrationInput format or register them via NestJS modules.");
|
|
22
|
+
}
|
|
23
|
+
throw new Error("Tools must be in ToolRegistrationInput format or a class constructor. Use the config-based or decorator-based approach.");
|
|
24
|
+
});
|
|
25
|
+
const config = {
|
|
26
|
+
tools,
|
|
27
|
+
resources: options.resources || [],
|
|
28
|
+
prompts: options.prompts || [],
|
|
29
|
+
serverInfo: options.serverInfo,
|
|
30
|
+
};
|
|
31
|
+
let mcpServerService = null;
|
|
32
|
+
let httpGateway = null;
|
|
33
|
+
const initPromise = (async () => {
|
|
34
|
+
await EasyMCP_1.EasyMCP.initialize(config);
|
|
35
|
+
const appContext = EasyMCP_1.EasyMCP.app;
|
|
36
|
+
mcpServerService = appContext.get(mcp_server_service_1.McpServerService);
|
|
37
|
+
httpGateway = new http_gateway_service_1.HttpGatewayService();
|
|
38
|
+
if (mcpServerService) {
|
|
39
|
+
httpGateway.setMcpServerService(mcpServerService);
|
|
40
|
+
}
|
|
41
|
+
})();
|
|
42
|
+
router.use(async (req, res, next) => {
|
|
43
|
+
try {
|
|
44
|
+
await initPromise;
|
|
45
|
+
next();
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
logger_util_1.logger.error("ExpressAdapter", "Failed to initialize EasyMCP", {
|
|
49
|
+
error: (0, sanitize_util_1.sanitizeErrorMessage)(error),
|
|
50
|
+
});
|
|
51
|
+
res.status(500).json({
|
|
52
|
+
jsonrpc: "2.0",
|
|
53
|
+
id: null,
|
|
54
|
+
error: {
|
|
55
|
+
code: -32603,
|
|
56
|
+
message: "Internal error",
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
if (options.auth) {
|
|
62
|
+
router.use(options.auth);
|
|
63
|
+
}
|
|
64
|
+
else if (options.oauth) {
|
|
65
|
+
const oauthProvider = new oauth_provider_service_1.OAuthProviderService();
|
|
66
|
+
oauthProvider.setConfig(options.oauth);
|
|
67
|
+
router.use((0, oauth_middleware_1.createOAuthMiddleware)(oauthProvider));
|
|
68
|
+
}
|
|
69
|
+
const extractContext = (req) => {
|
|
70
|
+
if (req.mcpContext) {
|
|
71
|
+
return req.mcpContext;
|
|
72
|
+
}
|
|
73
|
+
if (options.auth || options.oauth) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
const context = {};
|
|
77
|
+
if (req.headers["x-user-id"]) {
|
|
78
|
+
context.userId = String(req.headers["x-user-id"]);
|
|
79
|
+
}
|
|
80
|
+
if (req.headers["x-scopes"]) {
|
|
81
|
+
const scopes = req.headers["x-scopes"];
|
|
82
|
+
context.scopes = Array.isArray(scopes)
|
|
83
|
+
? scopes.map(String)
|
|
84
|
+
: String(scopes).split(",").map(s => s.trim());
|
|
85
|
+
}
|
|
86
|
+
if (req.headers["x-building-ids"]) {
|
|
87
|
+
const buildingIds = req.headers["x-building-ids"];
|
|
88
|
+
context.buildingIds = Array.isArray(buildingIds)
|
|
89
|
+
? buildingIds.map(String)
|
|
90
|
+
: String(buildingIds).split(",").map(s => s.trim());
|
|
91
|
+
}
|
|
92
|
+
if (Object.keys(context).length > 0) {
|
|
93
|
+
logger_util_1.logger.warn("ExpressAdapter", "Using unauthenticated headers for context extraction", {
|
|
94
|
+
component: "ExpressAdapter",
|
|
95
|
+
warning: "Headers are not authenticated and can be spoofed. Use auth middleware in production.",
|
|
96
|
+
});
|
|
97
|
+
return context;
|
|
98
|
+
}
|
|
99
|
+
return undefined;
|
|
100
|
+
};
|
|
101
|
+
router.post("/", (0, express_1.json)({ limit: constants_1.MAX_MESSAGE_SIZE_BYTES }), async (req, res) => {
|
|
102
|
+
if (!httpGateway || !mcpServerService) {
|
|
103
|
+
res.status(500).json({
|
|
104
|
+
jsonrpc: "2.0",
|
|
105
|
+
id: null,
|
|
106
|
+
error: {
|
|
107
|
+
code: -32603,
|
|
108
|
+
message: "Internal error",
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const context = extractContext(req);
|
|
114
|
+
await httpGateway.handleHttpRequest(req, res, context);
|
|
115
|
+
});
|
|
116
|
+
router.get(`${pathPrefix}/health`, (req, res) => {
|
|
117
|
+
res.json({
|
|
118
|
+
status: "ok",
|
|
119
|
+
service: "mcp-server",
|
|
120
|
+
version: config.serverInfo?.version || "unknown",
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
return router;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=express-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express-adapter.js","sourceRoot":"","sources":["../../../src/adapters/express/express-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Request, Response } from "express";
|
|
2
|
+
import { IInterfaceLayer } from "../../interface/interface.interface";
|
|
3
|
+
import { McpServerService } from "../../core/mcp-server/mcp-server.service";
|
|
4
|
+
import { McpContext } from "../../core/context/mcp-context.interface";
|
|
5
|
+
export declare class HttpGatewayService implements IInterfaceLayer {
|
|
6
|
+
private mcpServerService;
|
|
7
|
+
private requestContextMap;
|
|
8
|
+
constructor();
|
|
9
|
+
setMcpServerService(service: McpServerService): void;
|
|
10
|
+
start(): Promise<void>;
|
|
11
|
+
sendMessage(sessionId: string, output: unknown): Promise<void>;
|
|
12
|
+
handleHttpRequest(req: Request, res: Response, context?: McpContext): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.HttpGatewayService = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const jsonrpc_interface_1 = require("../../interface/jsonrpc.interface");
|
|
15
|
+
const logger_util_1 = require("../../core/utils/logger.util");
|
|
16
|
+
const sanitize_util_1 = require("../../core/utils/sanitize.util");
|
|
17
|
+
const constants_1 = require("../../config/constants");
|
|
18
|
+
let HttpGatewayService = class HttpGatewayService {
|
|
19
|
+
mcpServerService;
|
|
20
|
+
requestContextMap = new Map();
|
|
21
|
+
constructor() {
|
|
22
|
+
logger_util_1.logger.info("HttpGatewayService", "HttpGatewayService initialized", {
|
|
23
|
+
component: "Layer 1: HTTP Interface",
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
setMcpServerService(service) {
|
|
27
|
+
this.mcpServerService = service;
|
|
28
|
+
}
|
|
29
|
+
async start() {
|
|
30
|
+
logger_util_1.logger.info("HttpGatewayService", "HTTP gateway ready (handled by Express)", {
|
|
31
|
+
component: "Layer 1: HTTP Interface",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async sendMessage(sessionId, output) {
|
|
35
|
+
logger_util_1.logger.debug("HttpGatewayService", "sendMessage called", {
|
|
36
|
+
component: "Layer 1: HTTP Interface",
|
|
37
|
+
sessionId,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
async handleHttpRequest(req, res, context) {
|
|
41
|
+
const requestId = req.headers["x-request-id"] || String(Date.now());
|
|
42
|
+
if (context) {
|
|
43
|
+
this.requestContextMap.set(String(requestId), context);
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const contentLength = req.get("content-length");
|
|
47
|
+
if (contentLength && parseInt(contentLength, 10) > constants_1.MAX_MESSAGE_SIZE_BYTES) {
|
|
48
|
+
const errorResponse = (0, jsonrpc_interface_1.createJsonRpcError)(null, jsonrpc_interface_1.JsonRpcErrorCode.InvalidRequest, "Request body too large");
|
|
49
|
+
res.status(413).json(errorResponse);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const body = req.body;
|
|
53
|
+
if (!body || typeof body !== "object") {
|
|
54
|
+
const errorResponse = (0, jsonrpc_interface_1.createJsonRpcError)(null, jsonrpc_interface_1.JsonRpcErrorCode.InvalidRequest, "Request body must be a valid JSON-RPC request");
|
|
55
|
+
res.status(400).json(errorResponse);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (!(0, jsonrpc_interface_1.isValidJsonRpcRequest)(body)) {
|
|
59
|
+
const errorResponse = (0, jsonrpc_interface_1.createJsonRpcError)(body.id || null, jsonrpc_interface_1.JsonRpcErrorCode.InvalidRequest, "Invalid JSON-RPC request structure");
|
|
60
|
+
res.status(400).json(errorResponse);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const request = {
|
|
64
|
+
...body,
|
|
65
|
+
metadata: context ? {
|
|
66
|
+
userId: context.userId,
|
|
67
|
+
scopes: context.scopes,
|
|
68
|
+
buildingIds: context.buildingIds,
|
|
69
|
+
sessionId: context.sessionId || String(requestId),
|
|
70
|
+
metadata: {
|
|
71
|
+
ip: req.ip || req.socket.remoteAddress,
|
|
72
|
+
userAgent: req.get("user-agent"),
|
|
73
|
+
},
|
|
74
|
+
} : undefined,
|
|
75
|
+
};
|
|
76
|
+
if (!this.mcpServerService) {
|
|
77
|
+
const errorResponse = (0, jsonrpc_interface_1.createJsonRpcError)(request.id, jsonrpc_interface_1.JsonRpcErrorCode.InternalError, "McpServerService not initialized");
|
|
78
|
+
res.status(500).json(errorResponse);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const response = await this.mcpServerService.handleRequest(request);
|
|
82
|
+
res.status(200).json(response);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
logger_util_1.logger.error("HttpGatewayService", "Error handling HTTP request", {
|
|
86
|
+
component: "Layer 1: HTTP Interface",
|
|
87
|
+
error: (0, sanitize_util_1.sanitizeErrorMessage)(error),
|
|
88
|
+
});
|
|
89
|
+
const errorResponse = (0, jsonrpc_interface_1.createJsonRpcError)(req.body?.id || null, jsonrpc_interface_1.JsonRpcErrorCode.InternalError, "Internal error during request handling");
|
|
90
|
+
res.status(500).json(errorResponse);
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
this.requestContextMap.delete(String(requestId));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
exports.HttpGatewayService = HttpGatewayService;
|
|
98
|
+
exports.HttpGatewayService = HttpGatewayService = __decorate([
|
|
99
|
+
(0, common_1.Injectable)(),
|
|
100
|
+
__metadata("design:paramtypes", [])
|
|
101
|
+
], HttpGatewayService);
|
|
102
|
+
//# sourceMappingURL=http-gateway.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-gateway.service.js","sourceRoot":"","sources":["../../../src/adapters/express/http-gateway.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpGatewayService = exports.createMcpExpressRouter = void 0;
|
|
4
|
+
var express_adapter_1 = require("./express-adapter");
|
|
5
|
+
Object.defineProperty(exports, "createMcpExpressRouter", { enumerable: true, get: function () { return express_adapter_1.createMcpExpressRouter; } });
|
|
6
|
+
var http_gateway_service_1 = require("./http-gateway.service");
|
|
7
|
+
Object.defineProperty(exports, "HttpGatewayService", { enumerable: true, get: function () { return http_gateway_service_1.HttpGatewayService; } });
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/express/index.ts"],"names":[],"mappings":";;;AAAA,qDAA2D;AAAlD,yHAAA,sBAAsB,OAAA;AAE/B,+DAA4D;AAAnD,0HAAA,kBAAkB,OAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from "express";
|
|
2
|
+
import { OAuthProviderConfig } from "../../auth/oauth/oauth-config.interface";
|
|
3
|
+
export type McpAuthMiddleware = (req: Request, res: Response, next: NextFunction) => void | Promise<void>;
|
|
4
|
+
export interface CreateMcpExpressRouterOptions {
|
|
5
|
+
tools?: any[];
|
|
6
|
+
resources?: any[];
|
|
7
|
+
prompts?: any[];
|
|
8
|
+
auth?: McpAuthMiddleware;
|
|
9
|
+
oauth?: OAuthProviderConfig;
|
|
10
|
+
serverInfo?: {
|
|
11
|
+
name: string;
|
|
12
|
+
version: string;
|
|
13
|
+
};
|
|
14
|
+
pathPrefix?: string;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapters/express/types.ts"],"names":[],"mappings":""}
|
package/dist/app.module.js
CHANGED
|
@@ -15,6 +15,7 @@ const constants_1 = require("./config/constants");
|
|
|
15
15
|
const interface_module_1 = require("./interface/interface.module");
|
|
16
16
|
const resource_module_1 = require("./resources/resource.module");
|
|
17
17
|
const prompt_module_1 = require("./prompts/prompt.module");
|
|
18
|
+
const context_provider_service_1 = require("./core/context/context-provider.service");
|
|
18
19
|
let AppModule = class AppModule {
|
|
19
20
|
};
|
|
20
21
|
exports.AppModule = AppModule;
|
|
@@ -25,6 +26,7 @@ exports.AppModule = AppModule = __decorate([
|
|
|
25
26
|
mcp_server_service_1.McpServerService,
|
|
26
27
|
tool_registry_service_1.ToolRegistryService,
|
|
27
28
|
config_holder_service_1.ConfigHolderService,
|
|
29
|
+
context_provider_service_1.ContextProviderService,
|
|
28
30
|
{
|
|
29
31
|
provide: constants_1.CONFIG_TOKEN,
|
|
30
32
|
useExisting: config_holder_service_1.ConfigHolderService,
|
package/dist/app.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;AAEA,2CAAwC;AACxC,6EAAwE;AACxE,yFAAoF;AACpF,0EAAqE;AACrE,kDAAkD;AAClD,mEAA+D;AAC/D,iEAA6D;AAC7D,2DAAuD;
|
|
1
|
+
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;AAEA,2CAAwC;AACxC,6EAAwE;AACxE,yFAAoF;AACpF,0EAAqE;AACrE,kDAAkD;AAClD,mEAA+D;AAC/D,iEAA6D;AAC7D,2DAAuD;AACvD,sFAAiF;AAwB1E,IAAM,SAAS,GAAf,MAAM,SAAS;CAAG,CAAA;AAAZ,8BAAS;oBAAT,SAAS;IAlBrB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,kCAAe,EAAE,gCAAc,EAAE,4BAAY,CAAC;QACxD,SAAS,EAAE;YAET,qCAAgB;YAEhB,2CAAmB;YACnB,2CAAmB;YAEnB,iDAAsB;YAEtB;gBACE,OAAO,EAAE,wBAAY;gBACrB,WAAW,EAAE,2CAAmB;aACjC;SACF;QACD,OAAO,EAAE,CAAC,qCAAgB,CAAC;KAC5B,CAAC;GACW,SAAS,CAAG"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createOAuthMiddleware = exports.OAuthProviderService = void 0;
|
|
4
|
+
var oauth_provider_service_1 = require("./oauth-provider.service");
|
|
5
|
+
Object.defineProperty(exports, "OAuthProviderService", { enumerable: true, get: function () { return oauth_provider_service_1.OAuthProviderService; } });
|
|
6
|
+
var oauth_middleware_1 = require("./oauth-middleware");
|
|
7
|
+
Object.defineProperty(exports, "createOAuthMiddleware", { enumerable: true, get: function () { return oauth_middleware_1.createOAuthMiddleware; } });
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/oauth/index.ts"],"names":[],"mappings":";;;AAAA,mEAAgE;AAAvD,8HAAA,oBAAoB,OAAA;AAC7B,uDAA2D;AAAlD,yHAAA,qBAAqB,OAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { McpContext } from "../../core/context/mcp-context.interface";
|
|
2
|
+
export type OAuthTokenValidator = (token: string) => Promise<any> | any;
|
|
3
|
+
export type OAuthContextExtractor = (payload: any) => McpContext;
|
|
4
|
+
export interface OAuthProviderConfig {
|
|
5
|
+
provider: string;
|
|
6
|
+
validateToken: OAuthTokenValidator;
|
|
7
|
+
extractContext: OAuthContextExtractor;
|
|
8
|
+
extractToken?: (req: any) => string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface OAuthConfig {
|
|
11
|
+
oauth: OAuthProviderConfig;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-config.interface.js","sourceRoot":"","sources":["../../../src/auth/oauth/oauth-config.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from "express";
|
|
2
|
+
import { OAuthProviderService } from "./oauth-provider.service";
|
|
3
|
+
export declare function createOAuthMiddleware(oauthProvider: OAuthProviderService): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createOAuthMiddleware = createOAuthMiddleware;
|
|
4
|
+
const logger_util_1 = require("../../core/utils/logger.util");
|
|
5
|
+
const sanitize_util_1 = require("../../core/utils/sanitize.util");
|
|
6
|
+
function createOAuthMiddleware(oauthProvider) {
|
|
7
|
+
return async (req, res, next) => {
|
|
8
|
+
const requestId = req.headers["x-request-id"] || req.body?.id || null;
|
|
9
|
+
const clientIp = req.ip || req.socket.remoteAddress || "unknown";
|
|
10
|
+
try {
|
|
11
|
+
const token = oauthProvider.extractTokenFromRequest(req);
|
|
12
|
+
if (!token) {
|
|
13
|
+
logger_util_1.logger.audit("OAuthMiddleware", "oauth/authenticate", "failure", {
|
|
14
|
+
reason: "No token provided",
|
|
15
|
+
clientIp,
|
|
16
|
+
}, requestId, clientIp);
|
|
17
|
+
res.status(401).json({
|
|
18
|
+
jsonrpc: "2.0",
|
|
19
|
+
id: null,
|
|
20
|
+
error: {
|
|
21
|
+
code: -32000,
|
|
22
|
+
message: "Unauthorized: No token provided",
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const context = await oauthProvider.validateAndExtractContext(token);
|
|
28
|
+
const actorId = (0, sanitize_util_1.sanitizeActorId)(context.sessionId || context.userId || undefined);
|
|
29
|
+
logger_util_1.logger.audit("OAuthMiddleware", "oauth/authenticate", "success", {
|
|
30
|
+
clientIp,
|
|
31
|
+
}, requestId, actorId);
|
|
32
|
+
req.mcpContext = context;
|
|
33
|
+
next();
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
logger_util_1.logger.error("OAuthMiddleware", "Token validation failed", {
|
|
37
|
+
error: (0, sanitize_util_1.sanitizeErrorMessage)(error),
|
|
38
|
+
});
|
|
39
|
+
logger_util_1.logger.audit("OAuthMiddleware", "oauth/authenticate", "failure", {
|
|
40
|
+
reason: "Token validation failed",
|
|
41
|
+
clientIp,
|
|
42
|
+
}, requestId, clientIp);
|
|
43
|
+
res.status(401).json({
|
|
44
|
+
jsonrpc: "2.0",
|
|
45
|
+
id: null,
|
|
46
|
+
error: {
|
|
47
|
+
code: -32000,
|
|
48
|
+
message: "Unauthorized: Invalid token",
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=oauth-middleware.js.map
|