@bryan-thompson/inspector-assessment 1.13.1 → 1.14.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 (26) hide show
  1. package/README.md +88 -0
  2. package/cli/build/assess-full.js +103 -0
  3. package/cli/build/assessmentState.js +168 -0
  4. package/client/dist/assets/{OAuthCallback-Dg3beipA.js → OAuthCallback-DaKwjxdn.js} +1 -1
  5. package/client/dist/assets/{OAuthDebugCallback-zRUPyR0T.js → OAuthDebugCallback-HiI2IPgB.js} +1 -1
  6. package/client/dist/assets/{index-DtKbQaUh.js → index-BAJG90Yd.js} +17 -8
  7. package/client/dist/assets/{index-Cuc9GxjD.css → index-BdXNC65t.css} +3 -0
  8. package/client/dist/index.html +2 -2
  9. package/client/lib/lib/assessmentDiffer.d.ts +79 -0
  10. package/client/lib/lib/assessmentDiffer.d.ts.map +1 -0
  11. package/client/lib/lib/assessmentDiffer.js +289 -0
  12. package/client/lib/lib/assessmentTypes.d.ts +53 -0
  13. package/client/lib/lib/assessmentTypes.d.ts.map +1 -1
  14. package/client/lib/lib/assessmentTypes.js +5 -0
  15. package/client/lib/lib/reportFormatters/DiffReportFormatter.d.ts +10 -0
  16. package/client/lib/lib/reportFormatters/DiffReportFormatter.d.ts.map +1 -0
  17. package/client/lib/lib/reportFormatters/DiffReportFormatter.js +177 -0
  18. package/client/lib/services/assessment/modules/AuthenticationAssessor.d.ts +48 -0
  19. package/client/lib/services/assessment/modules/AuthenticationAssessor.d.ts.map +1 -0
  20. package/client/lib/services/assessment/modules/AuthenticationAssessor.js +270 -0
  21. package/client/lib/services/assessment/modules/FunctionalityAssessor.d.ts.map +1 -1
  22. package/client/lib/services/assessment/modules/FunctionalityAssessor.js +7 -0
  23. package/client/lib/services/assessment/modules/ManifestValidationAssessor.d.ts +4 -0
  24. package/client/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -1
  25. package/client/lib/services/assessment/modules/ManifestValidationAssessor.js +118 -4
  26. package/package.json +1 -1
package/README.md CHANGED
@@ -588,6 +588,94 @@ mcp-inspector-assess-cli node build/index.js --assess functionality
588
588
  mcp-inspector-assess-cli node build/index.js --assess --output assessment-report.json
589
589
  ```
590
590
 
591
+ ### Full Assessment CLI
592
+
593
+ The full assessment CLI (`npm run assess:full`) provides comprehensive 12-module assessment with policy compliance mapping:
594
+
595
+ ```bash
596
+ # Basic full assessment
597
+ npm run assess:full -- --server <name> --config <path>
598
+
599
+ # With source code analysis (enables External API Scanner, AUP, Portability checks)
600
+ npm run assess:full -- --server <name> --config <path> --source <path-to-source>
601
+
602
+ # Generate markdown report with policy compliance
603
+ npm run assess:full -- --server <name> --config <path> --format markdown --include-policy
604
+
605
+ # Quick pre-flight validation only
606
+ npm run assess:full -- --server <name> --config <path> --preflight
607
+ ```
608
+
609
+ **CLI Options:**
610
+
611
+ | Option | Description |
612
+ | ----------------------------- | ------------------------------------------------------------------------------------ |
613
+ | `--server, -s <name>` | Server name (required) |
614
+ | `--config, -c <path>` | Path to server config JSON |
615
+ | `--output, -o <path>` | Output path (default: `/tmp/inspector-full-assessment-<server>.<ext>`) |
616
+ | `--source <path>` | Source code path for deep analysis (enables AUP, portability, external API scanning) |
617
+ | `--format, -f <type>` | Output format: `json` (default) or `markdown` |
618
+ | `--include-policy` | Include 30-requirement policy compliance mapping in report |
619
+ | `--preflight` | Quick validation only (tools exist, manifest valid, server responds) |
620
+ | `--pattern-config, -p <path>` | Path to custom annotation pattern JSON |
621
+ | `--claude-enabled` | Enable Claude Code integration for intelligent analysis |
622
+ | `--json` | Output only JSON path (no console summary) |
623
+ | `--verbose, -v` | Enable verbose logging |
624
+
625
+ **Config File Format (HTTP transport):**
626
+
627
+ ```json
628
+ {
629
+ "transport": "http",
630
+ "url": "http://localhost:10900/mcp"
631
+ }
632
+ ```
633
+
634
+ **Config File Format (STDIO transport):**
635
+
636
+ ```json
637
+ {
638
+ "transport": "stdio",
639
+ "command": "node",
640
+ "args": ["build/index.js"],
641
+ "env": {}
642
+ }
643
+ ```
644
+
645
+ **Pre-flight Mode:**
646
+
647
+ The `--preflight` flag runs quick validation without full assessment:
648
+
649
+ ```bash
650
+ npm run assess:full -- --server my-server --config config.json --preflight
651
+ ```
652
+
653
+ Returns JSON with:
654
+
655
+ - `passed`: boolean - overall validation result
656
+ - `toolCount`: number - tools discovered
657
+ - `manifestValid`: boolean - if manifest.json is valid (when --source provided)
658
+ - `serverResponsive`: boolean - if first tool call succeeds
659
+ - `errors`: string[] - any validation errors
660
+
661
+ **External API Scanner:**
662
+
663
+ When `--source` is provided, the External API Scanner automatically scans source code for:
664
+
665
+ - External API URLs (GitHub, Slack, AWS, OpenAI, Anthropic, etc.)
666
+ - Affiliation warnings (e.g., server named "github-mcp" by unaffiliated developer)
667
+ - Privacy policy considerations for detected services
668
+
669
+ **Policy Compliance Report:**
670
+
671
+ When `--include-policy` is used, the report includes mapping to Anthropic's 30 Software Directory Policy requirements across 5 categories:
672
+
673
+ - Safety & Security (6 requirements)
674
+ - Compatibility (6 requirements)
675
+ - Functionality (7 requirements)
676
+ - Developer Requirements (8 requirements)
677
+ - Unsupported Use Cases (3 requirements)
678
+
591
679
  ## Running the Inspector
592
680
 
593
681
  ### Requirements
@@ -22,6 +22,9 @@ import { DEFAULT_ASSESSMENT_CONFIG, } from "../../client/lib/lib/assessmentTypes
22
22
  import { FULL_CLAUDE_CODE_CONFIG } from "../../client/lib/services/assessment/lib/claudeCodeBridge.js";
23
23
  import { createFormatter, } from "../../client/lib/lib/reportFormatters/index.js";
24
24
  import { generatePolicyComplianceReport } from "../../client/lib/services/assessment/PolicyComplianceGenerator.js";
25
+ import { compareAssessments } from "../../client/lib/lib/assessmentDiffer.js";
26
+ import { formatDiffAsMarkdown } from "../../client/lib/lib/reportFormatters/DiffReportFormatter.js";
27
+ import { AssessmentStateManager } from "./assessmentState.js";
25
28
  /**
26
29
  * Load server configuration from Claude Code's MCP settings
27
30
  */
@@ -296,6 +299,34 @@ async function runFullAssessment(options) {
296
299
  if (!options.jsonOnly) {
297
300
  console.log(`🔧 Found ${tools.length} tool${tools.length !== 1 ? "s" : ""}`);
298
301
  }
302
+ // State management for resumable assessments
303
+ const stateManager = new AssessmentStateManager(options.serverName);
304
+ if (stateManager.exists() && !options.noResume) {
305
+ const summary = stateManager.getSummary();
306
+ if (summary) {
307
+ if (!options.jsonOnly) {
308
+ console.log(`\n📋 Found interrupted session from ${summary.startedAt}`);
309
+ console.log(` Completed modules: ${summary.completedModules.length > 0 ? summary.completedModules.join(", ") : "none"}`);
310
+ }
311
+ if (options.resume) {
312
+ if (!options.jsonOnly) {
313
+ console.log(" Resuming from previous state...");
314
+ }
315
+ // Will use partial results later
316
+ }
317
+ else if (!options.jsonOnly) {
318
+ console.log(" Use --resume to continue or --no-resume to start fresh");
319
+ // Clear state and start fresh by default
320
+ stateManager.clear();
321
+ }
322
+ }
323
+ }
324
+ else if (options.noResume && stateManager.exists()) {
325
+ stateManager.clear();
326
+ if (!options.jsonOnly) {
327
+ console.log("🗑️ Cleared previous assessment state");
328
+ }
329
+ }
299
330
  // Pre-flight validation checks
300
331
  if (options.preflightOnly) {
301
332
  const preflightResult = {
@@ -561,6 +592,18 @@ function parseArgs() {
561
592
  case "--preflight":
562
593
  options.preflightOnly = true;
563
594
  break;
595
+ case "--compare":
596
+ options.comparePath = args[++i];
597
+ break;
598
+ case "--diff-only":
599
+ options.diffOnly = true;
600
+ break;
601
+ case "--resume":
602
+ options.resume = true;
603
+ break;
604
+ case "--no-resume":
605
+ options.noResume = true;
606
+ break;
564
607
  case "--help":
565
608
  case "-h":
566
609
  printHelp();
@@ -608,6 +651,10 @@ Options:
608
651
  --format, -f <type> Output format: json (default) or markdown
609
652
  --include-policy Include policy compliance mapping in report (30 requirements)
610
653
  --preflight Run quick validation only (tools exist, manifest valid, server responds)
654
+ --compare <path> Compare current assessment against baseline JSON file
655
+ --diff-only Output only the comparison diff (requires --compare)
656
+ --resume Resume from previous interrupted assessment
657
+ --no-resume Force fresh start, clear any existing state
611
658
  --claude-enabled Enable Claude Code integration for intelligent analysis
612
659
  --full Enable all assessment modules (default)
613
660
  --json Output only JSON path (no console summary)
@@ -632,6 +679,8 @@ Examples:
632
679
  mcp-assess-full --server broken-mcp --claude-enabled
633
680
  mcp-assess-full --server my-server --source ./my-server --output ./results.json
634
681
  mcp-assess-full --server my-server --format markdown --include-policy
682
+ mcp-assess-full --server my-server --compare ./baseline.json
683
+ mcp-assess-full --server my-server --compare ./baseline.json --diff-only --format markdown
635
684
  `);
636
685
  }
637
686
  /**
@@ -648,6 +697,60 @@ async function main() {
648
697
  if (options.preflightOnly) {
649
698
  return;
650
699
  }
700
+ // Handle comparison mode
701
+ if (options.comparePath) {
702
+ if (!fs.existsSync(options.comparePath)) {
703
+ console.error(`Error: Baseline file not found: ${options.comparePath}`);
704
+ setTimeout(() => process.exit(1), 10);
705
+ return;
706
+ }
707
+ const baselineData = JSON.parse(fs.readFileSync(options.comparePath, "utf-8"));
708
+ const baseline = baselineData.functionality && baselineData.security
709
+ ? baselineData
710
+ : baselineData;
711
+ const diff = compareAssessments(baseline, results);
712
+ if (options.diffOnly) {
713
+ // Only output diff, not full assessment
714
+ if (options.format === "markdown") {
715
+ const diffPath = options.outputPath ||
716
+ `/tmp/inspector-diff-${options.serverName}.md`;
717
+ fs.writeFileSync(diffPath, formatDiffAsMarkdown(diff));
718
+ console.log(diffPath);
719
+ }
720
+ else {
721
+ const diffPath = options.outputPath ||
722
+ `/tmp/inspector-diff-${options.serverName}.json`;
723
+ fs.writeFileSync(diffPath, JSON.stringify(diff, null, 2));
724
+ console.log(diffPath);
725
+ }
726
+ const exitCode = diff.summary.overallChange === "regressed" ? 1 : 0;
727
+ setTimeout(() => process.exit(exitCode), 10);
728
+ return;
729
+ }
730
+ // Include diff in output alongside full assessment
731
+ if (!options.jsonOnly) {
732
+ console.log("\n" + "=".repeat(70));
733
+ console.log("VERSION COMPARISON");
734
+ console.log("=".repeat(70));
735
+ console.log(`Baseline: ${diff.baseline.version || "N/A"} (${diff.baseline.date})`);
736
+ console.log(`Current: ${diff.current.version || "N/A"} (${diff.current.date})`);
737
+ console.log(`Overall Change: ${diff.summary.overallChange.toUpperCase()}`);
738
+ console.log(`Modules Improved: ${diff.summary.modulesImproved}`);
739
+ console.log(`Modules Regressed: ${diff.summary.modulesRegressed}`);
740
+ if (diff.securityDelta.newVulnerabilities.length > 0) {
741
+ console.log(`\n⚠️ NEW VULNERABILITIES: ${diff.securityDelta.newVulnerabilities.length}`);
742
+ }
743
+ if (diff.securityDelta.fixedVulnerabilities.length > 0) {
744
+ console.log(`✅ FIXED VULNERABILITIES: ${diff.securityDelta.fixedVulnerabilities.length}`);
745
+ }
746
+ if (diff.functionalityDelta.newBrokenTools.length > 0) {
747
+ console.log(`❌ NEW BROKEN TOOLS: ${diff.functionalityDelta.newBrokenTools.length}`);
748
+ }
749
+ if (diff.functionalityDelta.fixedTools.length > 0) {
750
+ console.log(`✅ FIXED TOOLS: ${diff.functionalityDelta.fixedTools.length}`);
751
+ }
752
+ }
753
+ }
651
754
  if (!options.jsonOnly) {
652
755
  displaySummary(results);
653
756
  }
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Assessment State Manager
3
+ * File-based state management for resumable assessments.
4
+ *
5
+ * Purpose:
6
+ * - Allow long-running assessments to be paused and resumed
7
+ * - Checkpoint after each module completes
8
+ * - Recover from interruptions
9
+ */
10
+ import * as fs from "fs";
11
+ const STATE_VERSION = "1.0";
12
+ /**
13
+ * Manages assessment state persistence for resumable runs
14
+ */
15
+ export class AssessmentStateManager {
16
+ statePath;
17
+ constructor(serverName, stateDir = "/tmp") {
18
+ this.statePath = `${stateDir}/inspector-assessment-state-${serverName}.json`;
19
+ }
20
+ /**
21
+ * Check if a previous state exists
22
+ */
23
+ exists() {
24
+ return fs.existsSync(this.statePath);
25
+ }
26
+ /**
27
+ * Load state from disk
28
+ */
29
+ load() {
30
+ if (!this.exists())
31
+ return null;
32
+ try {
33
+ const data = fs.readFileSync(this.statePath, "utf-8");
34
+ const state = JSON.parse(data);
35
+ // Validate state version
36
+ if (state.version !== STATE_VERSION) {
37
+ console.warn(`[StateManager] State version mismatch: ${state.version} vs ${STATE_VERSION}, clearing`);
38
+ this.clear();
39
+ return null;
40
+ }
41
+ return state;
42
+ }
43
+ catch (error) {
44
+ console.warn("[StateManager] Failed to load state:", error);
45
+ return null;
46
+ }
47
+ }
48
+ /**
49
+ * Create a new state for a fresh assessment
50
+ */
51
+ create(serverName, config, toolsDiscovered) {
52
+ const state = {
53
+ sessionId: this.generateSessionId(),
54
+ serverName,
55
+ startedAt: new Date().toISOString(),
56
+ lastUpdatedAt: new Date().toISOString(),
57
+ config,
58
+ completedModules: [],
59
+ currentModule: null,
60
+ partialResults: {
61
+ serverName,
62
+ assessmentDate: new Date().toISOString(),
63
+ assessorVersion: "1.13.1", // Will be updated from package.json
64
+ },
65
+ toolsDiscovered,
66
+ version: STATE_VERSION,
67
+ };
68
+ this.save(state);
69
+ return state;
70
+ }
71
+ /**
72
+ * Save state to disk
73
+ */
74
+ save(state) {
75
+ state.lastUpdatedAt = new Date().toISOString();
76
+ fs.writeFileSync(this.statePath, JSON.stringify(state, null, 2));
77
+ }
78
+ /**
79
+ * Mark a module as starting
80
+ */
81
+ startModule(moduleName) {
82
+ const state = this.load();
83
+ if (state) {
84
+ state.currentModule = moduleName;
85
+ this.save(state);
86
+ }
87
+ }
88
+ /**
89
+ * Mark a module as complete and save its result
90
+ */
91
+ completeModule(moduleName, result) {
92
+ const state = this.load();
93
+ if (state) {
94
+ state.completedModules.push(moduleName);
95
+ state.currentModule = null;
96
+ // Store the result in partialResults
97
+ state.partialResults[moduleName] = result;
98
+ this.save(state);
99
+ }
100
+ }
101
+ /**
102
+ * Get list of completed modules
103
+ */
104
+ getCompletedModules() {
105
+ const state = this.load();
106
+ return state?.completedModules || [];
107
+ }
108
+ /**
109
+ * Check if a module was already completed
110
+ */
111
+ isModuleCompleted(moduleName) {
112
+ const state = this.load();
113
+ return state?.completedModules.includes(moduleName) || false;
114
+ }
115
+ /**
116
+ * Get partial results from previous run
117
+ */
118
+ getPartialResults() {
119
+ const state = this.load();
120
+ return state?.partialResults || null;
121
+ }
122
+ /**
123
+ * Clear state (delete state file)
124
+ */
125
+ clear() {
126
+ if (this.exists()) {
127
+ try {
128
+ fs.unlinkSync(this.statePath);
129
+ }
130
+ catch {
131
+ // Ignore errors on cleanup
132
+ }
133
+ }
134
+ }
135
+ /**
136
+ * Get state file path
137
+ */
138
+ getStatePath() {
139
+ return this.statePath;
140
+ }
141
+ /**
142
+ * Get state summary for display
143
+ */
144
+ getSummary() {
145
+ const state = this.load();
146
+ if (!state)
147
+ return null;
148
+ return {
149
+ sessionId: state.sessionId,
150
+ startedAt: state.startedAt,
151
+ completedModules: state.completedModules,
152
+ currentModule: state.currentModule,
153
+ toolsDiscovered: state.toolsDiscovered,
154
+ };
155
+ }
156
+ /**
157
+ * Generate unique session ID
158
+ */
159
+ generateSessionId() {
160
+ return `assess-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
161
+ }
162
+ }
163
+ /**
164
+ * Factory function to create state manager
165
+ */
166
+ export function createStateManager(serverName, stateDir) {
167
+ return new AssessmentStateManager(serverName, stateDir);
168
+ }
@@ -1,4 +1,4 @@
1
- import { u as useToast, r as reactExports, j as jsxRuntimeExports, p as parseOAuthCallbackParams, g as generateOAuthErrorDescription, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-DtKbQaUh.js";
1
+ import { u as useToast, r as reactExports, j as jsxRuntimeExports, p as parseOAuthCallbackParams, g as generateOAuthErrorDescription, S as SESSION_KEYS, I as InspectorOAuthClientProvider, a as auth } from "./index-BAJG90Yd.js";
2
2
  const OAuthCallback = ({ onConnect }) => {
3
3
  const { toast } = useToast();
4
4
  const hasProcessedRef = reactExports.useRef(false);
@@ -1,4 +1,4 @@
1
- import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-DtKbQaUh.js";
1
+ import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-BAJG90Yd.js";
2
2
  const OAuthDebugCallback = ({ onConnect }) => {
3
3
  reactExports.useEffect(() => {
4
4
  let isProcessed = false;
@@ -16320,7 +16320,7 @@ object({
16320
16320
  token_type_hint: string().optional()
16321
16321
  }).strip();
16322
16322
  const name = "@bryan-thompson/inspector-assessment-client";
16323
- const version$1 = "1.13.1";
16323
+ const version$1 = "1.14.0";
16324
16324
  const packageJson = {
16325
16325
  name,
16326
16326
  version: version$1
@@ -48863,7 +48863,7 @@ const useTheme = () => {
48863
48863
  [theme, setThemeWithSideEffect]
48864
48864
  );
48865
48865
  };
48866
- const version = "1.13.1";
48866
+ const version = "1.14.0";
48867
48867
  var [createTooltipContext] = createContextScope("Tooltip", [
48868
48868
  createPopperScope
48869
48869
  ]);
@@ -51556,7 +51556,8 @@ const DEFAULT_ASSESSMENT_CONFIG = {
51556
51556
  prohibitedLibraries: false,
51557
51557
  manifestValidation: false,
51558
51558
  portability: false,
51559
- externalAPIScanner: false
51559
+ externalAPIScanner: false,
51560
+ authentication: false
51560
51561
  }
51561
51562
  };
51562
51563
  const REVIEWER_MODE_CONFIG = {
@@ -51596,7 +51597,8 @@ const REVIEWER_MODE_CONFIG = {
51596
51597
  prohibitedLibraries: false,
51597
51598
  manifestValidation: false,
51598
51599
  portability: false,
51599
- externalAPIScanner: false
51600
+ externalAPIScanner: false,
51601
+ authentication: false
51600
51602
  }
51601
51603
  };
51602
51604
  const DEVELOPER_MODE_CONFIG = {
@@ -51633,7 +51635,8 @@ const DEVELOPER_MODE_CONFIG = {
51633
51635
  prohibitedLibraries: true,
51634
51636
  manifestValidation: true,
51635
51637
  portability: true,
51636
- externalAPIScanner: true
51638
+ externalAPIScanner: true,
51639
+ authentication: true
51637
51640
  }
51638
51641
  };
51639
51642
  class BaseAssessor {
@@ -54777,6 +54780,11 @@ class FunctionalityAssessor extends BaseAssessor {
54777
54780
  workingTools,
54778
54781
  brokenTools
54779
54782
  );
54783
+ const tools = context.tools.map((t) => ({
54784
+ name: t.name,
54785
+ description: t.description,
54786
+ inputSchema: t.inputSchema
54787
+ }));
54780
54788
  return {
54781
54789
  totalTools,
54782
54790
  testedTools,
@@ -54785,7 +54793,8 @@ class FunctionalityAssessor extends BaseAssessor {
54785
54793
  coveragePercentage,
54786
54794
  status,
54787
54795
  explanation,
54788
- toolResults
54796
+ toolResults,
54797
+ tools
54789
54798
  };
54790
54799
  }
54791
54800
  async testTool(tool, callTool) {
@@ -61868,13 +61877,13 @@ const App = () => {
61868
61877
  ) });
61869
61878
  if (window.location.pathname === "/oauth/callback") {
61870
61879
  const OAuthCallback = React.lazy(
61871
- () => __vitePreload(() => import("./OAuthCallback-Dg3beipA.js"), true ? [] : void 0)
61880
+ () => __vitePreload(() => import("./OAuthCallback-DaKwjxdn.js"), true ? [] : void 0)
61872
61881
  );
61873
61882
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
61874
61883
  }
61875
61884
  if (window.location.pathname === "/oauth/callback/debug") {
61876
61885
  const OAuthDebugCallback = React.lazy(
61877
- () => __vitePreload(() => import("./OAuthDebugCallback-zRUPyR0T.js"), true ? [] : void 0)
61886
+ () => __vitePreload(() => import("./OAuthDebugCallback-HiI2IPgB.js"), true ? [] : void 0)
61878
61887
  );
61879
61888
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
61880
61889
  }
@@ -1841,6 +1841,9 @@ video {
1841
1841
  .lowercase {
1842
1842
  text-transform: lowercase;
1843
1843
  }
1844
+ .capitalize {
1845
+ text-transform: capitalize;
1846
+ }
1844
1847
  .italic {
1845
1848
  font-style: italic;
1846
1849
  }
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/mcp.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>MCP Inspector</title>
8
- <script type="module" crossorigin src="/assets/index-DtKbQaUh.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-Cuc9GxjD.css">
8
+ <script type="module" crossorigin src="/assets/index-BAJG90Yd.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-BdXNC65t.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root" class="w-full"></div>
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Assessment Differ
3
+ * Compares two assessment runs to detect regressions or improvements.
4
+ *
5
+ * Use Cases:
6
+ * - Compare bundle v1.0 vs v1.1
7
+ * - Track assessment changes over time
8
+ * - CI/CD regression detection
9
+ */
10
+ import type { MCPDirectoryAssessment, AssessmentStatus } from "./assessmentTypes.js";
11
+ /**
12
+ * Change direction for a metric
13
+ */
14
+ export type ChangeDirection = "improved" | "regressed" | "unchanged";
15
+ /**
16
+ * Detailed change information for a single module
17
+ */
18
+ export interface ModuleChange {
19
+ module: string;
20
+ baselineStatus: AssessmentStatus;
21
+ currentStatus: AssessmentStatus;
22
+ baselineScore?: number;
23
+ currentScore?: number;
24
+ change: ChangeDirection;
25
+ details: string;
26
+ }
27
+ /**
28
+ * Security-specific delta tracking
29
+ */
30
+ export interface SecurityDelta {
31
+ newVulnerabilities: string[];
32
+ fixedVulnerabilities: string[];
33
+ netChange: number;
34
+ baselineCount: number;
35
+ currentCount: number;
36
+ }
37
+ /**
38
+ * Functionality-specific delta tracking
39
+ */
40
+ export interface FunctionalityDelta {
41
+ newBrokenTools: string[];
42
+ fixedTools: string[];
43
+ netChange: number;
44
+ baselineWorking: number;
45
+ currentWorking: number;
46
+ }
47
+ /**
48
+ * Full assessment comparison result
49
+ */
50
+ export interface AssessmentDiff {
51
+ serverName: string;
52
+ baseline: {
53
+ version?: string;
54
+ date: string;
55
+ assessorVersion: string;
56
+ };
57
+ current: {
58
+ version?: string;
59
+ date: string;
60
+ assessorVersion: string;
61
+ };
62
+ summary: {
63
+ overallChange: ChangeDirection;
64
+ baselineStatus: AssessmentStatus;
65
+ currentStatus: AssessmentStatus;
66
+ modulesImproved: number;
67
+ modulesRegressed: number;
68
+ modulesUnchanged: number;
69
+ };
70
+ moduleChanges: ModuleChange[];
71
+ securityDelta: SecurityDelta;
72
+ functionalityDelta: FunctionalityDelta;
73
+ recommendations: string[];
74
+ }
75
+ /**
76
+ * Compare two assessment runs
77
+ */
78
+ export declare function compareAssessments(baseline: MCPDirectoryAssessment, current: MCPDirectoryAssessment): AssessmentDiff;
79
+ //# sourceMappingURL=assessmentDiffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assessmentDiffer.d.ts","sourceRoot":"","sources":["../../src/lib/assessmentDiffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,gBAAgB,CAAC;IACjC,aAAa,EAAE,gBAAgB,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,OAAO,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,OAAO,EAAE;QACP,aAAa,EAAE,eAAe,CAAC;QAC/B,cAAc,EAAE,gBAAgB,CAAC;QACjC,aAAa,EAAE,gBAAgB,CAAC;QAChC,eAAe,EAAE,MAAM,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;QACzB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,aAAa,EAAE,aAAa,CAAC;IAC7B,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,sBAAsB,EAChC,OAAO,EAAE,sBAAsB,GAC9B,cAAc,CA4DhB"}