@carlonicora/nestjs-neo4jsonapi 1.110.3 → 1.112.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/dist/agents/graph/tools/describe-entity.tool.d.ts +1 -1
- package/dist/agents/graph/tools/describe-entity.tool.d.ts.map +1 -1
- package/dist/agents/graph/tools/describe-entity.tool.js +2 -1
- package/dist/agents/graph/tools/describe-entity.tool.js.map +1 -1
- package/dist/agents/graph/tools/read-entity.tool.d.ts +1 -1
- package/dist/agents/graph/tools/read-entity.tool.d.ts.map +1 -1
- package/dist/agents/graph/tools/read-entity.tool.js +2 -1
- package/dist/agents/graph/tools/read-entity.tool.js.map +1 -1
- package/dist/agents/graph/tools/resolve-entity.tool.d.ts +1 -1
- package/dist/agents/graph/tools/resolve-entity.tool.d.ts.map +1 -1
- package/dist/agents/graph/tools/resolve-entity.tool.js +2 -1
- package/dist/agents/graph/tools/resolve-entity.tool.js.map +1 -1
- package/dist/agents/graph/tools/search-entities.tool.d.ts +1 -1
- package/dist/agents/graph/tools/search-entities.tool.d.ts.map +1 -1
- package/dist/agents/graph/tools/search-entities.tool.js +2 -1
- package/dist/agents/graph/tools/search-entities.tool.js.map +1 -1
- package/dist/agents/graph/tools/traverse.tool.d.ts +1 -1
- package/dist/agents/graph/tools/traverse.tool.d.ts.map +1 -1
- package/dist/agents/graph/tools/traverse.tool.js +2 -1
- package/dist/agents/graph/tools/traverse.tool.js.map +1 -1
- package/dist/agents/operator/tools/search-documents.tool.d.ts +1 -1
- package/dist/agents/operator/tools/search-documents.tool.d.ts.map +1 -1
- package/dist/agents/operator/tools/search-documents.tool.js +2 -1
- package/dist/agents/operator/tools/search-documents.tool.js.map +1 -1
- package/dist/bootstrap/app.module.factory.d.ts.map +1 -1
- package/dist/bootstrap/app.module.factory.js +3 -0
- package/dist/bootstrap/app.module.factory.js.map +1 -1
- package/dist/bootstrap/bootstrap.options.d.ts +2 -0
- package/dist/bootstrap/bootstrap.options.d.ts.map +1 -1
- package/dist/config/base.config.d.ts.map +1 -1
- package/dist/config/base.config.js +15 -0
- package/dist/config/base.config.js.map +1 -1
- package/dist/config/interfaces/base.config.interface.d.ts +2 -0
- package/dist/config/interfaces/base.config.interface.d.ts.map +1 -1
- package/dist/config/interfaces/config.ai.interface.d.ts +29 -0
- package/dist/config/interfaces/config.ai.interface.d.ts.map +1 -1
- package/dist/config/interfaces/config.mcp.interface.d.ts +34 -0
- package/dist/config/interfaces/config.mcp.interface.d.ts.map +1 -0
- package/dist/config/interfaces/config.mcp.interface.js +3 -0
- package/dist/config/interfaces/config.mcp.interface.js.map +1 -0
- package/dist/config/interfaces/index.d.ts +1 -0
- package/dist/config/interfaces/index.d.ts.map +1 -1
- package/dist/config/interfaces/index.js +1 -0
- package/dist/config/interfaces/index.js.map +1 -1
- package/dist/core/llm/services/llm.service.d.ts +52 -0
- package/dist/core/llm/services/llm.service.d.ts.map +1 -1
- package/dist/core/llm/services/llm.service.js +163 -10
- package/dist/core/llm/services/llm.service.js.map +1 -1
- package/dist/core/llm/services/model.service.d.ts +2 -0
- package/dist/core/llm/services/model.service.d.ts.map +1 -1
- package/dist/core/llm/services/model.service.js +7 -0
- package/dist/core/llm/services/model.service.js.map +1 -1
- package/dist/foundations/oauth/constants/oauth.scopes.d.ts +2 -0
- package/dist/foundations/oauth/constants/oauth.scopes.d.ts.map +1 -1
- package/dist/foundations/oauth/constants/oauth.scopes.js +4 -0
- package/dist/foundations/oauth/constants/oauth.scopes.js.map +1 -1
- package/dist/foundations/oauth/controllers/index.d.ts +2 -0
- package/dist/foundations/oauth/controllers/index.d.ts.map +1 -1
- package/dist/foundations/oauth/controllers/index.js +2 -0
- package/dist/foundations/oauth/controllers/index.js.map +1 -1
- package/dist/foundations/oauth/controllers/oauth.discovery.controller.d.ts +46 -0
- package/dist/foundations/oauth/controllers/oauth.discovery.controller.d.ts.map +1 -0
- package/dist/foundations/oauth/controllers/oauth.discovery.controller.js +102 -0
- package/dist/foundations/oauth/controllers/oauth.discovery.controller.js.map +1 -0
- package/dist/foundations/oauth/controllers/oauth.registration.controller.d.ts +36 -0
- package/dist/foundations/oauth/controllers/oauth.registration.controller.d.ts.map +1 -0
- package/dist/foundations/oauth/controllers/oauth.registration.controller.js +81 -0
- package/dist/foundations/oauth/controllers/oauth.registration.controller.js.map +1 -0
- package/dist/foundations/oauth/dtos/index.d.ts +1 -0
- package/dist/foundations/oauth/dtos/index.d.ts.map +1 -1
- package/dist/foundations/oauth/dtos/index.js +1 -0
- package/dist/foundations/oauth/dtos/index.js.map +1 -1
- package/dist/foundations/oauth/dtos/oauth.register.dto.d.ts +14 -0
- package/dist/foundations/oauth/dtos/oauth.register.dto.d.ts.map +1 -0
- package/dist/foundations/oauth/dtos/oauth.register.dto.js +49 -0
- package/dist/foundations/oauth/dtos/oauth.register.dto.js.map +1 -0
- package/dist/foundations/oauth/index.d.ts +1 -0
- package/dist/foundations/oauth/index.d.ts.map +1 -1
- package/dist/foundations/oauth/index.js +3 -1
- package/dist/foundations/oauth/index.js.map +1 -1
- package/dist/foundations/oauth/oauth.module.d.ts +3 -1
- package/dist/foundations/oauth/oauth.module.d.ts.map +1 -1
- package/dist/foundations/oauth/oauth.module.js +12 -2
- package/dist/foundations/oauth/oauth.module.js.map +1 -1
- package/dist/foundations/oauth/repositories/oauth.repository.d.ts +2 -1
- package/dist/foundations/oauth/repositories/oauth.repository.d.ts.map +1 -1
- package/dist/foundations/oauth/repositories/oauth.repository.js +16 -34
- package/dist/foundations/oauth/repositories/oauth.repository.js.map +1 -1
- package/dist/foundations/oauth/services/oauth.client.service.d.ts +2 -1
- package/dist/foundations/oauth/services/oauth.client.service.d.ts.map +1 -1
- package/dist/foundations/oauth/services/oauth.client.service.js.map +1 -1
- package/dist/foundations/rbac/index.d.ts +4 -0
- package/dist/foundations/rbac/index.d.ts.map +1 -1
- package/dist/foundations/rbac/index.js +7 -1
- package/dist/foundations/rbac/index.js.map +1 -1
- package/dist/foundations/rbac/rbac-permission.module.d.ts +14 -0
- package/dist/foundations/rbac/rbac-permission.module.d.ts.map +1 -0
- package/dist/foundations/rbac/rbac-permission.module.js +33 -0
- package/dist/foundations/rbac/rbac-permission.module.js.map +1 -0
- package/dist/foundations/rbac/repositories/rbac-permission.repository.d.ts +31 -0
- package/dist/foundations/rbac/repositories/rbac-permission.repository.d.ts.map +1 -0
- package/dist/foundations/rbac/repositories/rbac-permission.repository.js +80 -0
- package/dist/foundations/rbac/repositories/rbac-permission.repository.js.map +1 -0
- package/dist/foundations/rbac/services/rbac-permission.service.d.ts +31 -0
- package/dist/foundations/rbac/services/rbac-permission.service.d.ts.map +1 -0
- package/dist/foundations/rbac/services/rbac-permission.service.js +41 -0
- package/dist/foundations/rbac/services/rbac-permission.service.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/controllers/mcp.controller.d.ts +34 -0
- package/dist/mcp/controllers/mcp.controller.d.ts.map +1 -0
- package/dist/mcp/controllers/mcp.controller.js +108 -0
- package/dist/mcp/controllers/mcp.controller.js.map +1 -0
- package/dist/mcp/filters/mcp.auth.filter.d.ts +21 -0
- package/dist/mcp/filters/mcp.auth.filter.d.ts.map +1 -0
- package/dist/mcp/filters/mcp.auth.filter.js +52 -0
- package/dist/mcp/filters/mcp.auth.filter.js.map +1 -0
- package/dist/mcp/index.d.ts +4 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/interfaces/mcp.tool.interface.d.ts +37 -0
- package/dist/mcp/interfaces/mcp.tool.interface.d.ts.map +1 -0
- package/dist/mcp/interfaces/mcp.tool.interface.js +6 -0
- package/dist/mcp/interfaces/mcp.tool.interface.js.map +1 -0
- package/dist/mcp/mcp.module.d.ts +23 -0
- package/dist/mcp/mcp.module.d.ts.map +1 -0
- package/dist/mcp/mcp.module.js +59 -0
- package/dist/mcp/mcp.module.js.map +1 -0
- package/dist/mcp/services/mcp.entity.write.service.d.ts +79 -0
- package/dist/mcp/services/mcp.entity.write.service.d.ts.map +1 -0
- package/dist/mcp/services/mcp.entity.write.service.js +270 -0
- package/dist/mcp/services/mcp.entity.write.service.js.map +1 -0
- package/dist/mcp/services/mcp.errors.d.ts +24 -0
- package/dist/mcp/services/mcp.errors.d.ts.map +1 -0
- package/dist/mcp/services/mcp.errors.js +50 -0
- package/dist/mcp/services/mcp.errors.js.map +1 -0
- package/dist/mcp/services/mcp.generic.tools.service.d.ts +26 -0
- package/dist/mcp/services/mcp.generic.tools.service.d.ts.map +1 -0
- package/dist/mcp/services/mcp.generic.tools.service.js +108 -0
- package/dist/mcp/services/mcp.generic.tools.service.js.map +1 -0
- package/dist/mcp/services/mcp.promoted.tools.factory.d.ts +58 -0
- package/dist/mcp/services/mcp.promoted.tools.factory.d.ts.map +1 -0
- package/dist/mcp/services/mcp.promoted.tools.factory.js +260 -0
- package/dist/mcp/services/mcp.promoted.tools.factory.js.map +1 -0
- package/dist/mcp/services/mcp.server.factory.d.ts +24 -0
- package/dist/mcp/services/mcp.server.factory.d.ts.map +1 -0
- package/dist/mcp/services/mcp.server.factory.js +60 -0
- package/dist/mcp/services/mcp.server.factory.js.map +1 -0
- package/dist/mcp/services/mcp.tool.registry.d.ts +21 -0
- package/dist/mcp/services/mcp.tool.registry.d.ts.map +1 -0
- package/dist/mcp/services/mcp.tool.registry.js +72 -0
- package/dist/mcp/services/mcp.tool.registry.js.map +1 -0
- package/package.json +17 -12
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac-permission.module.js","sourceRoot":"","sources":["../../../src/foundations/rbac/rbac-permission.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,0FAAqF;AACrF,gFAA2E;AAE3E;;;;;;;;;;GAUG;AAKI,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;CAAG,CAAA;AAAvB,oDAAoB;+BAApB,oBAAoB;IAJhC,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,qDAAwB,EAAE,+CAAqB,CAAC;QAC5D,OAAO,EAAE,CAAC,qDAAwB,EAAE,+CAAqB,CAAC;KAC3D,CAAC;GACW,oBAAoB,CAAG"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Neo4jService } from "../../../core/neo4j/services/neo4j.service";
|
|
2
|
+
import type { RbacAction } from "../services/rbac-permission.service";
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the effective per-module permission flags for a user. Mirrors the
|
|
5
|
+
* permission model used by the rest of the app (see AuthRepository and
|
|
6
|
+
* UserModulesRepository): a module is visible to the user iff its parent
|
|
7
|
+
* Feature is subscribed by the user's Company (or is a core Feature), and the
|
|
8
|
+
* effective permissions result from merging the Module's default
|
|
9
|
+
* `permissions` JSON with any role-level `HAS_PERMISSIONS` overrides.
|
|
10
|
+
*
|
|
11
|
+
* Used by RbacPermissionService to answer `can(userId, moduleId, action)`
|
|
12
|
+
* for the MCP layer.
|
|
13
|
+
*/
|
|
14
|
+
export declare class RbacPermissionRepository {
|
|
15
|
+
private readonly neo4j;
|
|
16
|
+
private readonly logger;
|
|
17
|
+
constructor(neo4j: Neo4jService);
|
|
18
|
+
/**
|
|
19
|
+
* Effective per-module permission flags for a user.
|
|
20
|
+
*
|
|
21
|
+
* The query reuses `featureModuleQuery` — identical to the permission
|
|
22
|
+
* resolution run at login by AuthRepository and by the chatbot's
|
|
23
|
+
* UserModulesRepository — so MCP permission checks are always in
|
|
24
|
+
* lock-step with the rest of the app. The resolved effective permissions
|
|
25
|
+
* are returned on a virtual module node as a JSON string on
|
|
26
|
+
* `properties.permissions`; we parse it and keep all four permission
|
|
27
|
+
* types (`read`, `create`, `update`, `delete`).
|
|
28
|
+
*/
|
|
29
|
+
findEffectivePermissionsForUser(userId: string): Promise<Map<string, Record<RbacAction, boolean>>>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=rbac-permission.repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac-permission.repository.d.ts","sourceRoot":"","sources":["../../../../src/foundations/rbac/repositories/rbac-permission.repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAC;AAE1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAOtE;;;;;;;;;;GAUG;AACH,qBACa,wBAAwB;IAGvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFlC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6C;gBAEvC,KAAK,EAAE,YAAY;IAEhD;;;;;;;;;;OAUG;IACG,+BAA+B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;CA+BzG"}
|
|
@@ -0,0 +1,80 @@
|
|
|
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
|
+
var RbacPermissionRepository_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.RbacPermissionRepository = void 0;
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const neo4j_service_1 = require("../../../core/neo4j/services/neo4j.service");
|
|
16
|
+
const feature_module_query_1 = require("../../module/queries/feature.module.query");
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the effective per-module permission flags for a user. Mirrors the
|
|
19
|
+
* permission model used by the rest of the app (see AuthRepository and
|
|
20
|
+
* UserModulesRepository): a module is visible to the user iff its parent
|
|
21
|
+
* Feature is subscribed by the user's Company (or is a core Feature), and the
|
|
22
|
+
* effective permissions result from merging the Module's default
|
|
23
|
+
* `permissions` JSON with any role-level `HAS_PERMISSIONS` overrides.
|
|
24
|
+
*
|
|
25
|
+
* Used by RbacPermissionService to answer `can(userId, moduleId, action)`
|
|
26
|
+
* for the MCP layer.
|
|
27
|
+
*/
|
|
28
|
+
let RbacPermissionRepository = RbacPermissionRepository_1 = class RbacPermissionRepository {
|
|
29
|
+
constructor(neo4j) {
|
|
30
|
+
this.neo4j = neo4j;
|
|
31
|
+
this.logger = new common_1.Logger(RbacPermissionRepository_1.name);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Effective per-module permission flags for a user.
|
|
35
|
+
*
|
|
36
|
+
* The query reuses `featureModuleQuery` — identical to the permission
|
|
37
|
+
* resolution run at login by AuthRepository and by the chatbot's
|
|
38
|
+
* UserModulesRepository — so MCP permission checks are always in
|
|
39
|
+
* lock-step with the rest of the app. The resolved effective permissions
|
|
40
|
+
* are returned on a virtual module node as a JSON string on
|
|
41
|
+
* `properties.permissions`; we parse it and keep all four permission
|
|
42
|
+
* types (`read`, `create`, `update`, `delete`).
|
|
43
|
+
*/
|
|
44
|
+
async findEffectivePermissionsForUser(userId) {
|
|
45
|
+
const result = await this.neo4j.read(`
|
|
46
|
+
MATCH (user:User {id: $userId})-[:BELONGS_TO]->(company:Company)
|
|
47
|
+
${feature_module_query_1.featureModuleQuery}
|
|
48
|
+
`, { userId });
|
|
49
|
+
const map = new Map();
|
|
50
|
+
for (const record of result.records) {
|
|
51
|
+
const moduleNode = record.get("module");
|
|
52
|
+
const props = moduleNode?.properties;
|
|
53
|
+
if (!props)
|
|
54
|
+
continue;
|
|
55
|
+
const id = props.id;
|
|
56
|
+
const permsJson = props.permissions;
|
|
57
|
+
if (typeof id !== "string" || !id.length || typeof permsJson !== "string")
|
|
58
|
+
continue;
|
|
59
|
+
try {
|
|
60
|
+
const perms = JSON.parse(permsJson);
|
|
61
|
+
map.set(id, {
|
|
62
|
+
read: perms.find((p) => p.type === "read")?.value === true,
|
|
63
|
+
create: perms.find((p) => p.type === "create")?.value === true,
|
|
64
|
+
update: perms.find((p) => p.type === "update")?.value === true,
|
|
65
|
+
delete: perms.find((p) => p.type === "delete")?.value === true,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
this.logger.warn(`findEffectivePermissionsForUser: malformed permissions JSON on module ${id}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return map;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
exports.RbacPermissionRepository = RbacPermissionRepository;
|
|
76
|
+
exports.RbacPermissionRepository = RbacPermissionRepository = RbacPermissionRepository_1 = __decorate([
|
|
77
|
+
(0, common_1.Injectable)(),
|
|
78
|
+
__metadata("design:paramtypes", [neo4j_service_1.Neo4jService])
|
|
79
|
+
], RbacPermissionRepository);
|
|
80
|
+
//# sourceMappingURL=rbac-permission.repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac-permission.repository.js","sourceRoot":"","sources":["../../../../src/foundations/rbac/repositories/rbac-permission.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AACpD,8EAA0E;AAC1E,oFAA+E;AAQ/E;;;;;;;;;;GAUG;AAEI,IAAM,wBAAwB,gCAA9B,MAAM,wBAAwB;IAGnC,YAA6B,KAAmB;QAAnB,UAAK,GAAL,KAAK,CAAc;QAF/B,WAAM,GAAG,IAAI,eAAM,CAAC,0BAAwB,CAAC,IAAI,CAAC,CAAC;IAEjB,CAAC;IAEpD;;;;;;;;;;OAUG;IACH,KAAK,CAAC,+BAA+B,CAAC,MAAc;QAClD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAClC;;QAEE,yCAAkB;OACnB,EACD,EAAE,MAAM,EAAE,CACX,CAAC;QAEF,MAAM,GAAG,GAAG,IAAI,GAAG,EAAuC,CAAC;QAC3D,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,MAAM,UAAU,GAAQ,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC7C,MAAM,KAAK,GAAG,UAAU,EAAE,UAAU,CAAC;YACrC,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;YACpB,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC;YACpC,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,EAAE,CAAC,MAAM,IAAI,OAAO,SAAS,KAAK,QAAQ;gBAAE,SAAS;YACpF,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAsB,CAAC;gBACzD,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE;oBACV,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,KAAK,KAAK,IAAI;oBAC1D,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI;oBAC9D,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI;oBAC9D,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI;iBAC/D,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yEAAyE,EAAE,EAAE,CAAC,CAAC;YAClG,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF,CAAA;AA/CY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,mBAAU,GAAE;qCAIyB,4BAAY;GAHrC,wBAAwB,CA+CpC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { RbacPermissionRepository } from "../repositories/rbac-permission.repository";
|
|
2
|
+
/**
|
|
3
|
+
* The four permission flags resolved per module by the RBAC permission model.
|
|
4
|
+
*
|
|
5
|
+
* String-literal union (not the `Action` enum from `common/enums/action.ts`)
|
|
6
|
+
* so it can be re-exported from the library root without a name collision —
|
|
7
|
+
* same reasoning as the rbac DSL's non-exported `Action` type.
|
|
8
|
+
*/
|
|
9
|
+
export type RbacAction = "read" | "create" | "update" | "delete";
|
|
10
|
+
/**
|
|
11
|
+
* Answers `can(userId, moduleId, action)` using the same `featureModuleQuery`
|
|
12
|
+
* permission resolution as the rest of the app (AuthRepository at login,
|
|
13
|
+
* UserModulesRepository for the chatbot catalog).
|
|
14
|
+
*
|
|
15
|
+
* Consumed by the MCP layer to gate reads and writes per tool call.
|
|
16
|
+
*/
|
|
17
|
+
export declare class RbacPermissionService {
|
|
18
|
+
private readonly repository;
|
|
19
|
+
constructor(repository: RbacPermissionRepository);
|
|
20
|
+
/**
|
|
21
|
+
* True iff the user's effective permission flag for `action` on the module
|
|
22
|
+
* resolves to `true`. Unknown modules (not in the user's effective set)
|
|
23
|
+
* always deny.
|
|
24
|
+
*/
|
|
25
|
+
can(params: {
|
|
26
|
+
userId: string;
|
|
27
|
+
moduleId: string;
|
|
28
|
+
action: RbacAction;
|
|
29
|
+
}): Promise<boolean>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=rbac-permission.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac-permission.service.d.ts","sourceRoot":"","sources":["../../../../src/foundations/rbac/services/rbac-permission.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,4CAA4C,CAAC;AAEtF;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEjE;;;;;;GAMG;AACH,qBACa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,wBAAwB;IAEjE;;;;OAIG;IACG,GAAG,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;CAI9F"}
|
|
@@ -0,0 +1,41 @@
|
|
|
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.RbacPermissionService = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const rbac_permission_repository_1 = require("../repositories/rbac-permission.repository");
|
|
15
|
+
/**
|
|
16
|
+
* Answers `can(userId, moduleId, action)` using the same `featureModuleQuery`
|
|
17
|
+
* permission resolution as the rest of the app (AuthRepository at login,
|
|
18
|
+
* UserModulesRepository for the chatbot catalog).
|
|
19
|
+
*
|
|
20
|
+
* Consumed by the MCP layer to gate reads and writes per tool call.
|
|
21
|
+
*/
|
|
22
|
+
let RbacPermissionService = class RbacPermissionService {
|
|
23
|
+
constructor(repository) {
|
|
24
|
+
this.repository = repository;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* True iff the user's effective permission flag for `action` on the module
|
|
28
|
+
* resolves to `true`. Unknown modules (not in the user's effective set)
|
|
29
|
+
* always deny.
|
|
30
|
+
*/
|
|
31
|
+
async can(params) {
|
|
32
|
+
const perms = await this.repository.findEffectivePermissionsForUser(params.userId);
|
|
33
|
+
return perms.get(params.moduleId)?.[params.action] === true;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
exports.RbacPermissionService = RbacPermissionService;
|
|
37
|
+
exports.RbacPermissionService = RbacPermissionService = __decorate([
|
|
38
|
+
(0, common_1.Injectable)(),
|
|
39
|
+
__metadata("design:paramtypes", [rbac_permission_repository_1.RbacPermissionRepository])
|
|
40
|
+
], RbacPermissionService);
|
|
41
|
+
//# sourceMappingURL=rbac-permission.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rbac-permission.service.js","sourceRoot":"","sources":["../../../../src/foundations/rbac/services/rbac-permission.service.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,2FAAsF;AAWtF;;;;;;GAMG;AAEI,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAChC,YAA6B,UAAoC;QAApC,eAAU,GAAV,UAAU,CAA0B;IAAG,CAAC;IAErE;;;;OAIG;IACH,KAAK,CAAC,GAAG,CAAC,MAAgE;QACxE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,+BAA+B,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnF,OAAO,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAC9D,CAAC;CACF,CAAA;AAZY,sDAAqB;gCAArB,qBAAqB;IADjC,IAAA,mBAAU,GAAE;qCAE8B,qDAAwB;GADtD,qBAAqB,CAYjC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./core/pdf";
|
|
|
10
10
|
export * from "./core/document";
|
|
11
11
|
export * from "./foundations";
|
|
12
12
|
export * from "./agents";
|
|
13
|
+
export * from "./mcp";
|
|
13
14
|
export * from "./bootstrap";
|
|
14
15
|
export * from "./openapi";
|
|
15
16
|
export { RedisLockService } from "./core/redis/services/redis.lock.service";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,UAAU,CAAC;AAGzB,cAAc,UAAU,CAAC;AAGzB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,eAAe,CAAC;AAG9B,cAAc,UAAU,CAAC;AAGzB,cAAc,aAAa,CAAC;AAG5B,cAAc,WAAW,CAAC;AAG1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,UAAU,CAAC;AAGzB,cAAc,UAAU,CAAC;AAGzB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,eAAe,CAAC;AAG9B,cAAc,UAAU,CAAC;AAGzB,cAAc,OAAO,CAAC;AAGtB,cAAc,aAAa,CAAC;AAG5B,cAAc,WAAW,CAAC;AAG1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,8 @@ __exportStar(require("./core/document"), exports);
|
|
|
32
32
|
__exportStar(require("./foundations"), exports);
|
|
33
33
|
// Agent module exports
|
|
34
34
|
__exportStar(require("./agents"), exports);
|
|
35
|
+
// MCP (Model Context Protocol) module exports
|
|
36
|
+
__exportStar(require("./mcp"), exports);
|
|
35
37
|
// Bootstrap utilities
|
|
36
38
|
__exportStar(require("./bootstrap"), exports);
|
|
37
39
|
// OpenAPI module exports
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;AAEH,iBAAiB;AACjB,2CAAyB;AAEzB,iBAAiB;AACjB,2CAAyB;AAEzB,sBAAsB;AACtB,yCAAuB;AACvB,6CAA2B;AAC3B,kDAAgC;AAEhC,4BAA4B;AAC5B,gDAA8B;AAE9B,uBAAuB;AACvB,2CAAyB;AAEzB,sBAAsB;AACtB,8CAA4B;AAE5B,yBAAyB;AACzB,4CAA0B;AAE1B,yFAAyF;AACzF,+EAA4E;AAAnE,sHAAA,gBAAgB,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;AAEH,iBAAiB;AACjB,2CAAyB;AAEzB,iBAAiB;AACjB,2CAAyB;AAEzB,sBAAsB;AACtB,yCAAuB;AACvB,6CAA2B;AAC3B,kDAAgC;AAEhC,4BAA4B;AAC5B,gDAA8B;AAE9B,uBAAuB;AACvB,2CAAyB;AAEzB,8CAA8C;AAC9C,wCAAsB;AAEtB,sBAAsB;AACtB,8CAA4B;AAE5B,yBAAyB;AACzB,4CAA0B;AAE1B,yFAAyF;AACzF,+EAA4E;AAAnE,sHAAA,gBAAgB,OAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ConfigService } from "@nestjs/config";
|
|
2
|
+
import { FastifyReply, FastifyRequest } from "fastify";
|
|
3
|
+
import { ClsService } from "nestjs-cls";
|
|
4
|
+
import { UserModulesRepository } from "../../agents/graph/repositories/user-modules.repository";
|
|
5
|
+
import { McpServerFactory } from "../services/mcp.server.factory";
|
|
6
|
+
/**
|
|
7
|
+
* MCP (Model Context Protocol) endpoint — stateless Streamable HTTP.
|
|
8
|
+
*
|
|
9
|
+
* Each `POST /mcp` request is authenticated by the existing OAuthTokenGuard
|
|
10
|
+
* (which populates CLS `userId`/`companyId`), then handed to a fresh per-request
|
|
11
|
+
* MCP Server + StreamableHTTPServerTransport pair (`sessionIdGenerator:
|
|
12
|
+
* undefined` — stateless mode, no session tracking). GET/DELETE are rejected
|
|
13
|
+
* with 405: stateless servers expose no SSE notification channel and no
|
|
14
|
+
* session to terminate.
|
|
15
|
+
*
|
|
16
|
+
* Uses `@Res()` with raw reply writing (the SDK transport writes directly to
|
|
17
|
+
* `res.raw`), which opts this handler out of Nest response serialization —
|
|
18
|
+
* the MCP wire format is JSON-RPC, not JSON:API, matching how the OAuth
|
|
19
|
+
* controllers speak their own RFC-mandated wire formats.
|
|
20
|
+
*/
|
|
21
|
+
export declare class McpController {
|
|
22
|
+
private readonly factory;
|
|
23
|
+
private readonly cls;
|
|
24
|
+
private readonly userModules;
|
|
25
|
+
private readonly configService;
|
|
26
|
+
constructor(factory: McpServerFactory, cls: ClsService, userModules: UserModulesRepository, configService: ConfigService);
|
|
27
|
+
/** Handles one stateless MCP Streamable-HTTP request (initialize, tools/list, tools/call, ...). */
|
|
28
|
+
handle(req: FastifyRequest, res: FastifyReply): Promise<void>;
|
|
29
|
+
/** Stateless server: no SSE notification stream is offered. */
|
|
30
|
+
rejectGet(): never;
|
|
31
|
+
/** Stateless server: there is no session to terminate. */
|
|
32
|
+
rejectDelete(): never;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=mcp.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.controller.d.ts","sourceRoot":"","sources":["../../../src/mcp/controllers/mcp.controller.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,yDAAyD,CAAC;AAKhG,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE;;;;;;;;;;;;;;GAcG;AACH,qBAGa,aAAa;IAEtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAHb,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,UAAU,EACf,WAAW,EAAE,qBAAqB,EAClC,aAAa,EAAE,aAAa;IAG/C,mGAAmG;IAE7F,MAAM,CAAQ,GAAG,EAAE,cAAc,EAAS,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAyBjF,+DAA+D;IAE/D,SAAS,IAAI,KAAK;IAIlB,0DAA0D;IAE1D,YAAY,IAAI,KAAK;CAGtB"}
|
|
@@ -0,0 +1,108 @@
|
|
|
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
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.McpController = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const config_1 = require("@nestjs/config");
|
|
18
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
19
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
20
|
+
const user_modules_repository_1 = require("../../agents/graph/repositories/user-modules.repository");
|
|
21
|
+
const oauth_token_guard_1 = require("../../foundations/oauth/guards/oauth.token.guard");
|
|
22
|
+
const mcp_auth_filter_1 = require("../filters/mcp.auth.filter");
|
|
23
|
+
const mcp_server_factory_1 = require("../services/mcp.server.factory");
|
|
24
|
+
/**
|
|
25
|
+
* MCP (Model Context Protocol) endpoint — stateless Streamable HTTP.
|
|
26
|
+
*
|
|
27
|
+
* Each `POST /mcp` request is authenticated by the existing OAuthTokenGuard
|
|
28
|
+
* (which populates CLS `userId`/`companyId`), then handed to a fresh per-request
|
|
29
|
+
* MCP Server + StreamableHTTPServerTransport pair (`sessionIdGenerator:
|
|
30
|
+
* undefined` — stateless mode, no session tracking). GET/DELETE are rejected
|
|
31
|
+
* with 405: stateless servers expose no SSE notification channel and no
|
|
32
|
+
* session to terminate.
|
|
33
|
+
*
|
|
34
|
+
* Uses `@Res()` with raw reply writing (the SDK transport writes directly to
|
|
35
|
+
* `res.raw`), which opts this handler out of Nest response serialization —
|
|
36
|
+
* the MCP wire format is JSON-RPC, not JSON:API, matching how the OAuth
|
|
37
|
+
* controllers speak their own RFC-mandated wire formats.
|
|
38
|
+
*/
|
|
39
|
+
let McpController = class McpController {
|
|
40
|
+
constructor(factory, cls, userModules, configService) {
|
|
41
|
+
this.factory = factory;
|
|
42
|
+
this.cls = cls;
|
|
43
|
+
this.userModules = userModules;
|
|
44
|
+
this.configService = configService;
|
|
45
|
+
}
|
|
46
|
+
/** Handles one stateless MCP Streamable-HTTP request (initialize, tools/list, tools/call, ...). */
|
|
47
|
+
async handle(req, res) {
|
|
48
|
+
if (!this.configService.get("mcp")?.enabled) {
|
|
49
|
+
throw new common_1.NotFoundException();
|
|
50
|
+
}
|
|
51
|
+
const userId = this.cls.get("userId");
|
|
52
|
+
const companyId = this.cls.get("companyId");
|
|
53
|
+
const ctx = {
|
|
54
|
+
userId,
|
|
55
|
+
companyId,
|
|
56
|
+
userModuleIds: await this.userModules.findModuleIdsForUser(userId),
|
|
57
|
+
};
|
|
58
|
+
const server = this.factory.create(ctx);
|
|
59
|
+
const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({ sessionIdGenerator: undefined }); // stateless
|
|
60
|
+
res.raw.on("close", () => {
|
|
61
|
+
void transport.close();
|
|
62
|
+
void server.close();
|
|
63
|
+
});
|
|
64
|
+
await server.connect(transport);
|
|
65
|
+
// Fastify has already parsed the JSON body — pass it through so the SDK
|
|
66
|
+
// does not attempt to re-read the (already consumed) request stream.
|
|
67
|
+
await transport.handleRequest(req.raw, res.raw, req.body);
|
|
68
|
+
}
|
|
69
|
+
/** Stateless server: no SSE notification stream is offered. */
|
|
70
|
+
rejectGet() {
|
|
71
|
+
throw new common_1.HttpException("Method Not Allowed", 405);
|
|
72
|
+
}
|
|
73
|
+
/** Stateless server: there is no session to terminate. */
|
|
74
|
+
rejectDelete() {
|
|
75
|
+
throw new common_1.HttpException("Method Not Allowed", 405);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
exports.McpController = McpController;
|
|
79
|
+
__decorate([
|
|
80
|
+
(0, common_1.Post)(),
|
|
81
|
+
__param(0, (0, common_1.Req)()),
|
|
82
|
+
__param(1, (0, common_1.Res)()),
|
|
83
|
+
__metadata("design:type", Function),
|
|
84
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
85
|
+
__metadata("design:returntype", Promise)
|
|
86
|
+
], McpController.prototype, "handle", null);
|
|
87
|
+
__decorate([
|
|
88
|
+
(0, common_1.Get)(),
|
|
89
|
+
__metadata("design:type", Function),
|
|
90
|
+
__metadata("design:paramtypes", []),
|
|
91
|
+
__metadata("design:returntype", void 0)
|
|
92
|
+
], McpController.prototype, "rejectGet", null);
|
|
93
|
+
__decorate([
|
|
94
|
+
(0, common_1.Delete)(),
|
|
95
|
+
__metadata("design:type", Function),
|
|
96
|
+
__metadata("design:paramtypes", []),
|
|
97
|
+
__metadata("design:returntype", void 0)
|
|
98
|
+
], McpController.prototype, "rejectDelete", null);
|
|
99
|
+
exports.McpController = McpController = __decorate([
|
|
100
|
+
(0, common_1.Controller)("mcp"),
|
|
101
|
+
(0, common_1.UseFilters)(mcp_auth_filter_1.McpAuthFilter),
|
|
102
|
+
(0, common_1.UseGuards)(oauth_token_guard_1.OAuthTokenGuard),
|
|
103
|
+
__metadata("design:paramtypes", [mcp_server_factory_1.McpServerFactory,
|
|
104
|
+
nestjs_cls_1.ClsService,
|
|
105
|
+
user_modules_repository_1.UserModulesRepository,
|
|
106
|
+
config_1.ConfigService])
|
|
107
|
+
], McpController);
|
|
108
|
+
//# sourceMappingURL=mcp.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.controller.js","sourceRoot":"","sources":["../../../src/mcp/controllers/mcp.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAWwB;AACxB,2CAA+C;AAC/C,0FAAmG;AAEnG,2CAAwC;AACxC,qGAAgG;AAEhG,wFAAmF;AACnF,gEAA2D;AAE3D,uEAAkE;AAElE;;;;;;;;;;;;;;GAcG;AAII,IAAM,aAAa,GAAnB,MAAM,aAAa;IACxB,YACmB,OAAyB,EACzB,GAAe,EACf,WAAkC,EAClC,aAA4B;QAH5B,YAAO,GAAP,OAAO,CAAkB;QACzB,QAAG,GAAH,GAAG,CAAY;QACf,gBAAW,GAAX,WAAW,CAAuB;QAClC,kBAAa,GAAb,aAAa,CAAe;IAC5C,CAAC;IAEJ,mGAAmG;IAE7F,AAAN,KAAK,CAAC,MAAM,CAAQ,GAAmB,EAAS,GAAiB;QAC/D,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAqB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;YAChE,MAAM,IAAI,0BAAiB,EAAE,CAAC;QAChC,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAmB;YAC1B,MAAM;YACN,SAAS;YACT,aAAa,EAAE,MAAM,IAAI,CAAC,WAAW,CAAC,oBAAoB,CAAC,MAAM,CAAC;SACnE,CAAC;QAEF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,iDAA6B,CAAC,EAAE,kBAAkB,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,YAAY;QACpG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACvB,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,wEAAwE;QACxE,qEAAqE;QACrE,MAAM,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC;IAED,+DAA+D;IAE/D,SAAS;QACP,MAAM,IAAI,sBAAa,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,0DAA0D;IAE1D,YAAY;QACV,MAAM,IAAI,sBAAa,CAAC,oBAAoB,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;CACF,CAAA;AA9CY,sCAAa;AAUlB;IADL,IAAA,aAAI,GAAE;IACO,WAAA,IAAA,YAAG,GAAE,CAAA;IAAuB,WAAA,IAAA,YAAG,GAAE,CAAA;;;;2CAuB9C;AAID;IADC,IAAA,YAAG,GAAE;;;;8CAGL;AAID;IADC,IAAA,eAAM,GAAE;;;;iDAGR;wBA7CU,aAAa;IAHzB,IAAA,mBAAU,EAAC,KAAK,CAAC;IACjB,IAAA,mBAAU,EAAC,+BAAa,CAAC;IACzB,IAAA,kBAAS,EAAC,mCAAe,CAAC;qCAGG,qCAAgB;QACpB,uBAAU;QACF,+CAAqB;QACnB,sBAAa;GALpC,aAAa,CA8CzB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ArgumentsHost, HttpException } from "@nestjs/common";
|
|
2
|
+
import { ConfigService } from "@nestjs/config";
|
|
3
|
+
import { HttpExceptionFilter } from "../../common/filters/http-exception.filter";
|
|
4
|
+
import { AppLoggingService } from "../../core/logging/services/logging.service";
|
|
5
|
+
/**
|
|
6
|
+
* MCP-scoped exception filter.
|
|
7
|
+
*
|
|
8
|
+
* RFC 9728 requires 401 responses from a protected resource to carry a
|
|
9
|
+
* `WWW-Authenticate` header pointing at the protected-resource metadata so MCP
|
|
10
|
+
* clients can discover the authorization server. On 401 this filter sets that
|
|
11
|
+
* header, then delegates the JSON error body to the library's standard
|
|
12
|
+
* HttpExceptionFilter; every other HttpException is handled identically to the
|
|
13
|
+
* global filter (non-HttpException errors fall through to the global filter
|
|
14
|
+
* because of the `@Catch(HttpException)` scope).
|
|
15
|
+
*/
|
|
16
|
+
export declare class McpAuthFilter extends HttpExceptionFilter {
|
|
17
|
+
private readonly configService;
|
|
18
|
+
constructor(configService: ConfigService, logger?: AppLoggingService);
|
|
19
|
+
catch(exception: HttpException, host: ArgumentsHost): void;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=mcp.auth.filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.auth.filter.d.ts","sourceRoot":"","sources":["../../../src/mcp/filters/mcp.auth.filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAS,aAAa,EAAY,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAEhF;;;;;;;;;;GAUG;AACH,qBACa,aAAc,SAAQ,mBAAmB;IAElD,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,aAAa,EACjC,MAAM,CAAC,EAAE,iBAAiB;IAKxC,KAAK,CAAC,SAAS,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI;CAQ3D"}
|
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.McpAuthFilter = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const config_1 = require("@nestjs/config");
|
|
18
|
+
const http_exception_filter_1 = require("../../common/filters/http-exception.filter");
|
|
19
|
+
const logging_service_1 = require("../../core/logging/services/logging.service");
|
|
20
|
+
/**
|
|
21
|
+
* MCP-scoped exception filter.
|
|
22
|
+
*
|
|
23
|
+
* RFC 9728 requires 401 responses from a protected resource to carry a
|
|
24
|
+
* `WWW-Authenticate` header pointing at the protected-resource metadata so MCP
|
|
25
|
+
* clients can discover the authorization server. On 401 this filter sets that
|
|
26
|
+
* header, then delegates the JSON error body to the library's standard
|
|
27
|
+
* HttpExceptionFilter; every other HttpException is handled identically to the
|
|
28
|
+
* global filter (non-HttpException errors fall through to the global filter
|
|
29
|
+
* because of the `@Catch(HttpException)` scope).
|
|
30
|
+
*/
|
|
31
|
+
let McpAuthFilter = class McpAuthFilter extends http_exception_filter_1.HttpExceptionFilter {
|
|
32
|
+
constructor(configService, logger) {
|
|
33
|
+
super(logger);
|
|
34
|
+
this.configService = configService;
|
|
35
|
+
}
|
|
36
|
+
catch(exception, host) {
|
|
37
|
+
if (exception.getStatus() === 401) {
|
|
38
|
+
const reply = host.switchToHttp().getResponse();
|
|
39
|
+
const base = (this.configService.get("api")?.url ?? "").replace(/\/$/, "");
|
|
40
|
+
reply.header("WWW-Authenticate", `Bearer resource_metadata="${base}/.well-known/oauth-protected-resource"`);
|
|
41
|
+
}
|
|
42
|
+
super.catch(exception, host);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
exports.McpAuthFilter = McpAuthFilter;
|
|
46
|
+
exports.McpAuthFilter = McpAuthFilter = __decorate([
|
|
47
|
+
(0, common_1.Catch)(common_1.HttpException),
|
|
48
|
+
__param(1, (0, common_1.Optional)()),
|
|
49
|
+
__metadata("design:paramtypes", [config_1.ConfigService,
|
|
50
|
+
logging_service_1.AppLoggingService])
|
|
51
|
+
], McpAuthFilter);
|
|
52
|
+
//# sourceMappingURL=mcp.auth.filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.auth.filter.js","sourceRoot":"","sources":["../../../src/mcp/filters/mcp.auth.filter.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA+E;AAC/E,2CAA+C;AAE/C,sFAAiF;AACjF,iFAAgF;AAEhF;;;;;;;;;;GAUG;AAEI,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,2CAAmB;IACpD,YACmB,aAA4B,EACjC,MAA0B;QAEtC,KAAK,CAAC,MAAM,CAAC,CAAC;QAHG,kBAAa,GAAb,aAAa,CAAe;IAI/C,CAAC;IAED,KAAK,CAAC,SAAwB,EAAE,IAAmB;QACjD,IAAI,SAAS,CAAC,SAAS,EAAE,KAAK,GAAG,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,WAAW,EAAgB,CAAC;YAC9D,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAkB,KAAK,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC5F,KAAK,CAAC,MAAM,CAAC,kBAAkB,EAAE,6BAA6B,IAAI,wCAAwC,CAAC,CAAC;QAC9G,CAAC;QACD,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;CACF,CAAA;AAhBY,sCAAa;wBAAb,aAAa;IADzB,IAAA,cAAK,EAAC,sBAAa,CAAC;IAIhB,WAAA,IAAA,iBAAQ,GAAE,CAAA;qCADqB,sBAAa;QACxB,mCAAiB;GAH7B,aAAa,CAgBzB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAC5D,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,cAAc,GACf,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// MCP (Model Context Protocol) server — public entry point.
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.MCP_TOOLS = exports.McpModule = void 0;
|
|
5
|
+
// Module (mounted via BootstrapOptions.mcp === true)
|
|
6
|
+
var mcp_module_1 = require("./mcp.module");
|
|
7
|
+
Object.defineProperty(exports, "McpModule", { enumerable: true, get: function () { return mcp_module_1.McpModule; } });
|
|
8
|
+
// App-contribution surface: register McpToolContribution factories under MCP_TOOLS.
|
|
9
|
+
var mcp_tool_interface_1 = require("./interfaces/mcp.tool.interface");
|
|
10
|
+
Object.defineProperty(exports, "MCP_TOOLS", { enumerable: true, get: function () { return mcp_tool_interface_1.MCP_TOOLS; } });
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";AAAA,4DAA4D;;;AAE5D,qDAAqD;AACrD,2CAAyC;AAAhC,uGAAA,SAAS,OAAA;AAElB,oFAAoF;AACpF,sEAA4D;AAAnD,+GAAA,SAAS,OAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** Per-request user context every MCP tool executes with (company scoping + RBAC module visibility). */
|
|
2
|
+
export interface McpUserContext {
|
|
3
|
+
userId: string;
|
|
4
|
+
companyId: string;
|
|
5
|
+
userModuleIds: string[];
|
|
6
|
+
}
|
|
7
|
+
/** MCP tool-call result: text content blocks, with `isError` set on failures. */
|
|
8
|
+
export interface McpToolResult {
|
|
9
|
+
content: Array<{
|
|
10
|
+
type: "text";
|
|
11
|
+
text: string;
|
|
12
|
+
}>;
|
|
13
|
+
isError?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A single MCP tool as exposed over tools/list + tools/call.
|
|
17
|
+
* `inputSchema` is JSON Schema (draft 2020-12); `readOnly` maps to `annotations.readOnlyHint`.
|
|
18
|
+
*/
|
|
19
|
+
export interface McpToolDefinition {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
inputSchema: Record<string, unknown>;
|
|
23
|
+
readOnly: boolean;
|
|
24
|
+
execute(input: Record<string, unknown>, ctx: McpUserContext): Promise<McpToolResult>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Factory contract for app-contributed MCP tools.
|
|
28
|
+
* Built once per request — like the built-ins — so contributed tools can
|
|
29
|
+
* apply company scoping and RBAC filtering from the request context.
|
|
30
|
+
*/
|
|
31
|
+
export interface McpToolContribution {
|
|
32
|
+
/** Called once per MCP request with the authenticated user context. */
|
|
33
|
+
build(ctx: McpUserContext): McpToolDefinition[];
|
|
34
|
+
}
|
|
35
|
+
/** Multi-provider DI token: consuming apps contribute McpToolContribution factories. */
|
|
36
|
+
export declare const MCP_TOOLS: unique symbol;
|
|
37
|
+
//# sourceMappingURL=mcp.tool.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.tool.interface.d.ts","sourceRoot":"","sources":["../../../src/mcp/interfaces/mcp.tool.interface.ts"],"names":[],"mappings":"AAAA,wGAAwG;AACxG,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,iFAAiF;AACjF,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CACtF;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,iBAAiB,EAAE,CAAC;CACjD;AAED,wFAAwF;AACxF,eAAO,MAAM,SAAS,eAAsB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MCP_TOOLS = void 0;
|
|
4
|
+
/** Multi-provider DI token: consuming apps contribute McpToolContribution factories. */
|
|
5
|
+
exports.MCP_TOOLS = Symbol("MCP_TOOLS");
|
|
6
|
+
//# sourceMappingURL=mcp.tool.interface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.tool.interface.js","sourceRoot":"","sources":["../../../src/mcp/interfaces/mcp.tool.interface.ts"],"names":[],"mappings":";;;AAmCA,wFAAwF;AAC3E,QAAA,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP (Model Context Protocol) server module.
|
|
3
|
+
*
|
|
4
|
+
* Mounted by the bootstrap gate (`BootstrapOptions.mcp === true`) and served
|
|
5
|
+
* at `POST /mcp`, OAuth-authenticated and RBAC-gated. Exports McpToolRegistry
|
|
6
|
+
* so consuming apps can contribute additional tools via the MCP_TOOLS token.
|
|
7
|
+
*
|
|
8
|
+
* Module wiring notes:
|
|
9
|
+
* - `RbacPermissionModule` supplies RbacPermissionService (the RbacModule
|
|
10
|
+
* proper is a config-requiring dynamic module and cannot be imported here).
|
|
11
|
+
* - Audit is NOT wired here: AbstractService.create/put audits internally when
|
|
12
|
+
* the concrete entity service injects AuditService, so MCP writes audit
|
|
13
|
+
* exactly like HTTP writes.
|
|
14
|
+
* - `SearchDocumentsTool` is provided locally: OperatorModule declares but
|
|
15
|
+
* does not export it, and importing OperatorModule would drag in its
|
|
16
|
+
* forwardRef(AssistantModule) cycle. Its dependencies (ToolFactory,
|
|
17
|
+
* ContextualiserService) are exported by AgentsModule's inner modules.
|
|
18
|
+
* - EntityServiceRegistry, Neo4jService, ClsService and ConfigService resolve
|
|
19
|
+
* through the global core/cls/config modules.
|
|
20
|
+
*/
|
|
21
|
+
export declare class McpModule {
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=mcp.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.module.d.ts","sourceRoot":"","sources":["../../src/mcp/mcp.module.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAaa,SAAS;CAAG"}
|