mcp4openapi 0.1.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.md +7 -0
- package/README.md +489 -0
- package/dist/composite-executor.d.ts +65 -0
- package/dist/composite-executor.d.ts.map +1 -0
- package/dist/composite-executor.js +147 -0
- package/dist/composite-executor.js.map +1 -0
- package/dist/constants.d.ts +36 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +36 -0
- package/dist/constants.js.map +1 -0
- package/dist/http-transport.d.ts +195 -0
- package/dist/http-transport.d.ts.map +1 -0
- package/dist/http-transport.js +760 -0
- package/dist/http-transport.js.map +1 -0
- package/dist/interceptors.d.ts +74 -0
- package/dist/interceptors.d.ts.map +1 -0
- package/dist/interceptors.js +220 -0
- package/dist/interceptors.js.map +1 -0
- package/dist/logger.d.ts +81 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +264 -0
- package/dist/logger.js.map +1 -0
- package/dist/mcp-server.d.ts +110 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +568 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/metrics.d.ts +86 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +229 -0
- package/dist/metrics.js.map +1 -0
- package/dist/openapi-parser.d.ts +35 -0
- package/dist/openapi-parser.d.ts.map +1 -0
- package/dist/openapi-parser.js +160 -0
- package/dist/openapi-parser.js.map +1 -0
- package/dist/profile-loader.d.ts +25 -0
- package/dist/profile-loader.d.ts.map +1 -0
- package/dist/profile-loader.js +134 -0
- package/dist/profile-loader.js.map +1 -0
- package/dist/schema-validator.d.ts +32 -0
- package/dist/schema-validator.d.ts.map +1 -0
- package/dist/schema-validator.js +126 -0
- package/dist/schema-validator.js.map +1 -0
- package/dist/scripts/validate-profile.d.ts +9 -0
- package/dist/scripts/validate-profile.d.ts.map +1 -0
- package/dist/scripts/validate-profile.js +289 -0
- package/dist/scripts/validate-profile.js.map +1 -0
- package/dist/scripts/validate-schema.d.ts +9 -0
- package/dist/scripts/validate-schema.d.ts.map +1 -0
- package/dist/scripts/validate-schema.js +84 -0
- package/dist/scripts/validate-schema.js.map +1 -0
- package/dist/src/composite-executor.d.ts +75 -0
- package/dist/src/composite-executor.d.ts.map +1 -0
- package/dist/src/composite-executor.js +175 -0
- package/dist/src/composite-executor.js.map +1 -0
- package/dist/src/constants.d.ts +36 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +36 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/dag-executor.d.ts +49 -0
- package/dist/src/dag-executor.d.ts.map +1 -0
- package/dist/src/dag-executor.js +138 -0
- package/dist/src/dag-executor.js.map +1 -0
- package/dist/src/errors.d.ts +47 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +99 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/generated-schemas.d.ts +661 -0
- package/dist/src/generated-schemas.d.ts.map +1 -0
- package/dist/src/generated-schemas.js +66 -0
- package/dist/src/generated-schemas.js.map +1 -0
- package/dist/src/http-client-factory.d.ts +62 -0
- package/dist/src/http-client-factory.d.ts.map +1 -0
- package/dist/src/http-client-factory.js +121 -0
- package/dist/src/http-client-factory.js.map +1 -0
- package/dist/src/http-transport.d.ts +194 -0
- package/dist/src/http-transport.d.ts.map +1 -0
- package/dist/src/http-transport.js +851 -0
- package/dist/src/http-transport.js.map +1 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +59 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interceptors.d.ts +78 -0
- package/dist/src/interceptors.d.ts.map +1 -0
- package/dist/src/interceptors.js +252 -0
- package/dist/src/interceptors.js.map +1 -0
- package/dist/src/jsonrpc-validator.d.ts +27 -0
- package/dist/src/jsonrpc-validator.d.ts.map +1 -0
- package/dist/src/jsonrpc-validator.js +58 -0
- package/dist/src/jsonrpc-validator.js.map +1 -0
- package/dist/src/lib.d.ts +8 -0
- package/dist/src/lib.d.ts.map +1 -0
- package/dist/src/lib.js +7 -0
- package/dist/src/lib.js.map +1 -0
- package/dist/src/logger.d.ts +81 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +264 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/mcp-server.d.ts +117 -0
- package/dist/src/mcp-server.d.ts.map +1 -0
- package/dist/src/mcp-server.js +621 -0
- package/dist/src/mcp-server.js.map +1 -0
- package/dist/src/metrics.d.ts +86 -0
- package/dist/src/metrics.d.ts.map +1 -0
- package/dist/src/metrics.js +229 -0
- package/dist/src/metrics.js.map +1 -0
- package/dist/src/naming-warnings.d.ts +23 -0
- package/dist/src/naming-warnings.d.ts.map +1 -0
- package/dist/src/naming-warnings.js +83 -0
- package/dist/src/naming-warnings.js.map +1 -0
- package/dist/src/naming.d.ts +58 -0
- package/dist/src/naming.d.ts.map +1 -0
- package/dist/src/naming.js +510 -0
- package/dist/src/naming.js.map +1 -0
- package/dist/src/openapi-parser.d.ts +49 -0
- package/dist/src/openapi-parser.d.ts.map +1 -0
- package/dist/src/openapi-parser.js +216 -0
- package/dist/src/openapi-parser.js.map +1 -0
- package/dist/src/profile-loader.d.ts +77 -0
- package/dist/src/profile-loader.d.ts.map +1 -0
- package/dist/src/profile-loader.js +443 -0
- package/dist/src/profile-loader.js.map +1 -0
- package/dist/src/schema-validator.d.ts +30 -0
- package/dist/src/schema-validator.d.ts.map +1 -0
- package/dist/src/schema-validator.js +115 -0
- package/dist/src/schema-validator.js.map +1 -0
- package/dist/src/testing/fixtures.d.ts +268 -0
- package/dist/src/testing/fixtures.d.ts.map +1 -0
- package/dist/src/testing/fixtures.js +210 -0
- package/dist/src/testing/fixtures.js.map +1 -0
- package/dist/src/testing/mock-gitlab-server.d.ts +34 -0
- package/dist/src/testing/mock-gitlab-server.d.ts.map +1 -0
- package/dist/src/testing/mock-gitlab-server.js +351 -0
- package/dist/src/testing/mock-gitlab-server.js.map +1 -0
- package/dist/src/testing/mock-utils.d.ts +41 -0
- package/dist/src/testing/mock-utils.d.ts.map +1 -0
- package/dist/src/testing/mock-utils.js +59 -0
- package/dist/src/testing/mock-utils.js.map +1 -0
- package/dist/src/testing/test-http-utils.d.ts +52 -0
- package/dist/src/testing/test-http-utils.d.ts.map +1 -0
- package/dist/src/testing/test-http-utils.js +109 -0
- package/dist/src/testing/test-http-utils.js.map +1 -0
- package/dist/src/testing/test-types.d.ts +76 -0
- package/dist/src/testing/test-types.d.ts.map +1 -0
- package/dist/src/testing/test-types.js +7 -0
- package/dist/src/testing/test-types.js.map +1 -0
- package/dist/src/tool-generator.d.ts +43 -0
- package/dist/src/tool-generator.d.ts.map +1 -0
- package/dist/src/tool-generator.js +123 -0
- package/dist/src/tool-generator.js.map +1 -0
- package/dist/src/types/http-transport.d.ts +45 -0
- package/dist/src/types/http-transport.d.ts.map +1 -0
- package/dist/src/types/http-transport.js +8 -0
- package/dist/src/types/http-transport.js.map +1 -0
- package/dist/src/types/openapi.d.ts +50 -0
- package/dist/src/types/openapi.d.ts.map +1 -0
- package/dist/src/types/openapi.js +9 -0
- package/dist/src/types/openapi.js.map +1 -0
- package/dist/src/types/profile.d.ts +80 -0
- package/dist/src/types/profile.d.ts.map +1 -0
- package/dist/src/types/profile.js +9 -0
- package/dist/src/types/profile.js.map +1 -0
- package/dist/src/validation-utils.d.ts +15 -0
- package/dist/src/validation-utils.d.ts.map +1 -0
- package/dist/src/validation-utils.js +25 -0
- package/dist/src/validation-utils.js.map +1 -0
- package/dist/testing/fixtures.d.ts +186 -0
- package/dist/testing/fixtures.d.ts.map +1 -0
- package/dist/testing/fixtures.js +135 -0
- package/dist/testing/fixtures.js.map +1 -0
- package/dist/testing/http-integration.test.d.ts +7 -0
- package/dist/testing/http-integration.test.d.ts.map +1 -0
- package/dist/testing/http-integration.test.js +383 -0
- package/dist/testing/http-integration.test.js.map +1 -0
- package/dist/testing/http-multiuser.test.d.ts +10 -0
- package/dist/testing/http-multiuser.test.d.ts.map +1 -0
- package/dist/testing/http-multiuser.test.js +255 -0
- package/dist/testing/http-multiuser.test.js.map +1 -0
- package/dist/testing/integration.test.d.ts +8 -0
- package/dist/testing/integration.test.d.ts.map +1 -0
- package/dist/testing/integration.test.js +247 -0
- package/dist/testing/integration.test.js.map +1 -0
- package/dist/testing/mock-gitlab-server.d.ts +34 -0
- package/dist/testing/mock-gitlab-server.d.ts.map +1 -0
- package/dist/testing/mock-gitlab-server.js +224 -0
- package/dist/testing/mock-gitlab-server.js.map +1 -0
- package/dist/testing/test-types.d.ts +59 -0
- package/dist/testing/test-types.d.ts.map +1 -0
- package/dist/testing/test-types.js +7 -0
- package/dist/testing/test-types.js.map +1 -0
- package/dist/tool-generator.d.ts +43 -0
- package/dist/tool-generator.d.ts.map +1 -0
- package/dist/tool-generator.js +123 -0
- package/dist/tool-generator.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/http-transport.d.ts +39 -0
- package/dist/types/http-transport.d.ts.map +1 -0
- package/dist/types/http-transport.js +8 -0
- package/dist/types/http-transport.js.map +1 -0
- package/dist/types/openapi.d.ts +50 -0
- package/dist/types/openapi.d.ts.map +1 -0
- package/dist/types/openapi.js +9 -0
- package/dist/types/openapi.js.map +1 -0
- package/dist/types/profile.d.ts +76 -0
- package/dist/types/profile.d.ts.map +1 -0
- package/dist/types/profile.js +9 -0
- package/dist/types/profile.js.map +1 -0
- package/package.json +84 -0
- package/profile-schema.json +369 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request body schema validator
|
|
3
|
+
*
|
|
4
|
+
* Why: Catch invalid requests before sending to API. Better error messages for users.
|
|
5
|
+
* Validates against OpenAPI schema definitions.
|
|
6
|
+
*/
|
|
7
|
+
export class SchemaValidator {
|
|
8
|
+
/**
|
|
9
|
+
* Validate request body against OpenAPI schema
|
|
10
|
+
*
|
|
11
|
+
* Why: Prevents sending malformed requests. OpenAPI schema is the source of truth.
|
|
12
|
+
*/
|
|
13
|
+
validateRequestBody(operation, body) {
|
|
14
|
+
if (!operation.requestBody?.content['application/json']?.schema) {
|
|
15
|
+
return { valid: true };
|
|
16
|
+
}
|
|
17
|
+
const schema = operation.requestBody.content['application/json'].schema;
|
|
18
|
+
const errors = [];
|
|
19
|
+
this.validateAgainstSchema(body, schema, '', errors);
|
|
20
|
+
return {
|
|
21
|
+
valid: errors.length === 0,
|
|
22
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Recursively validate data against schema
|
|
27
|
+
*/
|
|
28
|
+
validateAgainstSchema(data, schema, path, errors) {
|
|
29
|
+
// Null/undefined handling
|
|
30
|
+
if (data === null || data === undefined) {
|
|
31
|
+
if (schema.type && schema.type !== 'null') {
|
|
32
|
+
errors.push({
|
|
33
|
+
path: path || '(root)',
|
|
34
|
+
message: `Expected ${schema.type}, got ${data}`,
|
|
35
|
+
schema,
|
|
36
|
+
value: data,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Type validation
|
|
42
|
+
if (schema.type) {
|
|
43
|
+
const actualType = Array.isArray(data) ? 'array' : typeof data;
|
|
44
|
+
if (actualType !== schema.type) {
|
|
45
|
+
errors.push({
|
|
46
|
+
path: path || '(root)',
|
|
47
|
+
message: `Expected ${schema.type}, got ${actualType}`,
|
|
48
|
+
schema,
|
|
49
|
+
value: data,
|
|
50
|
+
});
|
|
51
|
+
return; // Stop validation if type is wrong
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Enum validation
|
|
55
|
+
// Note: Using 'as any' here is safe - we're checking if value exists in enum array
|
|
56
|
+
// TypeScript doesn't know the enum values at compile time
|
|
57
|
+
if (schema.enum && !schema.enum.includes(data)) {
|
|
58
|
+
errors.push({
|
|
59
|
+
path: path || '(root)',
|
|
60
|
+
message: `Value must be one of: ${schema.enum.join(', ')}`,
|
|
61
|
+
schema,
|
|
62
|
+
value: data,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// Object properties validation
|
|
66
|
+
if (schema.type === 'object' && schema.properties) {
|
|
67
|
+
const obj = data;
|
|
68
|
+
// Check required properties
|
|
69
|
+
for (const required of schema.required || []) {
|
|
70
|
+
if (obj[required] === undefined) {
|
|
71
|
+
errors.push({
|
|
72
|
+
path: path ? `${path}.${required}` : required,
|
|
73
|
+
message: 'Required property is missing',
|
|
74
|
+
schema,
|
|
75
|
+
value: undefined,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Validate each property
|
|
80
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
81
|
+
if (schema.properties[key]) {
|
|
82
|
+
this.validateAgainstSchema(value, schema.properties[key], path ? `${path}.${key}` : key, errors);
|
|
83
|
+
}
|
|
84
|
+
// Note: Not validating additionalProperties (too strict for most APIs)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Array items validation
|
|
88
|
+
if (schema.type === 'array' && schema.items && Array.isArray(data)) {
|
|
89
|
+
data.forEach((item, index) => {
|
|
90
|
+
this.validateAgainstSchema(item, schema.items, `${path}[${index}]`, errors);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// String format validation (basic)
|
|
94
|
+
if (schema.type === 'string' && schema.format && typeof data === 'string') {
|
|
95
|
+
if (schema.format === 'email' && !this.isEmail(data)) {
|
|
96
|
+
errors.push({
|
|
97
|
+
path: path || '(root)',
|
|
98
|
+
message: 'Invalid email format',
|
|
99
|
+
schema,
|
|
100
|
+
value: data,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (schema.format === 'uri' && !this.isUri(data)) {
|
|
104
|
+
errors.push({
|
|
105
|
+
path: path || '(root)',
|
|
106
|
+
message: 'Invalid URI format',
|
|
107
|
+
schema,
|
|
108
|
+
value: data,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
isEmail(value) {
|
|
114
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
115
|
+
}
|
|
116
|
+
isUri(value) {
|
|
117
|
+
try {
|
|
118
|
+
new URL(value);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=schema-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-validator.js","sourceRoot":"","sources":["../src/schema-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-profile.d.ts","sourceRoot":"","sources":["../../scripts/validate-profile.ts"],"names":[],"mappings":";AAEA;;;;;GAKG"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Profile validation script
|
|
4
|
+
*
|
|
5
|
+
* Why: Validates profile JSON against schema and checks logical consistency
|
|
6
|
+
* without requiring API access or tokens.
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'fs/promises';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { ProfileLoader } from '../dist/profile-loader.js';
|
|
12
|
+
import { OpenAPIParser } from '../dist/openapi-parser.js';
|
|
13
|
+
import { ToolGenerator } from '../dist/tool-generator.js';
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
16
|
+
async function validateProfile(profilePath, specPath) {
|
|
17
|
+
const result = {
|
|
18
|
+
valid: true,
|
|
19
|
+
errors: [],
|
|
20
|
+
warnings: [],
|
|
21
|
+
info: {},
|
|
22
|
+
};
|
|
23
|
+
try {
|
|
24
|
+
// 1. Check if profile file exists
|
|
25
|
+
try {
|
|
26
|
+
await fs.access(profilePath);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
result.valid = false;
|
|
30
|
+
result.errors.push(`Profile file not found: ${profilePath}`);
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
// 2. Check if it's valid JSON
|
|
34
|
+
let profileContent;
|
|
35
|
+
try {
|
|
36
|
+
profileContent = await fs.readFile(profilePath, 'utf-8');
|
|
37
|
+
JSON.parse(profileContent);
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
result.valid = false;
|
|
41
|
+
result.errors.push(`Invalid JSON: ${e.message}`);
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
// 3. Validate against schema using ProfileLoader
|
|
45
|
+
const loader = new ProfileLoader();
|
|
46
|
+
let profile;
|
|
47
|
+
try {
|
|
48
|
+
profile = await loader.load(profilePath);
|
|
49
|
+
result.info.profileName = profile.profile_name;
|
|
50
|
+
result.info.toolCount = profile.tools.length;
|
|
51
|
+
result.info.hasInterceptors = !!profile.interceptors;
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
result.valid = false;
|
|
55
|
+
result.errors.push(`Schema validation failed: ${e.message}`);
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
// 4. Check for common issues
|
|
59
|
+
// Check for duplicate tool names
|
|
60
|
+
const toolNames = new Set();
|
|
61
|
+
for (const tool of profile.tools) {
|
|
62
|
+
if (toolNames.has(tool.name)) {
|
|
63
|
+
result.valid = false;
|
|
64
|
+
result.errors.push(`Duplicate tool name: ${tool.name}`);
|
|
65
|
+
}
|
|
66
|
+
toolNames.add(tool.name);
|
|
67
|
+
}
|
|
68
|
+
// Check for missing action parameter in non-composite tools
|
|
69
|
+
for (const tool of profile.tools) {
|
|
70
|
+
if (!tool.composite && tool.operations) {
|
|
71
|
+
const actionCount = Object.keys(tool.operations).length;
|
|
72
|
+
if (actionCount > 1 && !tool.parameters.action) {
|
|
73
|
+
result.warnings.push(`Tool '${tool.name}' has ${actionCount} operations but no 'action' parameter`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Check for metadata_params that don't exist in parameters
|
|
78
|
+
for (const tool of profile.tools) {
|
|
79
|
+
if (tool.metadata_params) {
|
|
80
|
+
for (const metaParam of tool.metadata_params) {
|
|
81
|
+
if (!tool.parameters[metaParam]) {
|
|
82
|
+
result.warnings.push(`Tool '${tool.name}': metadata_param '${metaParam}' not found in parameters`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Check for required_for references to non-existent actions
|
|
88
|
+
for (const tool of profile.tools) {
|
|
89
|
+
if (!tool.operations)
|
|
90
|
+
continue;
|
|
91
|
+
// Extract valid actions from operation keys
|
|
92
|
+
// Supports patterns: "action", "action_suffix", "prefix_action"
|
|
93
|
+
const validActions = new Set();
|
|
94
|
+
for (const opKey of Object.keys(tool.operations)) {
|
|
95
|
+
validActions.add(opKey); // Add full key (e.g., "list_project")
|
|
96
|
+
// Extract parts: "approve_project" → ["approve", "project"]
|
|
97
|
+
const parts = opKey.split('_');
|
|
98
|
+
for (let i = 1; i <= parts.length; i++) {
|
|
99
|
+
// Add combinations: "approve", "approve_project"
|
|
100
|
+
validActions.add(parts.slice(0, i).join('_'));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
for (const [paramName, param] of Object.entries(tool.parameters)) {
|
|
104
|
+
if (param.required_for) {
|
|
105
|
+
for (const action of param.required_for) {
|
|
106
|
+
if (!validActions.has(action)) {
|
|
107
|
+
result.warnings.push(`Tool '${tool.name}', param '${paramName}': required_for '${action}' not found in operations: ${Object.keys(tool.operations).join(', ')}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// 5. If OpenAPI spec provided, validate operations exist
|
|
114
|
+
if (specPath) {
|
|
115
|
+
try {
|
|
116
|
+
await fs.access(specPath);
|
|
117
|
+
const parser = new OpenAPIParser();
|
|
118
|
+
await parser.load(specPath);
|
|
119
|
+
let operationCount = 0;
|
|
120
|
+
const missingOps = [];
|
|
121
|
+
for (const tool of profile.tools) {
|
|
122
|
+
if (tool.operations) {
|
|
123
|
+
for (const [action, operationId] of Object.entries(tool.operations)) {
|
|
124
|
+
operationCount++;
|
|
125
|
+
try {
|
|
126
|
+
parser.getOperation(operationId);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
missingOps.push(`${tool.name}.${action} → ${operationId}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (tool.steps) {
|
|
134
|
+
for (const step of tool.steps) {
|
|
135
|
+
operationCount++;
|
|
136
|
+
try {
|
|
137
|
+
parser.getOperation(step.call);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
missingOps.push(`${tool.name} step → ${step.call}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
result.info.operations = operationCount;
|
|
146
|
+
if (missingOps.length > 0) {
|
|
147
|
+
result.valid = false;
|
|
148
|
+
result.errors.push(`Missing operations in OpenAPI spec:\n - ${missingOps.join('\n - ')}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch (e) {
|
|
152
|
+
result.warnings.push(`Could not validate against OpenAPI spec: ${e.message}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
result.warnings.push('OpenAPI spec not provided, skipping operation validation');
|
|
157
|
+
}
|
|
158
|
+
// 6. Validate tool generation (smoke test)
|
|
159
|
+
if (specPath) {
|
|
160
|
+
try {
|
|
161
|
+
const parser = new OpenAPIParser();
|
|
162
|
+
await parser.load(specPath);
|
|
163
|
+
const generator = new ToolGenerator(parser);
|
|
164
|
+
for (const toolDef of profile.tools) {
|
|
165
|
+
try {
|
|
166
|
+
generator.generateTool(toolDef);
|
|
167
|
+
}
|
|
168
|
+
catch (e) {
|
|
169
|
+
result.warnings.push(`Tool generation failed for '${toolDef.name}': ${e.message}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// Already handled above
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// 7. Check for best practices
|
|
178
|
+
// Warn if too many tools (context pollution)
|
|
179
|
+
if (profile.tools.length > 20) {
|
|
180
|
+
result.warnings.push(`Profile has ${profile.tools.length} tools. Consider aggregating related operations to reduce LLM context pollution.`);
|
|
181
|
+
}
|
|
182
|
+
// Warn if no interceptors (likely needs auth)
|
|
183
|
+
if (!profile.interceptors || !profile.interceptors.auth) {
|
|
184
|
+
result.warnings.push('No authentication configured. Most APIs require authentication.');
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
result.valid = false;
|
|
189
|
+
result.errors.push(`Unexpected error: ${e.message}`);
|
|
190
|
+
}
|
|
191
|
+
return result;
|
|
192
|
+
}
|
|
193
|
+
function printResult(result) {
|
|
194
|
+
console.log('');
|
|
195
|
+
console.log('═══════════════════════════════════════════════════');
|
|
196
|
+
console.log(' PROFILE VALIDATION RESULTS');
|
|
197
|
+
console.log('═══════════════════════════════════════════════════');
|
|
198
|
+
console.log('');
|
|
199
|
+
// Info
|
|
200
|
+
if (result.info.profileName) {
|
|
201
|
+
console.log(`Profile: ${result.info.profileName}`);
|
|
202
|
+
}
|
|
203
|
+
if (result.info.toolCount !== undefined) {
|
|
204
|
+
console.log(`Tools: ${result.info.toolCount}`);
|
|
205
|
+
}
|
|
206
|
+
if (result.info.operations !== undefined) {
|
|
207
|
+
console.log(`Operations: ${result.info.operations}`);
|
|
208
|
+
}
|
|
209
|
+
if (result.info.hasInterceptors !== undefined) {
|
|
210
|
+
console.log(`Interceptors: ${result.info.hasInterceptors ? 'configured' : 'none'}`);
|
|
211
|
+
}
|
|
212
|
+
console.log('');
|
|
213
|
+
// Errors
|
|
214
|
+
if (result.errors.length > 0) {
|
|
215
|
+
console.log('❌ ERRORS:');
|
|
216
|
+
for (const error of result.errors) {
|
|
217
|
+
console.log(` • ${error}`);
|
|
218
|
+
}
|
|
219
|
+
console.log('');
|
|
220
|
+
}
|
|
221
|
+
// Warnings
|
|
222
|
+
if (result.warnings.length > 0) {
|
|
223
|
+
console.log('⚠️ WARNINGS:');
|
|
224
|
+
for (const warning of result.warnings) {
|
|
225
|
+
console.log(` • ${warning}`);
|
|
226
|
+
}
|
|
227
|
+
console.log('');
|
|
228
|
+
}
|
|
229
|
+
// Status
|
|
230
|
+
if (result.valid && result.errors.length === 0) {
|
|
231
|
+
if (result.warnings.length === 0) {
|
|
232
|
+
console.log('✅ VALID - No issues found');
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
console.log('✅ VALID - Profile is valid but has warnings');
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
console.log('❌ INVALID - Profile has errors');
|
|
240
|
+
}
|
|
241
|
+
console.log('');
|
|
242
|
+
console.log('═══════════════════════════════════════════════════');
|
|
243
|
+
}
|
|
244
|
+
async function main() {
|
|
245
|
+
const args = process.argv.slice(2);
|
|
246
|
+
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
|
|
247
|
+
console.log(`
|
|
248
|
+
Usage: npm run validate -- <profile.json> [openapi.yaml]
|
|
249
|
+
|
|
250
|
+
Validates MCP profile configuration without requiring API access.
|
|
251
|
+
|
|
252
|
+
Arguments:
|
|
253
|
+
<profile.json> Path to profile file (required)
|
|
254
|
+
[openapi.yaml] Path to OpenAPI spec (optional, enables operation validation)
|
|
255
|
+
|
|
256
|
+
Options:
|
|
257
|
+
--help, -h Show this help message
|
|
258
|
+
|
|
259
|
+
Examples:
|
|
260
|
+
npm run validate -- profiles/my-api-profile.json
|
|
261
|
+
npm run validate -- profiles/my-api-profile.json openapi.yaml
|
|
262
|
+
|
|
263
|
+
What is validated:
|
|
264
|
+
✓ JSON syntax
|
|
265
|
+
✓ Schema compliance (types, required fields, enums)
|
|
266
|
+
✓ Logical consistency (required_for references, metadata_params)
|
|
267
|
+
✓ No duplicate tool names
|
|
268
|
+
✓ Operations exist in OpenAPI spec (if provided)
|
|
269
|
+
✓ Tool generation (smoke test)
|
|
270
|
+
✓ Best practices (tool count, auth configuration)
|
|
271
|
+
`);
|
|
272
|
+
process.exit(0);
|
|
273
|
+
}
|
|
274
|
+
const profilePath = path.resolve(process.cwd(), args[0]);
|
|
275
|
+
const specPath = args[1] ? path.resolve(process.cwd(), args[1]) : undefined;
|
|
276
|
+
console.log('Validating profile...');
|
|
277
|
+
console.log(`Profile: ${profilePath}`);
|
|
278
|
+
if (specPath) {
|
|
279
|
+
console.log(`OpenAPI Spec: ${specPath}`);
|
|
280
|
+
}
|
|
281
|
+
const result = await validateProfile(profilePath, specPath);
|
|
282
|
+
printResult(result);
|
|
283
|
+
process.exit(result.valid ? 0 : 1);
|
|
284
|
+
}
|
|
285
|
+
main().catch((e) => {
|
|
286
|
+
console.error('Fatal error:', e);
|
|
287
|
+
process.exit(1);
|
|
288
|
+
});
|
|
289
|
+
//# sourceMappingURL=validate-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-profile.js","sourceRoot":"","sources":["../../scripts/validate-profile.ts"],"names":[],"mappings":";AAEA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAc3C,KAAK,UAAU,eAAe,CAC5B,WAAmB,EACnB,QAAiB;IAEjB,MAAM,MAAM,GAAqB;QAC/B,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,EAAE;KACT,CAAC;IAEF,IAAI,CAAC;QACH,kCAAkC;QAClC,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;YACrB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,WAAW,EAAE,CAAC,CAAC;YAC7D,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,8BAA8B;QAC9B,IAAI,cAAsB,CAAC;QAC3B,IAAI,CAAC;YACH,cAAc,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACzD,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC7B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;YACrB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAkB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5D,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,iDAAiD;QACjD,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QACnC,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACzC,MAAM,CAAC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;YAC/C,MAAM,CAAC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;QACvD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;YACrB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,6BAA8B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YACxE,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,6BAA6B;QAE7B,iCAAiC;QACjC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;QACpC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC7B,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;gBACrB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1D,CAAC;YACD,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QAED,4DAA4D;QAC5D,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACvC,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;gBACxD,IAAI,WAAW,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;oBAC/C,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,SAAS,IAAI,CAAC,IAAI,SAAS,WAAW,uCAAuC,CAC9E,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,2DAA2D;QAC3D,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;gBACzB,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;oBAC7C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;wBAChC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,SAAS,IAAI,CAAC,IAAI,sBAAsB,SAAS,2BAA2B,CAC7E,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,4DAA4D;QAC5D,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YACjC,IAAI,CAAC,IAAI,CAAC,UAAU;gBAAE,SAAS;YAE/B,4CAA4C;YAC5C,gEAAgE;YAChE,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;YACvC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBACjD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,sCAAsC;gBAE/D,4DAA4D;gBAC5D,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACvC,iDAAiD;oBACjD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;YAED,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;gBACjE,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;oBACvB,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;wBACxC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;4BAC9B,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,SAAS,IAAI,CAAC,IAAI,aAAa,SAAS,oBAAoB,MAAM,8BAA8B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC1I,CAAC;wBACJ,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,yDAAyD;QACzD,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAE1B,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;gBACnC,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAE5B,IAAI,cAAc,GAAG,CAAC,CAAC;gBACvB,MAAM,UAAU,GAAa,EAAE,CAAC;gBAEhC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;oBACjC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;wBACpB,KAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;4BACpE,cAAc,EAAE,CAAC;4BACjB,IAAI,CAAC;gCACH,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;4BACnC,CAAC;4BAAC,MAAM,CAAC;gCACP,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,MAAM,WAAW,EAAE,CAAC,CAAC;4BAC7D,CAAC;wBACH,CAAC;oBACH,CAAC;oBAED,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;wBACf,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;4BAC9B,cAAc,EAAE,CAAC;4BACjB,IAAI,CAAC;gCACH,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;4BACjC,CAAC;4BAAC,MAAM,CAAC;gCACP,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;4BACtD,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,MAAM,CAAC,IAAI,CAAC,UAAU,GAAG,cAAc,CAAC;gBAExC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1B,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;oBACrB,MAAM,CAAC,MAAM,CAAC,IAAI,CAChB,4CAA4C,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CACxE,CAAC;gBACJ,CAAC;YACH,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,4CAA6C,CAAW,CAAC,OAAO,EAAE,CACnE,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,0DAA0D,CAC3D,CAAC;QACJ,CAAC;QAED,2CAA2C;QAC3C,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;gBACnC,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC5B,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;gBAE5C,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;oBACpC,IAAI,CAAC;wBACH,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;oBAClC,CAAC;oBAAC,OAAO,CAAC,EAAE,CAAC;wBACX,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,+BAA+B,OAAO,CAAC,IAAI,MAAO,CAAW,CAAC,OAAO,EAAE,CACxE,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC;QAED,8BAA8B;QAE9B,6CAA6C;QAC7C,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YAC9B,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,eAAe,OAAO,CAAC,KAAK,CAAC,MAAM,kFAAkF,CACtH,CAAC;QACJ,CAAC;QAED,8CAA8C;QAC9C,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YACxD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAClB,iEAAiE,CAClE,CAAC;QACJ,CAAC;IAEH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAsB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,MAAwB;IAC3C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;IACnE,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;IACnE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,OAAO;IACP,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,CAAC,GAAG,CACT,iBAAiB,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,EAAE,CACvE,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,SAAS;IACT,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,WAAW;IACX,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC7B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,SAAS;IACT,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/C,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;AACrE,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;CAwBf,CAAC,CAAC;QACC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE5E,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,YAAY,WAAW,EAAE,CAAC,CAAC;IACvC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC5D,WAAW,CAAC,MAAM,CAAC,CAAC;IAEpB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;IACjB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;IACjC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Validates profile-schema.json against JSON Schema Draft-07 meta-schema
|
|
4
|
+
*
|
|
5
|
+
* Why: Ensures our schema is valid before users rely on it for validation
|
|
6
|
+
*/
|
|
7
|
+
declare function validateSchema(): Promise<void>;
|
|
8
|
+
export { validateSchema };
|
|
9
|
+
//# sourceMappingURL=validate-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-schema.d.ts","sourceRoot":"","sources":["../../scripts/validate-schema.ts"],"names":[],"mappings":";AAEA;;;;GAIG;AAWH,iBAAe,cAAc,kBAyE5B;AAOD,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Validates profile-schema.json against JSON Schema Draft-07 meta-schema
|
|
4
|
+
*
|
|
5
|
+
* Why: Ensures our schema is valid before users rely on it for validation
|
|
6
|
+
*/
|
|
7
|
+
import Ajv from 'ajv';
|
|
8
|
+
import addFormats from 'ajv-formats';
|
|
9
|
+
import fs from 'fs/promises';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
async function validateSchema() {
|
|
15
|
+
try {
|
|
16
|
+
// Read our profile schema (from project root)
|
|
17
|
+
const schemaPath = path.resolve(process.cwd(), 'profile-schema.json');
|
|
18
|
+
const schemaContent = await fs.readFile(schemaPath, 'utf-8');
|
|
19
|
+
const profileSchema = JSON.parse(schemaContent);
|
|
20
|
+
// Create Ajv instance with Draft-07 support
|
|
21
|
+
const ajv = new Ajv.default({
|
|
22
|
+
strict: true,
|
|
23
|
+
allErrors: true,
|
|
24
|
+
verbose: true,
|
|
25
|
+
});
|
|
26
|
+
// Add format validators (uri, etc.)
|
|
27
|
+
addFormats.default(ajv);
|
|
28
|
+
// Validate against meta-schema (Draft-07)
|
|
29
|
+
const validate = ajv.compile(ajv.getSchema('http://json-schema.org/draft-07/schema')?.schema || {});
|
|
30
|
+
const valid = validate(profileSchema);
|
|
31
|
+
console.log('');
|
|
32
|
+
console.log('═══════════════════════════════════════════════════');
|
|
33
|
+
console.log(' PROFILE SCHEMA VALIDATION');
|
|
34
|
+
console.log('═══════════════════════════════════════════════════');
|
|
35
|
+
console.log('');
|
|
36
|
+
console.log(`Schema: ${schemaPath}`);
|
|
37
|
+
console.log(`Meta-Schema: JSON Schema Draft-07`);
|
|
38
|
+
console.log('');
|
|
39
|
+
if (valid) {
|
|
40
|
+
console.log('✅ VALID - profile-schema.json is a valid JSON Schema');
|
|
41
|
+
console.log('');
|
|
42
|
+
// Test that it can compile
|
|
43
|
+
try {
|
|
44
|
+
ajv.compile(profileSchema);
|
|
45
|
+
console.log('✅ COMPILABLE - Schema can be used for validation');
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
console.log('⚠️ WARNING - Schema is valid but may have compilation issues:');
|
|
49
|
+
console.log(` ${e.message}`);
|
|
50
|
+
}
|
|
51
|
+
console.log('');
|
|
52
|
+
console.log('Schema Statistics:');
|
|
53
|
+
console.log(` Definitions: ${Object.keys(profileSchema.definitions || {}).length}`);
|
|
54
|
+
console.log(` Root properties: ${Object.keys(profileSchema.properties || {}).length}`);
|
|
55
|
+
console.log(` Required fields: ${(profileSchema.required || []).length}`);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.log('❌ INVALID - profile-schema.json has errors:');
|
|
59
|
+
console.log('');
|
|
60
|
+
if (validate.errors) {
|
|
61
|
+
for (const error of validate.errors) {
|
|
62
|
+
console.log(` • ${error.instancePath || '/'}: ${error.message}`);
|
|
63
|
+
if (error.params) {
|
|
64
|
+
console.log(` ${JSON.stringify(error.params)}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
console.log('');
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
console.log('');
|
|
72
|
+
console.log('═══════════════════════════════════════════════════');
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
console.error('Fatal error:', e.message);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Run if called directly
|
|
80
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
81
|
+
validateSchema();
|
|
82
|
+
}
|
|
83
|
+
export { validateSchema };
|
|
84
|
+
//# sourceMappingURL=validate-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-schema.js","sourceRoot":"","sources":["../../scripts/validate-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composite action executor for chaining API calls
|
|
3
|
+
*
|
|
4
|
+
* Why: Reduces roundtrips by fetching related data in sequence (e.g., MR + comments).
|
|
5
|
+
* Aggregates results into single JSON structure as defined by store_as paths.
|
|
6
|
+
*/
|
|
7
|
+
import type { CompositeStep } from './types/profile.js';
|
|
8
|
+
import type { HttpClient } from './interceptors.js';
|
|
9
|
+
import { OpenAPIParser } from './openapi-parser.js';
|
|
10
|
+
export interface CompositeResult {
|
|
11
|
+
data: Record<string, unknown>;
|
|
12
|
+
completed_steps: number;
|
|
13
|
+
total_steps: number;
|
|
14
|
+
errors?: StepError[];
|
|
15
|
+
}
|
|
16
|
+
export interface StepError {
|
|
17
|
+
step_index: number;
|
|
18
|
+
step_call: string;
|
|
19
|
+
error: string;
|
|
20
|
+
timestamp: string;
|
|
21
|
+
}
|
|
22
|
+
export declare class CompositeExecutor {
|
|
23
|
+
private parser;
|
|
24
|
+
private httpClient?;
|
|
25
|
+
constructor(parser: OpenAPIParser, httpClient?: HttpClient | undefined);
|
|
26
|
+
/**
|
|
27
|
+
* Execute a series of API calls and merge results
|
|
28
|
+
*
|
|
29
|
+
* Why parallel: Steps may have dependencies, but independent steps can run concurrently.
|
|
30
|
+
* Uses DAG analysis to determine safe parallelization while maintaining correctness.
|
|
31
|
+
*
|
|
32
|
+
* Supports partial results: If allowPartial=true, continues after errors and returns
|
|
33
|
+
* what was completed. Useful for composite actions where some data is better than none.
|
|
34
|
+
*/
|
|
35
|
+
execute(steps: CompositeStep[], args: Record<string, unknown>, allowPartial?: boolean, httpClient?: HttpClient): Promise<CompositeResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Execute single composite step (extracted for parallel execution)
|
|
38
|
+
*
|
|
39
|
+
* @param step The composite step to execute
|
|
40
|
+
* @param stepIndex Original index for error reporting
|
|
41
|
+
* @param args Arguments for parameter substitution
|
|
42
|
+
* @param httpClient Optional HTTP client override
|
|
43
|
+
* @returns Promise resolving to HTTP response
|
|
44
|
+
*/
|
|
45
|
+
private executeStep;
|
|
46
|
+
/**
|
|
47
|
+
* Parse composite step call syntax
|
|
48
|
+
*
|
|
49
|
+
* Format: "GET /projects/{id}/merge_requests/{iid}"
|
|
50
|
+
*/
|
|
51
|
+
private parseCall;
|
|
52
|
+
/**
|
|
53
|
+
* Resolve path template with actual values
|
|
54
|
+
*
|
|
55
|
+
* Example: "/projects/{id}" + {id: "123"} => "/projects/123"
|
|
56
|
+
*/
|
|
57
|
+
private resolvePath;
|
|
58
|
+
/**
|
|
59
|
+
* Extract query parameters from args based on operation definition
|
|
60
|
+
*/
|
|
61
|
+
private extractQueryParams;
|
|
62
|
+
/**
|
|
63
|
+
* Store value at JSONPath-like location
|
|
64
|
+
*
|
|
65
|
+
* Why nested: Allows semantic structure (comments belong under merge_request object).
|
|
66
|
+
*
|
|
67
|
+
* Examples:
|
|
68
|
+
* - "merge_request" => { merge_request: value }
|
|
69
|
+
* - "merge_request.comments" => { merge_request: { comments: value } }
|
|
70
|
+
*
|
|
71
|
+
* Validates path navigation to prevent overwriting non-object values.
|
|
72
|
+
*/
|
|
73
|
+
private storeResult;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=composite-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composite-executor.d.ts","sourceRoot":"","sources":["../../src/composite-executor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU,CAAC;gBADX,MAAM,EAAE,aAAa,EACrB,UAAU,CAAC,EAAE,UAAU,YAAA;IAGjC;;;;;;;;OAQG;IACG,OAAO,CACX,KAAK,EAAE,aAAa,EAAE,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,YAAY,GAAE,OAAe,EAC7B,UAAU,CAAC,EAAE,UAAU,GACtB,OAAO,CAAC,eAAe,CAAC;IA+D3B;;;;;;;;OAQG;YACW,WAAW;IA6BzB;;;;OAIG;IACH,OAAO,CAAC,SAAS;IAQjB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,WAAW;CAwBpB"}
|