Skip to content

Commit 688efb9

Browse files
committed
fix: properly handle malformed command output
Signed-off-by: Richard Gebhardt <[email protected]>
1 parent a04bce9 commit 688efb9

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

src/oci-api-mcp-server/oracle/oci_api_mcp_server/server.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -161,17 +161,30 @@ def run_oci_command(
161161
check=True,
162162
shell=False,
163163
)
164-
return (
165-
json.loads(result.stdout)
166-
if result.stdout
167-
else {
168-
"error": result.stderr,
169-
}
170-
)
164+
165+
result.check_returncode()
166+
167+
response = {
168+
"command": command,
169+
"output": result.stdout,
170+
"error": result.stderr,
171+
"returncode": result.returncode,
172+
}
173+
174+
try:
175+
response["output"] = json.loads(result.stdout)
176+
except TypeError:
177+
pass
178+
except json.JSONDecodeError:
179+
pass
180+
181+
return response
171182
except subprocess.CalledProcessError as e:
172183
return {
173-
"error": e.stderr,
184+
"command": command,
174185
"output": e.stdout,
186+
"error": e.stderr,
187+
"returncode": e.returncode,
175188
}
176189

177190

src/oci-api-mcp-server/oracle/oci_api_mcp_server/tests/test_oci_api_tools.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,45 +74,55 @@ async def test_get_oci_command_help_failure(self, mock_run):
7474
@patch("oracle.oci_api_mcp_server.server.subprocess.run")
7575
@patch("oracle.oci_api_mcp_server.server.json.loads")
7676
async def test_run_oci_command_success(self, mock_json_loads, mock_run):
77+
command = "compute instance list"
78+
7779
mock_result = MagicMock()
7880
mock_result.stdout = '{"key": "value"}'
7981
mock_result.stderr = ""
82+
mock_result.returncode = 0
8083
mock_run.return_value = mock_result
84+
8185
mock_json_loads.return_value = {"key": "value"}
8286

8387
async with Client(mcp) as client:
8488
result = (
85-
await client.call_tool(
86-
"run_oci_command", {"command": "compute instance list"}
87-
)
89+
await client.call_tool("run_oci_command", {"command": command})
8890
).data
8991

90-
assert result == {"key": "value"}
91-
mock_json_loads.assert_called_once_with('{"key": "value"}')
92+
assert result == {
93+
"command": command,
94+
"output": mock_json_loads.return_value,
95+
"error": mock_result.stderr,
96+
"returncode": mock_result.returncode,
97+
}
9298

9399
@pytest.mark.asyncio
94100
@patch("oracle.oci_api_mcp_server.server.subprocess.run")
95101
async def test_run_oci_command_failure(self, mock_run):
102+
command = "compute instance list"
103+
96104
mock_result = MagicMock()
97105
mock_result.stdout = "Some output"
98106
mock_result.stderr = "Some error"
107+
mock_result.returncode = 1
108+
99109
mock_run.side_effect = subprocess.CalledProcessError(
100-
returncode=1,
101-
cmd=["oci", "compute", "instance", "list"],
110+
returncode=mock_result.returncode,
111+
cmd=["oci"] + command.split(),
102112
output=mock_result.stdout,
103113
stderr=mock_result.stderr,
104114
)
105115

106116
async with Client(mcp) as client:
107117
result = (
108-
await client.call_tool(
109-
"run_oci_command", {"command": "compute instance list"}
110-
)
118+
await client.call_tool("run_oci_command", {"command": command})
111119
).data
112120

113121
assert result == {
114-
"error": "Some error",
115-
"output": "Some output",
122+
"command": command,
123+
"output": mock_result.stdout,
124+
"error": mock_result.stderr,
125+
"returncode": mock_result.returncode,
116126
}
117127

118128
@pytest.mark.asyncio

0 commit comments

Comments
 (0)