Skip to main content
Glama

OpenAPI MCP Server

MIT License
2,130
150
  • Apple
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" import { parseHeaders } from "../src/config" // We'll import loadConfig dynamically in each test after setting up mocks describe("parseHeaders", () => { it("should parse header string into a record", () => { const headerStr = "key1:value1,key2:value2" const result = parseHeaders(headerStr) expect(result).toEqual({ key1: "value1", key2: "value2", }) }) it("should handle whitespace in header string", () => { const headerStr = "key1: value1 , key2 :value2" const result = parseHeaders(headerStr) expect(result).toEqual({ key1: "value1", key2: "value2", }) }) it("should return empty object for undefined input", () => { const result = parseHeaders(undefined) expect(result).toEqual({}) }) it("should handle empty string input", () => { const result = parseHeaders("") expect(result).toEqual({}) }) it("should skip malformed headers", () => { const headerStr = "key1:value1,malformed,key2:value2" const result = parseHeaders(headerStr) expect(result).toEqual({ key1: "value1", key2: "value2", }) }) it("should handle header values containing colons", () => { const headerStr = "Authorization:Bearer V:fffff,X-API-Key:key123" const result = parseHeaders(headerStr) expect(result).toEqual({ Authorization: "Bearer V:fffff", "X-API-Key": "key123", }) }) it("should handle multiple colons in header values", () => { const headerStr = "Content-Type:application/json,Authorization:Bearer token:with:multiple:colons" const result = parseHeaders(headerStr) expect(result).toEqual({ "Content-Type": "application/json", Authorization: "Bearer token:with:multiple:colons", }) }) it("should handle empty header values", () => { const headerStr = "X-Custom-Header:,Authorization:Bearer token,X-Empty:" const result = parseHeaders(headerStr) expect(result).toEqual({ "X-Custom-Header": "", Authorization: "Bearer token", "X-Empty": "", }) }) it("should skip headers with empty or whitespace-only keys", () => { const headerStr = ":empty-key, :whitespace-key,Valid-Key:value" const result = parseHeaders(headerStr) expect(result).toEqual({ "Valid-Key": "value", }) }) }) describe("loadConfig", () => { const originalEnv = { ...process.env } const originalArgv = [...process.argv] beforeEach(() => { vi.resetModules() process.argv = ["node", "script.js"] // Clear environment variables that might affect tests delete process.env.API_BASE_URL delete process.env.OPENAPI_SPEC_PATH delete process.env.OPENAPI_SPEC_FROM_STDIN delete process.env.OPENAPI_SPEC_INLINE delete process.env.API_HEADERS delete process.env.SERVER_NAME delete process.env.SERVER_VERSION delete process.env.TRANSPORT_TYPE delete process.env.HTTP_PORT delete process.env.HTTP_HOST delete process.env.ENDPOINT_PATH delete process.env.TOOLS_MODE delete process.env.DISABLE_ABBREVIATION // Reset mocks before each test vi.clearAllMocks() // Clear all mocks vi.doMock("yargs", () => ({})) vi.doMock("yargs/helpers", () => ({})) }) afterEach(() => { process.env = { ...originalEnv } process.argv = [...originalArgv] vi.restoreAllMocks() vi.resetModules() }) it("should load config from command line arguments", async () => { // Setup mocks before importing the module vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", headers: "Authorization:Bearer token", name: "test-server", "server-version": "1.2.3", transport: "stdio", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) // Import the module after setting up mocks const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config).toEqual({ name: "test-server", version: "1.2.3", apiBaseUrl: "https://api.example.com", openApiSpec: "./spec.json", specInputMethod: "file", inlineSpecContent: undefined, headers: { Authorization: "Bearer token", }, transportType: "stdio", httpPort: 3000, httpHost: "127.0.0.1", endpointPath: "/mcp", includeTools: undefined, includeTags: undefined, includeResources: undefined, includeOperations: undefined, toolsMode: "all", disableAbbreviation: undefined, }) }) it("should throw error if API base URL is missing", async () => { // Setup mocks before importing the module vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "openapi-spec": "./spec.json", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) // Import the module after setting up mocks const { loadConfig } = await import("../src/config") expect(() => loadConfig()).toThrow("API base URL is required") }) it("should throw error if OpenAPI spec is missing", async () => { // Setup mocks before importing the module vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) // Import the module after setting up mocks const { loadConfig } = await import("../src/config") expect(() => loadConfig()).toThrow("OpenAPI spec is required") }) it("should use environment variables as fallback", async () => { // Setup mocks before importing the module vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ // empty object }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) // Set environment variables process.env.API_BASE_URL = "https://env.example.com" process.env.OPENAPI_SPEC_PATH = "./env-spec.json" process.env.API_HEADERS = "X-API-Key:12345" process.env.SERVER_NAME = "env-server" process.env.SERVER_VERSION = "3.2.1" process.env.TRANSPORT_TYPE = "stdio" // Import the module after setting up mocks const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config).toEqual({ name: "env-server", version: "3.2.1", apiBaseUrl: "https://env.example.com", openApiSpec: "./env-spec.json", specInputMethod: "file", inlineSpecContent: undefined, headers: { "X-API-Key": "12345", }, transportType: "stdio", httpPort: 3000, httpHost: "127.0.0.1", endpointPath: "/mcp", includeTools: undefined, includeTags: undefined, includeResources: undefined, includeOperations: undefined, toolsMode: "all", disableAbbreviation: undefined, }) }) it("should use default values for name and version if not provided", async () => { // Setup mocks before importing the module vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) // Import the module after setting up mocks const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.name).toBe("mcp-openapi-server") expect(config.version).toBe("1.0.0") expect(config.transportType).toBe("stdio") }) it("should handle disableAbbreviation from command line and environment", async () => { // Test with command line argument vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", "disable-abbreviation": true, }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) // Import the module after setting up mocks let { loadConfig } = await import("../src/config") let config = loadConfig() expect(config.disableAbbreviation).toBe(true) // Reset modules for next test vi.resetModules() // Test with environment variable (string 'true') vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) process.env.DISABLE_ABBREVIATION = "true" // Import the module again after resetting const configModule = await import("../src/config") loadConfig = configModule.loadConfig config = loadConfig() expect(config.disableAbbreviation).toBe(true) // Reset modules for next test vi.resetModules() // Test with environment variable (string 'false') vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) process.env.DISABLE_ABBREVIATION = "false" // Import the module again after resetting const configModule2 = await import("../src/config") loadConfig = configModule2.loadConfig config = loadConfig() expect(config.disableAbbreviation).toBeUndefined() // Test default value (undefined) vi.resetModules() delete process.env.DISABLE_ABBREVIATION vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const configModule3 = await import("../src/config") loadConfig = configModule3.loadConfig config = loadConfig() expect(config.disableAbbreviation).toBeUndefined() }) it("should load config with URL spec", async () => { // Setup mocks before importing the module vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "https://api.example.com/openapi.json", headers: "Authorization:Bearer token", name: "test-server", "server-version": "1.2.3", transport: "stdio", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) // Import the module after setting up mocks const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config).toEqual({ name: "test-server", version: "1.2.3", apiBaseUrl: "https://api.example.com", openApiSpec: "https://api.example.com/openapi.json", specInputMethod: "url", inlineSpecContent: undefined, headers: { Authorization: "Bearer token", }, transportType: "stdio", httpPort: 3000, httpHost: "127.0.0.1", endpointPath: "/mcp", includeTools: undefined, includeTags: undefined, includeResources: undefined, includeOperations: undefined, toolsMode: "all", disableAbbreviation: undefined, }) }) it("should load config with local file spec", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.specInputMethod).toBe("file") expect(config.openApiSpec).toBe("./spec.json") }) it("should load config with stdin spec", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "spec-from-stdin": true, }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.specInputMethod).toBe("stdin") expect(config.openApiSpec).toBe("stdin") }) it("should load config with inline spec", async () => { const inlineSpec = '{"openapi": "3.0.0", "info": {"title": "Test", "version": "1.0.0"}, "paths": {}}' vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "spec-inline": inlineSpec, }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.specInputMethod).toBe("inline") expect(config.openApiSpec).toBe("inline") expect(config.inlineSpecContent).toBe(inlineSpec) }) it("should load config with environment variables for stdin", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({}), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) process.env.API_BASE_URL = "https://env.example.com" process.env.OPENAPI_SPEC_FROM_STDIN = "true" const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.specInputMethod).toBe("stdin") expect(config.openApiSpec).toBe("stdin") }) it("should load config with environment variables for inline spec", async () => { const inlineSpec = '{"openapi": "3.0.0"}' vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({}), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) process.env.API_BASE_URL = "https://env.example.com" process.env.OPENAPI_SPEC_INLINE = inlineSpec const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.specInputMethod).toBe("inline") expect(config.inlineSpecContent).toBe(inlineSpec) }) it("should throw error if no spec input method is provided", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") expect(() => loadConfig()).toThrow( "OpenAPI spec is required. Use one of: --openapi-spec, --spec-from-stdin, or --spec-inline", ) }) it("should throw error if multiple spec input methods are provided", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", "spec-from-stdin": true, }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") expect(() => loadConfig()).toThrow( "Only one OpenAPI spec input method can be specified at a time", ) }) describe("Array Options Handling", () => { it("should handle array options for tools, tags, resources, and operations", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", tool: ["tool1", "tool2", "tool3"], tag: ["auth", "users"], resource: ["api/v1/users", "api/v1/posts"], operation: ["get", "post", "put"], }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.includeTools).toEqual(["tool1", "tool2", "tool3"]) expect(config.includeTags).toEqual(["auth", "users"]) expect(config.includeResources).toEqual(["api/v1/users", "api/v1/posts"]) expect(config.includeOperations).toEqual(["get", "post", "put"]) }) it("should handle single values for array options", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", tool: ["single-tool"], tag: ["single-tag"], resource: ["single-resource"], operation: ["get"], }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.includeTools).toEqual(["single-tool"]) expect(config.includeTags).toEqual(["single-tag"]) expect(config.includeResources).toEqual(["single-resource"]) expect(config.includeOperations).toEqual(["get"]) }) it("should handle empty arrays for array options", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", tool: [], tag: [], resource: [], operation: [], }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.includeTools).toEqual([]) expect(config.includeTags).toEqual([]) expect(config.includeResources).toEqual([]) expect(config.includeOperations).toEqual([]) }) it("should handle undefined array options", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", // No array options provided }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.includeTools).toBeUndefined() expect(config.includeTags).toBeUndefined() expect(config.includeResources).toBeUndefined() expect(config.includeOperations).toBeUndefined() }) }) describe("Enum Validation", () => { it("should handle valid transportType choices", async () => { // Test stdio vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", transport: "stdio", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) let { loadConfig } = await import("../src/config") let config = loadConfig() expect(config.transportType).toBe("stdio") // Reset and test http vi.resetModules() vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", transport: "http", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const configModule = await import("../src/config") loadConfig = configModule.loadConfig config = loadConfig() expect(config.transportType).toBe("http") }) it("should handle valid toolsMode choices", async () => { // Test all vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", tools: "all", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) let { loadConfig } = await import("../src/config") let config = loadConfig() expect(config.toolsMode).toBe("all") // Reset and test dynamic vi.resetModules() vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", tools: "dynamic", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) let configModule = await import("../src/config") loadConfig = configModule.loadConfig config = loadConfig() expect(config.toolsMode).toBe("dynamic") // Reset and test explicit vi.resetModules() vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", tools: "explicit", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) configModule = await import("../src/config") loadConfig = configModule.loadConfig config = loadConfig() expect(config.toolsMode).toBe("explicit") }) it("should handle toolsMode from environment variable", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) process.env.TOOLS_MODE = "dynamic" const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.toolsMode).toBe("dynamic") }) it("should default to 'all' for toolsMode when not specified", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.toolsMode).toBe("all") }) it("should handle transportType from environment variable", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) process.env.TRANSPORT_TYPE = "http" const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.transportType).toBe("http") }) it("should default to 'stdio' for transportType when not specified", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.transportType).toBe("stdio") }) // Note: Testing invalid enum values would require testing yargs validation directly, // which would happen at the yargs level before our code runs. Since we're mocking // yargs, we can't test the actual validation behavior. In a real scenario, yargs // would throw an error for invalid choices before loadConfig() is called. // The validation is handled by yargs' .choices() method in the actual implementation. }) describe("HTTP Configuration", () => { it("should handle HTTP transport configuration", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", transport: "http", port: 8080, host: "0.0.0.0", path: "/custom-mcp", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.transportType).toBe("http") expect(config.httpPort).toBe(8080) expect(config.httpHost).toBe("0.0.0.0") expect(config.endpointPath).toBe("/custom-mcp") }) it("should use default HTTP configuration values", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", transport: "http", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.transportType).toBe("http") expect(config.httpPort).toBe(3000) expect(config.httpHost).toBe("127.0.0.1") expect(config.endpointPath).toBe("/mcp") }) it("should handle HTTP configuration from environment variables", async () => { vi.doMock("yargs", () => ({ default: vi.fn().mockReturnValue({ option: vi.fn().mockReturnThis(), help: vi.fn().mockReturnThis(), parseSync: vi.fn().mockReturnValue({ "api-base-url": "https://api.example.com", "openapi-spec": "./spec.json", }), }), })) vi.doMock("yargs/helpers", () => ({ hideBin: vi.fn((arr) => arr), })) process.env.TRANSPORT_TYPE = "http" process.env.HTTP_PORT = "9000" process.env.HTTP_HOST = "localhost" process.env.ENDPOINT_PATH = "/api/mcp" const { loadConfig } = await import("../src/config") const config = loadConfig() expect(config.transportType).toBe("http") expect(config.httpPort).toBe(9000) expect(config.httpHost).toBe("localhost") expect(config.endpointPath).toBe("/api/mcp") }) }) })

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/ivo-toby/mcp-openapi-server'

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