Skip to content

Commit 03094cd

Browse files
committed
feat: logger level
1 parent 1cb290f commit 03094cd

File tree

6 files changed

+411
-322
lines changed

6 files changed

+411
-322
lines changed

src/client.ts

Lines changed: 84 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { StreamableHTTPClientTransport, StreamableHTTPClientTransportOptions } f
55
import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
66
import { TransportConfig, isSSEConfig, isStdioConfig, isHttpConfig } from './config.js';
77
import { EventSource } from 'eventsource';
8+
import { logger } from './logger.js'; // Import logger functions
89

910
const sleep = (time: number) => new Promise<void>(resolve => setTimeout(() => resolve(), time))
1011
export interface ConnectedClient {
@@ -27,10 +28,10 @@ const createClient = (name: string, transportConfig: TransportConfig): { client:
2728

2829
if (transportConfig.bearerToken) {
2930
customHeaders = { 'Authorization': `Bearer ${transportConfig.bearerToken}` };
30-
console.log(` Using Bearer Token for SSE connection to ${name}`);
31+
logger.debug(` Using Bearer Token for SSE connection to ${name}`); // Changed to debug
3132
} else if (transportConfig.apiKey) {
3233
customHeaders = { 'X-Api-Key': transportConfig.apiKey };
33-
console.log(` Using X-Api-Key for SSE connection to ${name}`);
34+
logger.debug(` Using X-Api-Key for SSE connection to ${name}`); // Changed to debug
3435
}
3536

3637
if (customHeaders) {
@@ -56,77 +57,77 @@ const createClient = (name: string, transportConfig: TransportConfig): { client:
5657
}
5758

5859
transport = new SSEClientTransport(new URL(transportConfig.url), transportOptions);
59-
} else if (isStdioConfig(transportConfig)) {
60-
transportType = 'stdio';
61-
const mergedEnv = {
62-
...process.env,
63-
...transportConfig.env
64-
};
65-
const filteredEnv: Record<string, string> = {};
66-
for (const key in mergedEnv) {
67-
if (Object.prototype.hasOwnProperty.call(mergedEnv, key) && mergedEnv[key] !== undefined) {
68-
filteredEnv[key] = mergedEnv[key] as string;
69-
}
70-
}
71-
transport = new StdioClientTransport({
72-
command: transportConfig.command,
73-
args: transportConfig.args,
74-
env: filteredEnv
75-
});
76-
} else if (isHttpConfig(transportConfig)) {
77-
transportType = 'http';
78-
const transportOptions: StreamableHTTPClientTransportOptions = {};
79-
let customHeaders: Record<string, string> | undefined;
80-
81-
if (transportConfig.bearerToken) {
82-
customHeaders = { 'Authorization': `Bearer ${transportConfig.bearerToken}` };
83-
console.log(` Using Bearer Token for StreamableHTTP connection to ${name}`);
84-
} else if (transportConfig.apiKey) {
85-
customHeaders = { 'X-Api-Key': transportConfig.apiKey };
86-
console.log(` Using X-Api-Key for StreamableHTTP connection to ${name}`);
87-
}
88-
89-
if (customHeaders) {
90-
transportOptions.requestInit = { headers: customHeaders };
91-
}
92-
// Note: StreamableHTTPClientTransport handles session ID internally if configured.
93-
// We might pass transportConfig.sessionId if we want to force a specific one.
94-
transport = new StreamableHTTPClientTransport(new URL(transportConfig.url), transportOptions);
95-
} else {
96-
console.error(`Invalid or unknown transport type in configuration for server: ${name}`);
97-
}
98-
} catch (error) {
99-
let transportType = 'unknown';
100-
if (isSSEConfig(transportConfig)) transportType = 'sse';
101-
else if (isStdioConfig(transportConfig)) transportType = 'stdio';
102-
else if (isHttpConfig(transportConfig)) transportType = 'http';
103-
console.error(`Failed to create transport ${transportType} to ${name}:`, error);
104-
}
105-
106-
if (!transport || !transportType) { // Also check transportType
107-
console.warn(`Transport or transportType for ${name} not available.`);
108-
return { transport: undefined, client: undefined, transportType: undefined };
109-
}
110-
111-
const client = new Client({
112-
name: 'mcp-proxy-client',
113-
version: '1.0.0',
114-
}, {
115-
capabilities: {
116-
prompts: {},
117-
resources: { subscribe: true },
118-
tools: {}
119-
}
120-
});
60+
} else if (isStdioConfig(transportConfig)) {
61+
transportType = 'stdio';
62+
const mergedEnv = {
63+
...process.env,
64+
...transportConfig.env
65+
};
66+
const filteredEnv: Record<string, string> = {};
67+
for (const key in mergedEnv) {
68+
if (Object.prototype.hasOwnProperty.call(mergedEnv, key) && mergedEnv[key] !== undefined) {
69+
filteredEnv[key] = mergedEnv[key] as string;
70+
}
71+
}
72+
transport = new StdioClientTransport({
73+
command: transportConfig.command,
74+
args: transportConfig.args,
75+
env: filteredEnv
76+
});
77+
} else if (isHttpConfig(transportConfig)) {
78+
transportType = 'http';
79+
const transportOptions: StreamableHTTPClientTransportOptions = {};
80+
let customHeaders: Record<string, string> | undefined;
81+
82+
if (transportConfig.bearerToken) {
83+
customHeaders = { 'Authorization': `Bearer ${transportConfig.bearerToken}` };
84+
logger.debug(` Using Bearer Token for StreamableHTTP connection to ${name}`); // Changed to debug
85+
} else if (transportConfig.apiKey) {
86+
customHeaders = { 'X-Api-Key': transportConfig.apiKey };
87+
logger.debug(` Using X-Api-Key for StreamableHTTP connection to ${name}`); // Changed to debug
88+
}
12189

122-
return { client, transport, transportType }
90+
if (customHeaders) {
91+
transportOptions.requestInit = { headers: customHeaders };
92+
}
93+
// Note: StreamableHTTPClientTransport handles session ID internally if configured.
94+
// We might pass transportConfig.sessionId if we want to force a specific one.
95+
transport = new StreamableHTTPClientTransport(new URL(transportConfig.url), transportOptions);
96+
} else {
97+
logger.error(`Invalid or unknown transport type in configuration for server: ${name}`); // Changed to error
98+
}
99+
} catch (error) {
100+
let transportType = 'unknown';
101+
if (isSSEConfig(transportConfig)) transportType = 'sse';
102+
else if (isStdioConfig(transportConfig)) transportType = 'stdio';
103+
else if (isHttpConfig(transportConfig)) transportType = 'http';
104+
logger.error(`Failed to create transport ${transportType} to ${name}:`, error); // Changed to error
105+
}
106+
107+
if (!transport || !transportType) { // Also check transportType
108+
logger.warn(`Transport or transportType for ${name} not available.`); // Changed to warn
109+
return { transport: undefined, client: undefined, transportType: undefined };
110+
}
111+
112+
const client = new Client({
113+
name: 'mcp-proxy-client',
114+
version: '1.0.0',
115+
}, {
116+
capabilities: {
117+
prompts: {},
118+
resources: { subscribe: true },
119+
tools: {}
120+
}
121+
});
122+
123+
return { client, transport, transportType }
123124
}
124125

125126
export const createClients = async (mcpServers: Record<string, TransportConfig>): Promise<ConnectedClient[]> => {
126127
const clients: ConnectedClient[] = [];
127128

128129
for (const [name, transportConfig] of Object.entries(mcpServers)) {
129-
console.log(`Connecting to server: ${name}`);
130+
logger.log(`Connecting to server: ${name}`); // Changed to log
130131

131132
const waitFor = 2500;
132133
const retries = 3;
@@ -137,13 +138,13 @@ export const createClients = async (mcpServers: Record<string, TransportConfig>)
137138

138139
const { client, transport, transportType } = createClient(name, transportConfig); // Capture transportType
139140
if (!client || !transport || !transportType) { // Check transportType
140-
console.warn(`Skipping client ${name} due to failed client/transport creation.`);
141+
logger.warn(`Skipping client ${name} due to failed client/transport creation.`); // Changed to warn
141142
break;
142143
}
143144

144145
try {
145146
await client.connect(transport);
146-
console.log(`Connected to server: ${name}`);
147+
logger.log(`Connected to server: ${name}`); // Changed to log
147148

148149
clients.push({
149150
client,
@@ -157,15 +158,15 @@ export const createClients = async (mcpServers: Record<string, TransportConfig>)
157158

158159
break
159160

160-
} catch (error) {
161-
console.error(`Failed to connect to ${name}:`, error);
161+
} catch (error: any) {
162+
logger.error(`Failed to connect to ${name}: ${error.message}`); // Log error message
162163
count++;
163164
retry = (count < retries);
164165
if (retry) {
165166
try {
166167
await client.close();
167168
} catch { }
168-
console.log(`Retry connection to ${name} in ${waitFor}ms (${count}/${retries})`);
169+
logger.log(`Retry connection to ${name} in ${waitFor}ms (${count}/${retries})`); // Changed to log
169170
await sleep(waitFor);
170171
}
171172
}
@@ -185,14 +186,14 @@ export async function reconnectSingleClient(
185186
transportConfig: TransportConfig,
186187
existingCleanup?: () => Promise<void>
187188
): Promise<Omit<ConnectedClient, 'name'>> { // Returns the parts needed to reconstruct a ConnectedClient
188-
console.log(`Attempting to reconnect client: ${name}`);
189+
logger.log(`Attempting to reconnect client: ${name}`); // Changed to log
189190

190191
if (existingCleanup) {
191192
try {
192193
await existingCleanup();
193-
console.log(`Existing client ${name} cleaned up before reconnecting.`);
194+
logger.log(`Existing client ${name} cleaned up before reconnecting.`); // Changed to log
194195
} catch (e: any) {
195-
console.warn(`Error during cleanup of existing client ${name} before reconnect: ${e.message}`);
196+
logger.warn(`Error during cleanup of existing client ${name} before reconnect: ${e.message}`); // Changed to warn
196197
}
197198
}
198199

@@ -206,10 +207,10 @@ export async function reconnectSingleClient(
206207
let customHeaders: Record<string, string> | undefined;
207208
if (transportConfig.bearerToken) {
208209
customHeaders = { 'Authorization': `Bearer ${transportConfig.bearerToken}` };
209-
console.log(` Using Bearer Token for SSE connection to ${name} (reconnect)`);
210+
logger.debug(` Using Bearer Token for SSE connection to ${name} (reconnect)`); // Changed to debug
210211
} else if (transportConfig.apiKey) {
211212
customHeaders = { 'X-Api-Key': transportConfig.apiKey };
212-
console.log(` Using X-Api-Key for SSE connection to ${name} (reconnect)`);
213+
logger.debug(` Using X-Api-Key for SSE connection to ${name} (reconnect)`); // Changed to debug
213214
}
214215
if (customHeaders) {
215216
transportOptions.requestInit = { headers: customHeaders };
@@ -239,17 +240,17 @@ export async function reconnectSingleClient(
239240
args: transportConfig.args,
240241
env: filteredEnv
241242
});
242-
console.log(` Configured Stdio transport for ${name} (reconnect)`);
243+
logger.debug(` Configured Stdio transport for ${name} (reconnect)`); // Changed to debug
243244
} else if (isHttpConfig(transportConfig)) {
244245
determinedTransportType = 'http';
245246
const transportOptions: StreamableHTTPClientTransportOptions = {};
246247
let customHeaders: Record<string, string> | undefined;
247248
if (transportConfig.bearerToken) {
248249
customHeaders = { 'Authorization': `Bearer ${transportConfig.bearerToken}` };
249-
console.log(` Using Bearer Token for StreamableHTTP connection to ${name} (reconnect)`);
250+
logger.debug(` Using Bearer Token for StreamableHTTP connection to ${name} (reconnect)`); // Changed to debug
250251
} else if (transportConfig.apiKey) {
251252
customHeaders = { 'X-Api-Key': transportConfig.apiKey };
252-
console.log(` Using X-Api-Key for StreamableHTTP connection to ${name} (reconnect)`);
253+
logger.debug(` Using X-Api-Key for StreamableHTTP connection to ${name} (reconnect)`); // Changed to debug
253254
}
254255
if (customHeaders) {
255256
transportOptions.requestInit = { headers: customHeaders };
@@ -259,7 +260,7 @@ export async function reconnectSingleClient(
259260
throw new Error(`Invalid or unknown transport type in configuration for server: ${name}`);
260261
}
261262
} catch (error: any) {
262-
console.error(`Failed to create transport for ${name} during reconnect: ${error.message}`);
263+
logger.error(`Failed to create transport for ${name} during reconnect: ${error.message}`); // Changed to error
263264
throw error;
264265
}
265266

@@ -276,7 +277,7 @@ export async function reconnectSingleClient(
276277

277278
try {
278279
await newSdkClient.connect(transport);
279-
console.log(`Successfully reconnected to server: ${name}`);
280+
logger.log(`Successfully reconnected to server: ${name}`); // Changed to log
280281
const finalTransport = transport; // Capture for closure
281282
return {
282283
client: newSdkClient,
@@ -289,13 +290,13 @@ export async function reconnectSingleClient(
289290
}
290291
};
291292
} catch (error: any) {
292-
console.error(`Failed to connect to ${name} during reconnect attempt: ${error.message}`);
293+
logger.error(`Failed to connect to ${name} during reconnect attempt: ${error.message}`); // Changed to error
293294
try {
294295
if (transport) {
295296
await transport.close();
296297
}
297298
} catch (closeError: any) {
298-
console.warn(`Failed to close transport for ${name} after reconnect failure: ${closeError.message}`);
299+
logger.warn(`Failed to close transport for ${name} after reconnect failure: ${closeError.message}`); // Changed to warn
299300
}
300301
throw error;
301302
}

0 commit comments

Comments
 (0)