mcp-medic 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 +169 -0
- package/action.yml +57 -0
- package/dist/checks/index.d.ts +6 -0
- package/dist/checks/index.js +17 -0
- package/dist/checks/malformed-schema.d.ts +2 -0
- package/dist/checks/malformed-schema.js +63 -0
- package/dist/checks/missing-description.d.ts +2 -0
- package/dist/checks/missing-description.js +71 -0
- package/dist/checks/missing-required-fields.d.ts +2 -0
- package/dist/checks/missing-required-fields.js +55 -0
- package/dist/checks/sample-call-simulation.d.ts +2 -0
- package/dist/checks/sample-call-simulation.js +239 -0
- package/dist/checks/type-mismatch.d.ts +2 -0
- package/dist/checks/type-mismatch.js +154 -0
- package/dist/cli.d.ts +20 -0
- package/dist/cli.js +457 -0
- package/dist/config-loader.d.ts +6 -0
- package/dist/config-loader.js +77 -0
- package/dist/conformance.d.ts +10 -0
- package/dist/conformance.js +112 -0
- package/dist/discovery.d.ts +9 -0
- package/dist/discovery.js +76 -0
- package/dist/extension/index.d.ts +79 -0
- package/dist/extension/index.js +125 -0
- package/dist/fleet.d.ts +48 -0
- package/dist/fleet.js +153 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +13 -0
- package/dist/junit.d.ts +10 -0
- package/dist/junit.js +87 -0
- package/dist/orchestrator.d.ts +6 -0
- package/dist/orchestrator.js +60 -0
- package/dist/policy.d.ts +16 -0
- package/dist/policy.js +143 -0
- package/dist/protocol/connect.d.ts +2 -0
- package/dist/protocol/connect.js +417 -0
- package/dist/protocol/index.d.ts +3 -0
- package/dist/protocol/index.js +6 -0
- package/dist/registry.d.ts +16 -0
- package/dist/registry.js +87 -0
- package/dist/report.d.ts +7 -0
- package/dist/report.js +30 -0
- package/dist/types.d.ts +70 -0
- package/dist/types.js +4 -0
- package/dist/watch.d.ts +12 -0
- package/dist/watch.js +85 -0
- package/package.json +56 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
function generatePlaceholderForType(propDef) {
|
|
2
|
+
// 1. If enum is specified
|
|
3
|
+
if (Array.isArray(propDef.enum)) {
|
|
4
|
+
if (propDef.enum.length === 0) {
|
|
5
|
+
throw new Error('required enum array is empty');
|
|
6
|
+
}
|
|
7
|
+
return { value: propDef.enum[0] };
|
|
8
|
+
}
|
|
9
|
+
// 2. If default is specified
|
|
10
|
+
if (propDef.default !== undefined) {
|
|
11
|
+
return { value: propDef.default };
|
|
12
|
+
}
|
|
13
|
+
// 3. Match by type
|
|
14
|
+
const rawType = propDef.type;
|
|
15
|
+
const targetType = Array.isArray(rawType) ? rawType[0] : rawType;
|
|
16
|
+
if (targetType === 'string') {
|
|
17
|
+
if (typeof propDef.minLength === 'number' && propDef.minLength > 0) {
|
|
18
|
+
return { value: 'a'.repeat(propDef.minLength) };
|
|
19
|
+
}
|
|
20
|
+
return { value: '' };
|
|
21
|
+
}
|
|
22
|
+
if (targetType === 'number' || targetType === 'integer') {
|
|
23
|
+
if (typeof propDef.minimum === 'number' && propDef.minimum > 0) {
|
|
24
|
+
return { value: propDef.minimum };
|
|
25
|
+
}
|
|
26
|
+
return { value: 0 };
|
|
27
|
+
}
|
|
28
|
+
if (targetType === 'boolean') {
|
|
29
|
+
return { value: false };
|
|
30
|
+
}
|
|
31
|
+
if (targetType === 'array') {
|
|
32
|
+
return { value: [] };
|
|
33
|
+
}
|
|
34
|
+
if (targetType === 'object') {
|
|
35
|
+
return { value: {} };
|
|
36
|
+
}
|
|
37
|
+
if (targetType === 'null') {
|
|
38
|
+
return { value: null };
|
|
39
|
+
}
|
|
40
|
+
// Fallback if type is missing or complex
|
|
41
|
+
return {
|
|
42
|
+
value: '',
|
|
43
|
+
caveat: `unknown or missing type "${String(rawType)}", defaulted to empty string`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function validateSyntheticPayload(payload, schema) {
|
|
47
|
+
const errors = [];
|
|
48
|
+
const caveats = [];
|
|
49
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
50
|
+
const properties = schema.properties && typeof schema.properties === 'object' && !Array.isArray(schema.properties)
|
|
51
|
+
? schema.properties
|
|
52
|
+
: {};
|
|
53
|
+
// Verify all required fields are present
|
|
54
|
+
for (const req of required) {
|
|
55
|
+
if (typeof req === 'string' && !(req in payload)) {
|
|
56
|
+
errors.push(`Missing required field "${req}" in synthetic payload.`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Validate properties
|
|
60
|
+
for (const [key, val] of Object.entries(payload)) {
|
|
61
|
+
const propDef = properties[key];
|
|
62
|
+
if (!propDef || typeof propDef !== 'object' || Array.isArray(propDef)) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const propObj = propDef;
|
|
66
|
+
// Enum validation
|
|
67
|
+
if (Array.isArray(propObj.enum)) {
|
|
68
|
+
if (propObj.enum.length === 0) {
|
|
69
|
+
errors.push(`Field "${key}" specifies an empty enum array.`);
|
|
70
|
+
}
|
|
71
|
+
else if (!propObj.enum.includes(val)) {
|
|
72
|
+
errors.push(`Field "${key}" value ${JSON.stringify(val)} is not in enum [${propObj.enum.map((e) => JSON.stringify(e)).join(', ')}].`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Number constraints check
|
|
76
|
+
if (typeof val === 'number') {
|
|
77
|
+
if (typeof propObj.minimum === 'number' && typeof propObj.maximum === 'number') {
|
|
78
|
+
if (propObj.minimum > propObj.maximum) {
|
|
79
|
+
errors.push(`Field "${key}" has contradictory bounds: minimum (${propObj.minimum}) > maximum (${propObj.maximum}).`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (typeof propObj.minimum === 'number' && val < propObj.minimum) {
|
|
83
|
+
errors.push(`Field "${key}" value ${val} is less than minimum ${propObj.minimum}.`);
|
|
84
|
+
}
|
|
85
|
+
if (typeof propObj.maximum === 'number' && val > propObj.maximum) {
|
|
86
|
+
errors.push(`Field "${key}" value ${val} is greater than maximum ${propObj.maximum}.`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// String constraints check
|
|
90
|
+
if (typeof val === 'string') {
|
|
91
|
+
if (typeof propObj.minLength === 'number' && typeof propObj.maxLength === 'number') {
|
|
92
|
+
if (propObj.minLength > propObj.maxLength) {
|
|
93
|
+
errors.push(`Field "${key}" has contradictory bounds: minLength (${propObj.minLength}) > maxLength (${propObj.maxLength}).`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (schema.$ref || schema.oneOf || schema.anyOf || schema.allOf) {
|
|
99
|
+
caveats.push('Schema uses complex combinators or references ($ref/oneOf/anyOf/allOf).');
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
valid: errors.length === 0,
|
|
103
|
+
errors,
|
|
104
|
+
caveats,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
export const sampleCallSimulationCheck = {
|
|
108
|
+
id: 'schema.sample-call-simulation',
|
|
109
|
+
description: 'Generates and validates a minimal synthetic argument object against the tool inputSchema.',
|
|
110
|
+
run(connection) {
|
|
111
|
+
const results = [];
|
|
112
|
+
try {
|
|
113
|
+
if (!connection.tools || !Array.isArray(connection.tools)) {
|
|
114
|
+
return results;
|
|
115
|
+
}
|
|
116
|
+
for (const tool of connection.tools) {
|
|
117
|
+
const schema = tool.inputSchema;
|
|
118
|
+
if (!schema || typeof schema !== 'object' || Array.isArray(schema)) {
|
|
119
|
+
results.push({
|
|
120
|
+
checkId: 'schema.sample-call-simulation',
|
|
121
|
+
severity: 'error',
|
|
122
|
+
message: `Cannot simulate sample call for tool "${tool.name}": inputSchema is not a valid object.`,
|
|
123
|
+
serverName: connection.server.name,
|
|
124
|
+
toolName: tool.name,
|
|
125
|
+
});
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const schemaObj = schema;
|
|
129
|
+
const required = Array.isArray(schemaObj.required) ? schemaObj.required : [];
|
|
130
|
+
const properties = schemaObj.properties &&
|
|
131
|
+
typeof schemaObj.properties === 'object' &&
|
|
132
|
+
!Array.isArray(schemaObj.properties)
|
|
133
|
+
? schemaObj.properties
|
|
134
|
+
: {};
|
|
135
|
+
const syntheticArgs = {};
|
|
136
|
+
const generationCaveats = [];
|
|
137
|
+
let generationFailed = false;
|
|
138
|
+
for (const reqField of required) {
|
|
139
|
+
if (typeof reqField !== 'string')
|
|
140
|
+
continue;
|
|
141
|
+
if (!(reqField in properties)) {
|
|
142
|
+
results.push({
|
|
143
|
+
checkId: 'schema.sample-call-simulation',
|
|
144
|
+
severity: 'error',
|
|
145
|
+
message: `Sample call generation failed for tool "${tool.name}": required field "${reqField}" has no property definition.`,
|
|
146
|
+
serverName: connection.server.name,
|
|
147
|
+
toolName: tool.name,
|
|
148
|
+
details: { missingRequiredProperty: reqField },
|
|
149
|
+
suggestedFix: {
|
|
150
|
+
description: `Define property "${reqField}" under inputSchema.properties with a valid type.`,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
generationFailed = true;
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
const propDef = properties[reqField];
|
|
157
|
+
if (!propDef || typeof propDef !== 'object' || Array.isArray(propDef)) {
|
|
158
|
+
results.push({
|
|
159
|
+
checkId: 'schema.sample-call-simulation',
|
|
160
|
+
severity: 'error',
|
|
161
|
+
message: `Sample call generation failed for tool "${tool.name}": property definition for "${reqField}" is not an object.`,
|
|
162
|
+
serverName: connection.server.name,
|
|
163
|
+
toolName: tool.name,
|
|
164
|
+
suggestedFix: {
|
|
165
|
+
description: `Update property definition for "${reqField}" to be a valid object with a "type" field.`,
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
generationFailed = true;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
const { value, caveat } = generatePlaceholderForType(propDef);
|
|
173
|
+
syntheticArgs[reqField] = value;
|
|
174
|
+
if (caveat)
|
|
175
|
+
generationCaveats.push(caveat);
|
|
176
|
+
}
|
|
177
|
+
catch (genErr) {
|
|
178
|
+
results.push({
|
|
179
|
+
checkId: 'schema.sample-call-simulation',
|
|
180
|
+
severity: 'error',
|
|
181
|
+
message: `Sample call generation failed for tool "${tool.name}" on required field "${reqField}": ${genErr instanceof Error ? genErr.message : String(genErr)}`,
|
|
182
|
+
serverName: connection.server.name,
|
|
183
|
+
toolName: tool.name,
|
|
184
|
+
suggestedFix: {
|
|
185
|
+
description: `Provide valid enum options or valid bounds for required property "${reqField}".`,
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
generationFailed = true;
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (generationFailed) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
// Validate the generated payload against the schema
|
|
196
|
+
const outcome = validateSyntheticPayload(syntheticArgs, schemaObj);
|
|
197
|
+
if (!outcome.valid) {
|
|
198
|
+
results.push({
|
|
199
|
+
checkId: 'schema.sample-call-simulation',
|
|
200
|
+
severity: 'error',
|
|
201
|
+
message: `Sample call simulation validation failed for tool "${tool.name}": ${outcome.errors.join('; ')}`,
|
|
202
|
+
serverName: connection.server.name,
|
|
203
|
+
toolName: tool.name,
|
|
204
|
+
details: {
|
|
205
|
+
syntheticArgs,
|
|
206
|
+
errors: outcome.errors,
|
|
207
|
+
},
|
|
208
|
+
suggestedFix: {
|
|
209
|
+
description: 'Fix conflicting property constraints (e.g. minimum <= maximum, non-empty enums).',
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
else if (generationCaveats.length > 0 || outcome.caveats.length > 0) {
|
|
214
|
+
const allCaveats = [...generationCaveats, ...outcome.caveats];
|
|
215
|
+
results.push({
|
|
216
|
+
checkId: 'schema.sample-call-simulation',
|
|
217
|
+
severity: 'warning',
|
|
218
|
+
message: `Sample call simulation succeeded with caveats for tool "${tool.name}": ${allCaveats.join('; ')}`,
|
|
219
|
+
serverName: connection.server.name,
|
|
220
|
+
toolName: tool.name,
|
|
221
|
+
details: {
|
|
222
|
+
syntheticArgs,
|
|
223
|
+
caveats: allCaveats,
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
results.push({
|
|
231
|
+
checkId: 'schema.sample-call-simulation',
|
|
232
|
+
severity: 'error',
|
|
233
|
+
message: `check failed internally: ${err instanceof Error ? err.message : String(err)}`,
|
|
234
|
+
serverName: connection.server.name,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
return results;
|
|
238
|
+
},
|
|
239
|
+
};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
const VALID_JSON_SCHEMA_TYPES = new Set([
|
|
2
|
+
'string',
|
|
3
|
+
'number',
|
|
4
|
+
'integer',
|
|
5
|
+
'boolean',
|
|
6
|
+
'object',
|
|
7
|
+
'array',
|
|
8
|
+
'null',
|
|
9
|
+
]);
|
|
10
|
+
function matchesDeclaredType(value, declaredType) {
|
|
11
|
+
if (value === null) {
|
|
12
|
+
return declaredType === 'null';
|
|
13
|
+
}
|
|
14
|
+
if (Array.isArray(value)) {
|
|
15
|
+
return declaredType === 'array';
|
|
16
|
+
}
|
|
17
|
+
const jsType = typeof value;
|
|
18
|
+
if (jsType === 'string') {
|
|
19
|
+
return declaredType === 'string';
|
|
20
|
+
}
|
|
21
|
+
if (jsType === 'number') {
|
|
22
|
+
if (declaredType === 'number')
|
|
23
|
+
return true;
|
|
24
|
+
if (declaredType === 'integer')
|
|
25
|
+
return Number.isInteger(value);
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
if (jsType === 'boolean') {
|
|
29
|
+
return declaredType === 'boolean';
|
|
30
|
+
}
|
|
31
|
+
if (jsType === 'object') {
|
|
32
|
+
return declaredType === 'object';
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
function valueMatchesTypeDefinition(value, typeDef) {
|
|
37
|
+
if (typeof typeDef === 'string') {
|
|
38
|
+
return matchesDeclaredType(value, typeDef);
|
|
39
|
+
}
|
|
40
|
+
if (Array.isArray(typeDef)) {
|
|
41
|
+
return typeDef.some((t) => typeof t === 'string' && matchesDeclaredType(value, t));
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
export const typeMismatchCheck = {
|
|
46
|
+
id: 'schema.type-mismatch',
|
|
47
|
+
description: 'Flags properties with invalid types or enum values that do not match their declared type.',
|
|
48
|
+
run(connection) {
|
|
49
|
+
const results = [];
|
|
50
|
+
try {
|
|
51
|
+
if (!connection.tools || !Array.isArray(connection.tools)) {
|
|
52
|
+
return results;
|
|
53
|
+
}
|
|
54
|
+
for (const tool of connection.tools) {
|
|
55
|
+
const schema = tool.inputSchema;
|
|
56
|
+
if (!schema || typeof schema !== 'object' || Array.isArray(schema)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const schemaObj = schema;
|
|
60
|
+
if (!schemaObj.properties ||
|
|
61
|
+
typeof schemaObj.properties !== 'object' ||
|
|
62
|
+
Array.isArray(schemaObj.properties)) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const properties = schemaObj.properties;
|
|
66
|
+
for (const [propName, propDef] of Object.entries(properties)) {
|
|
67
|
+
if (!propDef || typeof propDef !== 'object' || Array.isArray(propDef)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const propObj = propDef;
|
|
71
|
+
const declaredType = propObj.type;
|
|
72
|
+
if (declaredType !== undefined) {
|
|
73
|
+
if (typeof declaredType === 'string') {
|
|
74
|
+
if (!VALID_JSON_SCHEMA_TYPES.has(declaredType)) {
|
|
75
|
+
results.push({
|
|
76
|
+
checkId: 'schema.type-mismatch',
|
|
77
|
+
severity: 'warning',
|
|
78
|
+
message: `Property "${propName}" in tool "${tool.name}" has invalid or unrecognized type "${declaredType}".`,
|
|
79
|
+
serverName: connection.server.name,
|
|
80
|
+
toolName: tool.name,
|
|
81
|
+
details: { property: propName, invalidType: declaredType },
|
|
82
|
+
suggestedFix: {
|
|
83
|
+
description: `Change type of property "${propName}" to a valid JSON Schema type (e.g. "string", "number", "integer", "boolean", "object", "array", "null").`,
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else if (Array.isArray(declaredType)) {
|
|
89
|
+
for (const item of declaredType) {
|
|
90
|
+
if (typeof item !== 'string' || !VALID_JSON_SCHEMA_TYPES.has(item)) {
|
|
91
|
+
results.push({
|
|
92
|
+
checkId: 'schema.type-mismatch',
|
|
93
|
+
severity: 'warning',
|
|
94
|
+
message: `Property "${propName}" in tool "${tool.name}" has invalid type union entry "${String(item)}".`,
|
|
95
|
+
serverName: connection.server.name,
|
|
96
|
+
toolName: tool.name,
|
|
97
|
+
details: { property: propName, invalidTypeEntry: item },
|
|
98
|
+
suggestedFix: {
|
|
99
|
+
description: `Remove or correct invalid type entry "${String(item)}" in union type for property "${propName}".`,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
results.push({
|
|
107
|
+
checkId: 'schema.type-mismatch',
|
|
108
|
+
severity: 'warning',
|
|
109
|
+
message: `Property "${propName}" in tool "${tool.name}" has invalid type descriptor of type ${typeof declaredType}.`,
|
|
110
|
+
serverName: connection.server.name,
|
|
111
|
+
toolName: tool.name,
|
|
112
|
+
details: { property: propName, typeDescriptor: declaredType },
|
|
113
|
+
suggestedFix: {
|
|
114
|
+
description: `Specify property "${propName}" type as a string (e.g. "string") or array of strings.`,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Check enum values against declared type
|
|
120
|
+
if (Array.isArray(propObj.enum) && declaredType !== undefined) {
|
|
121
|
+
for (const enumVal of propObj.enum) {
|
|
122
|
+
if (!valueMatchesTypeDefinition(enumVal, declaredType)) {
|
|
123
|
+
results.push({
|
|
124
|
+
checkId: 'schema.type-mismatch',
|
|
125
|
+
severity: 'warning',
|
|
126
|
+
message: `Enum value ${JSON.stringify(enumVal)} for property "${propName}" in tool "${tool.name}" does not match declared type "${JSON.stringify(declaredType)}".`,
|
|
127
|
+
serverName: connection.server.name,
|
|
128
|
+
toolName: tool.name,
|
|
129
|
+
details: {
|
|
130
|
+
property: propName,
|
|
131
|
+
enumValue: enumVal,
|
|
132
|
+
declaredType,
|
|
133
|
+
},
|
|
134
|
+
suggestedFix: {
|
|
135
|
+
description: `Ensure all enum entries for property "${propName}" conform to declared type "${JSON.stringify(declaredType)}".`,
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
results.push({
|
|
146
|
+
checkId: 'schema.type-mismatch',
|
|
147
|
+
severity: 'error',
|
|
148
|
+
message: `check failed internally: ${err instanceof Error ? err.message : String(err)}`,
|
|
149
|
+
serverName: connection.server.name,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return results;
|
|
153
|
+
},
|
|
154
|
+
};
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export interface ParsedArgs {
|
|
3
|
+
command: 'check' | 'watch' | 'check-all' | 'diff' | 'help';
|
|
4
|
+
configPath?: string;
|
|
5
|
+
configPathB?: string;
|
|
6
|
+
globPattern?: string;
|
|
7
|
+
registryServer?: string;
|
|
8
|
+
policyPath?: string;
|
|
9
|
+
exportJunit?: string;
|
|
10
|
+
exportJson?: string;
|
|
11
|
+
snapshotPath?: string;
|
|
12
|
+
updateSnapshotPath?: string;
|
|
13
|
+
json: boolean;
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
showFixes: boolean;
|
|
16
|
+
verbose: boolean;
|
|
17
|
+
failOn: 'error' | 'warning';
|
|
18
|
+
}
|
|
19
|
+
export declare function parseArgs(argv: string[]): ParsedArgs;
|
|
20
|
+
export declare function main(argv?: string[]): Promise<number>;
|