diff --git a/scripts/lib/devtool/ide_plugins/__init__.py b/scripts/lib/devtool/ide_plugins/__init__.py
index 4a1686a034..cfb067548d 100644
--- a/scripts/lib/devtool/ide_plugins/__init__.py
+++ b/scripts/lib/devtool/ide_plugins/__init__.py
@@ -170,11 +170,14 @@ class GdbCrossConfig(DebuggerCrossConfig):
             else:
                 raise DevtoolError("Cannot use gdbserver attach mode for binary %s. No PID found." % self.binary.binary_path)
         elif server_mode == DebuggerServerModes.MULTI:
-            gdbserver_cmd_start = "test -f %s && exit 0; " % self._gdbserver_pid_file(server_mode)
+            hex_port = "%04X" % self.debug_server_port
+            gdbserver_cmd_start = "grep -q :%s /proc/net/tcp /proc/net/tcp6 2>/dev/null && exit 0; " % hex_port
             gdbserver_cmd_start += "mkdir -p %s; " % self._gdbserver_tmp_dir(server_mode)
             gdbserver_cmd_start += "%s --multi :%s > %s 2>&1 & " % (
                 self.debugger_cross.debug_server_path, self.debug_server_port, self._gdbserver_log_file(server_mode))
-            gdbserver_cmd_start += "echo \\$! > %s;" % self._gdbserver_pid_file(server_mode)
+            gdbserver_cmd_start += "echo \\$! > %s; " % self._gdbserver_pid_file(server_mode)
+            gdbserver_cmd_start += "_w=0; while ! grep -q :%s /proc/net/tcp /proc/net/tcp6 2>/dev/null; " % hex_port
+            gdbserver_cmd_start += "do _w=\\$((_w+1)); [ \\$_w -lt 100 ] || exit 1; sleep 0.1; done;"
         else:
             raise DevtoolError("Unsupported gdbserver mode: %s" % server_mode)
         return "\"/bin/sh -c '" + gdbserver_cmd_start + "'\""
diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py
index dfaba3cff6..d237ab8f66 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -456,30 +456,45 @@ class IdeVSCode(IdeBase):
             if cross_debug_config.modified_recipe is not modified_recipe:
                 continue
             for server_mode in cross_debug_config.server_modes():
-                new_task = {
-                    "label": cross_debug_config.id_pretty_mode(server_mode),
-                    "type": "shell",
-                    "isBackground": True,
-                    "command": cross_debug_config.debugger_cross.target_device.ssh_sshexec,
-                    "args": cross_debug_config.target_ssh_gdbserver_start_args(server_mode),
-                    "problemMatcher": [
-                        {
-                            "pattern": [
-                                {
-                                    "regexp": ".",
-                                    "file": 1,
-                                    "location": 2,
-                                    "message": 3
+                if server_mode == DebuggerServerModes.MULTI:
+                    # MULTI mode: the SSH command blocks until the port is ready
+                    # (wait loop in _target_start_cmd), so VSCode treats this as
+                    # a regular non-background task.
+                    new_task = {
+                        "label": cross_debug_config.id_pretty_mode(server_mode),
+                        "type": "shell",
+                        "command": cross_debug_config.debugger_cross.target_device.ssh_sshexec,
+                        "args": cross_debug_config.target_ssh_gdbserver_start_args(server_mode),
+                        "problemMatcher": []
+                    }
+                else:
+                    # ONCE / ATTACH: gdbserver runs in the foreground for the
+                    # whole session, so VSCode needs isBackground + a pattern
+                    # matcher to avoid waiting for the task to exit.
+                    new_task = {
+                        "label": cross_debug_config.id_pretty_mode(server_mode),
+                        "type": "shell",
+                        "isBackground": True,
+                        "command": cross_debug_config.debugger_cross.target_device.ssh_sshexec,
+                        "args": cross_debug_config.target_ssh_gdbserver_start_args(server_mode),
+                        "problemMatcher": [
+                            {
+                                "pattern": [
+                                    {
+                                        "regexp": ".",
+                                        "file": 1,
+                                        "location": 2,
+                                        "message": 3
+                                    }
+                                ],
+                                "background": {
+                                    "activeOnStart": True,
+                                    "beginsPattern": ".",
+                                    "endsPattern": ".",
                                 }
-                            ],
-                            "background": {
-                                "activeOnStart": True,
-                                "beginsPattern": ".",
-                                "endsPattern": ".",
                             }
-                        }
-                    ]
-                }
+                        ]
+                    }
                 # Deploy the artifacts to the target before starting gdbserver if not already running
                 if server_mode != DebuggerServerModes.ATTACH:
                     new_task['dependsOn'] = [
