Skip to content

Commit 27cda66

Browse files
authored
Replace print statements with lightweight logging implementation (#41)
* Replace print statements with logging * Replace usage of `package:logging` with an internal lightweight Logger * Add test case to verify the internal logger uses the configured LogHandler
1 parent e7a6ccd commit 27cda66

File tree

13 files changed

+182
-83
lines changed

13 files changed

+182
-83
lines changed

lib/mcp_dart.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ library;
1111
// Common exports for all platforms
1212
export 'src/types.dart'; // Exports shared types used across the MCP protocol.
1313
export 'src/shared/uuid.dart'; // Exports UUID generation utilities.
14+
export 'src/shared/logging.dart'; // Exports logging for customization
1415

1516
// Platform-specific exports
1617
export 'src/exports.dart' // Stub export for other platforms

lib/src/client/client.dart

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import 'dart:async';
2+
import 'package:mcp_dart/src/shared/logging.dart';
23
import 'package:mcp_dart/src/shared/protocol.dart';
34
import 'package:mcp_dart/src/shared/transport.dart';
45
import 'package:mcp_dart/src/types.dart';
56

7+
final _logger = Logger("mcp_dart.client");
8+
69
/// Options for configuring the MCP [Client].
710
class ClientOptions extends ProtocolOptions {
811
/// Capabilities to advertise as being supported by this client.
@@ -88,11 +91,11 @@ class Client extends Protocol {
8891
const initializedNotification = JsonRpcInitializedNotification();
8992
await notification(initializedNotification);
9093

91-
print(
94+
_logger.debug(
9295
"MCP Client Initialized. Server: ${result.serverInfo.name} ${result.serverInfo.version}, Protocol: ${result.protocolVersion}",
9396
);
9497
} catch (error) {
95-
print("MCP Client Initialization Failed: $error");
98+
_logger.error("MCP Client Initialization Failed: $error");
9699
await close();
97100
rethrow;
98101
}
@@ -150,8 +153,8 @@ class Client extends Protocol {
150153
requiredCapability = 'prompts or resources';
151154
break;
152155
default:
153-
print(
154-
"Warning: assertCapabilityForMethod called for potentially custom client request: $method",
156+
_logger.warn(
157+
"assertCapabilityForMethod called for potentially custom client request: $method",
155158
);
156159
supported = true;
157160
}
@@ -175,8 +178,8 @@ class Client extends Protocol {
175178
}
176179
break;
177180
default:
178-
print(
179-
"Warning: assertNotificationCapability called for potentially custom client notification: $method",
181+
_logger.warn(
182+
"assertNotificationCapability called for potentially custom client notification: $method",
180183
);
181184
}
182185
}
@@ -199,8 +202,8 @@ class Client extends Protocol {
199202
}
200203
break;
201204
default:
202-
print(
203-
"Info: Setting request handler for potentially custom method '$method'. Ensure client capabilities match.",
205+
_logger.info(
206+
"Setting request handler for potentially custom method '$method'. Ensure client capabilities match.",
204207
);
205208
}
206209
}

lib/src/client/stdio.dart

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import 'package:mcp_dart/src/shared/stdio.dart'; // Adjust import path as needed
99
import 'package:mcp_dart/src/shared/transport.dart'; // Adjust import path as needed
1010
// Assume types are defined in types.dart
1111
import 'package:mcp_dart/src/types.dart'; // Adjust import path as needed
12+
import 'package:mcp_dart/src/shared/logging.dart';
13+
14+
final _logger = Logger("mcp_dart.client.stdio");
1215

1316
/// Configuration parameters for launching the stdio server process.
1417
class StdioServerParameters {
@@ -127,7 +130,9 @@ class StdioClientTransport implements Transport {
127130
mode: mode, // Handles stdin/stdout/stderr piping/inheritance
128131
);
129132

130-
print("StdioClientTransport: Process started (PID: ${_process?.pid})");
133+
_logger.debug(
134+
"StdioClientTransport: Process started (PID: ${_process?.pid})",
135+
);
131136

132137
// --- Setup stream listeners ---
133138

@@ -144,7 +149,7 @@ class StdioClientTransport implements Transport {
144149
// Expose stderr via getter, let user handle it.
145150
// Optionally add logging here:
146151
_stderrSubscription = _process!.stderr.listen(
147-
(data) => print(
152+
(data) => _logger.debug(
148153
"Server stderr: ${utf8.decode(data, allowMalformed: true)}",
149154
),
150155
onError: _onStreamError, // Report stderr stream errors too
@@ -158,15 +163,15 @@ class StdioClientTransport implements Transport {
158163
return Future.value();
159164
} catch (error, stackTrace) {
160165
// Handle errors during Process.start()
161-
print("StdioClientTransport: Failed to start process: $error");
166+
_logger.error("StdioClientTransport: Failed to start process: $error");
162167
_started = false; // Reset state
163168
final startError = StateError(
164169
"Failed to start server process: $error\n$stackTrace",
165170
);
166171
try {
167172
onerror?.call(startError);
168173
} catch (e) {
169-
print("Error in onerror handler: $e");
174+
_logger.warn("Error in onerror handler: $e");
170175
}
171176
throw startError; // Rethrow to signal failure
172177
}
@@ -193,7 +198,7 @@ class StdioClientTransport implements Transport {
193198

194199
/// Internal handler for when the process's stdout stream closes.
195200
void _onStdoutDone() {
196-
print("StdioClientTransport: Process stdout closed.");
201+
_logger.debug("StdioClientTransport: Process stdout closed.");
197202
// Consider if this should trigger close() - depends if server exiting is expected.
198203
// Maybe only close if the process has also exited?
199204
// close(); // Optionally close transport when stdout ends
@@ -207,7 +212,7 @@ class StdioClientTransport implements Transport {
207212
try {
208213
onerror?.call(streamError);
209214
} catch (e) {
210-
print("Error in onerror handler: $e");
215+
_logger.warn("Error in onerror handler: $e");
211216
}
212217
// Consider if stream errors should trigger close()
213218
// close();
@@ -222,7 +227,7 @@ class StdioClientTransport implements Transport {
222227
try {
223228
onmessage?.call(message);
224229
} catch (e) {
225-
print("Error in onmessage handler: $e");
230+
_logger.warn("Error in onmessage handler: $e");
226231
onerror?.call(StateError("Error in onmessage handler: $e"));
227232
}
228233
} catch (error) {
@@ -232,9 +237,9 @@ class StdioClientTransport implements Transport {
232237
try {
233238
onerror?.call(parseError);
234239
} catch (e) {
235-
print("Error in onerror handler: $e");
240+
_logger.warn("Error in onerror handler: $e");
236241
}
237-
print(
242+
_logger.error(
238243
"StdioClientTransport: Error processing read buffer: $parseError. Skipping data.",
239244
);
240245
// Consider clearing buffer or attempting recovery depending on error type.
@@ -247,7 +252,7 @@ class StdioClientTransport implements Transport {
247252

248253
/// Internal handler for when the process exits.
249254
void _onProcessExit(int exitCode) {
250-
print("StdioClientTransport: Process exited with code $exitCode.");
255+
_logger.debug("StdioClientTransport: Process exited with code $exitCode.");
251256
if (!_exitCompleter.isCompleted) {
252257
_exitCompleter.complete(); // Signal exit if not already closing
253258
}
@@ -256,14 +261,16 @@ class StdioClientTransport implements Transport {
256261

257262
/// Internal handler for errors retrieving the process exit code.
258263
void _onProcessExitError(dynamic error, StackTrace stackTrace) {
259-
print("StdioClientTransport: Error waiting for process exit: $error");
264+
_logger.debug(
265+
"StdioClientTransport: Error waiting for process exit: $error",
266+
);
260267
final Error exitError = (error is Error)
261268
? error
262269
: StateError("Process exit error: $error\n$stackTrace");
263270
try {
264271
onerror?.call(exitError);
265272
} catch (e) {
266-
print("Error in onerror handler: $e");
273+
_logger.warn("Error in onerror handler: $e");
267274
}
268275
if (!_exitCompleter.isCompleted) {
269276
_exitCompleter.completeError(exitError);
@@ -279,7 +286,7 @@ class StdioClientTransport implements Transport {
279286
Future<void> close() async {
280287
if (!_started) return; // Already closed or never started
281288

282-
print("StdioClientTransport: Closing transport...");
289+
_logger.debug("StdioClientTransport: Closing transport...");
283290

284291
// Mark as closing immediately to prevent further sends/starts
285292
_started = false;
@@ -297,13 +304,13 @@ class StdioClientTransport implements Transport {
297304
_process = null; // Clear reference
298305

299306
if (processToKill != null) {
300-
print(
307+
_logger.debug(
301308
"StdioClientTransport: Terminating process (PID: ${processToKill.pid})...",
302309
);
303310
// Attempt graceful termination first
304311
bool killed = processToKill.kill(io.ProcessSignal.sigterm);
305312
if (!killed) {
306-
print(
313+
_logger.debug(
307314
"StdioClientTransport: Failed to send SIGTERM or process already exited.",
308315
);
309316
// If SIGTERM fails or wasn't sent (e.g., process already dead),
@@ -312,15 +319,15 @@ class StdioClientTransport implements Transport {
312319
// Give a short grace period for SIGTERM before SIGKILL
313320
try {
314321
await _exitCompleter.future.timeout(const Duration(seconds: 2));
315-
print("StdioClientTransport: Process terminated gracefully.");
322+
_logger.debug("StdioClientTransport: Process terminated gracefully.");
316323
} on TimeoutException {
317-
print(
324+
_logger.warn(
318325
"StdioClientTransport: Process did not exit after SIGTERM, sending SIGKILL.",
319326
);
320327
processToKill.kill(io.ProcessSignal.sigkill); // Force kill
321328
} catch (e) {
322329
// Error waiting for exit after SIGTERM (might have exited quickly)
323-
print(
330+
_logger.error(
324331
"StdioClientTransport: Error waiting for process exit after SIGTERM: $e",
325332
);
326333
}
@@ -336,9 +343,9 @@ class StdioClientTransport implements Transport {
336343
try {
337344
onclose?.call();
338345
} catch (e) {
339-
print("Error in onclose handler: $e");
346+
_logger.warn("Error in onclose handler: $e");
340347
}
341-
print("StdioClientTransport: Transport closed.");
348+
_logger.debug("StdioClientTransport: Transport closed.");
342349
}
343350

344351
/// Sends a [JsonRpcMessage] to the server process via its stdin.
@@ -361,14 +368,16 @@ class StdioClientTransport implements Transport {
361368
// Flushing stdin might be necessary depending on the server's reading behavior.
362369
await currentProcess.stdin.flush();
363370
} catch (error, stackTrace) {
364-
print("StdioClientTransport: Error writing to process stdin: $error");
371+
_logger.warn(
372+
"StdioClientTransport: Error writing to process stdin: $error",
373+
);
365374
final Error sendError = (error is Error)
366375
? error
367376
: StateError("Process stdin write error: $error\n$stackTrace");
368377
try {
369378
onerror?.call(sendError);
370379
} catch (e) {
371-
print("Error in onerror handler: $e");
380+
_logger.warn("Error in onerror handler: $e");
372381
}
373382
// Consider closing the transport on stdin write failure
374383
close();

lib/src/server/mcp.dart

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import 'dart:async';
22

3+
import 'package:mcp_dart/src/shared/logging.dart';
34
import 'package:mcp_dart/src/shared/protocol.dart';
45
import 'package:mcp_dart/src/shared/transport.dart';
56
import 'package:mcp_dart/src/shared/uri_template.dart';
67
import 'package:mcp_dart/src/types.dart';
78

89
import 'server.dart';
910

11+
final _logger = Logger("mcp_dart.server.mcp");
12+
1013
typedef CompleteCallback = Future<List<String>> Function(String value);
1114

1215
class CompletableDef {
@@ -244,7 +247,7 @@ class McpServer {
244247
registeredTool.callback(args: toolArgs, extra: extra),
245248
);
246249
} catch (error) {
247-
print("Error executing tool '$toolName': $error");
250+
_logger.warn("Error executing tool '$toolName': $error");
248251
return CallToolResult.fromContent(
249252
content: [TextContent(text: error.toString())],
250253
isError: true,
@@ -295,7 +298,7 @@ class McpServer {
295298
try {
296299
return _createCompletionResult(await completer(argInfo.value));
297300
} catch (e) {
298-
print(
301+
_logger.warn(
299302
"Error during prompt argument completion for '${ref.name}.${argInfo.name}': $e",
300303
);
301304
throw McpError(ErrorCode.internalError.value, "Completion failed");
@@ -319,7 +322,7 @@ class McpServer {
319322
try {
320323
return _createCompletionResult(await completer(argInfo.value));
321324
} catch (e) {
322-
print(
325+
_logger.warn(
323326
"Error during resource template completion for '${ref.uri}' variable '${argInfo.name}': $e",
324327
);
325328
throw McpError(ErrorCode.internalError.value, "Completion failed");
@@ -359,7 +362,7 @@ class McpServer {
359362
)
360363
.toList();
361364
} catch (e) {
362-
print("Error listing resources for template: $e");
365+
_logger.warn("Error listing resources for template: $e");
363366
return <Resource>[];
364367
}
365368
});
@@ -475,7 +478,7 @@ class McpServer {
475478
throw StateError("No callback found");
476479
}
477480
} catch (error) {
478-
print("Error executing prompt '$name': $error");
481+
_logger.warn("Error executing prompt '$name': $error");
479482
if (error is McpError) rethrow;
480483
throw McpError(
481484
ErrorCode.internalError.value,

lib/src/server/server.dart

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import 'dart:async';
22

3+
import 'package:mcp_dart/src/shared/logging.dart';
34
import 'package:mcp_dart/src/shared/protocol.dart';
45
import 'package:mcp_dart/src/types.dart';
56

7+
final _logger = Logger("mcp_dart.server");
8+
69
/// Options for configuring the MCP [Server].
710
class ServerOptions extends ProtocolOptions {
811
/// Capabilities to advertise as being supported by this server.
@@ -129,8 +132,8 @@ class Server extends Protocol {
129132
break;
130133

131134
default:
132-
print(
133-
"Warning: assertCapabilityForMethod called for unknown server-sent request method: $method",
135+
_logger.warn(
136+
"assertCapabilityForMethod called for unknown server-sent request method: $method",
134137
);
135138
}
136139
}
@@ -183,8 +186,8 @@ class Server extends Protocol {
183186
break;
184187

185188
default:
186-
print(
187-
"Warning: assertNotificationCapability called for unknown server-sent notification method: $method",
189+
_logger.warn(
190+
"assertNotificationCapability called for unknown server-sent notification method: $method",
188191
);
189192
}
190193
}
@@ -243,8 +246,8 @@ class Server extends Protocol {
243246
break;
244247

245248
default:
246-
print(
247-
"Info: Setting request handler for potentially custom method '$method'. Ensure server capabilities match.",
249+
_logger.info(
250+
"Setting request handler for potentially custom method '$method'. Ensure server capabilities match.",
248251
);
249252
}
250253
}

0 commit comments

Comments
 (0)