Fix `--log-file` option so it doesn't crash the server. (#207)

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 9c60be5..fffc49b 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,28 +1,33 @@
 {
-    // Use IntelliSense to learn about possible attributes.
-    // Hover to view descriptions of existing attributes.
-    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
-    "version": "0.2.0",
-    "configurations": [
-        {
-            "name": "counter_app",
-            "cwd": "pkgs/dart_tooling_mcp_server/test_fixtures/counter_app",
-            "request": "launch",
-            "type": "dart"
-        },
-        {
-            "name": "counter_app (profile mode)",
-            "cwd": "pkgs/dart_tooling_mcp_server/test_fixtures/counter_app",
-            "request": "launch",
-            "type": "dart",
-            "flutterMode": "profile"
-        },
-        {
-            "name": "counter_app (release mode)",
-            "cwd": "pkgs/dart_tooling_mcp_server/test_fixtures/counter_app",
-            "request": "launch",
-            "type": "dart",
-            "flutterMode": "release"
-        }
-    ]
+  "version": "0.2.0",
+  "configurations": [
+    {
+      "name": "test_mcp",
+      "program": "pkgs/dart_mcp_server/bin/main.dart",
+      "cwd": "${workspaceFolder}",
+      "args": ["--log-file", "pkgs/dart_mcp_server/log.txt"],
+      "request": "launch",
+      "type": "dart"
+    },
+    {
+      "name": "counter_app",
+      "cwd": "pkgs/dart_tooling_mcp_server/test_fixtures/counter_app",
+      "request": "launch",
+      "type": "dart"
+    },
+    {
+      "name": "counter_app (profile mode)",
+      "cwd": "pkgs/dart_tooling_mcp_server/test_fixtures/counter_app",
+      "request": "launch",
+      "type": "dart",
+      "flutterMode": "profile"
+    },
+    {
+      "name": "counter_app (release mode)",
+      "cwd": "pkgs/dart_tooling_mcp_server/test_fixtures/counter_app",
+      "request": "launch",
+      "type": "dart",
+      "flutterMode": "release"
+    }
+  ]
 }
diff --git a/pkgs/dart_mcp/CHANGELOG.md b/pkgs/dart_mcp/CHANGELOG.md
index 28118c8..59240c6 100644
--- a/pkgs/dart_mcp/CHANGELOG.md
+++ b/pkgs/dart_mcp/CHANGELOG.md
@@ -20,6 +20,8 @@
   and stdout streams instead of starting processes itself. This enables custom
   process spawning (such as using package:process), and also enables the client
   to run in browser environments.
+- Fixed a problem where specifying `--log-file` would cause the server to stop
+  working.
 
 ## 0.2.2
 
diff --git a/pkgs/dart_mcp/lib/src/api/initialization.dart b/pkgs/dart_mcp/lib/src/api/initialization.dart
index 81d7b6b..bcbd8f4 100644
--- a/pkgs/dart_mcp/lib/src/api/initialization.dart
+++ b/pkgs/dart_mcp/lib/src/api/initialization.dart
@@ -28,7 +28,7 @@
   ///
   /// May be `null` if the version is not recognized.
   ProtocolVersion? get protocolVersion =>
-      ProtocolVersion.tryParse(_value['protocolVersion'] as String);
+      ProtocolVersion.tryParse(_value['protocolVersion'] as String? ?? '');
 
   ClientCapabilities get capabilities {
     final capabilities = _value['capabilities'] as ClientCapabilities?;
diff --git a/pkgs/dart_mcp_server/lib/src/mixins/analyzer.dart b/pkgs/dart_mcp_server/lib/src/mixins/analyzer.dart
index 10ae558..52cf80d 100644
--- a/pkgs/dart_mcp_server/lib/src/mixins/analyzer.dart
+++ b/pkgs/dart_mcp_server/lib/src/mixins/analyzer.dart
@@ -24,10 +24,10 @@
     on ToolsSupport, LoggingSupport, RootsTrackingSupport
     implements SdkSupport {
   /// The LSP server connection for the analysis server.
-  late final Peer _lspConnection;
+  Peer? _lspConnection;
 
   /// The actual process for the LSP server.
-  late final Process _lspServer;
+  Process? _lspServer;
 
   /// The current diagnostics for a given file.
   Map<Uri, List<lsp.Diagnostic>> diagnostics = {};
@@ -91,7 +91,7 @@
   ///
   /// On failure, returns a reason for the failure.
   Future<String?> _initializeAnalyzerLspServer() async {
-    _lspServer = await Process.start(sdk.dartExecutablePath, [
+    final lspServer = await Process.start(sdk.dartExecutablePath, [
       'language-server',
       // Required even though it is documented as the default.
       // https://github.com/dart-lang/sdk/issues/60574
@@ -101,7 +101,8 @@
       // '--protocol-traffic-log',
       // 'language-server-protocol.log',
     ]);
-    _lspServer.stderr
+    _lspServer = lspServer;
+    lspServer.stderr
         .transform(utf8.decoder)
         .transform(const LineSplitter())
         .listen((line) async {
@@ -109,8 +110,8 @@
           log(LoggingLevel.warning, line, logger: 'DartLanguageServer');
         });
 
-    _lspConnection =
-        Peer(lspChannel(_lspServer.stdout, _lspServer.stdin))
+    final lspConnection =
+        Peer(lspChannel(lspServer.stdout, lspServer.stdin))
           ..registerMethod(
             lsp.Method.textDocument_publishDiagnostics.toString(),
             _handleDiagnostics,
@@ -122,8 +123,9 @@
               () => 'Unhandled LSP message: ${params.method} - ${params.asMap}',
             );
           });
+    _lspConnection = lspConnection;
 
-    unawaited(_lspConnection.listen());
+    unawaited(lspConnection.listen());
 
     log(LoggingLevel.debug, 'Connecting to analyzer lsp server');
     lsp.InitializeResult? initializeResult;
@@ -131,7 +133,7 @@
     try {
       // Initialize with the server.
       initializeResult = lsp.InitializeResult.fromJson(
-        (await _lspConnection.sendRequest(
+        (await lspConnection.sendRequest(
               lsp.Method.initialize.toString(),
               lsp.InitializeParams(
                 capabilities: lsp.ClientCapabilities(
@@ -221,10 +223,10 @@
     }
 
     if (error != null) {
-      _lspServer.kill();
-      await _lspConnection.close();
+      lspServer.kill();
+      await lspConnection.close();
     } else {
-      _lspConnection.sendNotification(
+      lspConnection.sendNotification(
         lsp.Method.initialized.toString(),
         lsp.InitializedParams().toJson(),
       );
@@ -235,8 +237,8 @@
   @override
   Future<void> shutdown() async {
     await super.shutdown();
-    _lspServer.kill();
-    await _lspConnection.close();
+    _lspServer?.kill();
+    await _lspConnection?.close();
   }
 
   /// Implementation of the [analyzeFilesTool], analyzes all the files in all
@@ -270,7 +272,7 @@
     if (errorResult != null) return errorResult;
 
     final query = request.arguments![ParameterNames.query] as String;
-    final result = await _lspConnection.sendRequest(
+    final result = await _lspConnection!.sendRequest(
       lsp.Method.workspace_symbol.toString(),
       lsp.WorkspaceSymbolParams(query: query).toJson(),
     );
@@ -288,7 +290,7 @@
       line: request.arguments![ParameterNames.line] as int,
       character: request.arguments![ParameterNames.column] as int,
     );
-    final result = await _lspConnection.sendRequest(
+    final result = await _lspConnection!.sendRequest(
       lsp.Method.textDocument_signatureHelp.toString(),
       lsp.SignatureHelpParams(
         textDocument: lsp.TextDocumentIdentifier(uri: uri),
@@ -309,7 +311,7 @@
       line: request.arguments![ParameterNames.line] as int,
       character: request.arguments![ParameterNames.column] as int,
     );
-    final result = await _lspConnection.sendRequest(
+    final result = await _lspConnection!.sendRequest(
       lsp.Method.textDocument_hover.toString(),
       lsp.HoverParams(
         textDocument: lsp.TextDocumentIdentifier(uri: uri),
@@ -396,7 +398,7 @@
         () => 'Notifying of workspace root change: ${event.toJson()}',
       );
 
-      _lspConnection.sendNotification(
+      _lspConnection!.sendNotification(
         lsp.Method.workspace_didChangeWorkspaceFolders.toString(),
         lsp.DidChangeWorkspaceFoldersParams(event: event).toJson(),
       );
diff --git a/pkgs/dart_mcp_server/lib/src/server.dart b/pkgs/dart_mcp_server/lib/src/server.dart
index 04af79d..e900dd6 100644
--- a/pkgs/dart_mcp_server/lib/src/server.dart
+++ b/pkgs/dart_mcp_server/lib/src/server.dart
@@ -252,12 +252,15 @@
     StreamSinkTransformer.fromHandlers(
       handleData: (data, innerSink) {
         innerSink.add(utf8.encode(data));
-        // It's a log, so we want to make sure it's always up-to-date.
-        fileByteSink.flush();
       },
-      handleDone: (innerSink) {
+      handleDone: (innerSink) async {
         innerSink.close();
       },
+      handleError: (Object e, StackTrace s, _) {
+        io.stderr.writeln(
+          'Error in writing to log file ${logFile.path}: $e\n$s',
+        );
+      },
     ),
   );
 }
diff --git a/pkgs/dart_mcp_server/test/dart_tooling_mcp_server_test.dart b/pkgs/dart_mcp_server/test/dart_tooling_mcp_server_test.dart
index 606be7f..2857be0 100644
--- a/pkgs/dart_mcp_server/test/dart_tooling_mcp_server_test.dart
+++ b/pkgs/dart_mcp_server/test/dart_tooling_mcp_server_test.dart
@@ -123,7 +123,7 @@
 
       // Wait for the process to release the file.
       await doWithRetries(() => File(logDescriptor.io.path).delete());
-    }, skip: 'https://github.com/dart-lang/ai/issues/181');
+    });
   });
 }