@bryan-thompson/inspector-assessment-client 1.5.0 → 1.7.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.
Files changed (74) hide show
  1. package/dist/assets/{OAuthCallback-DGVqLct6.js → OAuthCallback-Xo9zS7pv.js} +1 -1
  2. package/dist/assets/{OAuthDebugCallback-DHflRQgp.js → OAuthDebugCallback-CaIey8K_.js} +1 -1
  3. package/dist/assets/{index-Btl7vuTl.js → index-nCPw6E-c.js} +4 -4
  4. package/dist/index.html +1 -1
  5. package/lib/lib/assessmentTypes.d.ts +670 -0
  6. package/lib/lib/assessmentTypes.d.ts.map +1 -0
  7. package/lib/lib/assessmentTypes.js +220 -0
  8. package/lib/lib/aupPatterns.d.ts +63 -0
  9. package/lib/lib/aupPatterns.d.ts.map +1 -0
  10. package/lib/lib/aupPatterns.js +344 -0
  11. package/lib/lib/prohibitedLibraries.d.ts +76 -0
  12. package/lib/lib/prohibitedLibraries.d.ts.map +1 -0
  13. package/lib/lib/prohibitedLibraries.js +364 -0
  14. package/lib/lib/securityPatterns.d.ts +64 -0
  15. package/lib/lib/securityPatterns.d.ts.map +1 -0
  16. package/lib/lib/securityPatterns.js +453 -0
  17. package/lib/services/assessment/AssessmentOrchestrator.d.ts +88 -0
  18. package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -0
  19. package/lib/services/assessment/AssessmentOrchestrator.js +418 -0
  20. package/lib/services/assessment/ResponseValidator.d.ts +69 -0
  21. package/lib/services/assessment/ResponseValidator.d.ts.map +1 -0
  22. package/lib/services/assessment/ResponseValidator.js +1038 -0
  23. package/lib/services/assessment/TestDataGenerator.d.ts +86 -0
  24. package/lib/services/assessment/TestDataGenerator.d.ts.map +1 -0
  25. package/lib/services/assessment/TestDataGenerator.js +669 -0
  26. package/lib/services/assessment/TestScenarioEngine.d.ts +91 -0
  27. package/lib/services/assessment/TestScenarioEngine.d.ts.map +1 -0
  28. package/lib/services/assessment/TestScenarioEngine.js +505 -0
  29. package/lib/services/assessment/ToolClassifier.d.ts +61 -0
  30. package/lib/services/assessment/ToolClassifier.d.ts.map +1 -0
  31. package/lib/services/assessment/ToolClassifier.js +349 -0
  32. package/lib/services/assessment/lib/claudeCodeBridge.d.ts +160 -0
  33. package/lib/services/assessment/lib/claudeCodeBridge.d.ts.map +1 -0
  34. package/lib/services/assessment/lib/claudeCodeBridge.js +357 -0
  35. package/lib/services/assessment/modules/AUPComplianceAssessor.d.ts +100 -0
  36. package/lib/services/assessment/modules/AUPComplianceAssessor.d.ts.map +1 -0
  37. package/lib/services/assessment/modules/AUPComplianceAssessor.js +474 -0
  38. package/lib/services/assessment/modules/BaseAssessor.d.ts +71 -0
  39. package/lib/services/assessment/modules/BaseAssessor.d.ts.map +1 -0
  40. package/lib/services/assessment/modules/BaseAssessor.js +171 -0
  41. package/lib/services/assessment/modules/DocumentationAssessor.d.ts +45 -0
  42. package/lib/services/assessment/modules/DocumentationAssessor.d.ts.map +1 -0
  43. package/lib/services/assessment/modules/DocumentationAssessor.js +355 -0
  44. package/lib/services/assessment/modules/ErrorHandlingAssessor.d.ts +25 -0
  45. package/lib/services/assessment/modules/ErrorHandlingAssessor.d.ts.map +1 -0
  46. package/lib/services/assessment/modules/ErrorHandlingAssessor.js +564 -0
  47. package/lib/services/assessment/modules/FunctionalityAssessor.d.ts +20 -0
  48. package/lib/services/assessment/modules/FunctionalityAssessor.d.ts.map +1 -0
  49. package/lib/services/assessment/modules/FunctionalityAssessor.js +253 -0
  50. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts +70 -0
  51. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts.map +1 -0
  52. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.js +508 -0
  53. package/lib/services/assessment/modules/ManifestValidationAssessor.d.ts +70 -0
  54. package/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -0
  55. package/lib/services/assessment/modules/ManifestValidationAssessor.js +430 -0
  56. package/lib/services/assessment/modules/PortabilityAssessor.d.ts +43 -0
  57. package/lib/services/assessment/modules/PortabilityAssessor.d.ts.map +1 -0
  58. package/lib/services/assessment/modules/PortabilityAssessor.js +347 -0
  59. package/lib/services/assessment/modules/ProhibitedLibrariesAssessor.d.ts +41 -0
  60. package/lib/services/assessment/modules/ProhibitedLibrariesAssessor.d.ts.map +1 -0
  61. package/lib/services/assessment/modules/ProhibitedLibrariesAssessor.js +256 -0
  62. package/lib/services/assessment/modules/SecurityAssessor.d.ts +176 -0
  63. package/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -0
  64. package/lib/services/assessment/modules/SecurityAssessor.js +1333 -0
  65. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts +96 -0
  66. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts.map +1 -0
  67. package/lib/services/assessment/modules/ToolAnnotationAssessor.js +593 -0
  68. package/lib/services/assessment/modules/UsabilityAssessor.d.ts +21 -0
  69. package/lib/services/assessment/modules/UsabilityAssessor.d.ts.map +1 -0
  70. package/lib/services/assessment/modules/UsabilityAssessor.js +241 -0
  71. package/lib/services/assessment/modules/index.d.ts +33 -0
  72. package/lib/services/assessment/modules/index.d.ts.map +1 -0
  73. package/lib/services/assessment/modules/index.js +35 -0
  74. package/package.json +15 -3
@@ -0,0 +1,430 @@
1
+ /**
2
+ * Manifest Validation Assessor
3
+ * Validates MCPB manifest.json against spec requirements
4
+ *
5
+ * Checks:
6
+ * - manifest_version (must be 0.3)
7
+ * - Required fields: name, version, description, author
8
+ * - mcp_config structure
9
+ * - icon.png presence
10
+ *
11
+ * Reference: MCPB Specification
12
+ */
13
+ import { BaseAssessor } from "./BaseAssessor.js";
14
+ const REQUIRED_FIELDS = ["name", "version", "mcp_config"];
15
+ const RECOMMENDED_FIELDS = ["description", "author", "repository"];
16
+ const CURRENT_MANIFEST_VERSION = "0.3";
17
+ export class ManifestValidationAssessor extends BaseAssessor {
18
+ /**
19
+ * Run manifest validation assessment
20
+ */
21
+ async assess(context) {
22
+ this.log("Starting manifest validation assessment");
23
+ this.testCount = 0;
24
+ // Check if manifest is available
25
+ if (!context.manifestJson && !context.manifestRaw) {
26
+ return this.createNoManifestResult();
27
+ }
28
+ const validationResults = [];
29
+ let hasIcon = false;
30
+ let hasRequiredFields = true;
31
+ const missingFields = [];
32
+ // Parse manifest if raw string provided
33
+ let manifest = null;
34
+ if (context.manifestJson) {
35
+ manifest = context.manifestJson;
36
+ }
37
+ else if (context.manifestRaw) {
38
+ try {
39
+ manifest = JSON.parse(context.manifestRaw);
40
+ }
41
+ catch (error) {
42
+ this.testCount++;
43
+ validationResults.push({
44
+ field: "manifest.json",
45
+ valid: false,
46
+ issue: `Invalid JSON: ${error instanceof Error ? error.message : "Parse error"}`,
47
+ severity: "ERROR",
48
+ });
49
+ return this.createInvalidJsonResult(validationResults);
50
+ }
51
+ }
52
+ if (!manifest) {
53
+ return this.createNoManifestResult();
54
+ }
55
+ // Validate manifest_version
56
+ this.testCount++;
57
+ validationResults.push(this.validateManifestVersion(manifest));
58
+ // Validate required fields
59
+ for (const field of REQUIRED_FIELDS) {
60
+ this.testCount++;
61
+ const result = this.validateRequiredField(manifest, field);
62
+ validationResults.push(result);
63
+ if (!result.valid) {
64
+ hasRequiredFields = false;
65
+ missingFields.push(field);
66
+ }
67
+ }
68
+ // Validate recommended fields
69
+ for (const field of RECOMMENDED_FIELDS) {
70
+ this.testCount++;
71
+ validationResults.push(this.validateRecommendedField(manifest, field));
72
+ }
73
+ // Validate mcp_config structure
74
+ if (manifest.mcp_config) {
75
+ this.testCount++;
76
+ validationResults.push(this.validateMcpConfig(manifest.mcp_config));
77
+ }
78
+ // Check for icon
79
+ this.testCount++;
80
+ const iconResult = this.validateIcon(manifest, context);
81
+ validationResults.push(iconResult);
82
+ hasIcon = iconResult.valid;
83
+ // Validate name format
84
+ this.testCount++;
85
+ validationResults.push(this.validateNameFormat(manifest.name));
86
+ // Validate version format
87
+ this.testCount++;
88
+ validationResults.push(this.validateVersionFormat(manifest.version));
89
+ const status = this.determineManifestStatus(validationResults, hasRequiredFields);
90
+ const explanation = this.generateExplanation(validationResults, hasRequiredFields, hasIcon);
91
+ const recommendations = this.generateRecommendations(validationResults);
92
+ this.log(`Assessment complete: ${validationResults.filter((r) => r.valid).length}/${validationResults.length} checks passed`);
93
+ return {
94
+ hasManifest: true,
95
+ manifestVersion: manifest.manifest_version,
96
+ validationResults,
97
+ hasIcon,
98
+ hasRequiredFields,
99
+ missingFields,
100
+ status,
101
+ explanation,
102
+ recommendations,
103
+ };
104
+ }
105
+ /**
106
+ * Create result when no manifest is available
107
+ */
108
+ createNoManifestResult() {
109
+ return {
110
+ hasManifest: false,
111
+ validationResults: [
112
+ {
113
+ field: "manifest.json",
114
+ valid: false,
115
+ issue: "No manifest.json found - required for MCPB bundles",
116
+ severity: "ERROR",
117
+ },
118
+ ],
119
+ hasIcon: false,
120
+ hasRequiredFields: false,
121
+ missingFields: [...REQUIRED_FIELDS],
122
+ status: "FAIL",
123
+ explanation: "No manifest.json found. This file is required for MCPB bundle validation.",
124
+ recommendations: [
125
+ "Create a manifest.json file following the MCPB specification",
126
+ "Required fields: manifest_version, name, version, mcp_config",
127
+ "Recommended: description, author, repository, icon",
128
+ ],
129
+ };
130
+ }
131
+ /**
132
+ * Create result when manifest JSON is invalid
133
+ */
134
+ createInvalidJsonResult(validationResults) {
135
+ return {
136
+ hasManifest: true,
137
+ validationResults,
138
+ hasIcon: false,
139
+ hasRequiredFields: false,
140
+ missingFields: [...REQUIRED_FIELDS],
141
+ status: "FAIL",
142
+ explanation: "manifest.json contains invalid JSON and could not be parsed.",
143
+ recommendations: [
144
+ "Fix JSON syntax errors in manifest.json",
145
+ "Validate JSON using a JSON linter",
146
+ ],
147
+ };
148
+ }
149
+ /**
150
+ * Validate manifest_version field
151
+ */
152
+ validateManifestVersion(manifest) {
153
+ if (!manifest.manifest_version) {
154
+ return {
155
+ field: "manifest_version",
156
+ valid: false,
157
+ issue: "Missing manifest_version field",
158
+ expectedType: "string",
159
+ severity: "ERROR",
160
+ };
161
+ }
162
+ if (manifest.manifest_version !== CURRENT_MANIFEST_VERSION) {
163
+ return {
164
+ field: "manifest_version",
165
+ valid: false,
166
+ value: manifest.manifest_version,
167
+ issue: `Expected manifest_version "${CURRENT_MANIFEST_VERSION}", got "${manifest.manifest_version}"`,
168
+ expectedType: "string",
169
+ severity: "WARNING",
170
+ };
171
+ }
172
+ return {
173
+ field: "manifest_version",
174
+ valid: true,
175
+ value: manifest.manifest_version,
176
+ severity: "INFO",
177
+ };
178
+ }
179
+ /**
180
+ * Validate required field presence
181
+ */
182
+ validateRequiredField(manifest, field) {
183
+ const value = manifest[field];
184
+ if (value === undefined || value === null) {
185
+ return {
186
+ field,
187
+ valid: false,
188
+ issue: `Missing required field: ${field}`,
189
+ severity: "ERROR",
190
+ };
191
+ }
192
+ if (typeof value === "string" && value.trim() === "") {
193
+ return {
194
+ field,
195
+ valid: false,
196
+ value,
197
+ issue: `Required field ${field} is empty`,
198
+ severity: "ERROR",
199
+ };
200
+ }
201
+ return {
202
+ field,
203
+ valid: true,
204
+ value,
205
+ severity: "INFO",
206
+ };
207
+ }
208
+ /**
209
+ * Validate recommended field presence
210
+ */
211
+ validateRecommendedField(manifest, field) {
212
+ const value = manifest[field];
213
+ if (value === undefined || value === null) {
214
+ return {
215
+ field,
216
+ valid: true, // Recommended fields don't fail validation
217
+ issue: `Missing recommended field: ${field}`,
218
+ severity: "WARNING",
219
+ };
220
+ }
221
+ if (typeof value === "string" && value.trim() === "") {
222
+ return {
223
+ field,
224
+ valid: true,
225
+ value,
226
+ issue: `Recommended field ${field} is empty`,
227
+ severity: "WARNING",
228
+ };
229
+ }
230
+ return {
231
+ field,
232
+ valid: true,
233
+ value,
234
+ severity: "INFO",
235
+ };
236
+ }
237
+ /**
238
+ * Validate mcp_config structure
239
+ */
240
+ validateMcpConfig(mcpConfig) {
241
+ if (!mcpConfig.command) {
242
+ return {
243
+ field: "mcp_config.command",
244
+ valid: false,
245
+ issue: "Missing required mcp_config.command field",
246
+ severity: "ERROR",
247
+ };
248
+ }
249
+ // Check for ${BUNDLE_ROOT} anti-pattern
250
+ const configStr = JSON.stringify(mcpConfig);
251
+ if (configStr.includes("${BUNDLE_ROOT}")) {
252
+ return {
253
+ field: "mcp_config",
254
+ valid: false,
255
+ issue: "Uses ${BUNDLE_ROOT} which is not supported - use ${__dirname} instead",
256
+ severity: "ERROR",
257
+ };
258
+ }
259
+ // Check for hardcoded absolute paths
260
+ if (mcpConfig.command.startsWith("/") ||
261
+ mcpConfig.command.match(/^[A-Z]:\\/)) {
262
+ return {
263
+ field: "mcp_config.command",
264
+ valid: false,
265
+ value: mcpConfig.command,
266
+ issue: "Command uses hardcoded absolute path - use relative or ${__dirname}",
267
+ severity: "ERROR",
268
+ };
269
+ }
270
+ return {
271
+ field: "mcp_config",
272
+ valid: true,
273
+ value: mcpConfig,
274
+ severity: "INFO",
275
+ };
276
+ }
277
+ /**
278
+ * Validate icon presence
279
+ */
280
+ validateIcon(manifest, context) {
281
+ // Check manifest icon field
282
+ if (manifest.icon) {
283
+ return {
284
+ field: "icon",
285
+ valid: true,
286
+ value: manifest.icon,
287
+ severity: "INFO",
288
+ };
289
+ }
290
+ // Check if icon.png exists in source files
291
+ if (context.sourceCodeFiles) {
292
+ for (const filePath of context.sourceCodeFiles.keys()) {
293
+ if (filePath.endsWith("icon.png") || filePath.endsWith("icon.svg")) {
294
+ return {
295
+ field: "icon",
296
+ valid: true,
297
+ value: filePath,
298
+ issue: "Icon file found but not referenced in manifest",
299
+ severity: "WARNING",
300
+ };
301
+ }
302
+ }
303
+ }
304
+ return {
305
+ field: "icon",
306
+ valid: false,
307
+ issue: "Missing icon.png - recommended for MCPB bundles",
308
+ severity: "WARNING",
309
+ };
310
+ }
311
+ /**
312
+ * Validate name format
313
+ */
314
+ validateNameFormat(name) {
315
+ if (!name) {
316
+ return {
317
+ field: "name (format)",
318
+ valid: false,
319
+ issue: "Name is required",
320
+ severity: "ERROR",
321
+ };
322
+ }
323
+ // Check for valid npm-style name
324
+ const validNamePattern = /^[a-z0-9][a-z0-9._-]*$/;
325
+ if (!validNamePattern.test(name.toLowerCase())) {
326
+ return {
327
+ field: "name (format)",
328
+ valid: false,
329
+ value: name,
330
+ issue: "Name should be lowercase, alphanumeric, and may include .-_ characters",
331
+ severity: "WARNING",
332
+ };
333
+ }
334
+ return {
335
+ field: "name (format)",
336
+ valid: true,
337
+ value: name,
338
+ severity: "INFO",
339
+ };
340
+ }
341
+ /**
342
+ * Validate version format (semver)
343
+ */
344
+ validateVersionFormat(version) {
345
+ if (!version) {
346
+ return {
347
+ field: "version (format)",
348
+ valid: false,
349
+ issue: "Version is required",
350
+ severity: "ERROR",
351
+ };
352
+ }
353
+ // Check for semver format
354
+ const semverPattern = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?(\+[a-zA-Z0-9.]+)?$/;
355
+ if (!semverPattern.test(version)) {
356
+ return {
357
+ field: "version (format)",
358
+ valid: false,
359
+ value: version,
360
+ issue: "Version should follow semver format (e.g., 1.0.0)",
361
+ severity: "WARNING",
362
+ };
363
+ }
364
+ return {
365
+ field: "version (format)",
366
+ valid: true,
367
+ value: version,
368
+ severity: "INFO",
369
+ };
370
+ }
371
+ /**
372
+ * Determine overall status
373
+ */
374
+ determineManifestStatus(results, hasRequiredFields) {
375
+ const errors = results.filter((r) => !r.valid && r.severity === "ERROR").length;
376
+ const warnings = results.filter((r) => !r.valid && r.severity === "WARNING").length;
377
+ if (errors > 0 || !hasRequiredFields) {
378
+ return "FAIL";
379
+ }
380
+ if (warnings > 0) {
381
+ return "NEED_MORE_INFO";
382
+ }
383
+ return "PASS";
384
+ }
385
+ /**
386
+ * Generate explanation
387
+ */
388
+ generateExplanation(results, hasRequiredFields, hasIcon) {
389
+ const parts = [];
390
+ const passed = results.filter((r) => r.valid).length;
391
+ const total = results.length;
392
+ parts.push(`Manifest validation: ${passed}/${total} checks passed.`);
393
+ if (!hasRequiredFields) {
394
+ parts.push("Missing required fields in manifest.json.");
395
+ }
396
+ if (!hasIcon) {
397
+ parts.push("No icon found - recommended for MCPB bundles.");
398
+ }
399
+ const errors = results.filter((r) => !r.valid && r.severity === "ERROR");
400
+ if (errors.length > 0) {
401
+ parts.push(`${errors.length} error(s) require attention.`);
402
+ }
403
+ return parts.join(" ");
404
+ }
405
+ /**
406
+ * Generate recommendations
407
+ */
408
+ generateRecommendations(results) {
409
+ const recommendations = [];
410
+ // Group by severity
411
+ const errors = results.filter((r) => !r.valid && r.severity === "ERROR");
412
+ const warnings = results.filter((r) => r.severity === "WARNING" && r.issue);
413
+ if (errors.length > 0) {
414
+ recommendations.push("FIX REQUIRED - Manifest errors:");
415
+ for (const error of errors) {
416
+ recommendations.push(`- ${error.field}: ${error.issue}`);
417
+ }
418
+ }
419
+ if (warnings.length > 0) {
420
+ recommendations.push("RECOMMENDED - Manifest improvements:");
421
+ for (const warning of warnings.slice(0, 3)) {
422
+ recommendations.push(`- ${warning.field}: ${warning.issue}`);
423
+ }
424
+ }
425
+ if (recommendations.length === 0) {
426
+ recommendations.push("Manifest validation passed. All required fields are present and valid.");
427
+ }
428
+ return recommendations;
429
+ }
430
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Portability Assessor
3
+ * Detects hardcoded paths and platform-specific code
4
+ *
5
+ * Checks:
6
+ * - Hardcoded absolute paths
7
+ * - User home directory references
8
+ * - ${BUNDLE_ROOT} anti-pattern (should use ${__dirname})
9
+ * - Platform-specific code without fallbacks
10
+ * - ${__dirname} usage (correct pattern)
11
+ *
12
+ * Reference: MCPB Bundle Portability Requirements
13
+ */
14
+ import { BaseAssessor } from "./BaseAssessor.js";
15
+ import { AssessmentContext } from "../AssessmentOrchestrator.js";
16
+ import type { PortabilityAssessment } from "../../../lib/assessmentTypes.js";
17
+ export declare class PortabilityAssessor extends BaseAssessor {
18
+ /**
19
+ * Run portability assessment
20
+ */
21
+ assess(context: AssessmentContext): Promise<PortabilityAssessment>;
22
+ /**
23
+ * Scan a file for portability issues
24
+ */
25
+ private scanFile;
26
+ /**
27
+ * Check if file should be skipped
28
+ */
29
+ private shouldSkipFile;
30
+ /**
31
+ * Determine overall status
32
+ */
33
+ private determinePortabilityStatus;
34
+ /**
35
+ * Generate explanation
36
+ */
37
+ private generateExplanation;
38
+ /**
39
+ * Generate recommendations
40
+ */
41
+ private generateRecommendations;
42
+ }
43
+ //# sourceMappingURL=PortabilityAssessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PortabilityAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/PortabilityAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EACV,qBAAqB,EAGtB,MAAM,uBAAuB,CAAC;AA2C/B,qBAAa,mBAAoB,SAAQ,YAAY;IACnD;;OAEG;IACG,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAgHxE;;OAEG;IACH,OAAO,CAAC,QAAQ;IAgIhB;;OAEG;IACH,OAAO,CAAC,cAAc;IAkBtB;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAmClC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAqC3B;;OAEG;IACH,OAAO,CAAC,uBAAuB;CAmDhC"}