fridayy 1.0.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/LICENSE +21 -0
- package/README.md +283 -0
- package/bin/fridayy.js +12 -0
- package/dist/adapters/base.d.ts +40 -0
- package/dist/adapters/base.d.ts.map +1 -0
- package/dist/adapters/base.js +7 -0
- package/dist/adapters/base.js.map +1 -0
- package/dist/adapters/manual/adapter.d.ts +18 -0
- package/dist/adapters/manual/adapter.d.ts.map +1 -0
- package/dist/adapters/manual/adapter.js +52 -0
- package/dist/adapters/manual/adapter.js.map +1 -0
- package/dist/adapters/nodejs/adapter.d.ts +19 -0
- package/dist/adapters/nodejs/adapter.d.ts.map +1 -0
- package/dist/adapters/nodejs/adapter.js +135 -0
- package/dist/adapters/nodejs/adapter.js.map +1 -0
- package/dist/adapters/nodejs/ast-scanner.d.ts +21 -0
- package/dist/adapters/nodejs/ast-scanner.d.ts.map +1 -0
- package/dist/adapters/nodejs/ast-scanner.js +102 -0
- package/dist/adapters/nodejs/ast-scanner.js.map +1 -0
- package/dist/adapters/openapi/adapter.d.ts +22 -0
- package/dist/adapters/openapi/adapter.d.ts.map +1 -0
- package/dist/adapters/openapi/adapter.js +271 -0
- package/dist/adapters/openapi/adapter.js.map +1 -0
- package/dist/adapters/openapi/parser.d.ts +30 -0
- package/dist/adapters/openapi/parser.d.ts.map +1 -0
- package/dist/adapters/openapi/parser.js +136 -0
- package/dist/adapters/openapi/parser.js.map +1 -0
- package/dist/adapters/openapi/request-builder.d.ts +13 -0
- package/dist/adapters/openapi/request-builder.d.ts.map +1 -0
- package/dist/adapters/openapi/request-builder.js +83 -0
- package/dist/adapters/openapi/request-builder.js.map +1 -0
- package/dist/adapters/registry.d.ts +28 -0
- package/dist/adapters/registry.d.ts.map +1 -0
- package/dist/adapters/registry.js +46 -0
- package/dist/adapters/registry.js.map +1 -0
- package/dist/adapters/rest/adapter.d.ts +18 -0
- package/dist/adapters/rest/adapter.d.ts.map +1 -0
- package/dist/adapters/rest/adapter.js +41 -0
- package/dist/adapters/rest/adapter.js.map +1 -0
- package/dist/adapters/rest/executor.d.ts +19 -0
- package/dist/adapters/rest/executor.d.ts.map +1 -0
- package/dist/adapters/rest/executor.js +101 -0
- package/dist/adapters/rest/executor.js.map +1 -0
- package/dist/cli/commands/config.d.ts +7 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +92 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +7 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +126 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +7 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +58 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +7 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +54 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/review.d.ts +7 -0
- package/dist/cli/commands/review.d.ts.map +1 -0
- package/dist/cli/commands/review.js +151 -0
- package/dist/cli/commands/review.js.map +1 -0
- package/dist/cli/commands/scan.d.ts +7 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/scan.js +77 -0
- package/dist/cli/commands/scan.js.map +1 -0
- package/dist/cli/commands/start.d.ts +7 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +54 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/tools.d.ts +7 -0
- package/dist/cli/commands/tools.d.ts.map +1 -0
- package/dist/cli/commands/tools.js +48 -0
- package/dist/cli/commands/tools.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +42 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ui/banner.d.ts +6 -0
- package/dist/cli/ui/banner.d.ts.map +1 -0
- package/dist/cli/ui/banner.js +20 -0
- package/dist/cli/ui/banner.js.map +1 -0
- package/dist/cli/ui/logger.d.ts +12 -0
- package/dist/cli/ui/logger.d.ts.map +1 -0
- package/dist/cli/ui/logger.js +13 -0
- package/dist/cli/ui/logger.js.map +1 -0
- package/dist/cli/ui/tables.d.ts +9 -0
- package/dist/cli/ui/tables.d.ts.map +1 -0
- package/dist/cli/ui/tables.js +72 -0
- package/dist/cli/ui/tables.js.map +1 -0
- package/dist/config/config-manager.d.ts +37 -0
- package/dist/config/config-manager.d.ts.map +1 -0
- package/dist/config/config-manager.js +129 -0
- package/dist/config/config-manager.js.map +1 -0
- package/dist/config/defaults.d.ts +8 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +37 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/core/authentication/manager.d.ts +20 -0
- package/dist/core/authentication/manager.d.ts.map +1 -0
- package/dist/core/authentication/manager.js +71 -0
- package/dist/core/authentication/manager.js.map +1 -0
- package/dist/core/authentication/secret-resolver.d.ts +39 -0
- package/dist/core/authentication/secret-resolver.d.ts.map +1 -0
- package/dist/core/authentication/secret-resolver.js +89 -0
- package/dist/core/authentication/secret-resolver.js.map +1 -0
- package/dist/core/discovery/index.d.ts +5 -0
- package/dist/core/discovery/index.d.ts.map +1 -0
- package/dist/core/discovery/index.js +5 -0
- package/dist/core/discovery/index.js.map +1 -0
- package/dist/core/discovery/project-scanner.d.ts +20 -0
- package/dist/core/discovery/project-scanner.d.ts.map +1 -0
- package/dist/core/discovery/project-scanner.js +174 -0
- package/dist/core/discovery/project-scanner.js.map +1 -0
- package/dist/core/permissions/classifier.d.ts +25 -0
- package/dist/core/permissions/classifier.d.ts.map +1 -0
- package/dist/core/permissions/classifier.js +92 -0
- package/dist/core/permissions/classifier.js.map +1 -0
- package/dist/core/permissions/enforcer.d.ts +24 -0
- package/dist/core/permissions/enforcer.d.ts.map +1 -0
- package/dist/core/permissions/enforcer.js +71 -0
- package/dist/core/permissions/enforcer.js.map +1 -0
- package/dist/core/schema/json-schema.d.ts +29 -0
- package/dist/core/schema/json-schema.d.ts.map +1 -0
- package/dist/core/schema/json-schema.js +129 -0
- package/dist/core/schema/json-schema.js.map +1 -0
- package/dist/core/schema/types.d.ts +187 -0
- package/dist/core/schema/types.d.ts.map +1 -0
- package/dist/core/schema/types.js +6 -0
- package/dist/core/schema/types.js.map +1 -0
- package/dist/core/tool-generator/description-builder.d.ts +15 -0
- package/dist/core/tool-generator/description-builder.d.ts.map +1 -0
- package/dist/core/tool-generator/description-builder.js +32 -0
- package/dist/core/tool-generator/description-builder.js.map +1 -0
- package/dist/core/tool-generator/generator.d.ts +21 -0
- package/dist/core/tool-generator/generator.d.ts.map +1 -0
- package/dist/core/tool-generator/generator.js +61 -0
- package/dist/core/tool-generator/generator.js.map +1 -0
- package/dist/core/tool-generator/name-sanitizer.d.ts +21 -0
- package/dist/core/tool-generator/name-sanitizer.d.ts.map +1 -0
- package/dist/core/tool-generator/name-sanitizer.js +84 -0
- package/dist/core/tool-generator/name-sanitizer.js.map +1 -0
- package/dist/core/validation/config-schema.d.ts +1458 -0
- package/dist/core/validation/config-schema.d.ts.map +1 -0
- package/dist/core/validation/config-schema.js +137 -0
- package/dist/core/validation/config-schema.js.map +1 -0
- package/dist/core/validation/validator.d.ts +28 -0
- package/dist/core/validation/validator.d.ts.map +1 -0
- package/dist/core/validation/validator.js +108 -0
- package/dist/core/validation/validator.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/prompts/prompt-registry.d.ts +28 -0
- package/dist/mcp/prompts/prompt-registry.d.ts.map +1 -0
- package/dist/mcp/prompts/prompt-registry.js +65 -0
- package/dist/mcp/prompts/prompt-registry.js.map +1 -0
- package/dist/mcp/resources/resource-registry.d.ts +26 -0
- package/dist/mcp/resources/resource-registry.d.ts.map +1 -0
- package/dist/mcp/resources/resource-registry.js +87 -0
- package/dist/mcp/resources/resource-registry.js.map +1 -0
- package/dist/mcp/server/fridayy-server.d.ts +38 -0
- package/dist/mcp/server/fridayy-server.d.ts.map +1 -0
- package/dist/mcp/server/fridayy-server.js +143 -0
- package/dist/mcp/server/fridayy-server.js.map +1 -0
- package/dist/mcp/tools/tool-handler.d.ts +29 -0
- package/dist/mcp/tools/tool-handler.d.ts.map +1 -0
- package/dist/mcp/tools/tool-handler.js +206 -0
- package/dist/mcp/tools/tool-handler.js.map +1 -0
- package/dist/mcp/tools/tool-registry.d.ts +20 -0
- package/dist/mcp/tools/tool-registry.d.ts.map +1 -0
- package/dist/mcp/tools/tool-registry.js +38 -0
- package/dist/mcp/tools/tool-registry.js.map +1 -0
- package/dist/security/allowlist.d.ts +10 -0
- package/dist/security/allowlist.d.ts.map +1 -0
- package/dist/security/allowlist.js +30 -0
- package/dist/security/allowlist.js.map +1 -0
- package/dist/security/audit-logger.d.ts +35 -0
- package/dist/security/audit-logger.d.ts.map +1 -0
- package/dist/security/audit-logger.js +52 -0
- package/dist/security/audit-logger.js.map +1 -0
- package/dist/security/rate-limiter.d.ts +28 -0
- package/dist/security/rate-limiter.d.ts.map +1 -0
- package/dist/security/rate-limiter.js +64 -0
- package/dist/security/rate-limiter.js.map +1 -0
- package/dist/security/sanitizer.d.ts +17 -0
- package/dist/security/sanitizer.d.ts.map +1 -0
- package/dist/security/sanitizer.js +70 -0
- package/dist/security/sanitizer.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/discovery/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/discovery/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fridayy - Project Scanner & Capability Discovery
|
|
3
|
+
* Analyzes projects, repositories, and APIs to detect capabilities, specs, and auth mechanisms.
|
|
4
|
+
*/
|
|
5
|
+
import { ScanResult } from '../schema/types.js';
|
|
6
|
+
import { AdapterRegistry } from '../../adapters/registry.js';
|
|
7
|
+
export declare class ProjectScanner {
|
|
8
|
+
private adapterRegistry;
|
|
9
|
+
private openApiParser;
|
|
10
|
+
private nodeJsScanner;
|
|
11
|
+
constructor(adapterRegistry?: AdapterRegistry);
|
|
12
|
+
/**
|
|
13
|
+
* Scans a root directory and returns comprehensive capability detection results.
|
|
14
|
+
*/
|
|
15
|
+
scan(rootDir?: string): Promise<ScanResult>;
|
|
16
|
+
private findOpenApiFiles;
|
|
17
|
+
private countEndpoints;
|
|
18
|
+
}
|
|
19
|
+
export declare const defaultProjectScanner: ProjectScanner;
|
|
20
|
+
//# sourceMappingURL=project-scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-scanner.d.ts","sourceRoot":"","sources":["../../../src/core/discovery/project-scanner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,UAAU,EAAiB,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAA0B,MAAM,4BAA4B,CAAC;AAIrF,qBAAa,cAAc;IACzB,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,aAAa,CAAuB;gBAEhC,eAAe,GAAE,eAAwC;IAIrE;;OAEG;IACU,IAAI,CAAC,OAAO,GAAE,MAAsB,GAAG,OAAO,CAAC,UAAU,CAAC;IAyGvE,OAAO,CAAC,gBAAgB;IAuCxB,OAAO,CAAC,cAAc;CAcvB;AAED,eAAO,MAAM,qBAAqB,gBAAuB,CAAC"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fridayy - Project Scanner & Capability Discovery
|
|
3
|
+
* Analyzes projects, repositories, and APIs to detect capabilities, specs, and auth mechanisms.
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { defaultAdapterRegistry } from '../../adapters/registry.js';
|
|
8
|
+
import { OpenApiParser } from '../../adapters/openapi/parser.js';
|
|
9
|
+
import { NodeJsScanner } from '../../adapters/nodejs/ast-scanner.js';
|
|
10
|
+
export class ProjectScanner {
|
|
11
|
+
adapterRegistry;
|
|
12
|
+
openApiParser = new OpenApiParser();
|
|
13
|
+
nodeJsScanner = new NodeJsScanner();
|
|
14
|
+
constructor(adapterRegistry = defaultAdapterRegistry) {
|
|
15
|
+
this.adapterRegistry = adapterRegistry;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Scans a root directory and returns comprehensive capability detection results.
|
|
19
|
+
*/
|
|
20
|
+
async scan(rootDir = process.cwd()) {
|
|
21
|
+
const absRoot = path.resolve(rootDir);
|
|
22
|
+
// 1. Scan for OpenAPI files
|
|
23
|
+
const openApiFiles = this.findOpenApiFiles(absRoot);
|
|
24
|
+
const hasOpenApi = openApiFiles.length > 0;
|
|
25
|
+
const openApiSpecsDetails = [];
|
|
26
|
+
const authSchemesDetected = new Set();
|
|
27
|
+
let totalEndpoints = 0;
|
|
28
|
+
for (const relFile of openApiFiles) {
|
|
29
|
+
try {
|
|
30
|
+
const parsed = await this.openApiParser.parse(relFile, absRoot);
|
|
31
|
+
const opCount = this.countEndpoints(parsed.paths);
|
|
32
|
+
totalEndpoints += opCount;
|
|
33
|
+
openApiSpecsDetails.push({
|
|
34
|
+
path: relFile,
|
|
35
|
+
version: parsed.version,
|
|
36
|
+
title: parsed.title,
|
|
37
|
+
endpointsCount: opCount
|
|
38
|
+
});
|
|
39
|
+
// Collect security schemes
|
|
40
|
+
if (parsed.securityDefinitions) {
|
|
41
|
+
for (const [schemeName, schemeDef] of Object.entries(parsed.securityDefinitions)) {
|
|
42
|
+
authSchemesDetected.add(schemeName);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Skip unparseable specs
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// 2. Scan for Node.js routes & frameworks
|
|
51
|
+
const pkgJsonPath = path.join(absRoot, 'package.json');
|
|
52
|
+
let hasNodeJs = false;
|
|
53
|
+
let nodeJsFramework = 'none';
|
|
54
|
+
if (fs.existsSync(pkgJsonPath)) {
|
|
55
|
+
hasNodeJs = true;
|
|
56
|
+
try {
|
|
57
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
|
|
58
|
+
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
59
|
+
if (allDeps.express)
|
|
60
|
+
nodeJsFramework = 'express';
|
|
61
|
+
else if (allDeps.fastify)
|
|
62
|
+
nodeJsFramework = 'fastify';
|
|
63
|
+
else if (allDeps.koa)
|
|
64
|
+
nodeJsFramework = 'koa';
|
|
65
|
+
else if (allDeps['@nestjs/core'])
|
|
66
|
+
nodeJsFramework = 'nestjs';
|
|
67
|
+
else
|
|
68
|
+
nodeJsFramework = 'custom';
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
nodeJsFramework = 'custom';
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const discoveredRoutes = await this.nodeJsScanner.scanDirectory(absRoot, 100);
|
|
75
|
+
if (discoveredRoutes.length > 0 && !hasOpenApi) {
|
|
76
|
+
totalEndpoints += discoveredRoutes.length;
|
|
77
|
+
}
|
|
78
|
+
// 3. Formulate recommended configuration
|
|
79
|
+
const projectName = path.basename(absRoot);
|
|
80
|
+
const recommendedConfig = {
|
|
81
|
+
name: projectName,
|
|
82
|
+
version: '1.0.0',
|
|
83
|
+
source: hasOpenApi
|
|
84
|
+
? {
|
|
85
|
+
type: 'openapi',
|
|
86
|
+
path: openApiFiles[0]
|
|
87
|
+
}
|
|
88
|
+
: hasNodeJs && discoveredRoutes.length > 0
|
|
89
|
+
? {
|
|
90
|
+
type: 'nodejs',
|
|
91
|
+
rootDir: './'
|
|
92
|
+
}
|
|
93
|
+
: {
|
|
94
|
+
type: 'openapi',
|
|
95
|
+
path: './openapi.yaml'
|
|
96
|
+
},
|
|
97
|
+
server: {
|
|
98
|
+
name: `${projectName}-mcp`,
|
|
99
|
+
version: '1.0.0',
|
|
100
|
+
transport: 'stdio'
|
|
101
|
+
},
|
|
102
|
+
security: {
|
|
103
|
+
requireApprovalForDestructive: true,
|
|
104
|
+
autoApproveRead: true,
|
|
105
|
+
autoApproveWrite: false
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
return {
|
|
109
|
+
hasOpenApi,
|
|
110
|
+
openApiFiles,
|
|
111
|
+
hasNodeJs,
|
|
112
|
+
nodeJsFramework,
|
|
113
|
+
discoveredEndpointsCount: totalEndpoints,
|
|
114
|
+
authSchemesDetected: Array.from(authSchemesDetected),
|
|
115
|
+
recommendedConfig,
|
|
116
|
+
details: {
|
|
117
|
+
openApiSpecs: openApiSpecsDetails,
|
|
118
|
+
routes: discoveredRoutes
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
findOpenApiFiles(rootDir) {
|
|
123
|
+
const candidates = [
|
|
124
|
+
'openapi.yaml',
|
|
125
|
+
'openapi.yml',
|
|
126
|
+
'openapi.json',
|
|
127
|
+
'swagger.yaml',
|
|
128
|
+
'swagger.yml',
|
|
129
|
+
'swagger.json',
|
|
130
|
+
'api/openapi.yaml',
|
|
131
|
+
'api/openapi.json',
|
|
132
|
+
'docs/openapi.yaml',
|
|
133
|
+
'docs/openapi.json'
|
|
134
|
+
];
|
|
135
|
+
const found = [];
|
|
136
|
+
for (const rel of candidates) {
|
|
137
|
+
if (fs.existsSync(path.join(rootDir, rel))) {
|
|
138
|
+
found.push(rel);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Also search root for any *.openapi.json or *.swagger.yaml
|
|
142
|
+
try {
|
|
143
|
+
const files = fs.readdirSync(rootDir);
|
|
144
|
+
for (const file of files) {
|
|
145
|
+
if ((file.includes('openapi') || file.includes('swagger')) && !found.includes(file)) {
|
|
146
|
+
const ext = path.extname(file).toLowerCase();
|
|
147
|
+
if (['.json', '.yaml', '.yml'].includes(ext)) {
|
|
148
|
+
found.push(file);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
// ignore
|
|
155
|
+
}
|
|
156
|
+
return found;
|
|
157
|
+
}
|
|
158
|
+
countEndpoints(paths) {
|
|
159
|
+
let count = 0;
|
|
160
|
+
const methods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options'];
|
|
161
|
+
for (const pathItem of Object.values(paths)) {
|
|
162
|
+
if (pathItem && typeof pathItem === 'object') {
|
|
163
|
+
for (const m of methods) {
|
|
164
|
+
if (pathItem[m]) {
|
|
165
|
+
count++;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return count;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
export const defaultProjectScanner = new ProjectScanner();
|
|
174
|
+
//# sourceMappingURL=project-scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-scanner.js","sourceRoot":"","sources":["../../../src/core/discovery/project-scanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fridayy - Permission Classifier & Risk Assessment Engine
|
|
3
|
+
* Classifies API endpoints into READ, WRITE, and DESTRUCTIVE with risk scoring.
|
|
4
|
+
*/
|
|
5
|
+
import { ToolRiskLevel, ToolApprovalStatus, ToolPermissions, FridayyConfig } from '../schema/types.js';
|
|
6
|
+
export interface ClassificationContext {
|
|
7
|
+
method?: string;
|
|
8
|
+
path?: string;
|
|
9
|
+
operationId?: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
summary?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
tags?: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface ClassificationResult {
|
|
16
|
+
permissions: ToolPermissions;
|
|
17
|
+
risk: ToolRiskLevel;
|
|
18
|
+
status: ToolApprovalStatus;
|
|
19
|
+
reason: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Classifies an operation based on HTTP method, path, operationId, and naming keywords.
|
|
23
|
+
*/
|
|
24
|
+
export declare function classifyOperation(ctx: ClassificationContext, config?: FridayyConfig): ClassificationResult;
|
|
25
|
+
//# sourceMappingURL=classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../../../src/core/permissions/classifier.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEL,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,aAAa,EACd,MAAM,oBAAoB,CAAC;AAqB5B,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,qBAAqB,EAC1B,MAAM,CAAC,EAAE,aAAa,GACrB,oBAAoB,CAqEtB"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fridayy - Permission Classifier & Risk Assessment Engine
|
|
3
|
+
* Classifies API endpoints into READ, WRITE, and DESTRUCTIVE with risk scoring.
|
|
4
|
+
*/
|
|
5
|
+
const DESTRUCTIVE_KEYWORDS = [
|
|
6
|
+
'delete',
|
|
7
|
+
'remove',
|
|
8
|
+
'destroy',
|
|
9
|
+
'purge',
|
|
10
|
+
'erase',
|
|
11
|
+
'drop',
|
|
12
|
+
'truncate',
|
|
13
|
+
'kill',
|
|
14
|
+
'terminate',
|
|
15
|
+
'wipe',
|
|
16
|
+
'reset',
|
|
17
|
+
'cancel',
|
|
18
|
+
'revoke',
|
|
19
|
+
'uninstall',
|
|
20
|
+
'expire',
|
|
21
|
+
'block'
|
|
22
|
+
];
|
|
23
|
+
/**
|
|
24
|
+
* Classifies an operation based on HTTP method, path, operationId, and naming keywords.
|
|
25
|
+
*/
|
|
26
|
+
export function classifyOperation(ctx, config) {
|
|
27
|
+
const method = (ctx.method || 'GET').toUpperCase();
|
|
28
|
+
const fullText = [
|
|
29
|
+
ctx.name || '',
|
|
30
|
+
ctx.operationId || '',
|
|
31
|
+
ctx.path || '',
|
|
32
|
+
ctx.summary || '',
|
|
33
|
+
ctx.description || ''
|
|
34
|
+
]
|
|
35
|
+
.join(' ')
|
|
36
|
+
.toLowerCase();
|
|
37
|
+
// 1. Check for DESTRUCTIVE operations
|
|
38
|
+
const isDeleteMethod = method === 'DELETE';
|
|
39
|
+
const hasDestructiveKeyword = DESTRUCTIVE_KEYWORDS.some(kw => {
|
|
40
|
+
// Word boundary or underscore boundary check
|
|
41
|
+
const regex = new RegExp(`\\b${kw}\\b|_${kw}_|^${kw}_|_${kw}$`, 'i');
|
|
42
|
+
return regex.test(fullText);
|
|
43
|
+
});
|
|
44
|
+
if (isDeleteMethod || hasDestructiveKeyword) {
|
|
45
|
+
const isExplicitlyApproved = false;
|
|
46
|
+
return {
|
|
47
|
+
permissions: {
|
|
48
|
+
type: 'DESTRUCTIVE',
|
|
49
|
+
read: false,
|
|
50
|
+
write: true,
|
|
51
|
+
destructive: true,
|
|
52
|
+
requiresConfirmation: true
|
|
53
|
+
},
|
|
54
|
+
risk: 'high',
|
|
55
|
+
status: isExplicitlyApproved ? 'APPROVED' : 'BLOCKED',
|
|
56
|
+
reason: isDeleteMethod
|
|
57
|
+
? 'DELETE HTTP method carries destructive risk.'
|
|
58
|
+
: `Operation contains destructive action keyword: "${hasDestructiveKeyword}".`
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// 2. Check for READ operations
|
|
62
|
+
if (method === 'GET' || method === 'HEAD' || method === 'OPTIONS') {
|
|
63
|
+
const autoApproveRead = config?.security?.autoApproveRead ?? true;
|
|
64
|
+
return {
|
|
65
|
+
permissions: {
|
|
66
|
+
type: 'READ',
|
|
67
|
+
read: true,
|
|
68
|
+
write: false,
|
|
69
|
+
destructive: false,
|
|
70
|
+
requiresConfirmation: false
|
|
71
|
+
},
|
|
72
|
+
risk: 'low',
|
|
73
|
+
status: autoApproveRead ? 'APPROVED' : 'PENDING',
|
|
74
|
+
reason: `${method} HTTP method is a safe read-only operation.`
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
// 3. WRITE operations (POST, PUT, PATCH)
|
|
78
|
+
const autoApproveWrite = config?.security?.autoApproveWrite ?? false;
|
|
79
|
+
return {
|
|
80
|
+
permissions: {
|
|
81
|
+
type: 'WRITE',
|
|
82
|
+
read: false,
|
|
83
|
+
write: true,
|
|
84
|
+
destructive: false,
|
|
85
|
+
requiresConfirmation: false
|
|
86
|
+
},
|
|
87
|
+
risk: 'medium',
|
|
88
|
+
status: autoApproveWrite ? 'APPROVED' : 'PENDING',
|
|
89
|
+
reason: `${method} HTTP method mutates server state (WRITE operation).`
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifier.js","sourceRoot":"","sources":["../../../src/core/permissions/classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fridayy - Permission & Security Enforcer
|
|
3
|
+
* Enforces permission gates, status checks, and access rules for MCP tool invocation.
|
|
4
|
+
*/
|
|
5
|
+
import { FridayyToolDefinition, FridayyConfig } from '../schema/types.js';
|
|
6
|
+
export declare class PermissionDeniedError extends Error {
|
|
7
|
+
readonly code: string;
|
|
8
|
+
readonly toolName: string;
|
|
9
|
+
readonly details?: any;
|
|
10
|
+
constructor(message: string, toolName: string, code?: string, details?: any);
|
|
11
|
+
}
|
|
12
|
+
export declare class PermissionEnforcer {
|
|
13
|
+
private config?;
|
|
14
|
+
constructor(config?: FridayyConfig);
|
|
15
|
+
/**
|
|
16
|
+
* Checks if a tool should be visible and exposable to MCP clients.
|
|
17
|
+
*/
|
|
18
|
+
isToolExposed(tool: FridayyToolDefinition): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Enforces permissions before executing a tool. Throws PermissionDeniedError if execution is not allowed.
|
|
21
|
+
*/
|
|
22
|
+
validateExecution(tool: FridayyToolDefinition): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=enforcer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforcer.d.ts","sourceRoot":"","sources":["../../../src/core/permissions/enforcer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAE1E,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,OAAO,CAAC,EAAE,GAAG,CAAC;gBAElB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,SAAsB,EAAE,OAAO,CAAC,EAAE,GAAG;CAOzF;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAC,CAAgB;gBAEnB,MAAM,CAAC,EAAE,aAAa;IAIlC;;OAEG;IACI,aAAa,CAAC,IAAI,EAAE,qBAAqB,GAAG,OAAO;IAsB1D;;OAEG;IACI,iBAAiB,CAAC,IAAI,EAAE,qBAAqB,GAAG,IAAI;CAyD5D"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fridayy - Permission & Security Enforcer
|
|
3
|
+
* Enforces permission gates, status checks, and access rules for MCP tool invocation.
|
|
4
|
+
*/
|
|
5
|
+
export class PermissionDeniedError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
toolName;
|
|
8
|
+
details;
|
|
9
|
+
constructor(message, toolName, code = 'PERMISSION_DENIED', details) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'PermissionDeniedError';
|
|
12
|
+
this.code = code;
|
|
13
|
+
this.toolName = toolName;
|
|
14
|
+
this.details = details;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export class PermissionEnforcer {
|
|
18
|
+
config;
|
|
19
|
+
constructor(config) {
|
|
20
|
+
this.config = config;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Checks if a tool should be visible and exposable to MCP clients.
|
|
24
|
+
*/
|
|
25
|
+
isToolExposed(tool) {
|
|
26
|
+
// 1. Must be APPROVED
|
|
27
|
+
if (tool.status !== 'APPROVED') {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
// 2. Check allowlist / denylist from config
|
|
31
|
+
const toolName = tool.name;
|
|
32
|
+
const allowlist = this.config?.security?.allowlist;
|
|
33
|
+
const denylist = this.config?.security?.denylist;
|
|
34
|
+
if (denylist && denylist.includes(toolName)) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
if (allowlist && allowlist.length > 0 && !allowlist.includes(toolName) && !allowlist.includes('*')) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Enforces permissions before executing a tool. Throws PermissionDeniedError if execution is not allowed.
|
|
44
|
+
*/
|
|
45
|
+
validateExecution(tool) {
|
|
46
|
+
// Check status
|
|
47
|
+
if (tool.status === 'BLOCKED') {
|
|
48
|
+
throw new PermissionDeniedError(`Tool "${tool.name}" is BLOCKED. Destructive operations require explicit developer approval via 'fridayy review'.`, tool.name, 'TOOL_BLOCKED', { status: tool.status, permissions: tool.permissions });
|
|
49
|
+
}
|
|
50
|
+
if (tool.status === 'REJECTED') {
|
|
51
|
+
throw new PermissionDeniedError(`Tool "${tool.name}" is REJECTED and cannot be executed.`, tool.name, 'TOOL_REJECTED', { status: tool.status });
|
|
52
|
+
}
|
|
53
|
+
if (tool.status === 'PENDING') {
|
|
54
|
+
throw new PermissionDeniedError(`Tool "${tool.name}" is PENDING developer review. Run 'fridayy review' to approve it before invoking.`, tool.name, 'TOOL_PENDING_APPROVAL', { status: tool.status });
|
|
55
|
+
}
|
|
56
|
+
if (tool.status !== 'APPROVED') {
|
|
57
|
+
throw new PermissionDeniedError(`Tool "${tool.name}" has invalid status "${tool.status}" and cannot be executed.`, tool.name, 'TOOL_NOT_APPROVED');
|
|
58
|
+
}
|
|
59
|
+
// Denylist check
|
|
60
|
+
const denylist = this.config?.security?.denylist;
|
|
61
|
+
if (denylist && denylist.includes(tool.name)) {
|
|
62
|
+
throw new PermissionDeniedError(`Tool "${tool.name}" is explicitly denylisted in fridayy configuration.`, tool.name, 'TOOL_DENYLISTED');
|
|
63
|
+
}
|
|
64
|
+
// Allowlist check
|
|
65
|
+
const allowlist = this.config?.security?.allowlist;
|
|
66
|
+
if (allowlist && allowlist.length > 0 && !allowlist.includes(tool.name) && !allowlist.includes('*')) {
|
|
67
|
+
throw new PermissionDeniedError(`Tool "${tool.name}" is not included in the security allowlist.`, tool.name, 'TOOL_NOT_ALLOWLISTED');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=enforcer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforcer.js","sourceRoot":"","sources":["../../../src/core/permissions/enforcer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9B,IAAI,CAAS;IACb,QAAQ,CAAS;IACjB,OAAO,CAAO;IAE9B,YAAY,OAAe,EAAE,QAAgB,EAAE,IAAI,GAAG,mBAAmB,EAAE,OAAa;QACtF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,MAAM,OAAO,kBAAkB;IACrB,MAAM,CAAiB;IAE/B,YAAY,MAAsB;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACI,aAAa,CAAC,IAA2B;QAC9C,sBAAsB;QACtB,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC/B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,4CAA4C;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC;QAEjD,IAAI,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACnG,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACI,iBAAiB,CAAC,IAA2B;QAClD,eAAe;QACf,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,qBAAqB,CAC7B,SAAS,IAAI,CAAC,IAAI,gGAAgG,EAClH,IAAI,CAAC,IAAI,EACT,cAAc,EACd,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CACvD,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC/B,MAAM,IAAI,qBAAqB,CAC7B,SAAS,IAAI,CAAC,IAAI,uCAAuC,EACzD,IAAI,CAAC,IAAI,EACT,eAAe,EACf,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CACxB,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,qBAAqB,CAC7B,SAAS,IAAI,CAAC,IAAI,oFAAoF,EACtG,IAAI,CAAC,IAAI,EACT,uBAAuB,EACvB,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CACxB,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC/B,MAAM,IAAI,qBAAqB,CAC7B,SAAS,IAAI,CAAC,IAAI,yBAAyB,IAAI,CAAC,MAAM,2BAA2B,EACjF,IAAI,CAAC,IAAI,EACT,mBAAmB,CACpB,CAAC;QACJ,CAAC;QAED,iBAAiB;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC;QACjD,IAAI,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,qBAAqB,CAC7B,SAAS,IAAI,CAAC,IAAI,sDAAsD,EACxE,IAAI,CAAC,IAAI,EACT,iBAAiB,CAClB,CAAC;QACJ,CAAC;QAED,kBAAkB;QAClB,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC;QACnD,IAAI,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACpG,MAAM,IAAI,qBAAqB,CAC7B,SAAS,IAAI,CAAC,IAAI,8CAA8C,EAChE,IAAI,CAAC,IAAI,EACT,sBAAsB,CACvB,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fridayy - JSON Schema Unifier and Normalizer
|
|
3
|
+
* Combines OpenAPI/REST path, query, header parameters and request bodies
|
|
4
|
+
* into a single unified JSON Schema for standard MCP tools.
|
|
5
|
+
*/
|
|
6
|
+
import { ParameterDefinition, RequestBodyDefinition } from './types.js';
|
|
7
|
+
export interface UnifySchemaOptions {
|
|
8
|
+
parameters?: {
|
|
9
|
+
path?: ParameterDefinition[];
|
|
10
|
+
query?: ParameterDefinition[];
|
|
11
|
+
header?: ParameterDefinition[];
|
|
12
|
+
cookie?: ParameterDefinition[];
|
|
13
|
+
};
|
|
14
|
+
requestBody?: RequestBodyDefinition;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Normalizes an OpenAPI / JSON Schema type object into standard JSON Schema Draft-7 / 2020-12
|
|
18
|
+
*/
|
|
19
|
+
export declare function normalizeSchema(rawSchema: any): Record<string, any>;
|
|
20
|
+
/**
|
|
21
|
+
* Unifies all parameters and request body into a top-level MCP Tool inputSchema object.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildUnifiedInputSchema(options: UnifySchemaOptions): {
|
|
24
|
+
type: 'object';
|
|
25
|
+
properties: Record<string, any>;
|
|
26
|
+
required: string[];
|
|
27
|
+
additionalProperties?: boolean;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=json-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-schema.d.ts","sourceRoot":"","sources":["../../../src/core/schema/json-schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExE,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE;QACX,IAAI,CAAC,EAAE,mBAAmB,EAAE,CAAC;QAC7B,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;QAC9B,MAAM,CAAC,EAAE,mBAAmB,EAAE,CAAC;QAC/B,MAAM,CAAC,EAAE,mBAAmB,EAAE,CAAC;KAChC,CAAC;IACF,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAmCnE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,kBAAkB,GAAG;IACpE,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CA0FA"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fridayy - JSON Schema Unifier and Normalizer
|
|
3
|
+
* Combines OpenAPI/REST path, query, header parameters and request bodies
|
|
4
|
+
* into a single unified JSON Schema for standard MCP tools.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Normalizes an OpenAPI / JSON Schema type object into standard JSON Schema Draft-7 / 2020-12
|
|
8
|
+
*/
|
|
9
|
+
export function normalizeSchema(rawSchema) {
|
|
10
|
+
if (!rawSchema || typeof rawSchema !== 'object') {
|
|
11
|
+
return { type: 'string' };
|
|
12
|
+
}
|
|
13
|
+
const schema = { ...rawSchema };
|
|
14
|
+
// Handle nullable
|
|
15
|
+
if (schema.nullable && schema.type) {
|
|
16
|
+
if (typeof schema.type === 'string') {
|
|
17
|
+
schema.type = [schema.type, 'null'];
|
|
18
|
+
}
|
|
19
|
+
delete schema.nullable;
|
|
20
|
+
}
|
|
21
|
+
// Handle recursive objects
|
|
22
|
+
if (schema.type === 'object' && schema.properties) {
|
|
23
|
+
const normalizedProps = {};
|
|
24
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
25
|
+
normalizedProps[key] = normalizeSchema(prop);
|
|
26
|
+
}
|
|
27
|
+
schema.properties = normalizedProps;
|
|
28
|
+
}
|
|
29
|
+
// Handle arrays
|
|
30
|
+
if (schema.type === 'array' && schema.items) {
|
|
31
|
+
schema.items = normalizeSchema(schema.items);
|
|
32
|
+
}
|
|
33
|
+
// Clean up non-standard OpenAPI properties from tool input schema
|
|
34
|
+
delete schema.xml;
|
|
35
|
+
delete schema.externalDocs;
|
|
36
|
+
delete schema.example;
|
|
37
|
+
return schema;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Unifies all parameters and request body into a top-level MCP Tool inputSchema object.
|
|
41
|
+
*/
|
|
42
|
+
export function buildUnifiedInputSchema(options) {
|
|
43
|
+
const properties = {};
|
|
44
|
+
const requiredFields = new Set();
|
|
45
|
+
// 1. Process Path Parameters
|
|
46
|
+
if (options.parameters?.path) {
|
|
47
|
+
for (const param of options.parameters.path) {
|
|
48
|
+
const propSchema = normalizeSchema(param.schema);
|
|
49
|
+
if (param.description && !propSchema.description) {
|
|
50
|
+
propSchema.description = param.description;
|
|
51
|
+
}
|
|
52
|
+
properties[param.name] = propSchema;
|
|
53
|
+
// Path parameters are always required
|
|
54
|
+
requiredFields.add(param.name);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// 2. Process Query Parameters
|
|
58
|
+
if (options.parameters?.query) {
|
|
59
|
+
for (const param of options.parameters.query) {
|
|
60
|
+
const propSchema = normalizeSchema(param.schema);
|
|
61
|
+
if (param.description && !propSchema.description) {
|
|
62
|
+
propSchema.description = param.description;
|
|
63
|
+
}
|
|
64
|
+
properties[param.name] = propSchema;
|
|
65
|
+
if (param.required) {
|
|
66
|
+
requiredFields.add(param.name);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// 3. Process Header Parameters (skip standard auth headers to avoid exposing secrets)
|
|
71
|
+
if (options.parameters?.header) {
|
|
72
|
+
for (const param of options.parameters.header) {
|
|
73
|
+
const lower = param.name.toLowerCase();
|
|
74
|
+
if (lower === 'authorization' || lower === 'x-api-key') {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const propSchema = normalizeSchema(param.schema);
|
|
78
|
+
if (param.description && !propSchema.description) {
|
|
79
|
+
propSchema.description = param.description;
|
|
80
|
+
}
|
|
81
|
+
properties[param.name] = propSchema;
|
|
82
|
+
if (param.required) {
|
|
83
|
+
requiredFields.add(param.name);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// 4. Process Request Body
|
|
88
|
+
if (options.requestBody && options.requestBody.schema) {
|
|
89
|
+
const bodySchema = normalizeSchema(options.requestBody.schema);
|
|
90
|
+
if (bodySchema.type === 'object' && bodySchema.properties) {
|
|
91
|
+
// Flatten top-level properties if they don't collide with path/query params
|
|
92
|
+
for (const [propName, propVal] of Object.entries(bodySchema.properties)) {
|
|
93
|
+
if (!properties[propName]) {
|
|
94
|
+
properties[propName] = propVal;
|
|
95
|
+
if (Array.isArray(bodySchema.required) && bodySchema.required.includes(propName)) {
|
|
96
|
+
if (options.requestBody.required) {
|
|
97
|
+
requiredFields.add(propName);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// If collision, put into a nested body object
|
|
103
|
+
properties['body'] = bodySchema;
|
|
104
|
+
if (options.requestBody.required) {
|
|
105
|
+
requiredFields.add('body');
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Primitive or array body
|
|
113
|
+
properties['body'] = {
|
|
114
|
+
...bodySchema,
|
|
115
|
+
description: options.requestBody.description || 'Request payload'
|
|
116
|
+
};
|
|
117
|
+
if (options.requestBody.required) {
|
|
118
|
+
requiredFields.add('body');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
type: 'object',
|
|
124
|
+
properties,
|
|
125
|
+
required: Array.from(requiredFields),
|
|
126
|
+
additionalProperties: false
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=json-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-schema.js","sourceRoot":"","sources":["../../../src/core/schema/json-schema.ts"],"names":[],"mappings":"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"}
|