Skip to main content
Glama

hypertool-mcp

validation.test.tsโ€ข11.6 kB
/** * Extension Validation Service Tests */ import { describe, it, expect } from "vitest"; import { ExtensionValidationService } from "./validation.js"; import { DxtManifest, ExtensionUserConfig } from "../config/dxt-config.js"; describe("ExtensionValidationService", () => { const validationService = new ExtensionValidationService(); describe("validateExtensionConfig", () => { it("should validate successfully when no user_config in manifest", () => { const manifest: DxtManifest = { dxt_version: "0.1", name: "test-extension", version: "1.0.0", server: { type: "node", mcp_config: { command: "node", args: ["server.js"], }, }, }; const result = validationService.validateExtensionConfig(manifest); expect(result.isValid).toBe(true); expect(result.errors).toHaveLength(0); expect(result.warnings).toHaveLength(0); }); it("should validate required string parameter", () => { const manifest: DxtManifest = { dxt_version: "0.1", name: "test-extension", version: "1.0.0", server: { type: "node", mcp_config: { command: "node", args: ["server.js"], }, }, user_config: { api_key: { type: "string", required: true, title: "API Key", }, }, }; // Missing required parameter const resultMissing = validationService.validateExtensionConfig(manifest); expect(resultMissing.isValid).toBe(false); expect(resultMissing.errors).toContain( "Missing required config: api_key" ); // Valid parameter const userSettings: ExtensionUserConfig = { isEnabled: true, userConfig: { api_key: "test-key", }, }; const resultValid = validationService.validateExtensionConfig( manifest, userSettings ); expect(resultValid.isValid).toBe(true); // Invalid type const userSettingsInvalid: ExtensionUserConfig = { isEnabled: true, userConfig: { api_key: 123, }, }; const resultInvalid = validationService.validateExtensionConfig( manifest, userSettingsInvalid ); expect(resultInvalid.isValid).toBe(false); expect(resultInvalid.errors).toContain( "Invalid type for api_key. Expected string, got number" ); }); it("should validate number parameter with range", () => { const manifest: DxtManifest = { dxt_version: "0.1", name: "test-extension", version: "1.0.0", server: { type: "node", mcp_config: { command: "node", args: ["server.js"], }, }, user_config: { timeout: { type: "number", min: 1, max: 300, default: 30, }, }, }; // Valid value const userSettingsValid: ExtensionUserConfig = { isEnabled: true, userConfig: { timeout: 60, }, }; const resultValid = validationService.validateExtensionConfig( manifest, userSettingsValid ); expect(resultValid.isValid).toBe(true); // Below minimum const userSettingsLow: ExtensionUserConfig = { isEnabled: true, userConfig: { timeout: 0, }, }; const resultLow = validationService.validateExtensionConfig( manifest, userSettingsLow ); expect(resultLow.isValid).toBe(false); expect(resultLow.errors).toContain("Value for timeout must be >= 1"); // Above maximum const userSettingsHigh: ExtensionUserConfig = { isEnabled: true, userConfig: { timeout: 400, }, }; const resultHigh = validationService.validateExtensionConfig( manifest, userSettingsHigh ); expect(resultHigh.isValid).toBe(false); expect(resultHigh.errors).toContain("Value for timeout must be <= 300"); }); it("should validate multiple values", () => { const manifest: DxtManifest = { dxt_version: "0.1", name: "test-extension", version: "1.0.0", server: { type: "node", mcp_config: { command: "node", args: ["server.js"], }, }, user_config: { directories: { type: "directory", multiple: true, required: true, }, single_dir: { type: "directory", multiple: false, }, }, }; // Valid multiple values const userSettingsValid: ExtensionUserConfig = { isEnabled: true, userConfig: { directories: ["/path/one", "/path/two"], single_dir: "/single/path", }, }; const resultValid = validationService.validateExtensionConfig( manifest, userSettingsValid ); expect(resultValid.isValid).toBe(true); // Invalid: array for non-multiple const userSettingsInvalid: ExtensionUserConfig = { isEnabled: true, userConfig: { directories: ["/path/one", "/path/two"], single_dir: ["/single/path"], }, }; const resultInvalid = validationService.validateExtensionConfig( manifest, userSettingsInvalid ); expect(resultInvalid.isValid).toBe(false); expect( resultInvalid.errors.some( (error) => error.includes("got object") || error.includes("not be an array") ) ).toBe(true); // Invalid: non-array for multiple const userSettingsInvalid2: ExtensionUserConfig = { isEnabled: true, userConfig: { directories: "/single/path", }, }; const resultInvalid2 = validationService.validateExtensionConfig( manifest, userSettingsInvalid2 ); expect(resultInvalid2.isValid).toBe(false); expect( resultInvalid2.errors.some( (error) => error.includes("must be an array") || error.includes("Expected directory") ) ).toBe(true); }); it("should warn about unknown config keys", () => { const manifest: DxtManifest = { dxt_version: "0.1", name: "test-extension", version: "1.0.0", server: { type: "node", mcp_config: { command: "node", args: ["server.js"], }, }, user_config: { known_param: { type: "string", }, }, }; const userSettings: ExtensionUserConfig = { isEnabled: true, userConfig: { known_param: "value", unknown_param: "unknown", }, }; const result = validationService.validateExtensionConfig( manifest, userSettings ); expect(result.isValid).toBe(true); expect(result.warnings).toContain( "Unknown config key: unknown_param (not defined in manifest user_config)" ); }); it("should validate boolean parameters", () => { const manifest: DxtManifest = { dxt_version: "0.1", name: "test-extension", version: "1.0.0", server: { type: "node", mcp_config: { command: "node", args: ["server.js"], }, }, user_config: { enabled: { type: "boolean", default: false, }, }, }; // Valid boolean const userSettingsValid: ExtensionUserConfig = { isEnabled: true, userConfig: { enabled: true, }, }; const resultValid = validationService.validateExtensionConfig( manifest, userSettingsValid ); expect(resultValid.isValid).toBe(true); // Invalid type const userSettingsInvalid: ExtensionUserConfig = { isEnabled: true, userConfig: { enabled: "true", }, }; const resultInvalid = validationService.validateExtensionConfig( manifest, userSettingsInvalid ); expect(resultInvalid.isValid).toBe(false); expect(resultInvalid.errors).toContain( "Invalid type for enabled. Expected boolean, got string" ); }); }); describe("getValidationSummary", () => { it("should generate correct summary for valid extension", () => { const result = { isValid: true, errors: [], warnings: [], }; const summary = validationService.getValidationSummary( "test-ext", result ); expect(summary).toBe("Extension 'test-ext' is valid"); }); it("should generate correct summary for valid extension with warnings", () => { const result = { isValid: true, errors: [], warnings: ["Unknown config key: test"], }; const summary = validationService.getValidationSummary( "test-ext", result ); expect(summary).toBe( "Extension 'test-ext' is valid with warnings: Unknown config key: test" ); }); it("should generate correct summary for invalid extension", () => { const result = { isValid: false, errors: ["Missing required config: api_key"], warnings: [], }; const summary = validationService.getValidationSummary( "test-ext", result ); expect(summary).toBe( "Extension 'test-ext' is invalid: Missing required config: api_key" ); }); }); describe("createValidationReport", () => { it("should create detailed validation report", () => { const manifest: DxtManifest = { dxt_version: "0.1", name: "test-extension", version: "1.0.0", server: { type: "node", mcp_config: { command: "node", args: ["server.js"], }, }, user_config: { api_key: { type: "string", required: true, title: "API Key", description: "Your API key for authentication", }, timeout: { type: "number", min: 1, max: 300, default: 30, title: "Timeout", description: "Request timeout in seconds", }, }, }; const userSettings: ExtensionUserConfig = { isEnabled: true, userConfig: { timeout: 60, }, }; const validationResult = { isValid: false, errors: ["Missing required config: api_key"], warnings: [], }; const report = validationService.createValidationReport( "test-ext", manifest, userSettings, validationResult ); expect(report).toContain("Validation Report for Extension: test-ext"); expect(report).toContain("Status: INVALID"); expect(report).toContain("Missing required config: api_key"); expect(report).toContain("api_key: string (required)"); expect(report).toContain("Your API key for authentication"); expect(report).toContain("timeout: number (1-300)"); expect(report).toContain("Current: 60"); }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/toolprint/hypertool-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server