Skip to content

Commit db89228

Browse files
abueideclaude
andcommitted
fix(tests,mcp): fix CI failures and add logFile parameter to devbox_run
Fix test-server.sh and test-tools.sh to use test_passed/test_failed (renamed in the framework refactor). Fix integration tests to use example project fixtures instead of deleted tests/fixtures/ directory, switch from /tmp/ to make_temp_dir(), and update device name assertions. Add optional logFile parameter to MCP devbox_run tool for redirecting large output to a file instead of returning inline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 579fa9b commit db89228

7 files changed

Lines changed: 146 additions & 96 deletions

File tree

plugins/devbox-mcp/src/index.js

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
ListToolsRequestSchema,
77
} from "@modelcontextprotocol/sdk/types.js";
88
import { execFile } from "child_process";
9+
import { writeFile } from "fs/promises";
910
import { promisify } from "util";
1011

1112
const execFileAsync = promisify(execFile);
@@ -217,7 +218,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
217218
"- devbox.d/: Per-project configuration directory\n" +
218219
"- .devbox/virtenv/: Temporary runtime directory (auto-regenerated, never edit directly)\n\n" +
219220
"The .devbox/virtenv/ directory is automatically regenerated on 'devbox shell' or 'devbox run'. " +
220-
"Any manual changes to files in .devbox/virtenv/ will be lost.",
221+
"Any manual changes to files in .devbox/virtenv/ will be lost.\n\n" +
222+
"OUTPUT MANAGEMENT: For commands that produce large output (builds, test suites, logs), " +
223+
"use the 'logFile' parameter to write output to a file instead of returning it inline. " +
224+
"This keeps context tokens low. The response will include the file path, exit status, " +
225+
"and a short summary. You can then read the log file selectively if needed.",
221226
inputSchema: {
222227
type: "object",
223228
properties: {
@@ -250,6 +255,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
250255
description: "Timeout in milliseconds (default: 120000)",
251256
default: 120000,
252257
},
258+
logFile: {
259+
type: "string",
260+
description:
261+
"Absolute path to write stdout+stderr to instead of returning inline. " +
262+
"Use for commands with large output (builds, test suites) to avoid filling context. " +
263+
"When set, the response returns a short summary with the log file path.",
264+
},
253265
},
254266
required: ["command"],
255267
},
@@ -424,7 +436,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
424436

425437
switch (name) {
426438
case "devbox_run": {
427-
const { command, args: cmdArgs = [], pure = false, env = {}, cwd, timeout } = args;
439+
const { command, args: cmdArgs = [], pure = false, env = {}, cwd, timeout, logFile } = args;
428440

429441
const devboxArgs = ["run"];
430442
if (pure) devboxArgs.push("--pure");
@@ -441,6 +453,44 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
441453

442454
const result = await runDevbox(devboxArgs, { cwd, timeout });
443455

456+
// If logFile is specified, write output to file and return summary
457+
if (logFile) {
458+
const fullOutput = [
459+
result.stdout || "",
460+
result.stderr ? `\n--- stderr ---\n${result.stderr}` : "",
461+
].join("");
462+
463+
try {
464+
await writeFile(logFile, fullOutput, "utf-8");
465+
} catch (writeErr) {
466+
return {
467+
content: [
468+
{
469+
type: "text",
470+
text: `✗ Failed to write log file: ${writeErr.message}\n\nCommand ${result.success ? "succeeded" : `failed (exit ${result.exitCode})`}`,
471+
},
472+
],
473+
isError: true,
474+
};
475+
}
476+
477+
const lines = fullOutput.split("\n");
478+
const lineCount = lines.length;
479+
const tail = lines.slice(-5).join("\n");
480+
481+
return {
482+
content: [
483+
{
484+
type: "text",
485+
text: result.success
486+
? `✓ Command succeeded (${lineCount} lines written to ${logFile})\n\nLast 5 lines:\n${tail}`
487+
: `✗ Command failed (exit ${result.exitCode}, ${lineCount} lines written to ${logFile})\n\nLast 5 lines:\n${tail}`,
488+
},
489+
],
490+
isError: !result.success,
491+
};
492+
}
493+
444494
return {
445495
content: [
446496
{

plugins/devbox-mcp/tests/test-server.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ echo "Validating Node.js syntax..."
3232
# Change to repo root to use devbox run
3333
cd "${SCRIPT_DIR}/../.." || exit 1
3434
if devbox run node --check plugins/devbox-mcp/src/index.js >/dev/null 2>&1; then
35-
TEST_PASS=$((TEST_PASS + 1))
35+
test_passed=$((test_passed + 1))
3636
echo "✓ Server JavaScript syntax is valid"
3737
else
38-
TEST_FAIL=$((TEST_FAIL + 1))
38+
test_failed=$((test_failed + 1))
3939
echo "✗ Server JavaScript syntax has errors"
4040
fi
4141
cd "${SCRIPT_DIR}" || exit 1
@@ -45,10 +45,10 @@ echo "Checking required tools are defined..."
4545
required_tools="devbox_run devbox_list devbox_add devbox_info devbox_search devbox_docs_search devbox_docs_list devbox_docs_read devbox_init devbox_shell_env devbox_sync"
4646
for tool in $required_tools; do
4747
if grep -q "name: \"$tool\"" "${MCP_DIR}/src/index.js"; then
48-
TEST_PASS=$((TEST_PASS + 1))
48+
test_passed=$((test_passed + 1))
4949
echo "✓ Tool defined: $tool"
5050
else
51-
TEST_FAIL=$((TEST_FAIL + 1))
51+
test_failed=$((test_failed + 1))
5252
echo "✗ Tool missing: $tool"
5353
fi
5454
done
@@ -60,4 +60,4 @@ assert_file_contains "${MCP_DIR}/src/index.js" "StdioServerTransport" "Server im
6060
# Test 8: Check server has proper error handling
6161
assert_file_contains "${MCP_DIR}/src/index.js" "catch.*error" "Server has error handling"
6262

63-
test_summary
63+
test_summary "devbox-mcp-server"

plugins/devbox-mcp/tests/test-tools.sh

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ fi
2121
# Test 1: Server starts without errors
2222
echo "Testing server startup (5 second timeout)..."
2323
if timeout 5 node "${MCP_DIR}/src/index.js" </dev/null 2>&1 | grep -q "Devbox MCP server running"; then
24-
TEST_PASS=$((TEST_PASS + 1))
24+
test_passed=$((test_passed + 1))
2525
echo "✓ Server starts successfully"
2626
else
27-
TEST_FAIL=$((TEST_FAIL + 1))
27+
test_failed=$((test_failed + 1))
2828
echo "✗ Server failed to start"
2929
fi
3030

@@ -34,117 +34,117 @@ server_content="$(cat "${MCP_DIR}/src/index.js")"
3434

3535
# devbox_run tool checks
3636
if echo "$server_content" | grep -q 'name: "devbox_run"'; then
37-
TEST_PASS=$((TEST_PASS + 1))
37+
test_passed=$((test_passed + 1))
3838
echo "✓ devbox_run tool defined"
3939
else
40-
TEST_FAIL=$((TEST_FAIL + 1))
40+
test_failed=$((test_failed + 1))
4141
echo "✗ devbox_run tool not found"
4242
fi
4343

4444
if echo "$server_content" | grep -q 'command:'; then
45-
TEST_PASS=$((TEST_PASS + 1))
45+
test_passed=$((test_passed + 1))
4646
echo "✓ devbox_run has command parameter"
4747
else
48-
TEST_FAIL=$((TEST_FAIL + 1))
48+
test_failed=$((test_failed + 1))
4949
echo "✗ devbox_run missing command parameter"
5050
fi
5151

5252
# devbox_list tool checks
5353
if echo "$server_content" | grep -q 'name: "devbox_list"'; then
54-
TEST_PASS=$((TEST_PASS + 1))
54+
test_passed=$((test_passed + 1))
5555
echo "✓ devbox_list tool defined"
5656
else
57-
TEST_FAIL=$((TEST_FAIL + 1))
57+
test_failed=$((test_failed + 1))
5858
echo "✗ devbox_list tool not found"
5959
fi
6060

6161
# devbox_add tool checks
6262
if echo "$server_content" | grep -q 'name: "devbox_add"'; then
63-
TEST_PASS=$((TEST_PASS + 1))
63+
test_passed=$((test_passed + 1))
6464
echo "✓ devbox_add tool defined"
6565
else
66-
TEST_FAIL=$((TEST_FAIL + 1))
66+
test_failed=$((test_failed + 1))
6767
echo "✗ devbox_add tool not found"
6868
fi
6969

7070
if echo "$server_content" | grep -q 'packages:'; then
71-
TEST_PASS=$((TEST_PASS + 1))
71+
test_passed=$((test_passed + 1))
7272
echo "✓ devbox_add has packages parameter"
7373
else
74-
TEST_FAIL=$((TEST_FAIL + 1))
74+
test_failed=$((test_failed + 1))
7575
echo "✗ devbox_add missing packages parameter"
7676
fi
7777

7878
# devbox_info tool checks
7979
if echo "$server_content" | grep -q 'name: "devbox_info"'; then
80-
TEST_PASS=$((TEST_PASS + 1))
80+
test_passed=$((test_passed + 1))
8181
echo "✓ devbox_info tool defined"
8282
else
83-
TEST_FAIL=$((TEST_FAIL + 1))
83+
test_failed=$((test_failed + 1))
8484
echo "✗ devbox_info tool not found"
8585
fi
8686

8787
# devbox_search tool checks
8888
if echo "$server_content" | grep -q 'name: "devbox_search"'; then
89-
TEST_PASS=$((TEST_PASS + 1))
89+
test_passed=$((test_passed + 1))
9090
echo "✓ devbox_search tool defined"
9191
else
92-
TEST_FAIL=$((TEST_FAIL + 1))
92+
test_failed=$((test_failed + 1))
9393
echo "✗ devbox_search tool not found"
9494
fi
9595

9696
# devbox_docs_search tool checks
9797
if echo "$server_content" | grep -q 'name: "devbox_docs_search"'; then
98-
TEST_PASS=$((TEST_PASS + 1))
98+
test_passed=$((test_passed + 1))
9999
echo "✓ devbox_docs_search tool defined"
100100
else
101-
TEST_FAIL=$((TEST_FAIL + 1))
101+
test_failed=$((test_failed + 1))
102102
echo "✗ devbox_docs_search tool not found"
103103
fi
104104

105105
if echo "$server_content" | grep -q 'maxResults'; then
106-
TEST_PASS=$((TEST_PASS + 1))
106+
test_passed=$((test_passed + 1))
107107
echo "✓ devbox_docs_search has maxResults parameter"
108108
else
109-
TEST_FAIL=$((TEST_FAIL + 1))
109+
test_failed=$((test_failed + 1))
110110
echo "✗ devbox_docs_search missing maxResults parameter"
111111
fi
112112

113113
# devbox_docs_list tool checks
114114
if echo "$server_content" | grep -q 'name: "devbox_docs_list"'; then
115-
TEST_PASS=$((TEST_PASS + 1))
115+
test_passed=$((test_passed + 1))
116116
echo "✓ devbox_docs_list tool defined"
117117
else
118-
TEST_FAIL=$((TEST_FAIL + 1))
118+
test_failed=$((test_failed + 1))
119119
echo "✗ devbox_docs_list tool not found"
120120
fi
121121

122122
# devbox_docs_read tool checks
123123
if echo "$server_content" | grep -q 'name: "devbox_docs_read"'; then
124-
TEST_PASS=$((TEST_PASS + 1))
124+
test_passed=$((test_passed + 1))
125125
echo "✓ devbox_docs_read tool defined"
126126
else
127-
TEST_FAIL=$((TEST_FAIL + 1))
127+
test_failed=$((test_failed + 1))
128128
echo "✗ devbox_docs_read tool not found"
129129
fi
130130

131131
if echo "$server_content" | grep -q 'filePath'; then
132-
TEST_PASS=$((TEST_PASS + 1))
132+
test_passed=$((test_passed + 1))
133133
echo "✓ devbox_docs_read has filePath parameter"
134134
else
135-
TEST_FAIL=$((TEST_FAIL + 1))
135+
test_failed=$((test_failed + 1))
136136
echo "✗ devbox_docs_read missing filePath parameter"
137137
fi
138138

139139
# Test 3: Check helper functions exist
140140
echo "Checking helper functions..."
141-
helper_functions="runDevbox ensureDocsRepo searchDocs listDocs readDoc"
141+
helper_functions="runDevbox fetchDocsList fetchRawContent searchDocs listDocs readDoc"
142142
for func in $helper_functions; do
143143
if echo "$server_content" | grep -q "function $func"; then
144-
TEST_PASS=$((TEST_PASS + 1))
144+
test_passed=$((test_passed + 1))
145145
echo "$func helper function defined"
146146
else
147-
TEST_FAIL=$((TEST_FAIL + 1))
147+
test_failed=$((test_failed + 1))
148148
echo "$func helper function not found"
149149
fi
150150
done
@@ -154,12 +154,12 @@ echo "Checking tool handlers..."
154154
tools="devbox_run devbox_list devbox_add devbox_info devbox_search devbox_docs_search devbox_docs_list devbox_docs_read devbox_init devbox_shell_env devbox_sync"
155155
for tool in $tools; do
156156
if echo "$server_content" | grep -q "case \"$tool\":"; then
157-
TEST_PASS=$((TEST_PASS + 1))
157+
test_passed=$((test_passed + 1))
158158
echo "✓ Handler exists for $tool"
159159
else
160-
TEST_FAIL=$((TEST_FAIL + 1))
160+
test_failed=$((test_failed + 1))
161161
echo "✗ Handler missing for $tool"
162162
fi
163163
done
164164

165-
test_summary
165+
test_summary "devbox-mcp-tools"

tests/integration/android/test-device-mgmt.sh

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ REPO_ROOT="$SCRIPT_DIR/../../.."
2020
. "$REPO_ROOT/plugins/tests/test-framework.sh"
2121

2222
# Setup test environment
23-
TEST_ROOT="/tmp/android-integration-test-$$"
23+
TEST_ROOT="$(make_temp_dir "android-integration")"
2424
mkdir -p "$TEST_ROOT/devbox.d/android/devices"
2525
mkdir -p "$TEST_ROOT/devbox.d/android/scripts"
2626

27-
# Copy fixtures
28-
cp "$SCRIPT_DIR/../../fixtures/android/devices/"*.json "$TEST_ROOT/devbox.d/android/devices/"
27+
# Copy device fixtures from example project
28+
cp "$REPO_ROOT/examples/android/devbox.d/android/devices/"*.json "$TEST_ROOT/devbox.d/android/devices/"
2929

3030
# Copy plugin scripts
3131
cp -r "$REPO_ROOT/plugins/android/virtenv/scripts/"* "$TEST_ROOT/devbox.d/android/scripts/"
@@ -43,10 +43,10 @@ cd "$TEST_ROOT"
4343
# Test 1: Device list command
4444
echo "Test: Device listing..."
4545
if sh "$ANDROID_SCRIPTS_DIR/user/devices.sh" list >/dev/null 2>&1; then
46-
TEST_PASS=$((TEST_PASS + 1))
46+
test_passed=$((test_passed + 1))
4747
echo "✓ Device list command succeeds"
4848
else
49-
TEST_FAIL=$((TEST_FAIL + 1))
49+
test_failed=$((test_failed + 1))
5050
echo "✗ Device list command failed"
5151
fi
5252

@@ -56,22 +56,22 @@ if sh "$ANDROID_SCRIPTS_DIR/user/devices.sh" eval >/dev/null 2>&1; then
5656
assert_file_exists "$ANDROID_DEVICES_DIR/devices.lock" "Lock file created after eval"
5757
else
5858
echo "✗ Device eval command failed"
59-
TEST_FAIL=$((TEST_FAIL + 1))
59+
test_failed=$((test_failed + 1))
6060
fi
6161

6262
# Test 3: Lock file structure
6363
echo "Test: Lock file structure..."
6464
if [ -f "$ANDROID_DEVICES_DIR/devices.lock" ]; then
6565
# Lock file should be valid JSON with devices array
6666
if jq -e '.devices' "$ANDROID_DEVICES_DIR/devices.lock" >/dev/null 2>&1; then
67-
TEST_PASS=$((TEST_PASS + 1))
67+
test_passed=$((test_passed + 1))
6868
echo "✓ Lock file has valid structure"
6969
else
70-
TEST_FAIL=$((TEST_FAIL + 1))
70+
test_failed=$((test_failed + 1))
7171
echo "✗ Lock file has invalid format"
7272
fi
7373
else
74-
TEST_FAIL=$((TEST_FAIL + 1))
74+
test_failed=$((test_failed + 1))
7575
echo "✗ Lock file not found"
7676
fi
7777

@@ -80,10 +80,10 @@ echo "Test: Device count validation..."
8080
device_count=$(jq '.devices | length' "$ANDROID_DEVICES_DIR/devices.lock")
8181
expected_count=$(ls -1 "$ANDROID_DEVICES_DIR"/*.json | wc -l | tr -d ' ')
8282
if [ "$device_count" = "$expected_count" ]; then
83-
TEST_PASS=$((TEST_PASS + 1))
83+
test_passed=$((test_passed + 1))
8484
echo "✓ All devices included in lock file ($device_count devices)"
8585
else
86-
TEST_FAIL=$((TEST_FAIL + 1))
86+
test_failed=$((test_failed + 1))
8787
echo "✗ Device count mismatch (expected $expected_count, got $device_count)"
8888
fi
8989

0 commit comments

Comments
 (0)