summaryrefslogtreecommitdiff
path: root/src/sailfish_devel_mcp/runner.py
diff options
context:
space:
mode:
authorAndrew Branson <andrew.branson@jolla.com>2026-06-02 00:18:14 +0200
committerAndrew Branson <andrew.branson@jolla.com>2026-06-02 00:18:14 +0200
commit5d24d33536d1041b4d9f107a5f5813bd43177530 (patch)
tree86b90f5e58747c31aaaff8ff5e52661421c7f69a /src/sailfish_devel_mcp/runner.py
parent0cdf2d00cdc1a9af5f5b0b14241a2afe717661f6 (diff)
Harden MCP transport error handling
Normalize timeout output to text, convert tool exceptions into tool errors, and keep stdio running after response serialization failures.
Diffstat (limited to 'src/sailfish_devel_mcp/runner.py')
-rw-r--r--src/sailfish_devel_mcp/runner.py20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/sailfish_devel_mcp/runner.py b/src/sailfish_devel_mcp/runner.py
index b0b88bf..74748f4 100644
--- a/src/sailfish_devel_mcp/runner.py
+++ b/src/sailfish_devel_mcp/runner.py
@@ -4,7 +4,7 @@ from dataclasses import dataclass
from pathlib import Path
import shlex
import subprocess
-from typing import Iterable, Sequence
+from typing import Any, Iterable, Sequence
from .config import DeviceConfig
@@ -39,6 +39,16 @@ def truncate(text: str, limit: int) -> tuple[str, bool]:
return text[:limit] + f"\n[truncated after {limit} characters]", True
+def ensure_text(value: Any) -> str:
+ if value is None:
+ return ""
+ if isinstance(value, str):
+ return value
+ if isinstance(value, bytes):
+ return value.decode("utf-8", errors="replace")
+ return str(value)
+
+
def run(
argv: Sequence[str],
*,
@@ -57,15 +67,15 @@ def run(
return CommandResult(
argv=tuple(str(arg) for arg in argv),
returncode=completed.returncode,
- stdout=completed.stdout,
- stderr=completed.stderr,
+ stdout=ensure_text(completed.stdout),
+ stderr=ensure_text(completed.stderr),
)
except subprocess.TimeoutExpired as exc:
return CommandResult(
argv=tuple(str(arg) for arg in argv),
returncode=124,
- stdout=exc.stdout or "",
- stderr=(exc.stderr or "") + f"\ncommand timed out after {timeout}s",
+ stdout=ensure_text(exc.stdout),
+ stderr=ensure_text(exc.stderr) + f"\ncommand timed out after {timeout}s",
)