@bryan-thompson/inspector-assessment 1.0.0 → 1.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/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # MCP Inspector Assessment
2
2
 
3
+ [![npm version](https://badge.fury.io/js/@bryan-thompson%2Finspector-assessment.svg)](https://www.npmjs.com/package/@bryan-thompson/inspector-assessment)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@bryan-thompson/inspector-assessment.svg)](https://www.npmjs.com/package/@bryan-thompson/inspector-assessment)
5
+
3
6
  The MCP inspector is a developer tool for testing and debugging MCP servers with comprehensive assessment capabilities for validating server functionality, security, documentation, and compliance.
4
7
 
5
8
  ![MCP Inspector Screenshot](./mcp-inspector.png)
@@ -42,6 +45,18 @@ bunx @bryan-thompson/inspector-assessment
42
45
 
43
46
  The web interface will open at http://localhost:6274
44
47
 
48
+ ## For MCP Directory Reviewers
49
+
50
+ If you're reviewing MCP servers for the Anthropic MCP Directory, see our **[Reviewer Quick Start Guide](docs/REVIEWER_QUICK_START.md)** for:
51
+
52
+ - **60-second fast screening** workflow for approve/reject decisions
53
+ - **5-minute detailed review** process for borderline cases
54
+ - **Common pitfalls** explanation (false positives in security, informational vs scored tests)
55
+ - **Decision matrix** with clear approval criteria
56
+ - **Fast CLI analysis** commands for troubleshooting
57
+
58
+ The quick start guide is optimized for fast reviewer onboarding and provides clear guidance on interpreting assessment results.
59
+
45
60
  ## About This Fork
46
61
 
47
62
  This is an enhanced fork of [Anthropic's MCP Inspector](https://github.com/modelcontextprotocol/inspector) with significantly expanded assessment capabilities for MCP server validation and testing.
@@ -49,6 +64,8 @@ This is an enhanced fork of [Anthropic's MCP Inspector](https://github.com/model
49
64
  **Original Repository**: https://github.com/modelcontextprotocol/inspector
50
65
  **Our Enhanced Fork**: https://github.com/triepod-ai/inspector-assessment
51
66
 
67
+ **⚠️ Important**: This is a published fork with assessment enhancements. If you want the official Anthropic inspector without assessment features, use `npx @modelcontextprotocol/inspector`.
68
+
52
69
  ### What We Added
53
70
 
54
71
  We've built a comprehensive assessment framework on top of the original inspector that transforms it from a debugging tool into a full validation suite for MCP servers. Our enhancements focus on accuracy, depth, and actionable insights for MCP server developers.
@@ -65,13 +82,14 @@ We've built a comprehensive assessment framework on top of the original inspecto
65
82
 
66
83
  Our enhanced fork maintains high code quality standards with comprehensive testing and validation:
67
84
 
68
- - **Test Coverage**: ✅ 464 tests passing (100% pass rate)
85
+ - **Test Coverage**: ✅ 582/582 tests passing (100% pass rate)
69
86
  - **Assessment Module Tests**: 208 tests specifically validating our assessment enhancements
70
87
  - Business logic error detection with confidence scoring
71
88
  - Progressive complexity testing (2 levels: minimal → simple)
72
89
  - Context-aware security testing with zero false positives
73
90
  - Realistic test data generation and boundary testing
74
- - **Total Project Tests**: 464 tests including assessment modules, UI components, and core inspector functionality
91
+ - **Total Project Tests**: 582 tests including assessment modules, UI components, and core inspector functionality
92
+ - All tests updated to reflect comprehensive mode (18 security patterns × 3 payloads per tool)
75
93
  - Test files: `client/src/services/__tests__/` and `client/src/services/assessment/__tests__/`
76
94
  - **Code Quality**: ✅ Production code uses proper TypeScript types
77
95
  - 229 lint issues remaining (down 18% from 280 after recent cleanup)
@@ -88,7 +106,7 @@ Our enhanced fork maintains high code quality standards with comprehensive testi
88
106
  **Testing Commands**:
89
107
 
90
108
  ```bash
91
- npm test # Run all 464 tests
109
+ npm test # Run all 582 tests
92
110
  npm test -- assessment # Run all 208 assessment module tests
93
111
  npm test -- assessmentService # Run assessment service integration tests (54 tests)
94
112
  npm test -- SecurityAssessor # Run security assessment tests (16 tests)
@@ -417,7 +435,7 @@ Our assessment capabilities are backed by a comprehensive test suite that valida
417
435
 
418
436
  **Test Coverage Summary**:
419
437
 
420
- - **464 passing tests** across all project modules (100% pass rate)
438
+ - **582 passing tests** across all project modules (100% pass rate)
421
439
  - **208 assessment module tests** specifically created for validation of our enhancements
422
440
 
423
441
  #### Assessment Module Test Breakdown
@@ -472,14 +490,15 @@ These 208 tests specifically validate:
472
490
  - **Optimization Tests**: Boundary scenario conditional generation, progressive complexity efficiency
473
491
  - **Test Files**: Located in `client/src/services/__tests__/` and `client/src/services/assessment/__tests__/`
474
492
  - **Recent Improvements**:
475
- - Achieved 100% test pass rate (464 passing, 0 failing) - 2025-10-05
493
+ - Achieved 100% test pass rate (582 passing, 0 failing) - 2025-10-11
494
+ - Updated all tests for comprehensive mode (18 security patterns × 3 payloads) - 2025-10-11
476
495
  - Fixed all failing tests after upstream sync - 2025-10-04
477
496
  - Added boundary testing optimization validation - 2025-10-05
478
497
 
479
498
  **Running the Test Suite**:
480
499
 
481
500
  ```bash
482
- npm test # Run all 464 tests
501
+ npm test # Run all 582 tests
483
502
  npm test -- assessmentService # Run main assessment tests
484
503
  npm test -- FunctionalityAssessor # Run specific assessor tests
485
504
  npm test -- SecurityAssessor # Run security tests
@@ -503,13 +522,15 @@ Programmatically run assessments using the CLI:
503
522
 
504
523
  ```bash
505
524
  # Run full assessment
506
- npx @modelcontextprotocol/inspector --cli node build/index.js --assess
525
+ mcp-inspector-assess-cli node build/index.js --assess
526
+ # or with npx
527
+ npx @bryan-thompson/inspector-assessment-cli node build/index.js --assess
507
528
 
508
529
  # Run specific category
509
- npx @modelcontextprotocol/inspector --cli node build/index.js --assess functionality
530
+ mcp-inspector-assess-cli node build/index.js --assess functionality
510
531
 
511
532
  # Export assessment results
512
- npx @modelcontextprotocol/inspector --cli node build/index.js --assess --output assessment-report.json
533
+ mcp-inspector-assess-cli node build/index.js --assess --output assessment-report.json
513
534
  ```
514
535
 
515
536
  ## Running the Inspector
@@ -523,14 +544,16 @@ npx @modelcontextprotocol/inspector --cli node build/index.js --assess --output
523
544
  To get up and running right away with the UI, just execute the following:
524
545
 
525
546
  ```bash
526
- npx @modelcontextprotocol/inspector
547
+ bunx @bryan-thompson/inspector-assessment
548
+ # or with npx
549
+ npx @bryan-thompson/inspector-assessment
527
550
  ```
528
551
 
529
552
  The server will start up and the UI will be accessible at `http://localhost:6274`.
530
553
 
531
554
  ### Docker Container
532
555
 
533
- You can also start it in a Docker container with the following command:
556
+ **Note**: Docker container is not yet available for `@bryan-thompson/inspector-assessment`. The Docker image below is for the upstream inspector only (without assessment features):
534
557
 
535
558
  ```bash
536
559
  docker run --rm --network host -p 6274:6274 -p 6277:6277 ghcr.io/modelcontextprotocol/inspector:latest
@@ -538,32 +561,34 @@ docker run --rm --network host -p 6274:6274 -p 6277:6277 ghcr.io/modelcontextpro
538
561
 
539
562
  ### From an MCP server repository
540
563
 
541
- To inspect an MCP server implementation, there's no need to clone this repo. Instead, use `npx`. For example, if your server is built at `build/index.js`:
564
+ To inspect an MCP server implementation, there's no need to clone this repo. Instead, use `bunx` or `npx`. For example, if your server is built at `build/index.js`:
542
565
 
543
566
  ```bash
544
- npx @modelcontextprotocol/inspector node build/index.js
567
+ bunx @bryan-thompson/inspector-assessment node build/index.js
568
+ # or with npx
569
+ npx @bryan-thompson/inspector-assessment node build/index.js
545
570
  ```
546
571
 
547
572
  You can pass both arguments and environment variables to your MCP server. Arguments are passed directly to your server, while environment variables can be set using the `-e` flag:
548
573
 
549
574
  ```bash
550
575
  # Pass arguments only
551
- npx @modelcontextprotocol/inspector node build/index.js arg1 arg2
576
+ bunx @bryan-thompson/inspector-assessment node build/index.js arg1 arg2
552
577
 
553
578
  # Pass environment variables only
554
- npx @modelcontextprotocol/inspector -e key=value -e key2=$VALUE2 node build/index.js
579
+ bunx @bryan-thompson/inspector-assessment -e key=value -e key2=$VALUE2 node build/index.js
555
580
 
556
581
  # Pass both environment variables and arguments
557
- npx @modelcontextprotocol/inspector -e key=value -e key2=$VALUE2 node build/index.js arg1 arg2
582
+ bunx @bryan-thompson/inspector-assessment -e key=value -e key2=$VALUE2 node build/index.js arg1 arg2
558
583
 
559
584
  # Use -- to separate inspector flags from server arguments
560
- npx @modelcontextprotocol/inspector -e key=$VALUE -- node build/index.js -e server-flag
585
+ bunx @bryan-thompson/inspector-assessment -e key=$VALUE -- node build/index.js -e server-flag
561
586
  ```
562
587
 
563
588
  The inspector runs both an MCP Inspector (MCPI) client UI (default port 6274) and an MCP Proxy (MCPP) server (default port 6277). Open the MCPI client UI in your browser to use the inspector. (These ports are derived from the T9 dialpad mapping of MCPI and MCPP respectively, as a mnemonic). You can customize the ports if needed:
564
589
 
565
590
  ```bash
566
- CLIENT_PORT=8080 SERVER_PORT=9000 npx @modelcontextprotocol/inspector node build/index.js
591
+ CLIENT_PORT=8080 SERVER_PORT=9000 bunx @bryan-thompson/inspector-assessment node build/index.js
567
592
  ```
568
593
 
569
594
  For more details on ways to use the inspector, see the [Inspector section of the MCP docs site](https://modelcontextprotocol.io/docs/tools/inspector). For help with debugging, see the [Debugging guide](https://modelcontextprotocol.io/docs/tools/debugging).
@@ -748,7 +773,7 @@ These settings can be adjusted in real-time through the UI and will persist acro
748
773
  The inspector also supports configuration files to store settings for different MCP servers. This is useful when working with multiple servers or complex configurations:
749
774
 
750
775
  ```bash
751
- npx @modelcontextprotocol/inspector --config path/to/config.json --server everything
776
+ bunx @bryan-thompson/inspector-assessment --config path/to/config.json --server everything
752
777
  ```
753
778
 
754
779
  Example server configuration file:
@@ -827,7 +852,7 @@ You can launch the inspector without specifying a server name if your config has
827
852
 
828
853
  ```bash
829
854
  # Automatically uses "my-server" if it's the only one
830
- npx @modelcontextprotocol/inspector --config mcp.json
855
+ bunx @bryan-thompson/inspector-assessment --config mcp.json
831
856
  ```
832
857
 
833
858
  2. **A server named "default-server"** - automatically selected:
@@ -900,47 +925,47 @@ npm start
900
925
  CLI mode enables programmatic interaction with MCP servers from the command line, ideal for scripting, automation, and integration with coding assistants. This creates an efficient feedback loop for MCP server development.
901
926
 
902
927
  ```bash
903
- npx @modelcontextprotocol/inspector --cli node build/index.js
928
+ mcp-inspector-assess-cli node build/index.js
904
929
  ```
905
930
 
906
931
  The CLI mode supports most operations across tools, resources, and prompts. A few examples:
907
932
 
908
933
  ```bash
909
934
  # Basic usage
910
- npx @modelcontextprotocol/inspector --cli node build/index.js
935
+ mcp-inspector-assess-cli node build/index.js
911
936
 
912
937
  # With config file
913
- npx @modelcontextprotocol/inspector --cli --config path/to/config.json --server myserver
938
+ mcp-inspector-assess-cli --config path/to/config.json --server myserver
914
939
 
915
940
  # List available tools
916
- npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list
941
+ mcp-inspector-assess-cli node build/index.js --method tools/list
917
942
 
918
943
  # Call a specific tool
919
- npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/call --tool-name mytool --tool-arg key=value --tool-arg another=value2
944
+ mcp-inspector-assess-cli node build/index.js --method tools/call --tool-name mytool --tool-arg key=value --tool-arg another=value2
920
945
 
921
946
  # Call a tool with JSON arguments
922
- npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/call --tool-name mytool --tool-arg 'options={"format": "json", "max_tokens": 100}'
947
+ mcp-inspector-assess-cli node build/index.js --method tools/call --tool-name mytool --tool-arg 'options={"format": "json", "max_tokens": 100}'
923
948
 
924
949
  # List available resources
925
- npx @modelcontextprotocol/inspector --cli node build/index.js --method resources/list
950
+ mcp-inspector-assess-cli node build/index.js --method resources/list
926
951
 
927
952
  # List available prompts
928
- npx @modelcontextprotocol/inspector --cli node build/index.js --method prompts/list
953
+ mcp-inspector-assess-cli node build/index.js --method prompts/list
929
954
 
930
955
  # Connect to a remote MCP server (default is SSE transport)
931
- npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com
956
+ mcp-inspector-assess-cli https://my-mcp-server.example.com
932
957
 
933
958
  # Connect to a remote MCP server (with Streamable HTTP transport)
934
- npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --transport http --method tools/list
959
+ mcp-inspector-assess-cli https://my-mcp-server.example.com --transport http --method tools/list
935
960
 
936
961
  # Connect to a remote MCP server (with custom headers)
937
- npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --transport http --method tools/list --header "X-API-Key: your-api-key"
962
+ mcp-inspector-assess-cli https://my-mcp-server.example.com --transport http --method tools/list --header "X-API-Key: your-api-key"
938
963
 
939
964
  # Call a tool on a remote server
940
- npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --method tools/call --tool-name remotetool --tool-arg param=value
965
+ mcp-inspector-assess-cli https://my-mcp-server.example.com --method tools/call --tool-name remotetool --tool-arg param=value
941
966
 
942
967
  # List resources from a remote server
943
- npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --method resources/list
968
+ mcp-inspector-assess-cli https://my-mcp-server.example.com --method resources/list
944
969
  ```
945
970
 
946
971
  ### UI Mode vs CLI Mode: When to Use Each
@@ -1037,6 +1062,16 @@ Please submit issues and pull requests to our repository: https://github.com/tri
1037
1062
 
1038
1063
  This project builds upon the excellent foundation provided by Anthropic's MCP Inspector team. We're grateful for their work on the original inspector and the MCP protocol specification.
1039
1064
 
1065
+ ## Links
1066
+
1067
+ - **npm Package**: https://www.npmjs.com/package/@bryan-thompson/inspector-assessment
1068
+ - **GitHub Repository**: https://github.com/triepod-ai/inspector-assessment
1069
+ - **Original MCP Inspector**: https://github.com/modelcontextprotocol/inspector
1070
+ - **Issues & Bug Reports**: https://github.com/triepod-ai/inspector-assessment/issues
1071
+ - **MCP Documentation**: https://modelcontextprotocol.io
1072
+ - **Publishing Guide**: [PUBLISHING_GUIDE.md](PUBLISHING_GUIDE.md)
1073
+ - **Changelog**: [CHANGELOG.md](CHANGELOG.md)
1074
+
1040
1075
  ## License
1041
1076
 
1042
1077
  This project is licensed under the MIT License—see the [LICENSE](LICENSE) file for details.
@@ -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-EfKh2svk.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-DrU0QB6A.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-EfKh2svk.js";
1
+ import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-DrU0QB6A.js";
2
2
  const OAuthDebugCallback = ({ onConnect }) => {
3
3
  reactExports.useEffect(() => {
4
4
  let isProcessed = false;
@@ -16205,7 +16205,7 @@ objectType({
16205
16205
  token_type_hint: stringType().optional()
16206
16206
  }).strip();
16207
16207
  const name = "@bryan-thompson/inspector-assessment-client";
16208
- const version$1 = "1.0.0";
16208
+ const version$1 = "1.1.0";
16209
16209
  const packageJson = {
16210
16210
  name,
16211
16211
  version: version$1
@@ -41736,7 +41736,7 @@ const useTheme = () => {
41736
41736
  [theme, setThemeWithSideEffect]
41737
41737
  );
41738
41738
  };
41739
- const version = "1.0.0";
41739
+ const version = "1.1.0";
41740
41740
  var [createTooltipContext] = createContextScope("Tooltip", [
41741
41741
  createPopperScope
41742
41742
  ]);
@@ -44133,6 +44133,8 @@ const ToolsTab = ({
44133
44133
  const DEFAULT_ASSESSMENT_CONFIG = {
44134
44134
  testTimeout: 3e4,
44135
44135
  // 30 seconds per tool
44136
+ delayBetweenTests: 0,
44137
+ // No delay by default
44136
44138
  skipBrokenTools: false,
44137
44139
  reviewerMode: false,
44138
44140
  enableExtendedAssessment: true,
@@ -44158,6 +44160,8 @@ const DEFAULT_ASSESSMENT_CONFIG = {
44158
44160
  const REVIEWER_MODE_CONFIG = {
44159
44161
  testTimeout: 1e4,
44160
44162
  // 10 seconds per tool (faster)
44163
+ delayBetweenTests: 100,
44164
+ // Small delay for rate limiting
44161
44165
  skipBrokenTools: true,
44162
44166
  // Skip broken tools to save time
44163
44167
  reviewerMode: true,
@@ -44188,6 +44192,8 @@ const REVIEWER_MODE_CONFIG = {
44188
44192
  const DEVELOPER_MODE_CONFIG = {
44189
44193
  testTimeout: 3e4,
44190
44194
  // 30 seconds per tool
44195
+ delayBetweenTests: 500,
44196
+ // Moderate delay for thorough testing
44191
44197
  skipBrokenTools: false,
44192
44198
  reviewerMode: false,
44193
44199
  enableExtendedAssessment: true,
@@ -44783,6 +44789,9 @@ class ErrorHandlingAssessor extends BaseAssessor {
44783
44789
  );
44784
44790
  testDetails.push(...toolTests);
44785
44791
  passedTests += toolTests.filter((t) => t.passed).length;
44792
+ if (this.config.delayBetweenTests && this.config.delayBetweenTests > 0) {
44793
+ await this.sleep(this.config.delayBetweenTests);
44794
+ }
44786
44795
  }
44787
44796
  this.testCount = testDetails.length;
44788
44797
  const metrics = this.calculateMetrics(testDetails, passedTests);
@@ -44837,7 +44846,7 @@ class ErrorHandlingAssessor extends BaseAssessor {
44837
44846
  return tests;
44838
44847
  }
44839
44848
  async testMissingParameters(tool, callTool) {
44840
- var _a;
44849
+ var _a, _b, _c;
44841
44850
  const testInput = {};
44842
44851
  const schema = this.getToolSchema(tool);
44843
44852
  const hasRequiredParams = (schema == null ? void 0 : schema.required) && Array.isArray(schema.required) && schema.required.length > 0;
@@ -44883,9 +44892,9 @@ class ErrorHandlingAssessor extends BaseAssessor {
44883
44892
  reason: isError ? void 0 : "Tool did not reject missing parameters"
44884
44893
  };
44885
44894
  } catch (error) {
44886
- const errorMessage = this.extractErrorMessage(error);
44887
- const messageLower = (errorMessage == null ? void 0 : errorMessage.toLowerCase()) ?? "";
44888
- const isMeaningfulError = messageLower.includes("required") || messageLower.includes("missing") || messageLower.includes("parameter") || messageLower.includes("must") || messageLower.includes("invalid") || messageLower.includes("validation") || (errorMessage == null ? void 0 : errorMessage.length) > 20;
44895
+ const errorInfo = this.extractErrorInfo(error);
44896
+ const messageLower = ((_b = errorInfo.message) == null ? void 0 : _b.toLowerCase()) ?? "";
44897
+ const isMeaningfulError = messageLower.includes("required") || messageLower.includes("missing") || messageLower.includes("parameter") || messageLower.includes("must") || messageLower.includes("invalid") || messageLower.includes("validation") || (((_c = errorInfo.message) == null ? void 0 : _c.length) ?? 0) > 20;
44889
44898
  return {
44890
44899
  toolName: tool.name,
44891
44900
  testType: "missing_required",
@@ -44893,7 +44902,8 @@ class ErrorHandlingAssessor extends BaseAssessor {
44893
44902
  expectedError: "Missing required parameters",
44894
44903
  actualResponse: {
44895
44904
  isError: true,
44896
- errorMessage,
44905
+ errorCode: errorInfo.code,
44906
+ errorMessage: errorInfo.message,
44897
44907
  rawResponse: error
44898
44908
  },
44899
44909
  passed: isMeaningfulError,
@@ -44902,7 +44912,7 @@ class ErrorHandlingAssessor extends BaseAssessor {
44902
44912
  }
44903
44913
  }
44904
44914
  async testWrongTypes(tool, callTool) {
44905
- var _a;
44915
+ var _a, _b, _c;
44906
44916
  const schema = this.getToolSchema(tool);
44907
44917
  const testInput = this.generateWrongTypeParams(schema);
44908
44918
  try {
@@ -44932,9 +44942,9 @@ class ErrorHandlingAssessor extends BaseAssessor {
44932
44942
  reason: isError ? void 0 : "Tool accepted wrong parameter types"
44933
44943
  };
44934
44944
  } catch (error) {
44935
- const errorMessage = this.extractErrorMessage(error);
44936
- const messageLower = (errorMessage == null ? void 0 : errorMessage.toLowerCase()) ?? "";
44937
- const isMeaningfulError = messageLower.includes("type") || messageLower.includes("invalid") || messageLower.includes("expected") || messageLower.includes("must be") || messageLower.includes("validation") || messageLower.includes("string") || messageLower.includes("number") || (errorMessage == null ? void 0 : errorMessage.length) > 20;
44945
+ const errorInfo = this.extractErrorInfo(error);
44946
+ const messageLower = ((_b = errorInfo.message) == null ? void 0 : _b.toLowerCase()) ?? "";
44947
+ const isMeaningfulError = messageLower.includes("type") || messageLower.includes("invalid") || messageLower.includes("expected") || messageLower.includes("must be") || messageLower.includes("validation") || messageLower.includes("string") || messageLower.includes("number") || (((_c = errorInfo.message) == null ? void 0 : _c.length) ?? 0) > 20;
44938
44948
  return {
44939
44949
  toolName: tool.name,
44940
44950
  testType: "wrong_type",
@@ -44942,7 +44952,8 @@ class ErrorHandlingAssessor extends BaseAssessor {
44942
44952
  expectedError: "Type validation error",
44943
44953
  actualResponse: {
44944
44954
  isError: true,
44945
- errorMessage,
44955
+ errorCode: errorInfo.code,
44956
+ errorMessage: errorInfo.message,
44946
44957
  rawResponse: error
44947
44958
  },
44948
44959
  passed: isMeaningfulError,
@@ -44951,6 +44962,7 @@ class ErrorHandlingAssessor extends BaseAssessor {
44951
44962
  }
44952
44963
  }
44953
44964
  async testInvalidValues(tool, callTool) {
44965
+ var _a, _b;
44954
44966
  const schema = this.getToolSchema(tool);
44955
44967
  const testInput = this.generateInvalidValueParams(schema);
44956
44968
  try {
@@ -44975,9 +44987,9 @@ class ErrorHandlingAssessor extends BaseAssessor {
44975
44987
  reason: isError ? void 0 : "Tool accepted invalid values"
44976
44988
  };
44977
44989
  } catch (error) {
44978
- const errorMessage = this.extractErrorMessage(error);
44979
- const messageLower = (errorMessage == null ? void 0 : errorMessage.toLowerCase()) ?? "";
44980
- const isMeaningfulError = messageLower.includes("invalid") || messageLower.includes("not allowed") || messageLower.includes("must") || messageLower.includes("cannot") || messageLower.includes("validation") || messageLower.includes("error") || (errorMessage == null ? void 0 : errorMessage.length) > 15;
44990
+ const errorInfo = this.extractErrorInfo(error);
44991
+ const messageLower = ((_a = errorInfo.message) == null ? void 0 : _a.toLowerCase()) ?? "";
44992
+ const isMeaningfulError = messageLower.includes("invalid") || messageLower.includes("not allowed") || messageLower.includes("must") || messageLower.includes("cannot") || messageLower.includes("validation") || messageLower.includes("error") || (((_b = errorInfo.message) == null ? void 0 : _b.length) ?? 0) > 15;
44981
44993
  return {
44982
44994
  toolName: tool.name,
44983
44995
  testType: "invalid_values",
@@ -44985,7 +44997,8 @@ class ErrorHandlingAssessor extends BaseAssessor {
44985
44997
  expectedError: "Invalid parameter values",
44986
44998
  actualResponse: {
44987
44999
  isError: true,
44988
- errorMessage,
45000
+ errorCode: errorInfo.code,
45001
+ errorMessage: errorInfo.message,
44989
45002
  rawResponse: error
44990
45003
  },
44991
45004
  passed: isMeaningfulError,
@@ -44994,6 +45007,7 @@ class ErrorHandlingAssessor extends BaseAssessor {
44994
45007
  }
44995
45008
  }
44996
45009
  async testExcessiveInput(tool, callTool) {
45010
+ var _a, _b;
44997
45011
  const largeString = "x".repeat(1e5);
44998
45012
  const testInput = this.generateParamsWithValue(tool, largeString);
44999
45013
  try {
@@ -45020,9 +45034,9 @@ class ErrorHandlingAssessor extends BaseAssessor {
45020
45034
  reason: !isError && !response ? "Tool crashed on large input" : void 0
45021
45035
  };
45022
45036
  } catch (error) {
45023
- const errorMessage = this.extractErrorMessage(error);
45024
- const messageLower = (errorMessage == null ? void 0 : errorMessage.toLowerCase()) ?? "";
45025
- const isMeaningfulError = messageLower.includes("size") || messageLower.includes("large") || messageLower.includes("limit") || messageLower.includes("exceed") || messageLower.includes("too") || messageLower.includes("maximum") || (errorMessage == null ? void 0 : errorMessage.length) > 10;
45037
+ const errorInfo = this.extractErrorInfo(error);
45038
+ const messageLower = ((_a = errorInfo.message) == null ? void 0 : _a.toLowerCase()) ?? "";
45039
+ const isMeaningfulError = messageLower.includes("size") || messageLower.includes("large") || messageLower.includes("limit") || messageLower.includes("exceed") || messageLower.includes("too") || messageLower.includes("maximum") || (((_b = errorInfo.message) == null ? void 0 : _b.length) ?? 0) > 10;
45026
45040
  return {
45027
45041
  toolName: tool.name,
45028
45042
  testType: "excessive_input",
@@ -45030,7 +45044,8 @@ class ErrorHandlingAssessor extends BaseAssessor {
45030
45044
  expectedError: "Input size limit exceeded",
45031
45045
  actualResponse: {
45032
45046
  isError: true,
45033
- errorMessage,
45047
+ errorCode: errorInfo.code,
45048
+ errorMessage: errorInfo.message,
45034
45049
  rawResponse: "[error details omitted]"
45035
45050
  },
45036
45051
  passed: isMeaningfulError,
@@ -45178,12 +45193,17 @@ class ErrorHandlingAssessor extends BaseAssessor {
45178
45193
  else if (score >= 70) quality = "good";
45179
45194
  else if (score >= 50) quality = "fair";
45180
45195
  else quality = "poor";
45181
- const hasProperErrorCodes = tests.some(
45196
+ const actualErrors = tests.filter((t) => t.actualResponse.isError);
45197
+ const errorsWithCodes = actualErrors.filter(
45182
45198
  (t) => t.actualResponse.errorCode !== void 0
45183
- );
45184
- const hasDescriptiveMessages = tests.some(
45199
+ ).length;
45200
+ const errorsWithMessages = actualErrors.filter(
45185
45201
  (t) => t.actualResponse.errorMessage && t.actualResponse.errorMessage.length > 10
45186
- );
45202
+ ).length;
45203
+ const hasProperErrorCodes = actualErrors.length === 0 || // If no errors were triggered, we can't assess this
45204
+ errorsWithCodes / actualErrors.length >= 0.5;
45205
+ const hasDescriptiveMessages = actualErrors.length === 0 || // If no errors were triggered, we can't assess this
45206
+ errorsWithMessages / actualErrors.length >= 0.5;
45187
45207
  const validatesInputs = tests.filter((t) => ["missing_required", "wrong_type"].includes(t.testType)).some((t) => t.passed);
45188
45208
  return {
45189
45209
  mcpComplianceScore: score,
@@ -48008,9 +48028,17 @@ class ResponseValidator {
48008
48028
  }
48009
48029
  }
48010
48030
  class TestScenarioEngine {
48011
- constructor(testTimeout = 5e3) {
48031
+ constructor(testTimeout = 5e3, delayBetweenTests = 0) {
48012
48032
  __publicField(this, "testTimeout");
48033
+ __publicField(this, "delayBetweenTests");
48013
48034
  this.testTimeout = testTimeout;
48035
+ this.delayBetweenTests = delayBetweenTests;
48036
+ }
48037
+ /**
48038
+ * Sleep for specified milliseconds (for rate limiting)
48039
+ */
48040
+ async sleep(ms) {
48041
+ return new Promise((resolve) => setTimeout(resolve, ms));
48014
48042
  }
48015
48043
  /**
48016
48044
  * Test tool with progressive complexity to identify failure points
@@ -48163,6 +48191,9 @@ class TestScenarioEngine {
48163
48191
  callTool
48164
48192
  );
48165
48193
  result.scenarioResults.push(scenarioResult);
48194
+ if (this.delayBetweenTests > 0) {
48195
+ await this.sleep(this.delayBetweenTests);
48196
+ }
48166
48197
  if (scenarioResult.executed) {
48167
48198
  result.scenariosExecuted++;
48168
48199
  if (scenarioResult.validation.isValid) {
@@ -48573,7 +48604,10 @@ class MCPAssessmentService {
48573
48604
  * Enhanced functionality assessment with multi-scenario testing
48574
48605
  */
48575
48606
  async assessFunctionalityEnhanced(tools, callTool) {
48576
- const engine = new TestScenarioEngine(this.config.testTimeout);
48607
+ const engine = new TestScenarioEngine(
48608
+ this.config.testTimeout,
48609
+ this.config.delayBetweenTests ?? 0
48610
+ );
48577
48611
  const toolResults = [];
48578
48612
  const enhancedResults = [];
48579
48613
  let workingCount = 0;
@@ -50718,6 +50752,30 @@ const AssessmentTab = ({
50718
50752
  ),
50719
50753
  !isLoadingTools && tools.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Select which tools to test for error handling (the most intensive tests). All tools are selected by default." })
50720
50754
  ] }),
50755
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [
50756
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Label$1, { htmlFor: "delay-between-tests", children: "Delay between tests (milliseconds)" }),
50757
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
50758
+ Input,
50759
+ {
50760
+ id: "delay-between-tests",
50761
+ type: "number",
50762
+ min: "0",
50763
+ max: "5000",
50764
+ step: "100",
50765
+ value: config.delayBetweenTests ?? 0,
50766
+ onChange: (e) => {
50767
+ const value = parseInt(e.target.value, 10);
50768
+ setConfig({
50769
+ ...config,
50770
+ delayBetweenTests: isNaN(value) ? 0 : value
50771
+ });
50772
+ },
50773
+ disabled: isRunning,
50774
+ placeholder: "0"
50775
+ }
50776
+ ),
50777
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: "Add a delay between tests to avoid rate limiting. Recommended: 500-1000ms for rate-limited APIs. Set to 0 for no delay (default)." })
50778
+ ] }),
50721
50779
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-2 border rounded-lg p-4 bg-blue-50 dark:bg-blue-950", children: [
50722
50780
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center space-x-2", children: [
50723
50781
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -50734,15 +50792,15 @@ const AssessmentTab = ({
50734
50792
  ),
50735
50793
  /* @__PURE__ */ jsxRuntimeExports.jsxs(Label$1, { htmlFor: "domain-testing", className: "cursor-pointer", children: [
50736
50794
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold", children: "Enable Advanced Security Testing" }),
50737
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2 text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-0.5 rounded", children: "18 Attack Patterns" })
50795
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ml-2 text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 px-2 py-0.5 rounded", children: "18 Patterns" })
50738
50796
  ] })
50739
50797
  ] }),
50740
50798
  /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-muted-foreground ml-6", children: [
50741
50799
  /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Basic:" }),
50742
- " 3 critical patterns (~48 tests).",
50800
+ " 3 common patterns (~48 checks).",
50743
50801
  " ",
50744
50802
  /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Advanced:" }),
50745
- " All 18 patterns. Advanced mode tests Direct Command Injection, Role Override, Data Exfiltration, System Commands, Tool Shadowing, Context Escape, and 12+ other attack vectors."
50803
+ " All 18 patterns. Designed to identify potential issues like Direct Command Injection, Role Override, Data Exfiltration, System Commands, Tool Shadowing, Context Escape, and 12+ other common attack vectors."
50746
50804
  ] })
50747
50805
  ] }),
50748
50806
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
@@ -51857,7 +51915,8 @@ const ErrorTestItem = ({ test }) => {
51857
51915
  {
51858
51916
  className: "text-xs border-l-2 pl-3 py-1",
51859
51917
  style: {
51860
- borderColor: test.passed ? "rgb(34 197 94)" : "rgb(239 68 68)"
51918
+ borderColor: test.testType === "invalid_values" ? "rgb(234 179 8)" : test.passed ? "rgb(34 197 94)" : "rgb(239 68 68)"
51919
+ // red-500 for FAIL
51861
51920
  },
51862
51921
  children: [
51863
51922
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -53106,13 +53165,13 @@ const App = () => {
53106
53165
  ) });
53107
53166
  if (window.location.pathname === "/oauth/callback") {
53108
53167
  const OAuthCallback = React.lazy(
53109
- () => __vitePreload(() => import("./OAuthCallback-CLEJW5KO.js"), true ? [] : void 0)
53168
+ () => __vitePreload(() => import("./OAuthCallback-aV2t2Zmo.js"), true ? [] : void 0)
53110
53169
  );
53111
53170
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
53112
53171
  }
53113
53172
  if (window.location.pathname === "/oauth/callback/debug") {
53114
53173
  const OAuthDebugCallback = React.lazy(
53115
- () => __vitePreload(() => import("./OAuthDebugCallback-B154gAVm.js"), true ? [] : void 0)
53174
+ () => __vitePreload(() => import("./OAuthDebugCallback-Ca01948b.js"), true ? [] : void 0)
53116
53175
  );
53117
53176
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
53118
53177
  }
@@ -5,7 +5,7 @@
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-EfKh2svk.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-DrU0QB6A.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-DYiWOife.css">
10
10
  </head>
11
11
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bryan-thompson/inspector-assessment",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Enhanced MCP Inspector with comprehensive assessment capabilities for server validation",
5
5
  "license": "MIT",
6
6
  "author": "Bryan Thompson <bryan@triepod.ai>",
File without changes