UNPKG

@toolprint/hypertool-mcp

Version:

HyperTool MCP proxy server for routing requests between clients and multiple underlying MCP servers

152 lines • 4 kB
/** * HTTP client implementation for MCP servers using official MCP SDK */ import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; import { EventEmitter } from "events"; import { BaseConnection } from "./base.js"; import { createChildLogger } from "../../utils/logging.js"; const logger = createChildLogger({ module: "clients/http" }); /** * HTTP client wrapper using proper MCP SDK Client */ export class HttpClient extends EventEmitter { config; client = null; isConnected = false; constructor(config) { super(); this.config = config; } get url() { return this.config.url; } /** * Connect to the HTTP server using SDK Client */ async connect() { if (this.isConnected) { return; } try { const transport = new StreamableHTTPClientTransport(new URL(this.config.url)); this.client = new Client({ name: "hypertool-mcp-client", version: "1.0.0", }, { capabilities: { tools: {}, }, }); await this.client.connect(transport); this.isConnected = true; this.emit("connect"); } catch (error) { this.client = null; throw new Error(`Failed to connect HTTP client: ${error.message}`); } } /** * Disconnect from the HTTP server */ async disconnect() { if (!this.client) { return; } try { await this.client.close(); } catch (error) { logger.error("Error closing HTTP client:", error); } finally { this.client = null; this.isConnected = false; } } /** * List tools from the MCP server */ async listTools() { if (!this.client) { throw new Error("Client not connected"); } return await this.client.listTools(); } /** * Call a tool on the MCP server */ async callTool(params) { if (!this.client) { throw new Error("Client not connected"); } return await this.client.callTool(params); } /** * Ping the server to check if it's responsive */ async ping() { if (!this.isConnected) { return false; } try { await this.listTools(); return true; } catch { return false; } } /** * Get the SDK client instance for advanced operations */ get sdkClient() { return this.client; } } /** * HTTP connection implementation */ export class HttpConnection extends BaseConnection { _client = null; constructor(serverName, config, options = {}) { super(serverName, config, options); } /** * Connect to the HTTP server */ async doConnect() { this._client = new HttpClient(this.config); // Forward client events this._client.on("error", (error) => { this.emit("error", this.createEvent("error", { error })); }); this._client.on("disconnect", () => { this.emit("disconnected", this.createEvent("disconnected")); }); this._client.on("message", (message) => { this.emit("message", message); }); await this._client.connect(); } /** * Disconnect from the HTTP server */ async doDisconnect() { if (this._client) { await this._client.disconnect(); this._client = null; } } /** * Ping the HTTP server */ async doPing() { if (!this._client) { return false; } return await this._client.ping(); } } //# sourceMappingURL=http.js.map