@bryan-thompson/inspector-assessment-server 1.32.1 → 1.32.3
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/build/__tests__/routes.test.js +25 -0
- package/build/index.js +26 -3
- package/package.json +1 -1
|
@@ -103,6 +103,31 @@ describe("POST /assessment/save", () => {
|
|
|
103
103
|
expect(response.status).toBe(200);
|
|
104
104
|
expect(response.body.path).toContain("unknown");
|
|
105
105
|
});
|
|
106
|
+
it("should return 400 when assessment is not an object", async () => {
|
|
107
|
+
const response = await request(app)
|
|
108
|
+
.post("/assessment/save")
|
|
109
|
+
.set("x-mcp-proxy-auth", `Bearer ${sessionToken}`)
|
|
110
|
+
.send({ serverName: "test", assessment: "not-an-object" });
|
|
111
|
+
expect(response.status).toBe(400);
|
|
112
|
+
expect(response.body.success).toBe(false);
|
|
113
|
+
});
|
|
114
|
+
it("should return 400 when assessment is an array", async () => {
|
|
115
|
+
const response = await request(app)
|
|
116
|
+
.post("/assessment/save")
|
|
117
|
+
.set("x-mcp-proxy-auth", `Bearer ${sessionToken}`)
|
|
118
|
+
.send({ serverName: "test", assessment: [1, 2, 3] });
|
|
119
|
+
expect(response.status).toBe(400);
|
|
120
|
+
expect(response.body.success).toBe(false);
|
|
121
|
+
});
|
|
122
|
+
it("should return 400 when serverName exceeds max length", async () => {
|
|
123
|
+
const longName = "a".repeat(300);
|
|
124
|
+
const response = await request(app)
|
|
125
|
+
.post("/assessment/save")
|
|
126
|
+
.set("x-mcp-proxy-auth", `Bearer ${sessionToken}`)
|
|
127
|
+
.send({ serverName: longName, assessment: {} });
|
|
128
|
+
expect(response.status).toBe(400);
|
|
129
|
+
expect(response.body.success).toBe(false);
|
|
130
|
+
});
|
|
106
131
|
it("should require authentication", async () => {
|
|
107
132
|
const response = await request(app)
|
|
108
133
|
.post("/assessment/save")
|
package/build/index.js
CHANGED
|
@@ -18,7 +18,13 @@ import { findActualExecutable } from "spawn-rx";
|
|
|
18
18
|
import mcpProxy from "./mcpProxy.js";
|
|
19
19
|
import { is401Error, getHttpHeaders, updateHeadersInPlace } from "./helpers.js";
|
|
20
20
|
import { randomUUID, randomBytes, timingSafeEqual } from "node:crypto";
|
|
21
|
+
import { z } from "zod";
|
|
21
22
|
const DEFAULT_MCP_PROXY_LISTEN_PORT = "6277";
|
|
23
|
+
// Schema for /assessment/save endpoint validation (Issue #87)
|
|
24
|
+
const AssessmentSaveSchema = z.object({
|
|
25
|
+
serverName: z.string().min(1).max(255).optional().default("unknown"),
|
|
26
|
+
assessment: z.object({}).passthrough(), // Must be object, allow any properties
|
|
27
|
+
});
|
|
22
28
|
const defaultEnvironment = {
|
|
23
29
|
...getDefaultEnvironment(),
|
|
24
30
|
...(process.env.MCP_ENV_VARS ? JSON.parse(process.env.MCP_ENV_VARS) : {}),
|
|
@@ -542,15 +548,32 @@ app.get("/health", (req, res) => {
|
|
|
542
548
|
app.post("/assessment/save", originValidationMiddleware, authMiddleware, express.json({ limit: "10mb" }), // Allow large JSON payloads
|
|
543
549
|
async (req, res) => {
|
|
544
550
|
try {
|
|
545
|
-
|
|
546
|
-
const
|
|
551
|
+
// Validate request body (Issue #87)
|
|
552
|
+
const parseResult = AssessmentSaveSchema.safeParse(req.body);
|
|
553
|
+
if (!parseResult.success) {
|
|
554
|
+
return res.status(400).json({
|
|
555
|
+
success: false,
|
|
556
|
+
error: "Invalid request structure",
|
|
557
|
+
details: parseResult.error.format(),
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
const { serverName, assessment } = parseResult.data;
|
|
561
|
+
// Check assessment size (10MB limit)
|
|
562
|
+
const jsonStr = JSON.stringify(assessment, null, 2);
|
|
563
|
+
if (jsonStr.length > 10 * 1024 * 1024) {
|
|
564
|
+
return res.status(413).json({
|
|
565
|
+
success: false,
|
|
566
|
+
error: "Assessment too large (max 10MB)",
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
const sanitizedName = serverName.replace(/[^a-zA-Z0-9-_]/g, "_");
|
|
547
570
|
const filename = `/tmp/inspector-assessment-${sanitizedName}.json`;
|
|
548
571
|
// Delete old file if exists (cleanup)
|
|
549
572
|
if (fs.existsSync(filename)) {
|
|
550
573
|
fs.unlinkSync(filename);
|
|
551
574
|
}
|
|
552
575
|
// Save new assessment
|
|
553
|
-
fs.writeFileSync(filename,
|
|
576
|
+
fs.writeFileSync(filename, jsonStr);
|
|
554
577
|
res.json({
|
|
555
578
|
success: true,
|
|
556
579
|
path: filename,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bryan-thompson/inspector-assessment-server",
|
|
3
|
-
"version": "1.32.
|
|
3
|
+
"version": "1.32.3",
|
|
4
4
|
"description": "Server-side application for the Enhanced MCP Inspector with assessment capabilities",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bryan Thompson <bryan@triepod.ai>",
|