Skip to main content
Glama
cli.test.ts7.12 kB
import { beforeEach, describe, expect, it, vi } from "vitest"; import { parseArgs, parseTransportConfig, startServer } from "../../src/cli.js"; const { connectMock, defaultTouchDesignerServerImpl, defaultStdioTransportImpl, TouchDesignerServerMock, StdioServerTransportMock, } = vi.hoisted(() => { const connectMock = vi.fn(); const defaultTouchDesignerServerImpl = function MockTouchDesignerServer(this: { connect: typeof connectMock; }) { this.connect = connectMock; }; const TouchDesignerServerMock = vi.fn(defaultTouchDesignerServerImpl); const defaultStdioTransportImpl = function MockStdioServerTransport() {}; const StdioServerTransportMock = vi.fn(defaultStdioTransportImpl); return { connectMock, defaultStdioTransportImpl, defaultTouchDesignerServerImpl, StdioServerTransportMock, TouchDesignerServerMock, }; }); // Mock dependencies vi.mock("@modelcontextprotocol/sdk/server/stdio.js", () => ({ StdioServerTransport: StdioServerTransportMock, })); vi.mock("../../src/server/touchDesignerServer.js", () => ({ TouchDesignerServer: TouchDesignerServerMock, })); describe("CLI", () => { describe("parseArgs functionality", () => { it("should parse host argument correctly", () => { expect(parseArgs(["--host=localhost"])).toEqual({ host: "localhost", port: 9981, }); }); it("should parse port argument correctly", () => { expect(parseArgs(["--port=8080"])).toEqual({ host: "http://127.0.0.1", port: 8080, }); }); it("should parse both host and port arguments", () => { expect(parseArgs(["--host=127.0.0.1", "--port=9090"])).toEqual({ host: "127.0.0.1", port: 9090, }); }); it("should ignore malformed arguments", () => { expect(parseArgs(["--host", "--port"])).toEqual({ host: "http://127.0.0.1", port: 9981, }); }); it("should handle invalid port number", () => { const result = parseArgs(["--port=invalid"]); expect(result.port).toBeNaN(); }); }); describe("parseTransportConfig functionality", () => { it("should default to stdio mode when no HTTP args provided", () => { const config = parseTransportConfig([]); expect(config.type).toBe("stdio"); }); it("should parse HTTP mode when --mcp-http-port is provided", () => { const config = parseTransportConfig(["--mcp-http-port=6280"]); expect(config.type).toBe("streamable-http"); if (config.type === "streamable-http") { expect(config.port).toBe(6280); expect(config.host).toBe("127.0.0.1"); expect(config.endpoint).toBe("/mcp"); } }); it("should use custom host when --mcp-http-host is provided", () => { const config = parseTransportConfig([ "--mcp-http-port=6280", "--mcp-http-host=localhost", ]); if (config.type === "streamable-http") { expect(config.host).toBe("localhost"); } }); it("should exit with error for non-numeric port value", () => { const mockExit = vi .spyOn(process, "exit") .mockImplementation(() => undefined as never); const mockConsoleError = vi .spyOn(console, "error") .mockImplementation(() => {}); parseTransportConfig(["--mcp-http-port=abc"]); expect(mockConsoleError).toHaveBeenCalledWith( expect.stringContaining('Invalid value for --mcp-http-port: "abc"'), ); expect(mockExit).toHaveBeenCalledWith(1); mockExit.mockRestore(); mockConsoleError.mockRestore(); }); it("should exit with error for port number below valid range", () => { const mockExit = vi .spyOn(process, "exit") .mockImplementation(() => undefined as never); const mockConsoleError = vi .spyOn(console, "error") .mockImplementation(() => {}); parseTransportConfig(["--mcp-http-port=0"]); expect(mockConsoleError).toHaveBeenCalledWith( expect.stringContaining('Invalid value for --mcp-http-port: "0"'), ); expect(mockExit).toHaveBeenCalledWith(1); mockExit.mockRestore(); mockConsoleError.mockRestore(); }); it("should exit with error for port number above valid range", () => { const mockExit = vi .spyOn(process, "exit") .mockImplementation(() => undefined as never); const mockConsoleError = vi .spyOn(console, "error") .mockImplementation(() => {}); parseTransportConfig(["--mcp-http-port=70000"]); expect(mockConsoleError).toHaveBeenCalledWith( expect.stringContaining('Invalid value for --mcp-http-port: "70000"'), ); expect(mockExit).toHaveBeenCalledWith(1); mockExit.mockRestore(); mockConsoleError.mockRestore(); }); }); describe("startServer functionality", () => { beforeEach(() => { // Clear environment variables delete process.env.TD_WEB_SERVER_HOST; delete process.env.TD_WEB_SERVER_PORT; connectMock.mockReset(); connectMock.mockResolvedValue({ success: true }); TouchDesignerServerMock.mockReset(); TouchDesignerServerMock.mockImplementation( defaultTouchDesignerServerImpl, ); StdioServerTransportMock.mockReset(); StdioServerTransportMock.mockImplementation(defaultStdioTransportImpl); vi.clearAllMocks(); }); it("should set environment variables from parsed arguments", async () => { await startServer({ argv: ["node", "cli.js", "--stdio", "--host=127.0.0.1", "--port=8080"], nodeEnv: "cli", }); expect(process.env.TD_WEB_SERVER_HOST).toBe("127.0.0.1"); expect(process.env.TD_WEB_SERVER_PORT).toBe("8080"); }); it("should create TouchDesigner server and connect in stdio mode", async () => { await startServer({ argv: ["node", "cli.js", "--stdio", "--host=127.0.0.1", "--port=8080"], nodeEnv: "cli", }); expect(TouchDesignerServerMock).toHaveBeenCalled(); expect(StdioServerTransportMock).toHaveBeenCalled(); expect(connectMock).toHaveBeenCalled(); }); it("should handle connection failure gracefully", async () => { connectMock.mockResolvedValue({ error: { message: "Connection failed" }, success: false, }); await expect( startServer({ argv: [ "node", "cli.js", "--stdio", "--host=127.0.0.1", "--port=8080", ], nodeEnv: "cli", }), ).rejects.toThrow( "Failed to initialize server: Failed to connect: Connection failed", ); }); it("should handle unexpected errors gracefully", async () => { TouchDesignerServerMock.mockImplementation(function ThrowingServer() { throw new Error("Unexpected error"); }); await expect( startServer({ argv: [ "node", "cli.js", "--stdio", "--host=127.0.0.1", "--port=8080", ], nodeEnv: "cli", }), ).rejects.toThrow("Failed to initialize server: Unexpected error"); }); it("should handle non-Error exceptions", async () => { TouchDesignerServerMock.mockImplementation(function ThrowingServer() { throw "String error"; }); await expect( startServer({ argv: [ "node", "cli.js", "--stdio", "--host=127.0.0.1", "--port=8080", ], nodeEnv: "cli", }), ).rejects.toThrow("Failed to initialize server: String error"); }); }); });

Latest Blog Posts

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/8beeeaaat/touchdesigner-mcp'

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