@rekog/mcp-nest 1.9.4 → 1.9.6
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 +5 -1
- package/dist/mcp/decorators/prompt.decorator.d.ts +1 -2
- package/dist/mcp/decorators/prompt.decorator.d.ts.map +1 -1
- package/dist/mcp/decorators/prompt.decorator.js.map +1 -1
- package/dist/mcp/index.d.ts +2 -2
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +2 -2
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/interfaces/dynamic-prompt.interface.d.ts +11 -0
- package/dist/mcp/interfaces/dynamic-prompt.interface.d.ts.map +1 -0
- package/dist/mcp/interfaces/dynamic-prompt.interface.js +3 -0
- package/dist/mcp/interfaces/dynamic-prompt.interface.js.map +1 -0
- package/dist/mcp/interfaces/dynamic-resource.interface.d.ts +11 -0
- package/dist/mcp/interfaces/dynamic-resource.interface.d.ts.map +1 -0
- package/dist/mcp/interfaces/dynamic-resource.interface.js +3 -0
- package/dist/mcp/interfaces/dynamic-resource.interface.js.map +1 -0
- package/dist/mcp/interfaces/dynamic-tool.interface.js.map +1 -1
- package/dist/mcp/interfaces/index.d.ts +2 -0
- package/dist/mcp/interfaces/index.d.ts.map +1 -1
- package/dist/mcp/interfaces/index.js.map +1 -1
- package/dist/mcp/mcp.module.d.ts.map +1 -1
- package/dist/mcp/mcp.module.js +15 -11
- package/dist/mcp/mcp.module.js.map +1 -1
- package/dist/mcp/services/handlers/mcp-handler.base.d.ts +4 -4
- package/dist/mcp/services/handlers/mcp-handler.base.d.ts.map +1 -1
- package/dist/mcp/services/handlers/mcp-handler.base.js.map +1 -1
- package/dist/mcp/services/handlers/mcp-prompts.handler.d.ts +2 -2
- package/dist/mcp/services/handlers/mcp-prompts.handler.d.ts.map +1 -1
- package/dist/mcp/services/handlers/mcp-prompts.handler.js +13 -3
- package/dist/mcp/services/handlers/mcp-prompts.handler.js.map +1 -1
- package/dist/mcp/services/handlers/mcp-resources.handler.d.ts +2 -2
- package/dist/mcp/services/handlers/mcp-resources.handler.d.ts.map +1 -1
- package/dist/mcp/services/handlers/mcp-resources.handler.js +12 -2
- package/dist/mcp/services/handlers/mcp-resources.handler.js.map +1 -1
- package/dist/mcp/services/handlers/mcp-tools.handler.d.ts +2 -2
- package/dist/mcp/services/handlers/mcp-tools.handler.d.ts.map +1 -1
- package/dist/mcp/services/handlers/mcp-tools.handler.js +5 -5
- package/dist/mcp/services/handlers/mcp-tools.handler.js.map +1 -1
- package/dist/mcp/services/mcp-dynamic-registry.service.d.ts +26 -0
- package/dist/mcp/services/mcp-dynamic-registry.service.d.ts.map +1 -0
- package/dist/mcp/services/mcp-dynamic-registry.service.js +133 -0
- package/dist/mcp/services/mcp-dynamic-registry.service.js.map +1 -0
- package/dist/mcp/services/mcp-executor.service.d.ts +2 -2
- package/dist/mcp/services/mcp-executor.service.d.ts.map +1 -1
- package/dist/mcp/services/mcp-executor.service.js +2 -2
- package/dist/mcp/services/mcp-executor.service.js.map +1 -1
- package/dist/mcp/services/{mcp-registry.service.d.ts → mcp-registry-discovery.service.d.ts} +16 -15
- package/dist/mcp/services/mcp-registry-discovery.service.d.ts.map +1 -0
- package/dist/mcp/services/{mcp-registry.service.js → mcp-registry-discovery.service.js} +41 -25
- package/dist/mcp/services/mcp-registry-discovery.service.js.map +1 -0
- package/dist/mcp/services/mcp-sse.service.d.ts +2 -2
- package/dist/mcp/services/mcp-sse.service.d.ts.map +1 -1
- package/dist/mcp/services/mcp-sse.service.js +2 -2
- package/dist/mcp/services/mcp-sse.service.js.map +1 -1
- package/dist/mcp/services/mcp-streamable-http.service.d.ts +2 -2
- package/dist/mcp/services/mcp-streamable-http.service.d.ts.map +1 -1
- package/dist/mcp/services/mcp-streamable-http.service.js +2 -2
- package/dist/mcp/services/mcp-streamable-http.service.js.map +1 -1
- package/dist/mcp/services/tool-authorization.service.d.ts +4 -4
- package/dist/mcp/services/tool-authorization.service.d.ts.map +1 -1
- package/dist/mcp/services/tool-authorization.service.js.map +1 -1
- package/dist/mcp/transport/stdio.service.d.ts +2 -2
- package/dist/mcp/transport/stdio.service.d.ts.map +1 -1
- package/dist/mcp/transport/stdio.service.js +7 -7
- package/dist/mcp/transport/stdio.service.js.map +1 -1
- package/dist/mcp/utils/capabilities-builder.d.ts +2 -2
- package/dist/mcp/utils/capabilities-builder.d.ts.map +1 -1
- package/dist/mcp/utils/capabilities-builder.js.map +1 -1
- package/dist/mcp/utils/mcp-server.factory.d.ts +2 -2
- package/dist/mcp/utils/mcp-server.factory.d.ts.map +1 -1
- package/dist/mcp/utils/mcp-server.factory.js.map +1 -1
- package/package.json +9 -9
- package/src/mcp/decorators/prompt.decorator.ts +1 -1
- package/src/mcp/index.ts +2 -2
- package/src/mcp/interfaces/dynamic-prompt.interface.ts +20 -0
- package/src/mcp/interfaces/dynamic-resource.interface.ts +22 -0
- package/src/mcp/interfaces/dynamic-tool.interface.ts +2 -2
- package/src/mcp/interfaces/index.ts +10 -0
- package/src/mcp/mcp.module.ts +15 -11
- package/src/mcp/services/handlers/mcp-handler.base.ts +6 -3
- package/src/mcp/services/handlers/mcp-prompts.handler.ts +36 -4
- package/src/mcp/services/handlers/mcp-resources.handler.ts +24 -2
- package/src/mcp/services/handlers/mcp-tools.handler.ts +11 -8
- package/src/mcp/services/mcp-dynamic-registry.service.ts +236 -0
- package/src/mcp/services/mcp-executor.service.ts +2 -2
- package/src/mcp/services/{mcp-registry.service.spec.ts → mcp-registry-discovery.service.spec.ts} +18 -12
- package/src/mcp/services/{mcp-registry.service.ts → mcp-registry-discovery.service.ts} +77 -35
- package/src/mcp/services/mcp-sse.service.ts +2 -2
- package/src/mcp/services/mcp-streamable-http.service.ts +2 -2
- package/src/mcp/services/tool-authorization.service.ts +4 -4
- package/src/mcp/transport/stdio.service.ts +8 -8
- package/src/mcp/utils/capabilities-builder.ts +2 -2
- package/src/mcp/utils/mcp-server.factory.ts +2 -2
- package/dist/authz/services/jwt-token.service.spec.d.ts +0 -2
- package/dist/authz/services/jwt-token.service.spec.d.ts.map +0 -1
- package/dist/authz/services/jwt-token.service.spec.js +0 -86
- package/dist/authz/services/jwt-token.service.spec.js.map +0 -1
- package/dist/authz/stores/memory-store.service.spec.d.ts +0 -2
- package/dist/authz/stores/memory-store.service.spec.d.ts.map +0 -1
- package/dist/authz/stores/memory-store.service.spec.js +0 -382
- package/dist/authz/stores/memory-store.service.spec.js.map +0 -1
- package/dist/authz/stores/typeorm/typeorm-store.service.spec.d.ts +0 -2
- package/dist/authz/stores/typeorm/typeorm-store.service.spec.d.ts.map +0 -1
- package/dist/authz/stores/typeorm/typeorm-store.service.spec.js +0 -340
- package/dist/authz/stores/typeorm/typeorm-store.service.spec.js.map +0 -1
- package/dist/mcp/services/mcp-registry.service.d.ts.map +0 -1
- package/dist/mcp/services/mcp-registry.service.js.map +0 -1
- package/dist/mcp/services/mcp-registry.service.spec.d.ts +0 -2
- package/dist/mcp/services/mcp-registry.service.spec.d.ts.map +0 -1
- package/dist/mcp/services/mcp-registry.service.spec.js +0 -245
- package/dist/mcp/services/mcp-registry.service.spec.js.map +0 -1
- package/dist/mcp/services/mcp-tool-builder.service.d.ts +0 -15
- package/dist/mcp/services/mcp-tool-builder.service.d.ts.map +0 -1
- package/dist/mcp/services/mcp-tool-builder.service.js +0 -70
- package/dist/mcp/services/mcp-tool-builder.service.js.map +0 -1
- package/dist/mcp/transport/custom-decorator.spec.d.ts +0 -2
- package/dist/mcp/transport/custom-decorator.spec.d.ts.map +0 -1
- package/dist/mcp/transport/custom-decorator.spec.js +0 -34
- package/dist/mcp/transport/custom-decorator.spec.js.map +0 -1
- package/dist/mcp/utils/mcp-logger.factory.spec.d.ts +0 -2
- package/dist/mcp/utils/mcp-logger.factory.spec.d.ts.map +0 -1
- package/dist/mcp/utils/mcp-logger.factory.spec.js +0 -150
- package/dist/mcp/utils/mcp-logger.factory.spec.js.map +0 -1
- package/dist/mcp/utils/normalize-endpoint.spec.d.ts +0 -2
- package/dist/mcp/utils/normalize-endpoint.spec.d.ts.map +0 -1
- package/dist/mcp/utils/normalize-endpoint.spec.js +0 -40
- package/dist/mcp/utils/normalize-endpoint.spec.js.map +0 -1
- package/src/mcp/services/mcp-tool-builder.service.ts +0 -151
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typeorm-store.service.spec.d.ts","sourceRoot":"","sources":["../../../../src/authz/stores/typeorm/typeorm-store.service.spec.ts"],"names":[],"mappings":""}
|
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const testing_1 = require("@nestjs/testing");
|
|
4
|
-
const typeorm_1 = require("@nestjs/typeorm");
|
|
5
|
-
const typeorm_store_service_1 = require("./typeorm-store.service");
|
|
6
|
-
const entities_1 = require("./entities");
|
|
7
|
-
const constants_1 = require("./constants");
|
|
8
|
-
describe('TypeOrmStore', () => {
|
|
9
|
-
let service;
|
|
10
|
-
let clientRepository;
|
|
11
|
-
let authCodeRepository;
|
|
12
|
-
let sessionRepository;
|
|
13
|
-
beforeEach(async () => {
|
|
14
|
-
const mockClientRepository = {
|
|
15
|
-
save: jest.fn(),
|
|
16
|
-
findOne: jest.fn(),
|
|
17
|
-
delete: jest.fn(),
|
|
18
|
-
};
|
|
19
|
-
const mockAuthCodeRepository = {
|
|
20
|
-
save: jest.fn(),
|
|
21
|
-
findOne: jest.fn(),
|
|
22
|
-
delete: jest.fn(),
|
|
23
|
-
};
|
|
24
|
-
const mockSessionRepository = {
|
|
25
|
-
save: jest.fn(),
|
|
26
|
-
findOne: jest.fn(),
|
|
27
|
-
delete: jest.fn(),
|
|
28
|
-
};
|
|
29
|
-
const mockUserProfileRepository = {
|
|
30
|
-
save: jest.fn(),
|
|
31
|
-
findOne: jest.fn(),
|
|
32
|
-
delete: jest.fn(),
|
|
33
|
-
};
|
|
34
|
-
const module = await testing_1.Test.createTestingModule({
|
|
35
|
-
providers: [
|
|
36
|
-
typeorm_store_service_1.TypeOrmStore,
|
|
37
|
-
{
|
|
38
|
-
provide: (0, typeorm_1.getRepositoryToken)(entities_1.OAuthClientEntity, constants_1.OAUTH_TYPEORM_CONNECTION_NAME),
|
|
39
|
-
useValue: mockClientRepository,
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
provide: (0, typeorm_1.getRepositoryToken)(entities_1.AuthorizationCodeEntity, constants_1.OAUTH_TYPEORM_CONNECTION_NAME),
|
|
43
|
-
useValue: mockAuthCodeRepository,
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
provide: (0, typeorm_1.getRepositoryToken)(entities_1.OAuthSessionEntity, constants_1.OAUTH_TYPEORM_CONNECTION_NAME),
|
|
47
|
-
useValue: mockSessionRepository,
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
provide: (0, typeorm_1.getRepositoryToken)(entities_1.OAuthUserProfileEntity, constants_1.OAUTH_TYPEORM_CONNECTION_NAME),
|
|
51
|
-
useValue: mockUserProfileRepository,
|
|
52
|
-
},
|
|
53
|
-
],
|
|
54
|
-
}).compile();
|
|
55
|
-
service = module.get(typeorm_store_service_1.TypeOrmStore);
|
|
56
|
-
clientRepository = module.get((0, typeorm_1.getRepositoryToken)(entities_1.OAuthClientEntity, constants_1.OAUTH_TYPEORM_CONNECTION_NAME));
|
|
57
|
-
authCodeRepository = module.get((0, typeorm_1.getRepositoryToken)(entities_1.AuthorizationCodeEntity, constants_1.OAUTH_TYPEORM_CONNECTION_NAME));
|
|
58
|
-
sessionRepository = module.get((0, typeorm_1.getRepositoryToken)(entities_1.OAuthSessionEntity, constants_1.OAUTH_TYPEORM_CONNECTION_NAME));
|
|
59
|
-
});
|
|
60
|
-
afterEach(() => {
|
|
61
|
-
jest.clearAllMocks();
|
|
62
|
-
});
|
|
63
|
-
it('should be defined', () => {
|
|
64
|
-
expect(service).toBeDefined();
|
|
65
|
-
});
|
|
66
|
-
describe('generateClientId', () => {
|
|
67
|
-
const mockClient = {
|
|
68
|
-
client_id: '',
|
|
69
|
-
client_name: 'Test Client',
|
|
70
|
-
client_description: 'A test OAuth client',
|
|
71
|
-
logo_uri: 'https://example.com/logo.png',
|
|
72
|
-
client_uri: 'https://example.com',
|
|
73
|
-
developer_name: 'Test Developer',
|
|
74
|
-
developer_email: 'test@example.com',
|
|
75
|
-
redirect_uris: ['http://localhost:3000/callback'],
|
|
76
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
77
|
-
response_types: ['code'],
|
|
78
|
-
token_endpoint_auth_method: 'none',
|
|
79
|
-
created_at: new Date(),
|
|
80
|
-
updated_at: new Date(),
|
|
81
|
-
};
|
|
82
|
-
it('should generate client IDs with correct format', () => {
|
|
83
|
-
const clientId = service.generateClientId(mockClient);
|
|
84
|
-
expect(clientId).toMatch(/^[a-z0-9]+_[a-f0-9]{8}$/);
|
|
85
|
-
});
|
|
86
|
-
it('should include normalized client name in the generated ID', () => {
|
|
87
|
-
const clientWithSpecialChars = {
|
|
88
|
-
...mockClient,
|
|
89
|
-
client_name: 'Test Client!@#',
|
|
90
|
-
};
|
|
91
|
-
const clientId = service.generateClientId(clientWithSpecialChars);
|
|
92
|
-
expect(clientId).toMatch(/^testclient_[a-f0-9]{8}$/);
|
|
93
|
-
});
|
|
94
|
-
it('should generate different IDs for different clients', () => {
|
|
95
|
-
const client1 = { ...mockClient, client_name: 'Client One' };
|
|
96
|
-
const client2 = { ...mockClient, client_name: 'Client Two' };
|
|
97
|
-
const id1 = service.generateClientId(client1);
|
|
98
|
-
const id2 = service.generateClientId(client2);
|
|
99
|
-
expect(id1).not.toBe(id2);
|
|
100
|
-
});
|
|
101
|
-
it('should generate different IDs on each call (non-deterministic)', () => {
|
|
102
|
-
const id1 = service.generateClientId(mockClient);
|
|
103
|
-
const id2 = service.generateClientId(mockClient);
|
|
104
|
-
expect(id1).not.toBe(id2);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
describe('Client Management', () => {
|
|
108
|
-
const mockClient = {
|
|
109
|
-
client_id: 'test-client-id',
|
|
110
|
-
client_name: 'Test Client',
|
|
111
|
-
client_description: 'A test OAuth client',
|
|
112
|
-
logo_uri: 'https://example.com/logo.png',
|
|
113
|
-
client_uri: 'https://example.com',
|
|
114
|
-
developer_name: 'Test Developer',
|
|
115
|
-
developer_email: 'test@example.com',
|
|
116
|
-
redirect_uris: ['http://localhost:3000/callback'],
|
|
117
|
-
grant_types: ['authorization_code', 'refresh_token'],
|
|
118
|
-
response_types: ['code'],
|
|
119
|
-
token_endpoint_auth_method: 'none',
|
|
120
|
-
created_at: new Date(),
|
|
121
|
-
updated_at: new Date(),
|
|
122
|
-
};
|
|
123
|
-
describe('storeClient', () => {
|
|
124
|
-
it('should store a client and return the saved result', async () => {
|
|
125
|
-
clientRepository.save.mockResolvedValue(mockClient);
|
|
126
|
-
const result = await service.storeClient(mockClient);
|
|
127
|
-
expect(clientRepository.save).toHaveBeenCalledWith(mockClient);
|
|
128
|
-
expect(result).toEqual(mockClient);
|
|
129
|
-
});
|
|
130
|
-
it('should handle database errors', async () => {
|
|
131
|
-
const error = new Error('Database error');
|
|
132
|
-
clientRepository.save.mockRejectedValue(error);
|
|
133
|
-
await expect(service.storeClient(mockClient)).rejects.toThrow('Database error');
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
describe('getClient', () => {
|
|
137
|
-
it('should return client when found', async () => {
|
|
138
|
-
clientRepository.findOne.mockResolvedValue(mockClient);
|
|
139
|
-
const result = await service.getClient('test-client-id');
|
|
140
|
-
expect(clientRepository.findOne).toHaveBeenCalledWith({
|
|
141
|
-
where: { client_id: 'test-client-id' },
|
|
142
|
-
});
|
|
143
|
-
expect(result).toEqual(mockClient);
|
|
144
|
-
});
|
|
145
|
-
it('should return undefined when client not found', async () => {
|
|
146
|
-
clientRepository.findOne.mockResolvedValue(null);
|
|
147
|
-
const result = await service.getClient('non-existent-id');
|
|
148
|
-
expect(result).toBeUndefined();
|
|
149
|
-
});
|
|
150
|
-
it('should handle database errors', async () => {
|
|
151
|
-
const error = new Error('Database error');
|
|
152
|
-
clientRepository.findOne.mockRejectedValue(error);
|
|
153
|
-
await expect(service.getClient('test-client-id')).rejects.toThrow('Database error');
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
describe('findClient', () => {
|
|
157
|
-
it('should find client by name when found', async () => {
|
|
158
|
-
clientRepository.findOne.mockResolvedValue(mockClient);
|
|
159
|
-
const result = await service.findClient('Test Client');
|
|
160
|
-
expect(clientRepository.findOne).toHaveBeenCalledWith({
|
|
161
|
-
where: { client_name: 'Test Client' },
|
|
162
|
-
});
|
|
163
|
-
expect(result).toEqual(mockClient);
|
|
164
|
-
});
|
|
165
|
-
it('should return undefined when client name not found', async () => {
|
|
166
|
-
clientRepository.findOne.mockResolvedValue(null);
|
|
167
|
-
const result = await service.findClient('Non-existent Client');
|
|
168
|
-
expect(result).toBeUndefined();
|
|
169
|
-
});
|
|
170
|
-
it('should handle database errors', async () => {
|
|
171
|
-
const error = new Error('Database error');
|
|
172
|
-
clientRepository.findOne.mockRejectedValue(error);
|
|
173
|
-
await expect(service.findClient('Test Client')).rejects.toThrow('Database error');
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
describe('Authorization Code Management', () => {
|
|
178
|
-
const mockAuthCode = {
|
|
179
|
-
code: 'test-auth-code',
|
|
180
|
-
user_id: 'user-123',
|
|
181
|
-
client_id: 'client-123',
|
|
182
|
-
redirect_uri: 'http://localhost:3000/callback',
|
|
183
|
-
code_challenge: 'test-challenge',
|
|
184
|
-
code_challenge_method: 'S256',
|
|
185
|
-
expires_at: Date.now() + 600000,
|
|
186
|
-
};
|
|
187
|
-
const expiredAuthCode = {
|
|
188
|
-
...mockAuthCode,
|
|
189
|
-
expires_at: Date.now() - 1000,
|
|
190
|
-
};
|
|
191
|
-
describe('storeAuthCode', () => {
|
|
192
|
-
it('should store an authorization code', async () => {
|
|
193
|
-
authCodeRepository.save.mockResolvedValue(mockAuthCode);
|
|
194
|
-
await service.storeAuthCode(mockAuthCode);
|
|
195
|
-
expect(authCodeRepository.save).toHaveBeenCalledWith(mockAuthCode);
|
|
196
|
-
});
|
|
197
|
-
it('should handle database errors', async () => {
|
|
198
|
-
const error = new Error('Database error');
|
|
199
|
-
authCodeRepository.save.mockRejectedValue(error);
|
|
200
|
-
await expect(service.storeAuthCode(mockAuthCode)).rejects.toThrow('Database error');
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
describe('getAuthCode', () => {
|
|
204
|
-
it('should return authorization code when found and not expired', async () => {
|
|
205
|
-
authCodeRepository.findOne.mockResolvedValue(mockAuthCode);
|
|
206
|
-
const result = await service.getAuthCode('test-auth-code');
|
|
207
|
-
expect(authCodeRepository.findOne).toHaveBeenCalledWith({
|
|
208
|
-
where: { code: 'test-auth-code' },
|
|
209
|
-
});
|
|
210
|
-
expect(result).toEqual(mockAuthCode);
|
|
211
|
-
});
|
|
212
|
-
it('should return undefined and delete expired authorization code', async () => {
|
|
213
|
-
authCodeRepository.findOne.mockResolvedValue(expiredAuthCode);
|
|
214
|
-
authCodeRepository.delete.mockResolvedValue({
|
|
215
|
-
raw: {},
|
|
216
|
-
affected: 1,
|
|
217
|
-
});
|
|
218
|
-
const result = await service.getAuthCode('expired-code');
|
|
219
|
-
expect(authCodeRepository.findOne).toHaveBeenCalledWith({
|
|
220
|
-
where: { code: 'expired-code' },
|
|
221
|
-
});
|
|
222
|
-
expect(authCodeRepository.delete).toHaveBeenCalledWith({
|
|
223
|
-
code: 'expired-code',
|
|
224
|
-
});
|
|
225
|
-
expect(result).toBeUndefined();
|
|
226
|
-
});
|
|
227
|
-
it('should return undefined when authorization code not found', async () => {
|
|
228
|
-
authCodeRepository.findOne.mockResolvedValue(null);
|
|
229
|
-
const result = await service.getAuthCode('non-existent-code');
|
|
230
|
-
expect(result).toBeUndefined();
|
|
231
|
-
});
|
|
232
|
-
it('should handle database errors', async () => {
|
|
233
|
-
const error = new Error('Database error');
|
|
234
|
-
authCodeRepository.findOne.mockRejectedValue(error);
|
|
235
|
-
await expect(service.getAuthCode('test-auth-code')).rejects.toThrow('Database error');
|
|
236
|
-
});
|
|
237
|
-
});
|
|
238
|
-
describe('removeAuthCode', () => {
|
|
239
|
-
it('should remove an authorization code', async () => {
|
|
240
|
-
authCodeRepository.delete.mockResolvedValue({
|
|
241
|
-
raw: {},
|
|
242
|
-
affected: 1,
|
|
243
|
-
});
|
|
244
|
-
await service.removeAuthCode('test-auth-code');
|
|
245
|
-
expect(authCodeRepository.delete).toHaveBeenCalledWith({
|
|
246
|
-
code: 'test-auth-code',
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
it('should handle database errors', async () => {
|
|
250
|
-
const error = new Error('Database error');
|
|
251
|
-
authCodeRepository.delete.mockRejectedValue(error);
|
|
252
|
-
await expect(service.removeAuthCode('test-auth-code')).rejects.toThrow('Database error');
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
describe('OAuth Session Management', () => {
|
|
257
|
-
const mockSession = {
|
|
258
|
-
sessionId: 'session-123',
|
|
259
|
-
state: 'test-state',
|
|
260
|
-
clientId: 'client-123',
|
|
261
|
-
redirectUri: 'http://localhost:3000/callback',
|
|
262
|
-
codeChallenge: 'test-challenge',
|
|
263
|
-
codeChallengeMethod: 'S256',
|
|
264
|
-
oauthState: 'oauth-state-123',
|
|
265
|
-
resource: 'test-resource',
|
|
266
|
-
expiresAt: Date.now() + 3600000,
|
|
267
|
-
};
|
|
268
|
-
const expiredSession = {
|
|
269
|
-
...mockSession,
|
|
270
|
-
sessionId: 'expired-session',
|
|
271
|
-
expiresAt: Date.now() - 1000,
|
|
272
|
-
};
|
|
273
|
-
describe('storeOAuthSession', () => {
|
|
274
|
-
it('should store an OAuth session', async () => {
|
|
275
|
-
const expectedEntity = { ...mockSession, sessionId: 'session-123' };
|
|
276
|
-
sessionRepository.save.mockResolvedValue(expectedEntity);
|
|
277
|
-
await service.storeOAuthSession('session-123', mockSession);
|
|
278
|
-
expect(sessionRepository.save).toHaveBeenCalledWith(expectedEntity);
|
|
279
|
-
});
|
|
280
|
-
it('should handle database errors', async () => {
|
|
281
|
-
const error = new Error('Database error');
|
|
282
|
-
sessionRepository.save.mockRejectedValue(error);
|
|
283
|
-
await expect(service.storeOAuthSession('session-123', mockSession)).rejects.toThrow('Database error');
|
|
284
|
-
});
|
|
285
|
-
});
|
|
286
|
-
describe('getOAuthSession', () => {
|
|
287
|
-
it('should return OAuth session when found and not expired', async () => {
|
|
288
|
-
sessionRepository.findOne.mockResolvedValue(mockSession);
|
|
289
|
-
const result = await service.getOAuthSession('session-123');
|
|
290
|
-
expect(sessionRepository.findOne).toHaveBeenCalledWith({
|
|
291
|
-
where: { sessionId: 'session-123' },
|
|
292
|
-
});
|
|
293
|
-
expect(result).toEqual(mockSession);
|
|
294
|
-
});
|
|
295
|
-
it('should return undefined and delete expired OAuth session', async () => {
|
|
296
|
-
sessionRepository.findOne.mockResolvedValue(expiredSession);
|
|
297
|
-
sessionRepository.delete.mockResolvedValue({
|
|
298
|
-
raw: {},
|
|
299
|
-
affected: 1,
|
|
300
|
-
});
|
|
301
|
-
const result = await service.getOAuthSession('expired-session');
|
|
302
|
-
expect(sessionRepository.findOne).toHaveBeenCalledWith({
|
|
303
|
-
where: { sessionId: 'expired-session' },
|
|
304
|
-
});
|
|
305
|
-
expect(sessionRepository.delete).toHaveBeenCalledWith({
|
|
306
|
-
sessionId: 'expired-session',
|
|
307
|
-
});
|
|
308
|
-
expect(result).toBeUndefined();
|
|
309
|
-
});
|
|
310
|
-
it('should return undefined when OAuth session not found', async () => {
|
|
311
|
-
sessionRepository.findOne.mockResolvedValue(null);
|
|
312
|
-
const result = await service.getOAuthSession('non-existent-session');
|
|
313
|
-
expect(result).toBeUndefined();
|
|
314
|
-
});
|
|
315
|
-
it('should handle database errors', async () => {
|
|
316
|
-
const error = new Error('Database error');
|
|
317
|
-
sessionRepository.findOne.mockRejectedValue(error);
|
|
318
|
-
await expect(service.getOAuthSession('session-123')).rejects.toThrow('Database error');
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
describe('removeOAuthSession', () => {
|
|
322
|
-
it('should remove an OAuth session', async () => {
|
|
323
|
-
sessionRepository.delete.mockResolvedValue({
|
|
324
|
-
raw: {},
|
|
325
|
-
affected: 1,
|
|
326
|
-
});
|
|
327
|
-
await service.removeOAuthSession('session-123');
|
|
328
|
-
expect(sessionRepository.delete).toHaveBeenCalledWith({
|
|
329
|
-
sessionId: 'session-123',
|
|
330
|
-
});
|
|
331
|
-
});
|
|
332
|
-
it('should handle database errors', async () => {
|
|
333
|
-
const error = new Error('Database error');
|
|
334
|
-
sessionRepository.delete.mockRejectedValue(error);
|
|
335
|
-
await expect(service.removeOAuthSession('session-123')).rejects.toThrow('Database error');
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
//# sourceMappingURL=typeorm-store.service.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typeorm-store.service.spec.js","sourceRoot":"","sources":["../../../../src/authz/stores/typeorm/typeorm-store.service.spec.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/unbound-method */\nimport { Test, TestingModule } from '@nestjs/testing';\nimport { getRepositoryToken } from '@nestjs/typeorm';\nimport { Repository, DeleteResult } from 'typeorm';\nimport { TypeOrmStore } from './typeorm-store.service';\nimport {\n OAuthClientEntity,\n AuthorizationCodeEntity,\n OAuthSessionEntity,\n OAuthUserProfileEntity,\n} from './entities';\nimport { OAuthClient, AuthorizationCode } from '../oauth-store.interface';\nimport { OAuthSession } from '../../providers/oauth-provider.interface';\nimport { OAUTH_TYPEORM_CONNECTION_NAME } from './constants';\n\ndescribe('TypeOrmStore', () => {\n let service: TypeOrmStore;\n let clientRepository: jest.Mocked<Repository<OAuthClientEntity>>;\n let authCodeRepository: jest.Mocked<Repository<AuthorizationCodeEntity>>;\n let sessionRepository: jest.Mocked<Repository<OAuthSessionEntity>>;\n\n beforeEach(async () => {\n // Create mocked repositories\n const mockClientRepository = {\n save: jest.fn(),\n findOne: jest.fn(),\n delete: jest.fn(),\n };\n\n const mockAuthCodeRepository = {\n save: jest.fn(),\n findOne: jest.fn(),\n delete: jest.fn(),\n };\n\n const mockSessionRepository = {\n save: jest.fn(),\n findOne: jest.fn(),\n delete: jest.fn(),\n };\n\n const mockUserProfileRepository = {\n save: jest.fn(),\n findOne: jest.fn(),\n delete: jest.fn(),\n };\n\n const module: TestingModule = await Test.createTestingModule({\n providers: [\n TypeOrmStore,\n {\n provide: getRepositoryToken(\n OAuthClientEntity,\n OAUTH_TYPEORM_CONNECTION_NAME,\n ),\n useValue: mockClientRepository,\n },\n {\n provide: getRepositoryToken(\n AuthorizationCodeEntity,\n OAUTH_TYPEORM_CONNECTION_NAME,\n ),\n useValue: mockAuthCodeRepository,\n },\n {\n provide: getRepositoryToken(\n OAuthSessionEntity,\n OAUTH_TYPEORM_CONNECTION_NAME,\n ),\n useValue: mockSessionRepository,\n },\n {\n provide: getRepositoryToken(\n OAuthUserProfileEntity,\n OAUTH_TYPEORM_CONNECTION_NAME,\n ),\n useValue: mockUserProfileRepository,\n },\n ],\n }).compile();\n\n service = module.get<TypeOrmStore>(TypeOrmStore);\n clientRepository = module.get(\n getRepositoryToken(OAuthClientEntity, OAUTH_TYPEORM_CONNECTION_NAME),\n );\n authCodeRepository = module.get(\n getRepositoryToken(\n AuthorizationCodeEntity,\n OAUTH_TYPEORM_CONNECTION_NAME,\n ),\n );\n sessionRepository = module.get(\n getRepositoryToken(OAuthSessionEntity, OAUTH_TYPEORM_CONNECTION_NAME),\n );\n // Note: userProfileRepository is not directly used in tests below; it's provided for completeness\n });\n\n afterEach(() => {\n jest.clearAllMocks();\n });\n\n it('should be defined', () => {\n expect(service).toBeDefined();\n });\n\n describe('generateClientId', () => {\n const mockClient: OAuthClient = {\n client_id: '',\n client_name: 'Test Client',\n client_description: 'A test OAuth client',\n logo_uri: 'https://example.com/logo.png',\n client_uri: 'https://example.com',\n developer_name: 'Test Developer',\n developer_email: 'test@example.com',\n redirect_uris: ['http://localhost:3000/callback'],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'none',\n created_at: new Date(),\n updated_at: new Date(),\n };\n\n it('should generate client IDs with correct format', () => {\n const clientId = service.generateClientId(mockClient);\n\n // Should match pattern: normalizedname_8hexchars\n expect(clientId).toMatch(/^[a-z0-9]+_[a-f0-9]{8}$/);\n });\n\n it('should include normalized client name in the generated ID', () => {\n const clientWithSpecialChars = {\n ...mockClient,\n client_name: 'Test Client!@#',\n };\n\n const clientId = service.generateClientId(clientWithSpecialChars);\n expect(clientId).toMatch(/^testclient_[a-f0-9]{8}$/);\n });\n\n it('should generate different IDs for different clients', () => {\n const client1 = { ...mockClient, client_name: 'Client One' };\n const client2 = { ...mockClient, client_name: 'Client Two' };\n\n const id1 = service.generateClientId(client1);\n const id2 = service.generateClientId(client2);\n\n expect(id1).not.toBe(id2);\n });\n\n it('should generate different IDs on each call (non-deterministic)', () => {\n const id1 = service.generateClientId(mockClient);\n const id2 = service.generateClientId(mockClient);\n\n // TypeORM store uses random bytes, so IDs should be different\n expect(id1).not.toBe(id2);\n });\n });\n\n describe('Client Management', () => {\n const mockClient: OAuthClient = {\n client_id: 'test-client-id',\n client_name: 'Test Client',\n client_description: 'A test OAuth client',\n logo_uri: 'https://example.com/logo.png',\n client_uri: 'https://example.com',\n developer_name: 'Test Developer',\n developer_email: 'test@example.com',\n redirect_uris: ['http://localhost:3000/callback'],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'none',\n created_at: new Date(),\n updated_at: new Date(),\n };\n\n describe('storeClient', () => {\n it('should store a client and return the saved result', async () => {\n clientRepository.save.mockResolvedValue(\n mockClient as OAuthClientEntity,\n );\n\n const result = await service.storeClient(mockClient);\n\n expect(clientRepository.save).toHaveBeenCalledWith(mockClient);\n expect(result).toEqual(mockClient);\n });\n\n it('should handle database errors', async () => {\n const error = new Error('Database error');\n clientRepository.save.mockRejectedValue(error);\n\n await expect(service.storeClient(mockClient)).rejects.toThrow(\n 'Database error',\n );\n });\n });\n\n describe('getClient', () => {\n it('should return client when found', async () => {\n clientRepository.findOne.mockResolvedValue(\n mockClient as OAuthClientEntity,\n );\n\n const result = await service.getClient('test-client-id');\n\n expect(clientRepository.findOne).toHaveBeenCalledWith({\n where: { client_id: 'test-client-id' },\n });\n expect(result).toEqual(mockClient);\n });\n\n it('should return undefined when client not found', async () => {\n clientRepository.findOne.mockResolvedValue(null);\n\n const result = await service.getClient('non-existent-id');\n\n expect(result).toBeUndefined();\n });\n\n it('should handle database errors', async () => {\n const error = new Error('Database error');\n clientRepository.findOne.mockRejectedValue(error);\n\n await expect(service.getClient('test-client-id')).rejects.toThrow(\n 'Database error',\n );\n });\n });\n\n describe('findClient', () => {\n it('should find client by name when found', async () => {\n clientRepository.findOne.mockResolvedValue(\n mockClient as OAuthClientEntity,\n );\n\n const result = await service.findClient('Test Client');\n\n expect(clientRepository.findOne).toHaveBeenCalledWith({\n where: { client_name: 'Test Client' },\n });\n expect(result).toEqual(mockClient);\n });\n\n it('should return undefined when client name not found', async () => {\n clientRepository.findOne.mockResolvedValue(null);\n\n const result = await service.findClient('Non-existent Client');\n\n expect(result).toBeUndefined();\n });\n\n it('should handle database errors', async () => {\n const error = new Error('Database error');\n clientRepository.findOne.mockRejectedValue(error);\n\n await expect(service.findClient('Test Client')).rejects.toThrow(\n 'Database error',\n );\n });\n });\n });\n\n describe('Authorization Code Management', () => {\n const mockAuthCode: AuthorizationCode = {\n code: 'test-auth-code',\n user_id: 'user-123',\n client_id: 'client-123',\n redirect_uri: 'http://localhost:3000/callback',\n code_challenge: 'test-challenge',\n code_challenge_method: 'S256',\n expires_at: Date.now() + 600000, // 10 minutes from now\n };\n\n const expiredAuthCode: AuthorizationCode = {\n ...mockAuthCode,\n expires_at: Date.now() - 1000, // 1 second ago\n };\n\n describe('storeAuthCode', () => {\n it('should store an authorization code', async () => {\n authCodeRepository.save.mockResolvedValue(\n mockAuthCode as AuthorizationCodeEntity,\n );\n\n await service.storeAuthCode(mockAuthCode);\n\n expect(authCodeRepository.save).toHaveBeenCalledWith(mockAuthCode);\n });\n\n it('should handle database errors', async () => {\n const error = new Error('Database error');\n authCodeRepository.save.mockRejectedValue(error);\n\n await expect(service.storeAuthCode(mockAuthCode)).rejects.toThrow(\n 'Database error',\n );\n });\n });\n\n describe('getAuthCode', () => {\n it('should return authorization code when found and not expired', async () => {\n authCodeRepository.findOne.mockResolvedValue(\n mockAuthCode as AuthorizationCodeEntity,\n );\n\n const result = await service.getAuthCode('test-auth-code');\n\n expect(authCodeRepository.findOne).toHaveBeenCalledWith({\n where: { code: 'test-auth-code' },\n });\n expect(result).toEqual(mockAuthCode);\n });\n\n it('should return undefined and delete expired authorization code', async () => {\n authCodeRepository.findOne.mockResolvedValue(\n expiredAuthCode as AuthorizationCodeEntity,\n );\n authCodeRepository.delete.mockResolvedValue({\n raw: {},\n affected: 1,\n } as DeleteResult);\n\n const result = await service.getAuthCode('expired-code');\n\n expect(authCodeRepository.findOne).toHaveBeenCalledWith({\n where: { code: 'expired-code' },\n });\n expect(authCodeRepository.delete).toHaveBeenCalledWith({\n code: 'expired-code',\n });\n expect(result).toBeUndefined();\n });\n\n it('should return undefined when authorization code not found', async () => {\n authCodeRepository.findOne.mockResolvedValue(null);\n\n const result = await service.getAuthCode('non-existent-code');\n\n expect(result).toBeUndefined();\n });\n\n it('should handle database errors', async () => {\n const error = new Error('Database error');\n authCodeRepository.findOne.mockRejectedValue(error);\n\n await expect(service.getAuthCode('test-auth-code')).rejects.toThrow(\n 'Database error',\n );\n });\n });\n\n describe('removeAuthCode', () => {\n it('should remove an authorization code', async () => {\n authCodeRepository.delete.mockResolvedValue({\n raw: {},\n affected: 1,\n } as DeleteResult);\n\n await service.removeAuthCode('test-auth-code');\n\n expect(authCodeRepository.delete).toHaveBeenCalledWith({\n code: 'test-auth-code',\n });\n });\n\n it('should handle database errors', async () => {\n const error = new Error('Database error');\n authCodeRepository.delete.mockRejectedValue(error);\n\n await expect(service.removeAuthCode('test-auth-code')).rejects.toThrow(\n 'Database error',\n );\n });\n });\n });\n\n describe('OAuth Session Management', () => {\n const mockSession: OAuthSession = {\n sessionId: 'session-123',\n state: 'test-state',\n clientId: 'client-123',\n redirectUri: 'http://localhost:3000/callback',\n codeChallenge: 'test-challenge',\n codeChallengeMethod: 'S256',\n oauthState: 'oauth-state-123',\n resource: 'test-resource',\n expiresAt: Date.now() + 3600000, // 1 hour from now\n };\n\n const expiredSession: OAuthSession = {\n ...mockSession,\n sessionId: 'expired-session',\n expiresAt: Date.now() - 1000, // 1 second ago\n };\n\n describe('storeOAuthSession', () => {\n it('should store an OAuth session', async () => {\n const expectedEntity = { ...mockSession, sessionId: 'session-123' };\n sessionRepository.save.mockResolvedValue(\n expectedEntity as OAuthSessionEntity,\n );\n\n await service.storeOAuthSession('session-123', mockSession);\n\n expect(sessionRepository.save).toHaveBeenCalledWith(expectedEntity);\n });\n\n it('should handle database errors', async () => {\n const error = new Error('Database error');\n sessionRepository.save.mockRejectedValue(error);\n\n await expect(\n service.storeOAuthSession('session-123', mockSession),\n ).rejects.toThrow('Database error');\n });\n });\n\n describe('getOAuthSession', () => {\n it('should return OAuth session when found and not expired', async () => {\n sessionRepository.findOne.mockResolvedValue(\n mockSession as OAuthSessionEntity,\n );\n\n const result = await service.getOAuthSession('session-123');\n\n expect(sessionRepository.findOne).toHaveBeenCalledWith({\n where: { sessionId: 'session-123' },\n });\n expect(result).toEqual(mockSession);\n });\n\n it('should return undefined and delete expired OAuth session', async () => {\n sessionRepository.findOne.mockResolvedValue(\n expiredSession as OAuthSessionEntity,\n );\n sessionRepository.delete.mockResolvedValue({\n raw: {},\n affected: 1,\n } as DeleteResult);\n\n const result = await service.getOAuthSession('expired-session');\n\n expect(sessionRepository.findOne).toHaveBeenCalledWith({\n where: { sessionId: 'expired-session' },\n });\n expect(sessionRepository.delete).toHaveBeenCalledWith({\n sessionId: 'expired-session',\n });\n expect(result).toBeUndefined();\n });\n\n it('should return undefined when OAuth session not found', async () => {\n sessionRepository.findOne.mockResolvedValue(null);\n\n const result = await service.getOAuthSession('non-existent-session');\n\n expect(result).toBeUndefined();\n });\n\n it('should handle database errors', async () => {\n const error = new Error('Database error');\n sessionRepository.findOne.mockRejectedValue(error);\n\n await expect(service.getOAuthSession('session-123')).rejects.toThrow(\n 'Database error',\n );\n });\n });\n\n describe('removeOAuthSession', () => {\n it('should remove an OAuth session', async () => {\n sessionRepository.delete.mockResolvedValue({\n raw: {},\n affected: 1,\n } as DeleteResult);\n\n await service.removeOAuthSession('session-123');\n\n expect(sessionRepository.delete).toHaveBeenCalledWith({\n sessionId: 'session-123',\n });\n });\n\n it('should handle database errors', async () => {\n const error = new Error('Database error');\n sessionRepository.delete.mockRejectedValue(error);\n\n await expect(service.removeOAuthSession('session-123')).rejects.toThrow(\n 'Database error',\n );\n });\n });\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-registry.service.d.ts","sourceRoot":"","sources":["../../../src/mcp/services/mcp-registry.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-registry.service.js","sourceRoot":"","sources":["../../../src/mcp/services/mcp-registry.service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Injectable,\n InjectionToken,\n Logger,\n OnApplicationBootstrap,\n Inject,\n Optional,\n} from '@nestjs/common';\nimport {\n DiscoveryService,\n MetadataScanner,\n ModulesContainer,\n} from '@nestjs/core';\nimport {\n MCP_PROMPT_METADATA_KEY,\n MCP_RESOURCE_METADATA_KEY,\n MCP_RESOURCE_TEMPLATE_METADATA_KEY,\n MCP_TOOL_METADATA_KEY,\n MCP_PUBLIC_METADATA_KEY,\n MCP_SCOPES_METADATA_KEY,\n MCP_ROLES_METADATA_KEY,\n MCP_GUARDS_METADATA_KEY,\n ToolMetadata,\n} from '../decorators';\nimport { ResourceMetadata } from '../decorators/resource.decorator';\nimport { match } from 'path-to-regexp';\nimport { PromptMetadata } from '../decorators/prompt.decorator';\nimport { Module } from '@nestjs/core/injector/module';\nimport { ResourceTemplateMetadata } from '../decorators/resource-template.decorator';\nimport type { McpOptions } from '../interfaces';\nimport { createMcpLogger } from '../utils/mcp-logger.factory';\nimport {\n MCP_FEATURE_REGISTRATION,\n McpFeatureRegistration,\n} from '../constants/feature-registration.constants';\n\n/**\n * Interface representing a discovered tool\n */\nexport type DiscoveredTool<T extends object> = {\n type: 'tool' | 'resource' | 'resource-template' | 'prompt';\n metadata: T;\n providerClass: InjectionToken;\n methodName: string;\n};\n\nexport type InjectionTokenWithName = InjectionToken & { name: string };\n\n/**\n * Singleton service that discovers and registers tools during application bootstrap\n */\n@Injectable()\nexport class McpRegistryService implements OnApplicationBootstrap {\n private readonly logger: Logger;\n private discoveredToolsByMcpModuleId: Map<string, DiscoveredTool<any>[]> =\n new Map();\n\n constructor(\n private readonly discovery: DiscoveryService,\n private readonly metadataScanner: MetadataScanner,\n private readonly modulesContainer: ModulesContainer,\n @Optional() @Inject('MCP_OPTIONS') private readonly options?: McpOptions,\n ) {\n this.logger = createMcpLogger(McpRegistryService.name, this.options);\n }\n\n onApplicationBootstrap() {\n this.discoverTools();\n }\n\n /**\n * Finds all modules that import the McpModule and scans only the root module providers and controllers.\n * This prevents unintentionally exposing tools from imported dependencies.\n */\n private discoverTools() {\n // First, build a map of server names to module IDs\n const serverNameToModuleId = this.buildServerNameToModuleIdMap();\n\n // Then, collect feature registrations\n const featureRegistrations = this.collectFeatureRegistrations();\n\n const getImportedMcpModules = (module: Module) =>\n Array.from(module.imports).filter(\n (m) =>\n (m.instance as any).__isMcpModule &&\n !(m.instance as any).__isMcpFeatureModule,\n );\n\n const pairs = Array.from(this.modulesContainer.values())\n .map((module): [Module, Module[]] => [\n module,\n getImportedMcpModules(module),\n ])\n .filter(([, importedMcpModules]) => importedMcpModules.length > 0);\n\n for (const [rootModule, mcpModules] of pairs) {\n this.logger.debug(\n `Discovering tools, resources, resource templates, and prompts for module: ${rootModule.name}`,\n );\n\n for (const mcpModule of mcpModules) {\n const mcpModuleId =\n mcpModule.getProviderByKey<string>('MCP_MODULE_ID')?.instance;\n\n this.discoverToolsForModuleSubtree(mcpModuleId, [rootModule]);\n }\n }\n\n // Process feature registrations\n this.processFeatureRegistrations(\n featureRegistrations,\n serverNameToModuleId,\n );\n }\n\n /**\n * Builds a map from server names to their module IDs.\n */\n private buildServerNameToModuleIdMap(): Map<string, string> {\n const map = new Map<string, string>();\n\n for (const module of this.modulesContainer.values()) {\n if ((module.instance as any)?.__isMcpModule) {\n const moduleId =\n module.getProviderByKey<string>('MCP_MODULE_ID')?.instance;\n const options =\n module.getProviderByKey<McpOptions>('MCP_OPTIONS')?.instance;\n\n if (moduleId && options?.name) {\n map.set(options.name, moduleId);\n }\n }\n }\n\n return map;\n }\n\n /**\n * Collects all feature registrations from modules that import McpModule.forFeature().\n */\n private collectFeatureRegistrations(): Array<{\n registration: McpFeatureRegistration;\n sourceModule: Module;\n }> {\n const registrations: Array<{\n registration: McpFeatureRegistration;\n sourceModule: Module;\n }> = [];\n\n for (const module of this.modulesContainer.values()) {\n // Check for feature registration providers (tokens start with MCP_FEATURE_REGISTRATION)\n for (const [key, provider] of module.providers) {\n if (\n typeof key === 'string' &&\n key.startsWith(MCP_FEATURE_REGISTRATION) &&\n provider?.instance\n ) {\n registrations.push({\n registration: provider.instance as McpFeatureRegistration,\n sourceModule: module,\n });\n }\n }\n }\n\n return registrations;\n }\n\n /**\n * Processes feature registrations and discovers tools from their providers.\n */\n private processFeatureRegistrations(\n registrations: Array<{\n registration: McpFeatureRegistration;\n sourceModule: Module;\n }>,\n serverNameToModuleId: Map<string, string>,\n ) {\n for (const { registration, sourceModule } of registrations) {\n const mcpModuleId = serverNameToModuleId.get(registration.serverName);\n\n if (!mcpModuleId) {\n this.logger.warn(\n `McpModule.forFeature: No MCP server found with name '${registration.serverName}'. ` +\n `Make sure McpModule.forRoot({ name: '${registration.serverName}', ... }) is imported.`,\n );\n continue;\n }\n\n this.logger.debug(\n `Processing forFeature registration for server '${registration.serverName}' ` +\n `with ${registration.providerTokens.length} provider(s)`,\n );\n\n // Find the module that actually provides these providers\n // The sourceModule imports the forFeature module, so we look at its parent\n const parentModule = this.findModuleWithProviders(\n registration.providerTokens,\n sourceModule,\n );\n\n if (parentModule) {\n this.discoverToolsFromProviders(\n mcpModuleId,\n registration.providerTokens,\n parentModule,\n );\n }\n }\n }\n\n /**\n * Finds a module that contains the specified providers.\n * Searches the source module and its parent modules.\n */\n private findModuleWithProviders(\n providerTokens: InjectionToken[],\n sourceModule: Module,\n ): Module | undefined {\n // First check if the source module's parent has the providers\n for (const module of this.modulesContainer.values()) {\n if (module.imports.has(sourceModule)) {\n // This module imports our source module, check if it has the providers\n const hasAllProviders = providerTokens.every((token) =>\n module.getProviderByKey(token),\n );\n if (hasAllProviders) {\n return module;\n }\n }\n }\n\n // Fallback: search all modules\n for (const module of this.modulesContainer.values()) {\n const hasAllProviders = providerTokens.every((token) =>\n module.getProviderByKey(token),\n );\n if (hasAllProviders) {\n return module;\n }\n }\n\n return undefined;\n }\n\n /**\n * Discovers tools from specific providers within a module.\n */\n private discoverToolsFromProviders(\n mcpModuleId: string,\n providerTokens: InjectionToken[],\n module: Module,\n ) {\n for (const token of providerTokens) {\n const provider = module.getProviderByKey(token);\n if (!provider?.instance || typeof provider.instance !== 'object') {\n this.logger.warn(\n `McpModule.forFeature: Provider '${String(token)}' not found or not instantiated`,\n );\n continue;\n }\n\n const instance = provider.instance as object;\n this.metadataScanner.getAllMethodNames(instance).forEach((methodName) => {\n const methodRef = instance[methodName] as object;\n const methodMetaKeys = Reflect.getOwnMetadataKeys(methodRef);\n\n if (methodMetaKeys.includes(MCP_TOOL_METADATA_KEY)) {\n this.addDiscoveryTool(\n mcpModuleId,\n methodRef,\n token as InjectionTokenWithName,\n methodName,\n );\n }\n\n if (methodMetaKeys.includes(MCP_RESOURCE_METADATA_KEY)) {\n this.addDiscoveryResource(\n mcpModuleId,\n methodRef,\n token as InjectionTokenWithName,\n methodName,\n );\n }\n\n if (methodMetaKeys.includes(MCP_RESOURCE_TEMPLATE_METADATA_KEY)) {\n this.addDiscoveryResourceTemplate(\n mcpModuleId,\n methodRef,\n token as InjectionTokenWithName,\n methodName,\n );\n }\n\n if (methodMetaKeys.includes(MCP_PROMPT_METADATA_KEY)) {\n this.addDiscoveryPrompt(\n mcpModuleId,\n methodRef,\n token as InjectionTokenWithName,\n methodName,\n );\n }\n });\n }\n }\n\n /**\n * Scans all providers and controllers for @Tool decorators\n */\n private discoverToolsForModuleSubtree(\n mcpModuleId: string,\n modules: Module[],\n ) {\n const providers = this.discovery.getProviders(undefined, modules);\n const controllers = this.discovery.getControllers(undefined, modules);\n const allInstances = [...providers, ...controllers]\n .filter(\n (wrapper) =>\n wrapper.instance &&\n typeof wrapper.instance === 'object' &&\n wrapper.instance !== null,\n )\n .map((wrapper) => ({\n instance: wrapper.instance as object,\n token: wrapper.token,\n }));\n\n allInstances.forEach(({ instance, token }) => {\n this.metadataScanner.getAllMethodNames(instance).forEach((methodName) => {\n const methodRef = instance[methodName] as object;\n const methodMetaKeys = Reflect.getOwnMetadataKeys(methodRef);\n\n if (methodMetaKeys.includes(MCP_TOOL_METADATA_KEY)) {\n this.addDiscoveryTool(\n mcpModuleId,\n methodRef,\n token as InjectionTokenWithName,\n methodName,\n );\n }\n\n if (methodMetaKeys.includes(MCP_RESOURCE_METADATA_KEY)) {\n this.addDiscoveryResource(\n mcpModuleId,\n methodRef,\n token as InjectionTokenWithName,\n methodName,\n );\n }\n\n if (methodMetaKeys.includes(MCP_RESOURCE_TEMPLATE_METADATA_KEY)) {\n this.addDiscoveryResourceTemplate(\n mcpModuleId,\n methodRef,\n token as InjectionTokenWithName,\n methodName,\n );\n }\n\n if (methodMetaKeys.includes(MCP_PROMPT_METADATA_KEY)) {\n this.addDiscoveryPrompt(\n mcpModuleId,\n methodRef,\n token as InjectionTokenWithName,\n methodName,\n );\n }\n });\n });\n }\n\n /**\n * Adds a discovered tool to the registry\n */\n private addDiscovery<T>(\n type: 'tool' | 'resource' | 'resource-template' | 'prompt',\n metadataKey: string,\n mcpModuleId: string,\n methodRef: object,\n token: InjectionTokenWithName,\n methodName: string,\n ) {\n const metadata: T = Reflect.getMetadata(metadataKey, methodRef);\n\n if (!metadata['name']) {\n metadata['name'] = methodName;\n }\n\n if (!this.discoveredToolsByMcpModuleId.has(mcpModuleId)) {\n this.discoveredToolsByMcpModuleId.set(mcpModuleId, []);\n }\n\n this.discoveredToolsByMcpModuleId.get(mcpModuleId)?.push({\n type,\n metadata,\n providerClass: token,\n methodName,\n });\n }\n\n private addDiscoveryPrompt(\n mcpModuleId: string,\n methodRef: object,\n token: InjectionTokenWithName,\n methodName: string,\n ) {\n this.logger.debug(\n `Prompt discovered: ${token.name}.${methodName} in module: ${mcpModuleId}`,\n );\n this.addDiscovery<PromptMetadata>(\n 'prompt',\n MCP_PROMPT_METADATA_KEY,\n mcpModuleId,\n methodRef,\n token,\n methodName,\n );\n }\n\n private addDiscoveryTool(\n mcpModuleId: string,\n methodRef: object,\n token: InjectionTokenWithName,\n methodName: string,\n ) {\n this.logger.debug(\n `Tool discovered: ${token.name}.${methodName} in module: ${mcpModuleId}`,\n );\n\n // Collect security metadata from decorators\n const isPublic = Reflect.getMetadata(MCP_PUBLIC_METADATA_KEY, methodRef);\n const requiredScopes = Reflect.getMetadata(\n MCP_SCOPES_METADATA_KEY,\n methodRef,\n );\n const requiredRoles = Reflect.getMetadata(\n MCP_ROLES_METADATA_KEY,\n methodRef,\n );\n const guards = Reflect.getMetadata(MCP_GUARDS_METADATA_KEY, methodRef);\n\n // Add tool with security metadata\n const baseMetadata: ToolMetadata = Reflect.getMetadata(\n MCP_TOOL_METADATA_KEY,\n methodRef,\n );\n\n if (!baseMetadata.name) {\n baseMetadata.name = methodName;\n }\n\n // Enrich with security metadata\n if (isPublic !== undefined) {\n baseMetadata.isPublic = isPublic;\n }\n if (requiredScopes) {\n baseMetadata.requiredScopes = requiredScopes;\n }\n if (requiredRoles) {\n baseMetadata.requiredRoles = requiredRoles;\n }\n if (guards) {\n baseMetadata.guards = guards;\n }\n\n if (!this.discoveredToolsByMcpModuleId.has(mcpModuleId)) {\n this.discoveredToolsByMcpModuleId.set(mcpModuleId, []);\n }\n\n this.discoveredToolsByMcpModuleId.get(mcpModuleId)?.push({\n type: 'tool',\n metadata: baseMetadata,\n providerClass: token,\n methodName,\n });\n }\n\n private addDiscoveryResource(\n mcpModuleId: string,\n methodRef: object,\n token: InjectionTokenWithName,\n methodName: string,\n ) {\n this.logger.debug(\n `Resource discovered: ${token.name}.${methodName} in module: ${mcpModuleId}`,\n );\n this.addDiscovery<ResourceMetadata>(\n 'resource',\n MCP_RESOURCE_METADATA_KEY,\n mcpModuleId,\n methodRef,\n token,\n methodName,\n );\n }\n\n private addDiscoveryResourceTemplate(\n mcpModuleId: string,\n methodRef: object,\n token: InjectionTokenWithName,\n methodName: string,\n ) {\n this.logger.debug(\n `Resource Template discovered: ${token.name}.${methodName} in module: ${mcpModuleId}`,\n );\n this.addDiscovery<ResourceTemplateMetadata>(\n 'resource-template',\n MCP_RESOURCE_TEMPLATE_METADATA_KEY,\n mcpModuleId,\n methodRef,\n token,\n methodName,\n );\n }\n\n /**\n * Return all discovered MCP module IDs\n */\n getMcpModuleIds(): string[] {\n return Array.from(this.discoveredToolsByMcpModuleId.keys());\n }\n\n /**\n * Get all discovered tools\n */\n getTools(mcpModuleId: string): DiscoveredTool<ToolMetadata>[] {\n return (\n this.discoveredToolsByMcpModuleId\n .get(mcpModuleId)\n ?.filter((tool) => tool.type === 'tool') ?? []\n );\n }\n\n /**\n * Find a tool by name\n */\n findTool(\n mcpModuleId: string,\n name: string,\n ): DiscoveredTool<ToolMetadata> | undefined {\n return this.getTools(mcpModuleId).find(\n (tool) => tool.metadata.name === name,\n );\n }\n\n /**\n * Get all discovered resources\n */\n getResources(mcpModuleId: string): DiscoveredTool<ResourceMetadata>[] {\n return (\n this.discoveredToolsByMcpModuleId\n .get(mcpModuleId)\n ?.filter((tool) => tool.type === 'resource') ?? []\n );\n }\n\n /**\n * Find a resource by name\n */\n findResource(\n mcpModuleId: string,\n name: string,\n ): DiscoveredTool<ResourceMetadata> | undefined {\n return this.getResources(mcpModuleId).find(\n (tool) => tool.metadata.name === name,\n );\n }\n\n /**\n * Get all discovered resource templates\n */\n getResourceTemplates(\n mcpModuleId: string,\n ): DiscoveredTool<ResourceTemplateMetadata>[] {\n return (\n this.discoveredToolsByMcpModuleId\n .get(mcpModuleId)\n ?.filter((tool) => tool.type === 'resource-template') ?? []\n );\n }\n\n /**\n * Find a resource by name\n */\n findResourceTemplate(\n mcpModuleId: string,\n name: string,\n ): DiscoveredTool<ResourceTemplateMetadata> | undefined {\n return this.getResourceTemplates(mcpModuleId).find(\n (tool) => tool.metadata.name === name,\n );\n }\n\n /**\n * Get all discovered prompts\n */\n getPrompts(mcpModuleId: string): DiscoveredTool<PromptMetadata>[] {\n return (\n this.discoveredToolsByMcpModuleId\n .get(mcpModuleId)\n ?.filter((tool) => tool.type === 'prompt') ?? []\n );\n }\n\n /**\n * Find a prompt by name\n */\n findPrompt(\n mcpModuleId: string,\n name: string,\n ): DiscoveredTool<PromptMetadata> | undefined {\n return this.getPrompts(mcpModuleId).find(\n (tool) => tool.metadata.name === name,\n );\n }\n\n /**\n * Convert RFC 6570 URI template to path-to-regexp compatible format.\n * Handles both path parameters {param} and query parameters {?param} or {?param1,param2}\n */\n private convertTemplate(template: string): string {\n if (!template) return template;\n\n // Remove RFC 6570 query parameter syntax {?...} from the template\n // These will be handled separately via URL query string parsing\n const withoutQueryParams = template.replace(/\\{\\?[^}]+\\}/g, '');\n\n // Convert path parameters {param} to path-to-regexp format :param\n return withoutQueryParams.replace(/{(\\w+)}/g, ':$1');\n }\n\n /**\n * Extract query parameter names from an RFC 6570 URI template.\n * E.g., 'mcp://example{?foo,bar}' returns ['foo', 'bar']\n */\n private extractTemplateQueryParams(template: string): string[] {\n const queryParamMatch = template.match(/\\{\\?([^}]+)\\}/);\n if (!queryParamMatch) return [];\n return queryParamMatch[1].split(',').map((p) => p.trim());\n }\n\n /**\n * Parse query string from a URI and return as key-value pairs.\n */\n private parseQueryString(uri: string): Record<string, string> {\n const queryIndex = uri.indexOf('?');\n if (queryIndex === -1) return {};\n\n const queryString = uri.substring(queryIndex + 1);\n const params: Record<string, string> = {};\n\n for (const pair of queryString.split('&')) {\n const [key, value] = pair.split('=');\n if (key) {\n params[decodeURIComponent(key)] = value\n ? decodeURIComponent(value)\n : '';\n }\n }\n\n return params;\n }\n\n /**\n * Strip query string from a URI, returning only the path portion.\n */\n private stripQueryString(uri: string): string {\n const queryIndex = uri.indexOf('?');\n return queryIndex === -1 ? uri : uri.substring(0, queryIndex);\n }\n\n private convertUri(uri: string): string {\n if (uri.includes('://')) {\n return uri.split('://')[1];\n }\n\n return uri;\n }\n\n /**\n * Find a resource by uri\n * @returns An object containing the found resource and extracted parameters, or undefined if no resource is found\n */\n findResourceByUri(\n mcpModuleId: string,\n uri: string,\n ):\n | {\n resource: DiscoveredTool<ResourceMetadata>;\n params: Record<string, string>;\n }\n | undefined {\n const resources = this.getResources(mcpModuleId).map((tool) => ({\n name: tool.metadata.name,\n uri: tool.metadata.uri,\n }));\n\n const strippedInputUri = this.convertUri(uri);\n\n for (const t of resources) {\n if (!t.uri) continue;\n\n const rawTemplate = t.uri;\n const templatePath = this.convertTemplate(this.convertUri(rawTemplate));\n const matcher = match(templatePath, { decode: decodeURIComponent });\n const result = matcher(strippedInputUri);\n\n if (result) {\n const foundResource = this.findResource(mcpModuleId, t.name);\n if (!foundResource) continue;\n\n return {\n resource: foundResource,\n params: result.params as Record<string, string>,\n };\n }\n }\n\n return undefined;\n }\n\n /**\n * Find a resource template by uri\n * @returns An object containing the found resource template and extracted parameters, or undefined if no resource template is found\n */\n findResourceTemplateByUri(\n mcpModuleId: string,\n uri: string,\n ):\n | {\n resourceTemplate: DiscoveredTool<ResourceTemplateMetadata>;\n params: Record<string, string>;\n }\n | undefined {\n const resourceTemplates = this.getResourceTemplates(mcpModuleId).map(\n (tool) => ({\n name: tool.metadata.name,\n uriTemplate: tool.metadata.uriTemplate,\n }),\n );\n\n // Strip query string from input URI for path matching\n const strippedInputUri = this.stripQueryString(this.convertUri(uri));\n // Parse query parameters from input URI\n const inputQueryParams = this.parseQueryString(uri);\n\n for (const t of resourceTemplates) {\n if (!t.uriTemplate) continue;\n\n const rawTemplate = t.uriTemplate;\n // Convert template (removes {?...} query params and converts {param} to :param)\n const templatePath = this.convertTemplate(this.convertUri(rawTemplate));\n const matcher = match(templatePath, { decode: decodeURIComponent });\n const result = matcher(strippedInputUri);\n\n if (result) {\n const foundResourceTemplate = this.findResourceTemplate(\n mcpModuleId,\n t.name,\n );\n if (!foundResourceTemplate) continue;\n\n // Get path params from matching\n const pathParams = result.params as Record<string, string>;\n\n // Get expected query params from template and filter input query params\n const expectedQueryParams =\n this.extractTemplateQueryParams(rawTemplate);\n const queryParams: Record<string, string> = {};\n for (const paramName of expectedQueryParams) {\n if (inputQueryParams[paramName] !== undefined) {\n queryParams[paramName] = inputQueryParams[paramName];\n }\n }\n\n return {\n resourceTemplate: foundResourceTemplate,\n params: { ...pathParams, ...queryParams },\n };\n }\n }\n\n return undefined;\n }\n\n /**\n * Register a tool programmatically (for dynamic tools).\n * Use McpToolBuilder.registerTool() instead of calling this directly.\n *\n * @param mcpModuleId - The module ID to register the tool with\n * @param tool - The discovered tool object to register\n */\n registerDynamicTool(\n mcpModuleId: string,\n tool: DiscoveredTool<ToolMetadata>,\n ): void {\n if (!this.discoveredToolsByMcpModuleId.has(mcpModuleId)) {\n this.discoveredToolsByMcpModuleId.set(mcpModuleId, []);\n }\n\n this.logger.debug(\n `Dynamic tool registered: ${tool.metadata.name} in module: ${mcpModuleId}`,\n );\n\n this.discoveredToolsByMcpModuleId.get(mcpModuleId)?.push(tool);\n }\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-registry.service.spec.d.ts","sourceRoot":"","sources":["../../../src/mcp/services/mcp-registry.service.spec.ts"],"names":[],"mappings":""}
|