Shared MCP (Model Context Protocol) client base class providing consistent timeout handling, automatic re-synchronization, and connection state management for VSCode extensions.
- Configurable Timeouts: Different timeout values for initialization vs. standard requests
- Automatic Re-synchronization: Exponential backoff retry logic when timeouts occur
- Connection State Management: Track and notify listeners of connection state changes
- Consistent Error Handling: Unified error messages and recovery options
- Extensible Architecture: Abstract base class that extensions can customize
- Comprehensive Logging: Structured logging with timestamps and request IDs
npm install @ai-capabilities-suite/mcp-client-baseimport {
BaseMCPClient,
MCPClientConfig,
} from "@ai-capabilities-suite/mcp-client-base";
import * as vscode from "vscode";
export class MyMCPClient extends BaseMCPClient {
constructor(
outputChannel: vscode.LogOutputChannel,
config?: Partial<MCPClientConfig>
) {
super(outputChannel, config);
}
protected getServerCommand(): { command: string; args: string[] } {
return {
command: "npx",
args: ["-y", "@my-org/my-mcp-server"],
};
}
protected getServerEnv(): Record<string, string> {
return { ...process.env };
}
protected async onServerReady(): Promise<void> {
// Extension-specific initialization
await this.callTool("my_tool", {});
}
// Add extension-specific methods
async myCustomMethod(params: any): Promise<any> {
return await this.callTool("my_custom_tool", params);
}
}const outputChannel = vscode.window.createOutputChannel("My Extension", {
log: true,
});
const client = new MyMCPClient(outputChannel, {
timeout: {
initializationTimeoutMs: 60000,
standardRequestTimeoutMs: 30000,
},
reSync: {
maxRetries: 3,
retryDelayMs: 2000,
backoffMultiplier: 1.5,
},
});
// Start the client
await client.start();
// Subscribe to connection state changes
client.getConnectionStatus(); // Get current status
client.onStateChange((status) => {
console.log("Connection state:", status.state);
});
// Use the client
const result = await client.myCustomMethod({ foo: "bar" });
// Stop the client
client.stop();interface TimeoutConfig {
initializationTimeoutMs: number; // Default: 60000 (60s)
standardRequestTimeoutMs: number; // Default: 30000 (30s)
toolsListTimeoutMs: number; // Default: 60000 (60s)
}interface ReSyncConfig {
maxRetries: number; // Default: 3
retryDelayMs: number; // Default: 2000 (2s)
backoffMultiplier: number; // Default: 1.5
}DISCONNECTED: Not connected to serverCONNECTING: Attempting to connectCONNECTED: Successfully connectedTIMEOUT_RETRYING: Timeout occurred, retrying connectionERROR: Unrecoverable error occurred
async start(): Promise<void>- Start the server and initialize connectionstop(): void- Stop the server and cleanupasync reconnect(): Promise<boolean>- Attempt to reconnect to the server
getConnectionStatus(): ConnectionStatus- Get current connection statusgetDiagnostics(): ServerDiagnostics- Get detailed diagnosticsisServerProcessAlive(): boolean- Check if server process is running
protected abstract getServerCommand(): { command: string; args: string[] }- Return server command and argsprotected abstract getServerEnv(): Record<string, string>- Return environment variables for serverprotected abstract onServerReady(): Promise<void>- Called when server is ready
MIT