@bryan-thompson/inspector-assessment 1.6.0 → 1.7.1

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 (76) hide show
  1. package/cli/build/assess-full.js +528 -0
  2. package/cli/build/assess-security.js +342 -0
  3. package/client/dist/assets/{OAuthCallback-ZcXdfhZQ.js → OAuthCallback-cGhwkoyY.js} +1 -1
  4. package/client/dist/assets/{OAuthDebugCallback-xt1SlIHS.js → OAuthDebugCallback-2rmUqser.js} +1 -1
  5. package/client/dist/assets/{index-B3lTiDVe.js → index-BnFixpvH.js} +4 -4
  6. package/client/dist/index.html +1 -1
  7. package/client/lib/lib/assessmentTypes.d.ts +670 -0
  8. package/client/lib/lib/assessmentTypes.d.ts.map +1 -0
  9. package/client/lib/lib/assessmentTypes.js +220 -0
  10. package/client/lib/lib/aupPatterns.d.ts +63 -0
  11. package/client/lib/lib/aupPatterns.d.ts.map +1 -0
  12. package/client/lib/lib/aupPatterns.js +344 -0
  13. package/client/lib/lib/prohibitedLibraries.d.ts +76 -0
  14. package/client/lib/lib/prohibitedLibraries.d.ts.map +1 -0
  15. package/client/lib/lib/prohibitedLibraries.js +364 -0
  16. package/client/lib/lib/securityPatterns.d.ts +64 -0
  17. package/client/lib/lib/securityPatterns.d.ts.map +1 -0
  18. package/client/lib/lib/securityPatterns.js +453 -0
  19. package/client/lib/services/assessment/AssessmentOrchestrator.d.ts +88 -0
  20. package/client/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -0
  21. package/client/lib/services/assessment/AssessmentOrchestrator.js +418 -0
  22. package/client/lib/services/assessment/ResponseValidator.d.ts +69 -0
  23. package/client/lib/services/assessment/ResponseValidator.d.ts.map +1 -0
  24. package/client/lib/services/assessment/ResponseValidator.js +1038 -0
  25. package/client/lib/services/assessment/TestDataGenerator.d.ts +86 -0
  26. package/client/lib/services/assessment/TestDataGenerator.d.ts.map +1 -0
  27. package/client/lib/services/assessment/TestDataGenerator.js +669 -0
  28. package/client/lib/services/assessment/TestScenarioEngine.d.ts +91 -0
  29. package/client/lib/services/assessment/TestScenarioEngine.d.ts.map +1 -0
  30. package/client/lib/services/assessment/TestScenarioEngine.js +505 -0
  31. package/client/lib/services/assessment/ToolClassifier.d.ts +61 -0
  32. package/client/lib/services/assessment/ToolClassifier.d.ts.map +1 -0
  33. package/client/lib/services/assessment/ToolClassifier.js +349 -0
  34. package/client/lib/services/assessment/lib/claudeCodeBridge.d.ts +160 -0
  35. package/client/lib/services/assessment/lib/claudeCodeBridge.d.ts.map +1 -0
  36. package/client/lib/services/assessment/lib/claudeCodeBridge.js +357 -0
  37. package/client/lib/services/assessment/modules/AUPComplianceAssessor.d.ts +100 -0
  38. package/client/lib/services/assessment/modules/AUPComplianceAssessor.d.ts.map +1 -0
  39. package/client/lib/services/assessment/modules/AUPComplianceAssessor.js +474 -0
  40. package/client/lib/services/assessment/modules/BaseAssessor.d.ts +71 -0
  41. package/client/lib/services/assessment/modules/BaseAssessor.d.ts.map +1 -0
  42. package/client/lib/services/assessment/modules/BaseAssessor.js +171 -0
  43. package/client/lib/services/assessment/modules/DocumentationAssessor.d.ts +45 -0
  44. package/client/lib/services/assessment/modules/DocumentationAssessor.d.ts.map +1 -0
  45. package/client/lib/services/assessment/modules/DocumentationAssessor.js +355 -0
  46. package/client/lib/services/assessment/modules/ErrorHandlingAssessor.d.ts +25 -0
  47. package/client/lib/services/assessment/modules/ErrorHandlingAssessor.d.ts.map +1 -0
  48. package/client/lib/services/assessment/modules/ErrorHandlingAssessor.js +564 -0
  49. package/client/lib/services/assessment/modules/FunctionalityAssessor.d.ts +20 -0
  50. package/client/lib/services/assessment/modules/FunctionalityAssessor.d.ts.map +1 -0
  51. package/client/lib/services/assessment/modules/FunctionalityAssessor.js +253 -0
  52. package/client/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts +70 -0
  53. package/client/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts.map +1 -0
  54. package/client/lib/services/assessment/modules/MCPSpecComplianceAssessor.js +508 -0
  55. package/client/lib/services/assessment/modules/ManifestValidationAssessor.d.ts +70 -0
  56. package/client/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -0
  57. package/client/lib/services/assessment/modules/ManifestValidationAssessor.js +430 -0
  58. package/client/lib/services/assessment/modules/PortabilityAssessor.d.ts +43 -0
  59. package/client/lib/services/assessment/modules/PortabilityAssessor.d.ts.map +1 -0
  60. package/client/lib/services/assessment/modules/PortabilityAssessor.js +347 -0
  61. package/client/lib/services/assessment/modules/ProhibitedLibrariesAssessor.d.ts +41 -0
  62. package/client/lib/services/assessment/modules/ProhibitedLibrariesAssessor.d.ts.map +1 -0
  63. package/client/lib/services/assessment/modules/ProhibitedLibrariesAssessor.js +256 -0
  64. package/client/lib/services/assessment/modules/SecurityAssessor.d.ts +176 -0
  65. package/client/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -0
  66. package/client/lib/services/assessment/modules/SecurityAssessor.js +1333 -0
  67. package/client/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts +96 -0
  68. package/client/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts.map +1 -0
  69. package/client/lib/services/assessment/modules/ToolAnnotationAssessor.js +593 -0
  70. package/client/lib/services/assessment/modules/UsabilityAssessor.d.ts +21 -0
  71. package/client/lib/services/assessment/modules/UsabilityAssessor.d.ts.map +1 -0
  72. package/client/lib/services/assessment/modules/UsabilityAssessor.js +241 -0
  73. package/client/lib/services/assessment/modules/index.d.ts +33 -0
  74. package/client/lib/services/assessment/modules/index.d.ts.map +1 -0
  75. package/client/lib/services/assessment/modules/index.js +35 -0
  76. package/package.json +5 -2
@@ -0,0 +1,342 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Standalone Security Assessment Runner CLI
4
+ *
5
+ * Runs security assessment against an MCP server without the web UI.
6
+ * Focuses on prompt injection and vulnerability testing.
7
+ *
8
+ * Usage:
9
+ * mcp-assess-security --server <server-name>
10
+ * mcp-assess-security --server broken-mcp --tool vulnerable_tool
11
+ */
12
+ import * as fs from "fs";
13
+ import * as path from "path";
14
+ import * as os from "os";
15
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
16
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
17
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
18
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
19
+ // Import from local client lib (will use package exports when published)
20
+ import { SecurityAssessor } from "../../client/lib/services/assessment/modules/SecurityAssessor.js";
21
+ import { DEFAULT_ASSESSMENT_CONFIG, } from "../../client/lib/lib/assessmentTypes.js";
22
+ /**
23
+ * Load server configuration from Claude Code's MCP settings
24
+ */
25
+ function loadServerConfig(serverName, configPath) {
26
+ const possiblePaths = [
27
+ configPath,
28
+ path.join(os.homedir(), ".config", "mcp", "servers", `${serverName}.json`),
29
+ path.join(os.homedir(), ".config", "claude", "claude_desktop_config.json"),
30
+ ].filter(Boolean);
31
+ for (const tryPath of possiblePaths) {
32
+ if (!fs.existsSync(tryPath))
33
+ continue;
34
+ const config = JSON.parse(fs.readFileSync(tryPath, "utf-8"));
35
+ if (config.mcpServers && config.mcpServers[serverName]) {
36
+ const serverConfig = config.mcpServers[serverName];
37
+ return {
38
+ transport: "stdio",
39
+ command: serverConfig.command,
40
+ args: serverConfig.args || [],
41
+ env: serverConfig.env || {},
42
+ };
43
+ }
44
+ if (config.url ||
45
+ config.transport === "http" ||
46
+ config.transport === "sse") {
47
+ if (!config.url) {
48
+ throw new Error(`Invalid server config: transport is '${config.transport}' but 'url' is missing`);
49
+ }
50
+ return {
51
+ transport: config.transport || "http",
52
+ url: config.url,
53
+ };
54
+ }
55
+ if (config.command) {
56
+ return {
57
+ transport: "stdio",
58
+ command: config.command,
59
+ args: config.args || [],
60
+ env: config.env || {},
61
+ };
62
+ }
63
+ }
64
+ throw new Error(`Server config not found for: ${serverName}\nTried: ${possiblePaths.join(", ")}`);
65
+ }
66
+ /**
67
+ * Connect to MCP server via configured transport
68
+ */
69
+ async function connectToServer(config) {
70
+ let transport;
71
+ switch (config.transport) {
72
+ case "http":
73
+ if (!config.url)
74
+ throw new Error("URL required for HTTP transport");
75
+ transport = new StreamableHTTPClientTransport(new URL(config.url));
76
+ break;
77
+ case "sse":
78
+ if (!config.url)
79
+ throw new Error("URL required for SSE transport");
80
+ transport = new SSEClientTransport(new URL(config.url));
81
+ break;
82
+ case "stdio":
83
+ default:
84
+ if (!config.command)
85
+ throw new Error("Command required for stdio transport");
86
+ transport = new StdioClientTransport({
87
+ command: config.command,
88
+ args: config.args,
89
+ env: {
90
+ ...Object.fromEntries(Object.entries(process.env).filter(([, v]) => v !== undefined)),
91
+ ...config.env,
92
+ },
93
+ stderr: "pipe",
94
+ });
95
+ break;
96
+ }
97
+ const client = new Client({
98
+ name: "mcp-assess-security",
99
+ version: "1.0.0",
100
+ }, {
101
+ capabilities: {},
102
+ });
103
+ await client.connect(transport);
104
+ return client;
105
+ }
106
+ /**
107
+ * Get list of tools from MCP server
108
+ */
109
+ async function getTools(client, toolNameFilter) {
110
+ const response = await client.listTools();
111
+ let tools = response.tools || [];
112
+ if (toolNameFilter) {
113
+ tools = tools.filter((t) => t.name === toolNameFilter);
114
+ if (tools.length === 0) {
115
+ throw new Error(`Tool not found: ${toolNameFilter}`);
116
+ }
117
+ }
118
+ return tools;
119
+ }
120
+ /**
121
+ * Create callTool wrapper for assessment context
122
+ */
123
+ function createCallToolWrapper(client) {
124
+ return async (name, params) => {
125
+ try {
126
+ const response = await client.callTool({
127
+ name,
128
+ arguments: params,
129
+ });
130
+ return {
131
+ content: response.content,
132
+ isError: response.isError || false,
133
+ structuredContent: response
134
+ .structuredContent,
135
+ };
136
+ }
137
+ catch (error) {
138
+ return {
139
+ content: [
140
+ {
141
+ type: "text",
142
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
143
+ },
144
+ ],
145
+ isError: true,
146
+ };
147
+ }
148
+ };
149
+ }
150
+ /**
151
+ * Run security assessment
152
+ */
153
+ async function runSecurityAssessment(options) {
154
+ console.log(`\n🔍 Connecting to MCP server: ${options.serverName}`);
155
+ const serverConfig = loadServerConfig(options.serverName, options.serverConfigPath);
156
+ const client = await connectToServer(serverConfig);
157
+ console.log("✅ Connected successfully");
158
+ const tools = await getTools(client, options.toolName);
159
+ console.log(`🔧 Found ${tools.length} tool${tools.length !== 1 ? "s" : ""}`);
160
+ if (options.toolName) {
161
+ console.log(` Testing only: ${options.toolName}`);
162
+ }
163
+ const config = {
164
+ ...DEFAULT_ASSESSMENT_CONFIG,
165
+ securityPatternsToTest: 17,
166
+ reviewerMode: false,
167
+ testTimeout: 30000,
168
+ };
169
+ const context = {
170
+ serverName: options.serverName,
171
+ tools,
172
+ callTool: createCallToolWrapper(client),
173
+ config,
174
+ };
175
+ console.log(`🛡️ Running security assessment with 17 attack patterns...`);
176
+ const assessor = new SecurityAssessor(config);
177
+ const results = await assessor.assess(context);
178
+ await client.close();
179
+ return results;
180
+ }
181
+ /**
182
+ * Save results to JSON file
183
+ */
184
+ function saveResults(serverName, results, outputPath) {
185
+ const defaultPath = `/tmp/inspector-security-assessment-${serverName}.json`;
186
+ const finalPath = outputPath || defaultPath;
187
+ const output = {
188
+ timestamp: new Date().toISOString(),
189
+ assessmentType: "security",
190
+ serverName,
191
+ security: results,
192
+ };
193
+ fs.writeFileSync(finalPath, JSON.stringify(output, null, 2));
194
+ return finalPath;
195
+ }
196
+ /**
197
+ * Display summary
198
+ */
199
+ function displaySummary(results) {
200
+ const { promptInjectionTests, vulnerabilities, overallRiskLevel } = results;
201
+ const vulnerableCount = promptInjectionTests.filter((t) => t.vulnerable).length;
202
+ const totalTests = promptInjectionTests.length;
203
+ console.log("\n" + "=".repeat(60));
204
+ console.log("SECURITY ASSESSMENT RESULTS");
205
+ console.log("=".repeat(60));
206
+ console.log(`Total Tests: ${totalTests}`);
207
+ console.log(`Vulnerabilities Found: ${vulnerableCount}`);
208
+ console.log(`Overall Risk Level: ${overallRiskLevel}`);
209
+ console.log("=".repeat(60));
210
+ if (vulnerableCount > 0) {
211
+ console.log("\n⚠️ VULNERABILITIES DETECTED:\n");
212
+ const vulnerableTests = promptInjectionTests.filter((t) => t.vulnerable);
213
+ for (const test of vulnerableTests) {
214
+ console.log(`🚨 ${test.toolName} - ${test.testName}`);
215
+ console.log(` Risk: ${test.riskLevel}`);
216
+ console.log(` Evidence: ${test.evidence}`);
217
+ console.log("");
218
+ }
219
+ }
220
+ else {
221
+ console.log("\n✅ No vulnerabilities detected\n");
222
+ }
223
+ }
224
+ /**
225
+ * Parse command-line arguments
226
+ */
227
+ function parseArgs() {
228
+ const args = process.argv.slice(2);
229
+ const options = {};
230
+ for (let i = 0; i < args.length; i++) {
231
+ const arg = args[i];
232
+ if (!arg)
233
+ continue;
234
+ switch (arg) {
235
+ case "--server":
236
+ case "-s":
237
+ options.serverName = args[++i];
238
+ break;
239
+ case "--config":
240
+ case "-c":
241
+ options.serverConfigPath = args[++i];
242
+ break;
243
+ case "--output":
244
+ case "-o":
245
+ options.outputPath = args[++i];
246
+ break;
247
+ case "--tool":
248
+ case "-t":
249
+ options.toolName = args[++i];
250
+ break;
251
+ case "--verbose":
252
+ case "-v":
253
+ options.verbose = true;
254
+ break;
255
+ case "--help":
256
+ case "-h":
257
+ printHelp();
258
+ options.helpRequested = true;
259
+ return options;
260
+ default:
261
+ if (!arg.startsWith("-")) {
262
+ if (!options.serverName) {
263
+ options.serverName = arg;
264
+ }
265
+ }
266
+ else {
267
+ console.error(`Unknown argument: ${arg}`);
268
+ printHelp();
269
+ setTimeout(() => process.exit(1), 10);
270
+ options.helpRequested = true;
271
+ return options;
272
+ }
273
+ }
274
+ }
275
+ if (!options.serverName) {
276
+ console.error("Error: --server is required");
277
+ printHelp();
278
+ setTimeout(() => process.exit(1), 10);
279
+ options.helpRequested = true;
280
+ return options;
281
+ }
282
+ return options;
283
+ }
284
+ /**
285
+ * Print help message
286
+ */
287
+ function printHelp() {
288
+ console.log(`
289
+ Usage: mcp-assess-security [options] [server-name]
290
+
291
+ Run security assessment against an MCP server with 17 attack patterns.
292
+
293
+ Options:
294
+ --server, -s <name> Server name (required, or pass as first positional arg)
295
+ --config, -c <path> Path to server config JSON
296
+ --output, -o <path> Output JSON path (default: /tmp/inspector-security-assessment-<server>.json)
297
+ --tool, -t <name> Test only specific tool (default: test all tools)
298
+ --verbose, -v Enable verbose logging
299
+ --help, -h Show this help message
300
+
301
+ Attack Patterns Tested (17 total):
302
+ • Direct prompt injection
303
+ • Indirect prompt injection
304
+ • Instruction override
305
+ • Role-playing attacks
306
+ • Encoding bypass
307
+ • Multi-turn manipulation
308
+ • Context poisoning
309
+ • And more...
310
+
311
+ Examples:
312
+ mcp-assess-security my-server
313
+ mcp-assess-security --server broken-mcp --tool vulnerable_calculator_tool
314
+ mcp-assess-security --server my-server --output ./security-results.json
315
+ `);
316
+ }
317
+ /**
318
+ * Main execution
319
+ */
320
+ async function main() {
321
+ try {
322
+ const options = parseArgs();
323
+ if (options.helpRequested) {
324
+ return;
325
+ }
326
+ const results = await runSecurityAssessment(options);
327
+ displaySummary(results);
328
+ const outputPath = saveResults(options.serverName, results, options.outputPath);
329
+ console.log(`📄 Results saved to: ${outputPath}\n`);
330
+ const exitCode = results.vulnerabilities.length > 0 ? 1 : 0;
331
+ setTimeout(() => process.exit(exitCode), 10);
332
+ }
333
+ catch (error) {
334
+ console.error("\n❌ Error:", error instanceof Error ? error.message : String(error));
335
+ if (error instanceof Error && error.stack && process.env.DEBUG) {
336
+ console.error("\nStack trace:");
337
+ console.error(error.stack);
338
+ }
339
+ setTimeout(() => process.exit(1), 10);
340
+ }
341
+ }
342
+ main();
@@ -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-B3lTiDVe.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-BnFixpvH.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-B3lTiDVe.js";
1
+ import { r as reactExports, S as SESSION_KEYS, p as parseOAuthCallbackParams, j as jsxRuntimeExports, g as generateOAuthErrorDescription } from "./index-BnFixpvH.js";
2
2
  const OAuthDebugCallback = ({ onConnect }) => {
3
3
  reactExports.useEffect(() => {
4
4
  let isProcessed = false;
@@ -16279,7 +16279,7 @@ object({
16279
16279
  token_type_hint: string().optional()
16280
16280
  }).strip();
16281
16281
  const name = "@bryan-thompson/inspector-assessment-client";
16282
- const version$1 = "1.6.0";
16282
+ const version$1 = "1.7.1";
16283
16283
  const packageJson = {
16284
16284
  name,
16285
16285
  version: version$1
@@ -48464,7 +48464,7 @@ const useTheme = () => {
48464
48464
  [theme, setThemeWithSideEffect]
48465
48465
  );
48466
48466
  };
48467
- const version = "1.6.0";
48467
+ const version = "1.7.1";
48468
48468
  var [createTooltipContext] = createContextScope("Tooltip", [
48469
48469
  createPopperScope
48470
48470
  ]);
@@ -60340,13 +60340,13 @@ const App = () => {
60340
60340
  ) });
60341
60341
  if (window.location.pathname === "/oauth/callback") {
60342
60342
  const OAuthCallback = React.lazy(
60343
- () => __vitePreload(() => import("./OAuthCallback-ZcXdfhZQ.js"), true ? [] : void 0)
60343
+ () => __vitePreload(() => import("./OAuthCallback-cGhwkoyY.js"), true ? [] : void 0)
60344
60344
  );
60345
60345
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthCallback, { onConnect: onOAuthConnect }) });
60346
60346
  }
60347
60347
  if (window.location.pathname === "/oauth/callback/debug") {
60348
60348
  const OAuthDebugCallback = React.lazy(
60349
- () => __vitePreload(() => import("./OAuthDebugCallback-xt1SlIHS.js"), true ? [] : void 0)
60349
+ () => __vitePreload(() => import("./OAuthDebugCallback-2rmUqser.js"), true ? [] : void 0)
60350
60350
  );
60351
60351
  return /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "Loading..." }), children: /* @__PURE__ */ jsxRuntimeExports.jsx(OAuthDebugCallback, { onConnect: onOAuthDebugConnect }) });
60352
60352
  }
@@ -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-B3lTiDVe.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-BnFixpvH.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-Bj7kEsw0.css">
10
10
  </head>
11
11
  <body>