@rekog/mcp-nest 1.1.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/.rinorism/index.d.ts +1 -0
  2. package/.vscode/settings.json +1 -0
  3. package/README.md +157 -15
  4. package/coverage/clover.xml +135 -121
  5. package/coverage/coverage-final.json +8 -8
  6. package/coverage/lcov-report/index.html +39 -39
  7. package/coverage/lcov.info +208 -207
  8. package/dist/controllers/sse.controller.factory.d.ts +13 -5
  9. package/dist/controllers/sse.controller.factory.d.ts.map +1 -1
  10. package/dist/controllers/sse.controller.factory.js +19 -6
  11. package/dist/controllers/sse.controller.factory.js.map +1 -1
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +2 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/interfaces/mcp-options.interface.d.ts +2 -0
  17. package/dist/interfaces/mcp-options.interface.d.ts.map +1 -1
  18. package/dist/mcp.module.d.ts.map +1 -1
  19. package/dist/mcp.module.js +10 -6
  20. package/dist/mcp.module.js.map +1 -1
  21. package/dist/services/mcp-tool-registry.service.d.ts +19 -0
  22. package/dist/services/mcp-tool-registry.service.d.ts.map +1 -0
  23. package/dist/services/mcp-tool-registry.service.js +66 -0
  24. package/dist/services/mcp-tool-registry.service.js.map +1 -0
  25. package/dist/services/mcp-tools-executor.service.d.ts +84 -0
  26. package/dist/services/mcp-tools-executor.service.d.ts.map +1 -0
  27. package/dist/services/mcp-tools-executor.service.js +154 -0
  28. package/dist/services/mcp-tools-executor.service.js.map +1 -0
  29. package/dist/services/mcp-tools.discovery.d.ts +19 -15
  30. package/dist/services/mcp-tools.discovery.d.ts.map +1 -1
  31. package/dist/services/mcp-tools.discovery.js +66 -127
  32. package/dist/services/mcp-tools.discovery.js.map +1 -1
  33. package/package.json +1 -1
  34. package/tests/mcp-auth.e2e.spec.ts +231 -0
  35. package/tests/mcp.e2e.spec.ts +30 -73
  36. package/tsconfig.tsbuildinfo +1 -1
@@ -8,174 +8,113 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  exports.McpToolsDiscovery = void 0;
13
16
  const common_1 = require("@nestjs/common");
14
17
  const core_1 = require("@nestjs/core");
15
- const decorators_1 = require("../decorators");
16
18
  const zod_1 = require("zod");
17
19
  const zod_to_json_schema_1 = require("zod-to-json-schema");
18
20
  const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
19
- const TextContentZodSchema = zod_1.z
20
- .object({
21
- type: zod_1.z.literal("text"),
22
- text: zod_1.z.string(),
23
- })
24
- .strict();
25
- const ContentZodSchema = zod_1.z.discriminatedUnion("type", [
26
- TextContentZodSchema,
27
- ]);
28
- const ContentResultZodSchema = zod_1.z
29
- .object({
30
- content: ContentZodSchema.array(),
31
- isError: zod_1.z.boolean().optional(),
32
- })
33
- .strict();
21
+ const mcp_tool_registry_service_1 = require("./mcp-tool-registry.service");
22
+ const TextContentZodSchema = zod_1.z.object({ type: zod_1.z.literal("text"), text: zod_1.z.string() }).strict();
23
+ const ImageContentZodSchema = zod_1.z.object({ type: zod_1.z.literal("image"), data: zod_1.z.string(), mimeType: zod_1.z.string() }).strict();
24
+ const AudioContentZodSchema = zod_1.z.object({ type: zod_1.z.literal("audio"), data: zod_1.z.string(), mimeType: zod_1.z.string() }).strict();
25
+ const ResourceZodSchema = zod_1.z.object({ uri: zod_1.z.string(), mimeType: zod_1.z.string().optional(), text: zod_1.z.string().optional(), blob: zod_1.z.string().optional(), name: zod_1.z.string().optional(), description: zod_1.z.string().optional(), size: zod_1.z.number().optional() }).refine(data => data.text !== undefined || data.blob !== undefined, { message: "Resource must have either text or blob content" });
26
+ const EmbeddedResourceZodSchema = zod_1.z.object({ type: zod_1.z.literal("resource"), resource: ResourceZodSchema }).strict();
27
+ const ContentZodSchema = zod_1.z.discriminatedUnion("type", [TextContentZodSchema, ImageContentZodSchema, AudioContentZodSchema, EmbeddedResourceZodSchema]);
28
+ const ContentResultZodSchema = zod_1.z.object({ content: ContentZodSchema.array().min(1), isError: zod_1.z.boolean().optional() }).strict();
34
29
  class UserError extends Error {
35
- constructor(message) {
36
- super(message);
37
- this.name = 'UserError';
38
- }
39
30
  }
40
31
  let McpToolsDiscovery = class McpToolsDiscovery {
41
- constructor(discovery, metadataScanner) {
42
- this.discovery = discovery;
43
- this.metadataScanner = metadataScanner;
44
- this.tools = [];
45
- }
46
- onApplicationBootstrap() {
47
- this.collectTools();
32
+ constructor(registry, moduleRef, request) {
33
+ this.registry = registry;
34
+ this.moduleRef = moduleRef;
35
+ this.request = request;
48
36
  }
49
- collectTools() {
50
- const providers = this.discovery.getProviders();
51
- const controllers = this.discovery.getControllers();
52
- const allInstances = [...providers, ...controllers]
53
- .filter((wrapper) => wrapper.instance)
54
- .map((wrapper) => wrapper.instance);
55
- allInstances.forEach((instance) => {
56
- if (!instance || typeof instance !== 'object') {
57
- return;
58
- }
59
- this.metadataScanner.getAllMethodNames(instance).forEach((methodName) => {
60
- const methodRef = instance[methodName];
61
- const methodMetaKeys = Reflect.getOwnMetadataKeys(methodRef);
62
- if (!methodMetaKeys.includes(decorators_1.MCP_TOOL_METADATA_KEY)) {
63
- return;
64
- }
65
- const metadata = Reflect.getMetadata(decorators_1.MCP_TOOL_METADATA_KEY, methodRef);
66
- this.tools.push({
67
- metadata,
68
- instance,
69
- methodName,
70
- });
71
- });
72
- });
73
- }
74
- registerTools(mcpServer) {
37
+ registerRequestHandlers(mcpServer) {
38
+ const tools = this.registry.getTools();
75
39
  mcpServer.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
76
- let tools = this.tools.map((tool) => ({
40
+ const toolList = tools.map((tool) => ({
77
41
  name: tool.metadata.name,
78
42
  description: tool.metadata.description,
79
43
  inputSchema: tool.metadata.parameters
80
44
  ? (0, zod_to_json_schema_1.zodToJsonSchema)(tool.metadata.parameters)
81
45
  : undefined,
82
46
  }));
83
- return {
84
- tools
85
- };
47
+ return { tools: toolList };
86
48
  });
87
- mcpServer.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
88
- const tool = this.tools.find((tool) => tool.metadata.name === request.params.name);
89
- if (!tool) {
90
- throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
91
- }
92
- const schema = tool.metadata.parameters;
93
- let parsedParams = request.params.arguments;
94
- if (schema && schema instanceof zod_1.z.ZodType) {
95
- const result = schema.safeParse(request.params.arguments);
96
- if (!result.success) {
97
- throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, `Invalid ${request.params.name} parameters: ${JSON.stringify(result.error.format())}`);
98
- }
99
- parsedParams = result.data;
49
+ mcpServer.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (callRequest, baseContext) => {
50
+ const toolInfo = this.registry.findTool(callRequest.params.name);
51
+ if (!toolInfo) {
52
+ throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${callRequest.params.name}`);
100
53
  }
101
- const progressToken = request.params?._meta?.progressToken;
54
+ const schema = toolInfo.metadata.parameters;
55
+ let parsedParams = callRequest.params.arguments;
56
+ let toolExecutionResult;
102
57
  try {
103
- const context = this.createContext(mcpServer, progressToken);
104
- const result = await tool.instance[tool.methodName].call(tool.instance, parsedParams, context);
105
- if (typeof result === "string") {
106
- return ContentResultZodSchema.parse({
107
- content: [{ type: "text", text: result }],
108
- });
58
+ const executionContext = this.createExecutionContext(mcpServer, callRequest.params?._meta?.progressToken, baseContext);
59
+ const toolInstance = await this.moduleRef.resolve(toolInfo.providerClass, undefined, { strict: false });
60
+ if (!toolInstance) {
61
+ throw new Error(`Failed to resolve instance for tool provider: ${toolInfo.providerClass.name}`);
109
62
  }
110
- else if (result && typeof result === "object" && "type" in result) {
111
- return ContentResultZodSchema.parse({
112
- content: [result],
113
- });
63
+ const resultFromMethod = await toolInstance[toolInfo.methodName].call(toolInstance, parsedParams, executionContext);
64
+ if (typeof resultFromMethod === "string") {
65
+ toolExecutionResult = { content: [{ type: "text", text: resultFromMethod }] };
114
66
  }
115
67
  else {
116
- return ContentResultZodSchema.parse(result);
68
+ const validation = ContentResultZodSchema.safeParse(resultFromMethod);
69
+ if (!validation.success) {
70
+ console.error(`Invalid result structure from tool ${toolInfo.metadata.name}:`, validation.error.format());
71
+ executionContext.log.error(`Invalid result structure from tool ${toolInfo.metadata.name}`, { error: validation.error.format() });
72
+ throw new Error(`Tool ${toolInfo.metadata.name} returned an invalid result structure.`);
73
+ }
74
+ toolExecutionResult = validation.data;
117
75
  }
118
76
  }
119
77
  catch (error) {
120
- if (error instanceof UserError) {
121
- return {
122
- content: [{ type: "text", text: error.message }],
123
- isError: true,
124
- };
78
+ const executionContextForLog = this.createExecutionContext(mcpServer, undefined, baseContext);
79
+ executionContextForLog.log.error(`Tool execution failed: ${toolInfo.metadata.name}`, { error: error.message });
80
+ if (error instanceof UserError || error instanceof types_js_1.McpError) {
81
+ toolExecutionResult = { content: [{ type: "text", text: error.message }], isError: true };
82
+ }
83
+ else {
84
+ toolExecutionResult = { content: [{ type: "text", text: "An internal error occurred." }], isError: true };
125
85
  }
126
- return {
127
- content: [{ type: "text", text: `Error: ${error}` }],
128
- isError: true,
129
- };
130
86
  }
87
+ return { result: toolExecutionResult };
131
88
  });
132
89
  }
133
- createContext(mcpServer, progressToken) {
90
+ createExecutionContext(mcpServer, progressToken, baseContext) {
91
+ const user = this.request.user;
134
92
  return {
93
+ user: user,
135
94
  reportProgress: async (progress) => {
136
- if (progressToken) {
137
- await mcpServer.server.notification({
138
- method: "notifications/progress",
139
- params: {
140
- ...progress,
141
- progressToken,
142
- },
143
- });
95
+ if (progressToken !== undefined) {
96
+ try {
97
+ await mcpServer.server.notification({ method: "notifications/progress", params: { ...progress, progressToken } });
98
+ }
99
+ catch (e) {
100
+ console.error("Failed to send progress notification:", e);
101
+ }
144
102
  }
145
103
  },
146
104
  log: {
147
- debug: (message, context) => {
148
- mcpServer.server.sendLoggingMessage({
149
- level: "debug",
150
- data: { message, context },
151
- });
152
- },
153
- error: (message, context) => {
154
- mcpServer.server.sendLoggingMessage({
155
- level: "error",
156
- data: { message, context },
157
- });
158
- },
159
- info: (message, context) => {
160
- mcpServer.server.sendLoggingMessage({
161
- level: "info",
162
- data: { message, context },
163
- });
164
- },
165
- warn: (message, context) => {
166
- mcpServer.server.sendLoggingMessage({
167
- level: "warning",
168
- data: { message, context },
169
- });
170
- },
105
+ debug: (message, context) => { mcpServer.server.sendLoggingMessage({ level: "debug", data: { message, context, user: user?.userId } }); },
106
+ error: (message, context) => { mcpServer.server.sendLoggingMessage({ level: "error", data: { message, context, user: user?.userId } }); },
107
+ info: (message, context) => { mcpServer.server.sendLoggingMessage({ level: "info", data: { message, context, user: user?.userId } }); },
108
+ warn: (message, context) => { mcpServer.server.sendLoggingMessage({ level: "warning", data: { message, context, user: user?.userId } }); },
171
109
  },
172
110
  };
173
111
  }
174
112
  };
175
113
  exports.McpToolsDiscovery = McpToolsDiscovery;
176
114
  exports.McpToolsDiscovery = McpToolsDiscovery = __decorate([
177
- (0, common_1.Injectable)(),
178
- __metadata("design:paramtypes", [core_1.DiscoveryService,
179
- core_1.MetadataScanner])
115
+ (0, common_1.Injectable)({ scope: common_1.Scope.REQUEST }),
116
+ __param(2, (0, common_1.Inject)(core_1.REQUEST)),
117
+ __metadata("design:paramtypes", [mcp_tool_registry_service_1.McpToolRegistryService,
118
+ core_1.ModuleRef, Object])
180
119
  ], McpToolsDiscovery);
181
120
  //# sourceMappingURL=mcp-tools.discovery.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-tools.discovery.js","sourceRoot":"","sources":["../../src/services/mcp-tools.discovery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mcp-tools.discovery.js","sourceRoot":"","sources":["../../src/services/mcp-tools.discovery.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rekog/mcp-nest",
3
- "version": "1.1.4",
3
+ "version": "1.2.0",
4
4
  "description": "NestJS module for creating Model Context Protocol (MCP) servers and exposing tools using SSE",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,231 @@
1
+ import { INestApplication, Injectable } from "@nestjs/common";
2
+ import { Test, TestingModule } from "@nestjs/testing";
3
+ import { z } from "zod";
4
+ import { Context, Tool } from "../src";
5
+ import { McpModule } from "../src/mcp.module";
6
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
7
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
8
+ import { Progress } from "@modelcontextprotocol/sdk/types.js";
9
+ import { CanActivate, ExecutionContext } from "@nestjs/common";
10
+
11
+ // Mock authentication guard
12
+ class MockAuthGuard implements CanActivate {
13
+ canActivate(context: ExecutionContext): boolean {
14
+ const request = context.switchToHttp().getRequest();
15
+
16
+
17
+ if (request.headers.authorization && request.headers.authorization.includes("token-xyz")) {
18
+ request.user = {
19
+ id: "user123",
20
+ name: "Test User",
21
+ orgMemberships: [
22
+ {
23
+ orgId: "org123",
24
+ organization: {
25
+ name: "Auth Test Org",
26
+ },
27
+ },
28
+ ],
29
+ };
30
+
31
+ return true;
32
+ }
33
+ return false;
34
+ }
35
+ }
36
+
37
+ // Mock user repository
38
+ @Injectable()
39
+ class MockUserRepository {
40
+ async findOne() {
41
+ return {
42
+ id: "userRepo123",
43
+ name: "Repository User",
44
+ orgMemberships: [
45
+ {
46
+ orgId: "org123",
47
+ organization: {
48
+ name: "Repository Org",
49
+ },
50
+ },
51
+ ],
52
+ };
53
+ }
54
+ }
55
+
56
+ // Greeting tool that uses the authentication context
57
+ @Injectable()
58
+ export class AuthGreetingTool {
59
+ constructor(private readonly userRepository: MockUserRepository) {}
60
+
61
+ @Tool({
62
+ name: "auth-hello-world",
63
+ description: "A sample tool that accesses the authenticated user",
64
+ parameters: z.object({
65
+ name: z.string().default("World"),
66
+ }),
67
+ })
68
+ async sayHello({ name }, context: Context, request: Request & { user: any }) {
69
+ // Access both repository data and the authenticated user context
70
+ const repoUser = await this.userRepository.findOne();
71
+ const authUser = request.user; // Authenticated user from the request
72
+
73
+ // Construct greeting using both data sources
74
+ const greeting = `Hello, ${name}! I'm ${authUser.name} from ${
75
+ authUser.orgMemberships[0].organization.name
76
+ }. Repository user is ${repoUser.name}.`;
77
+
78
+ // Report progress for demonstration
79
+ for (let i = 0; i < 5; i++) {
80
+ await new Promise((resolve) => setTimeout(resolve, 200));
81
+ await context.reportProgress({
82
+ progress: (i+1) * 20,
83
+ total: 100,
84
+ } as Progress);
85
+ }
86
+
87
+ return {
88
+ content: [
89
+ {
90
+ type: "text",
91
+ text: greeting,
92
+ },
93
+ ],
94
+ };
95
+ }
96
+ }
97
+
98
+ describe("E2E: MCP Server with Authentication", () => {
99
+ let app: INestApplication;
100
+ let testPort: number;
101
+
102
+ beforeAll(async () => {
103
+ const moduleFixture: TestingModule = await Test.createTestingModule({
104
+ imports: [
105
+ McpModule.forRoot({
106
+ name: "test-auth-mcp-server",
107
+ version: "0.0.1",
108
+ // Specify the MockAuthGuard to protect the messages endpoint
109
+ guards: [MockAuthGuard],
110
+ capabilities: {
111
+ tools: {
112
+ "auth-hello-world": {
113
+ description: "A sample tool that accesses the authenticated user",
114
+ input: {
115
+ name: {
116
+ type: "string",
117
+ default: "World",
118
+ },
119
+ },
120
+ },
121
+ },
122
+ },
123
+ }),
124
+ ],
125
+ providers: [AuthGreetingTool, MockUserRepository, MockAuthGuard],
126
+ }).compile();
127
+
128
+ app = moduleFixture.createNestApplication();
129
+ await app.listen(0);
130
+
131
+ const server = app.getHttpServer();
132
+ testPort = server.address().port;
133
+ });
134
+
135
+ afterAll(async () => {
136
+ await app.close();
137
+ });
138
+
139
+ it("should list tools", async () => {
140
+ const client = new Client(
141
+ { name: "example-client", version: "1.0.0" },
142
+ { capabilities: {} },
143
+ );
144
+ const sseUrl = new URL(`http://localhost:${testPort}/sse`);
145
+ const transport = new SSEClientTransport(sseUrl, {
146
+ requestInit: {
147
+ headers: {
148
+ Authorization: 'Bearer token-xyz'
149
+ }
150
+ }
151
+ });
152
+ await client.connect(transport);
153
+ const tools = await client.listTools();
154
+
155
+ // Verify that the authenticated tool is available
156
+ expect(tools.tools.length).toBeGreaterThan(0);
157
+ expect(tools.tools.find((t) => t.name === "auth-hello-world")).toBeDefined();
158
+
159
+ await client.close();
160
+ });
161
+
162
+ it('should inject authentication context into the tool', async () => {
163
+ const client = new Client(
164
+ { name: "example-client", version: "1.0.0" },
165
+ { capabilities: {} },
166
+ );
167
+ const sseUrl = new URL(`http://localhost:${testPort}/sse`);
168
+ const transport = new SSEClientTransport(sseUrl, {
169
+ requestInit: {
170
+ headers: {
171
+ Authorization: 'Bearer token-xyz'
172
+ }
173
+ }
174
+ });
175
+ await client.connect(transport);
176
+
177
+ let progressCount = 0;
178
+ const result: any = await client.callTool(
179
+ {
180
+ name: "auth-hello-world",
181
+ arguments: { name: "Authenticated User" },
182
+ },
183
+ undefined,
184
+ {
185
+ onprogress: (progress) => {
186
+ progressCount++;
187
+ },
188
+ },
189
+ );
190
+
191
+ // Verify that progress notifications were received
192
+ expect(progressCount).toBeGreaterThan(0);
193
+
194
+ // Verify that authentication context was available to the tool
195
+ expect(result.content[0].type).toBe("text");
196
+ expect(result.content[0].text).toContain("Auth Test Org");
197
+ expect(result.content[0].text).toContain("Test User");
198
+ expect(result.content[0].text).toContain("Repository user is Repository User");
199
+
200
+ await client.close();
201
+ });
202
+
203
+ it('should reject unauthenticated connections', async () => {
204
+ const client = new Client(
205
+ { name: "example-client", version: "1.0.0" },
206
+ { capabilities: {} },
207
+ );
208
+ const sseUrl = new URL(`http://localhost:${testPort}/sse`);
209
+
210
+ // Using invalid token
211
+ const transport = new SSEClientTransport(sseUrl, {
212
+ requestInit: {
213
+ headers: {
214
+ Authorization: 'Bearer invalid-token'
215
+ }
216
+ }
217
+ });
218
+
219
+ // Connection should be rejected
220
+ try {
221
+ await client.connect(transport);
222
+ // If we get here, the test should fail
223
+ fail('Connection should have been rejected');
224
+ } catch (error) {
225
+ // We expect an error to be thrown when authentication fails
226
+ expect(error).toBeDefined();
227
+ } finally {
228
+ await client.close();
229
+ }
230
+ });
231
+ });