MCPcopy Create free account
hub / github.com/MoonshotAI/kimi-code / HttpMcpClient

Class HttpMcpClient

packages/agent-core/src/mcp/client-http.ts:45–185  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

43 * OAuth providers are attached separately by the connection manager.
44 */
45export class HttpMcpClient implements MCPClient {
46 private readonly client: Client;
47 private readonly transport: StreamableHTTPClientTransport;
48 private readonly toolCallTimeoutMs?: number;
49 private started = false;
50 private closed = false;
51 // See StdioMcpClient.ready — distinguishes handshake-phase failures (caller
52 // sees them via `connect()` throwing, no unexpectedClose) from post-ready
53 // disconnects (the case `onUnexpectedClose` is designed to surface).
54 private ready = false;
55 private hooksInstalled = false;
56 private unexpectedCloseListener: UnexpectedCloseListener | undefined;
57 private lastTransportError: Error | undefined;
58 // See StdioMcpClient — buffered when the listener has not been installed
59 // yet so an early close is replayed instead of dropped.
60 private pendingUnexpectedClose: UnexpectedCloseReason | undefined;
61 // Latch so `onerror` and a (theoretical) `onclose` for the same transport
62 // failure do not double-fire. Once we have decided the connection is dead,
63 // additional SDK notifications are noise.
64 private unexpectedCloseFired = false;
65
66 constructor(config: McpServerHttpConfig, options: HttpMcpClientOptions = {}) {
67 const envLookup = options.envLookup ?? ((name) => process.env[name]);
68 const headers = buildMcpHttpHeaders(config, envLookup);
69
70 this.transport = new StreamableHTTPClientTransport(new URL(config.url), {
71 requestInit: headers !== undefined ? { headers } : undefined,
72 fetch: options.fetch,
73 authProvider: options.oauthProvider,
74 });
75 this.client = new Client({
76 name: options.clientName ?? KIMI_MCP_CLIENT_NAME,
77 version: options.clientVersion ?? KIMI_MCP_CLIENT_VERSION,
78 });
79 this.toolCallTimeoutMs = options.toolCallTimeoutMs;
80 }
81
82 async connect(): Promise<void> {
83 if (this.closed) {
84 throw new Error('MCP HTTP client is closed');
85 }
86 if (this.started) return;
87 this.started = true;
88 // Install hooks BEFORE the SDK handshake; see StdioMcpClient.connect.
89 this.installTransportHooks();
90 try {
91 await this.client.connect(this.transport);
92 } catch (error) {
93 await this.closeStartedClient();
94 throw error;
95 }
96 if (this.closed) {
97 await this.closeStartedClient();
98 throw new Error('MCP HTTP client was closed during startup');
99 }
100 this.ready = true;
101 }
102

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected