Skip to main content
Glama

hypertool-mcp

externalMcpDetector.test.ts6.14 kB
/** * Tests for external MCP detection functionality */ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; import { join } from "path"; import { homedir } from "os"; import { detectExternalMCPs, formatExternalMCPsMessage, } from "./externalMcpDetector.js"; import * as mcpSetupUtils from "./mcpSetupUtils.js"; // Mock the file system and mcpSetupUtils vi.mock("fs", () => ({ promises: { access: vi.fn(), readFile: vi.fn(), }, })); vi.mock("./mcpSetupUtils.js", () => ({ fileExists: vi.fn(), readJsonFile: vi.fn(), })); describe("externalMcpDetector", () => { const mockUtils = mcpSetupUtils as any; beforeEach(() => { vi.clearAllMocks(); }); afterEach(() => { vi.resetAllMocks(); }); describe("detectExternalMCPs", () => { it("should detect MCPs from Claude Code global config", async () => { // Setup mocks mockUtils.fileExists.mockImplementation((path: string) => { return path === join(homedir(), ".claude.json"); }); mockUtils.readJsonFile.mockImplementation((path: string) => { if (path === join(homedir(), ".claude.json")) { return Promise.resolve({ mcpServers: { "git-mcp": { type: "stdio", command: "git-mcp" }, "docker-mcp": { type: "stdio", command: "docker-mcp" }, }, }); } throw new Error("File not found"); }); const result = await detectExternalMCPs(); expect(result).toHaveLength(2); expect(result[0]).toEqual({ name: "git-mcp", source: "Claude Code (global)", config: { type: "stdio", command: "git-mcp" }, }); expect(result[1]).toEqual({ name: "docker-mcp", source: "Claude Code (global)", config: { type: "stdio", command: "docker-mcp" }, }); }); it("should skip hypertool MCP servers", async () => { mockUtils.fileExists.mockImplementation((path: string) => { return path === join(homedir(), ".claude.json"); }); mockUtils.readJsonFile.mockImplementation((path: string) => { if (path === join(homedir(), ".claude.json")) { return Promise.resolve({ mcpServers: { "hypertool-mcp": { type: "stdio", command: "hypertool" }, "git-mcp": { type: "stdio", command: "git-mcp" }, }, }); } throw new Error("File not found"); }); const result = await detectExternalMCPs(); expect(result).toHaveLength(1); expect(result[0].name).toBe("git-mcp"); expect(result.find((m) => m.name.includes("hypertool"))).toBeUndefined(); }); it("should detect MCPs from multiple sources", async () => { mockUtils.fileExists.mockImplementation((path: string) => { return ( path === join(homedir(), ".claude.json") || path === join( homedir(), "Library/Application Support/Claude/claude_desktop_config.json" ) ); }); mockUtils.readJsonFile.mockImplementation((path: string) => { if (path === join(homedir(), ".claude.json")) { return Promise.resolve({ mcpServers: { "git-mcp": { type: "stdio", command: "git-mcp" }, }, }); } if ( path === join( homedir(), "Library/Application Support/Claude/claude_desktop_config.json" ) ) { return Promise.resolve({ mcpServers: { "docker-mcp": { type: "stdio", command: "docker-mcp" }, }, }); } throw new Error("File not found"); }); const result = await detectExternalMCPs(); expect(result).toHaveLength(2); expect( result.find((m) => m.source === "Claude Code (global)") ).toBeDefined(); expect(result.find((m) => m.source === "Claude Desktop")).toBeDefined(); }); it("should handle missing config files gracefully", async () => { mockUtils.fileExists.mockResolvedValue(false); const result = await detectExternalMCPs(); expect(result).toHaveLength(0); }); it("should handle read errors gracefully", async () => { mockUtils.fileExists.mockResolvedValue(true); mockUtils.readJsonFile.mockRejectedValue(new Error("Permission denied")); const result = await detectExternalMCPs(); expect(result).toHaveLength(0); }); }); describe("formatExternalMCPsMessage", () => { it("should return empty string for no MCPs", () => { const result = formatExternalMCPsMessage([]); expect(result).toBe(""); }); it("should format single source correctly", () => { const mcps = [ { name: "git-mcp", source: "Claude Code (global)", config: { type: "stdio", command: "git-mcp" }, }, { name: "docker-mcp", source: "Claude Code (global)", config: { type: "stdio", command: "docker-mcp" }, }, ]; const result = formatExternalMCPsMessage(mcps); expect(result).toContain("⚠️ Other MCP servers detected"); expect(result).toContain("Claude Code (global):"); expect(result).toContain("- git-mcp"); expect(result).toContain("- docker-mcp"); expect(result).toContain("Run 'hypertool --install'"); }); it("should format multiple sources correctly", () => { const mcps = [ { name: "git-mcp", source: "Claude Code (global)", config: { type: "stdio", command: "git-mcp" }, }, { name: "docker-mcp", source: "Claude Desktop", config: { type: "stdio", command: "docker-mcp" }, }, ]; const result = formatExternalMCPsMessage(mcps); expect(result).toContain("Claude Code (global):"); expect(result).toContain("Claude Desktop:"); expect(result).toContain("- git-mcp"); expect(result).toContain("- docker-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/toolprint/hypertool-mcp'

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