mlgym-deploy 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ADD_TO_CURSOR_SETTINGS.json +28 -0
- package/CURSOR_SETUP.md +119 -0
- package/README.md +43 -0
- package/claude-desktop-config.json +8 -0
- package/cursor-config.json +13 -0
- package/cursor-integration.js +165 -0
- package/cursor-prompt-config.json +27 -0
- package/deploy-hello-world.sh +103 -0
- package/index-v2.js +1040 -0
- package/index-v3-explicit.js +129 -0
- package/index.js +5238 -0
- package/package.json +45 -0
- package/tests/README.md +90 -0
- package/tests/mlgym_auth_login_test.sh +170 -0
- package/tests/mlgym_auth_logout_test.sh +157 -0
- package/tests/mlgym_deployments_test.sh +204 -0
- package/tests/mlgym_project_init_test.sh +148 -0
- package/tests/mlgym_projects_get_test.sh +159 -0
- package/tests/mlgym_projects_list_test.sh +162 -0
- package/tests/mlgym_user_create_test.sh +203 -0
- package/tests/run-all-tests.sh +63 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Comprehensive test suite for mlgym_user_create
|
|
3
|
+
# Tests functional requirements, edge cases, and security
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
PASSED=0
|
|
8
|
+
FAILED=0
|
|
9
|
+
|
|
10
|
+
echo "=== mlgym_user_create Comprehensive Test Suite ==="
|
|
11
|
+
echo ""
|
|
12
|
+
|
|
13
|
+
# Helper to run test
|
|
14
|
+
run_test() {
|
|
15
|
+
local test_name="$1"
|
|
16
|
+
local email="$2"
|
|
17
|
+
local name="$3"
|
|
18
|
+
local password="$4"
|
|
19
|
+
local accept_terms="$5"
|
|
20
|
+
local expected_result="$6" # "success" or "error"
|
|
21
|
+
|
|
22
|
+
# Build JSON request
|
|
23
|
+
local terms_field=""
|
|
24
|
+
if [ -n "$accept_terms" ]; then
|
|
25
|
+
terms_field=",\"accept_terms\":$accept_terms"
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
local req="{\"jsonrpc\":\"2.0\",\"method\":\"tools/call\",\"params\":{\"name\":\"mlgym_user_create\",\"arguments\":{\"email\":\"$email\",\"name\":\"$name\",\"password\":\"$password\"$terms_field}},\"id\":99}"
|
|
29
|
+
local resp=$(echo "$req" | node index.js 2>/dev/null | tail -1)
|
|
30
|
+
|
|
31
|
+
# Check for user_id (success) or error message
|
|
32
|
+
local content=$(echo "$resp" | jq -r '.result.content[0].text' 2>/dev/null)
|
|
33
|
+
local user_id=$(echo "$content" | jq -r '.user_id' 2>/dev/null)
|
|
34
|
+
local error_msg=$(echo "$content" | jq -r '.message' 2>/dev/null)
|
|
35
|
+
local has_status=$(echo "$content" | jq -r '.status' 2>/dev/null)
|
|
36
|
+
|
|
37
|
+
if [ "$expected_result" = "success" ]; then
|
|
38
|
+
if [ -n "$user_id" ] && [ "$user_id" != "null" ]; then
|
|
39
|
+
echo "✅ $test_name (user_id: $user_id)"
|
|
40
|
+
PASSED=$((PASSED + 1))
|
|
41
|
+
else
|
|
42
|
+
echo "❌ $test_name (expected user creation, got: $error_msg)"
|
|
43
|
+
FAILED=$((FAILED + 1))
|
|
44
|
+
fi
|
|
45
|
+
else
|
|
46
|
+
# Expected error
|
|
47
|
+
if echo "$content" | grep -qE "error|missing|required|invalid|must"; then
|
|
48
|
+
echo "✅ $test_name"
|
|
49
|
+
PASSED=$((PASSED + 1))
|
|
50
|
+
else
|
|
51
|
+
echo "❌ $test_name (expected error, got success or no error)"
|
|
52
|
+
FAILED=$((FAILED + 1))
|
|
53
|
+
fi
|
|
54
|
+
fi
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# Test 1: Valid user creation with all fields
|
|
58
|
+
echo "Test 1: Valid user creation with all required fields"
|
|
59
|
+
TEST_EMAIL="createtest-$(date +%s)@example.com"
|
|
60
|
+
TEST_PASS="MyV3ryC0mpl3x!P@ssw0rd#2024"
|
|
61
|
+
run_test "Valid user creation" "$TEST_EMAIL" "Test User Full Name" "$TEST_PASS" "true" "success"
|
|
62
|
+
|
|
63
|
+
# Test 2: Missing email
|
|
64
|
+
run_test "Missing email" "" "Test User" "Pass123!Strong" "true" "error"
|
|
65
|
+
|
|
66
|
+
# Test 3: Missing name
|
|
67
|
+
run_test "Missing name" "test@example.com" "" "Pass123!Strong" "true" "error"
|
|
68
|
+
|
|
69
|
+
# Test 4: Missing password
|
|
70
|
+
run_test "Missing password" "test@example.com" "Test User" "" "true" "error"
|
|
71
|
+
|
|
72
|
+
# Test 5: accept_terms = false
|
|
73
|
+
run_test "Terms not accepted (false)" "test@example.com" "Test User" "Pass123!Strong" "false" "error"
|
|
74
|
+
|
|
75
|
+
# Test 6: accept_terms missing
|
|
76
|
+
echo "Test 6: Missing accept_terms parameter"
|
|
77
|
+
REQ='{"jsonrpc":"2.0","method":"tools/call","params":{"name":"mlgym_user_create","arguments":{"email":"test@example.com","name":"Test User","password":"Pass123!Strong"}},"id":100}'
|
|
78
|
+
RESP=$(echo "$REQ" | node index.js 2>/dev/null | tail -1)
|
|
79
|
+
CONTENT=$(echo "$RESP" | jq -r '.result.content[0].text')
|
|
80
|
+
if echo "$CONTENT" | grep -qE "error|missing|required|must"; then
|
|
81
|
+
echo "✅ Test 6: Missing accept_terms"
|
|
82
|
+
PASSED=$((PASSED + 1))
|
|
83
|
+
else
|
|
84
|
+
echo "❌ Test 6: Should reject missing accept_terms"
|
|
85
|
+
FAILED=$((FAILED + 1))
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Test 7: Invalid email format
|
|
89
|
+
run_test "Invalid email format" "not-an-email" "Test User" "Pass123!Strong" "true" "error"
|
|
90
|
+
|
|
91
|
+
# Test 8: Short password (< 8 chars)
|
|
92
|
+
run_test "Short password" "test@example.com" "Test User" "Pass12!" "true" "error"
|
|
93
|
+
|
|
94
|
+
# Test 9: Short name (< 2 chars)
|
|
95
|
+
run_test "Short name" "test@example.com" "T" "Pass123!Strong" "true" "error"
|
|
96
|
+
|
|
97
|
+
# Test 10: SQL injection in email
|
|
98
|
+
run_test "SQL injection (email)" "admin@test.com' OR '1'='1" "Test User" "Pass123!Strong" "true" "error"
|
|
99
|
+
|
|
100
|
+
# Test 11: SQL injection in name
|
|
101
|
+
run_test "SQL injection (name)" "test@example.com" "'; DROP TABLE users;--" "Pass123!Strong" "true" "error"
|
|
102
|
+
|
|
103
|
+
# Test 12: SQL injection in password
|
|
104
|
+
run_test "SQL injection (password)" "test@example.com" "Test User" "' OR '1'='1" "true" "error"
|
|
105
|
+
|
|
106
|
+
# Test 13: XSS attempt in email
|
|
107
|
+
run_test "XSS attempt (email)" "<script>alert(1)</script>@test.com" "Test User" "Pass123!Strong" "true" "error"
|
|
108
|
+
|
|
109
|
+
# Test 14: XSS attempt in name
|
|
110
|
+
run_test "XSS attempt (name)" "test@example.com" "<script>alert('XSS')</script>" "Pass123!Strong" "true" "error"
|
|
111
|
+
|
|
112
|
+
# Test 15: Buffer overflow in email
|
|
113
|
+
echo "Test 15: Buffer overflow (very long email)"
|
|
114
|
+
LONG_EMAIL=$(python3 -c "print('a' * 10000 + '@test.com')")
|
|
115
|
+
run_test "Buffer overflow (email)" "$LONG_EMAIL" "Test User" "Pass123!Strong" "true" "error"
|
|
116
|
+
|
|
117
|
+
# Test 16: Buffer overflow in name
|
|
118
|
+
echo "Test 16: Buffer overflow (very long name)"
|
|
119
|
+
LONG_NAME=$(python3 -c "print('A' * 10000)")
|
|
120
|
+
run_test "Buffer overflow (name)" "test@example.com" "$LONG_NAME" "Pass123!Strong" "true" "error"
|
|
121
|
+
|
|
122
|
+
# Test 17: Duplicate user creation
|
|
123
|
+
echo "Test 17: Duplicate user creation"
|
|
124
|
+
DUP_EMAIL="duplicate-$(date +%s)@example.com"
|
|
125
|
+
# Create first user
|
|
126
|
+
REQ="{\"jsonrpc\":\"2.0\",\"method\":\"tools/call\",\"params\":{\"name\":\"mlgym_user_create\",\"arguments\":{\"email\":\"$DUP_EMAIL\",\"name\":\"Duplicate User\",\"password\":\"Pass123!Strong\",\"accept_terms\":true}},\"id\":101}"
|
|
127
|
+
RESP=$(echo "$REQ" | node index.js 2>/dev/null | tail -1)
|
|
128
|
+
USER_ID=$(echo "$RESP" | jq -r '.result.content[0].text' | jq -r '.user_id')
|
|
129
|
+
if [ -n "$USER_ID" ] && [ "$USER_ID" != "null" ]; then
|
|
130
|
+
# Try to create duplicate
|
|
131
|
+
RESP2=$(echo "$REQ" | node index.js 2>/dev/null | tail -1)
|
|
132
|
+
CONTENT2=$(echo "$RESP2" | jq -r '.result.content[0].text')
|
|
133
|
+
if echo "$CONTENT2" | grep -qiE "error|exists|duplicate|already"; then
|
|
134
|
+
echo "✅ Test 17: Duplicate user rejected"
|
|
135
|
+
PASSED=$((PASSED + 1))
|
|
136
|
+
else
|
|
137
|
+
echo "❌ Test 17: Should reject duplicate user"
|
|
138
|
+
FAILED=$((FAILED + 1))
|
|
139
|
+
fi
|
|
140
|
+
else
|
|
141
|
+
echo "⚠️ Test 17: Couldn't create first user for duplicate test"
|
|
142
|
+
FAILED=$((FAILED + 1))
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
# Test 18: Response format validation
|
|
146
|
+
echo "Test 18: Response format validation"
|
|
147
|
+
RESP_EMAIL="resptest-$(date +%s)@example.com"
|
|
148
|
+
REQ="{\"jsonrpc\":\"2.0\",\"method\":\"tools/call\",\"params\":{\"name\":\"mlgym_user_create\",\"arguments\":{\"email\":\"$RESP_EMAIL\",\"name\":\"Response Test User\",\"password\":\"MyV3ryC0mpl3x!P@ssw0rd#2024\",\"accept_terms\":true}},\"id\":102}"
|
|
149
|
+
RESP=$(echo "$REQ" | node index.js 2>/dev/null | tail -1)
|
|
150
|
+
CONTENT=$(echo "$RESP" | jq -r '.result.content[0].text')
|
|
151
|
+
HAS_USER_ID=$(echo "$CONTENT" | jq -e '.user_id' > /dev/null 2>&1 && echo "yes" || echo "no")
|
|
152
|
+
HAS_EMAIL=$(echo "$CONTENT" | jq -e '.email' > /dev/null 2>&1 && echo "yes" || echo "no")
|
|
153
|
+
HAS_NAME=$(echo "$CONTENT" | jq -e '.name' > /dev/null 2>&1 && echo "yes" || echo "no")
|
|
154
|
+
HAS_TOKEN=$(echo "$CONTENT" | jq -e '.token' > /dev/null 2>&1 && echo "yes" || echo "no")
|
|
155
|
+
HAS_SSH=$(echo "$CONTENT" | jq -e '.ssh_key_path' > /dev/null 2>&1 && echo "yes" || echo "no")
|
|
156
|
+
if [ "$HAS_USER_ID" = "yes" ] && [ "$HAS_EMAIL" = "yes" ] && [ "$HAS_NAME" = "yes" ] && [ "$HAS_TOKEN" = "yes" ] && [ "$HAS_SSH" = "yes" ]; then
|
|
157
|
+
echo "✅ Test 18: Response format valid"
|
|
158
|
+
PASSED=$((PASSED + 1))
|
|
159
|
+
else
|
|
160
|
+
echo "❌ Test 18: Response format invalid (user_id:$HAS_USER_ID, email:$HAS_EMAIL, name:$HAS_NAME, token:$HAS_TOKEN, ssh:$HAS_SSH)"
|
|
161
|
+
FAILED=$((FAILED + 1))
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
# Test 19: SSH key generation verification
|
|
165
|
+
echo "Test 19: SSH key generation verification"
|
|
166
|
+
SSH_PATH=$(echo "$CONTENT" | jq -r '.ssh_key_path')
|
|
167
|
+
if [ -f "$SSH_PATH" ]; then
|
|
168
|
+
echo "✅ Test 19: SSH key file created at $SSH_PATH"
|
|
169
|
+
PASSED=$((PASSED + 1))
|
|
170
|
+
else
|
|
171
|
+
echo "❌ Test 19: SSH key file not found at $SSH_PATH"
|
|
172
|
+
FAILED=$((FAILED + 1))
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
# Test 20: Token storage verification
|
|
176
|
+
echo "Test 20: Token storage verification"
|
|
177
|
+
if [ -f ~/.mlgym/mcp_config.json ]; then
|
|
178
|
+
STORED_TOKEN=$(jq -r '.token' ~/.mlgym/mcp_config.json)
|
|
179
|
+
STORED_EMAIL=$(jq -r '.email' ~/.mlgym/mcp_config.json)
|
|
180
|
+
if [ -n "$STORED_TOKEN" ] && [ "$STORED_TOKEN" != "null" ]; then
|
|
181
|
+
echo "✅ Test 20: Token stored correctly (email: $STORED_EMAIL)"
|
|
182
|
+
PASSED=$((PASSED + 1))
|
|
183
|
+
else
|
|
184
|
+
echo "❌ Test 20: Token not stored properly"
|
|
185
|
+
FAILED=$((FAILED + 1))
|
|
186
|
+
fi
|
|
187
|
+
else
|
|
188
|
+
echo "❌ Test 20: Config file not created"
|
|
189
|
+
FAILED=$((FAILED + 1))
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
echo ""
|
|
193
|
+
echo "==============================================="
|
|
194
|
+
echo "RESULTS: $PASSED passed, $FAILED failed (Total: $((PASSED + FAILED)))"
|
|
195
|
+
echo "==============================================="
|
|
196
|
+
|
|
197
|
+
if [ $FAILED -eq 0 ]; then
|
|
198
|
+
echo "✅ ALL TESTS PASSED"
|
|
199
|
+
exit 0
|
|
200
|
+
else
|
|
201
|
+
echo "⚠️ SOME TESTS FAILED"
|
|
202
|
+
exit 1
|
|
203
|
+
fi
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Master test runner for all MCP functions
|
|
3
|
+
# Runs all individual test files and provides summary
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
cd "$SCRIPT_DIR/.."
|
|
9
|
+
|
|
10
|
+
TOTAL_TESTS=0
|
|
11
|
+
PASSED_TESTS=0
|
|
12
|
+
FAILED_TESTS=0
|
|
13
|
+
|
|
14
|
+
echo "=========================================="
|
|
15
|
+
echo "MCP Server Comprehensive Test Suite"
|
|
16
|
+
echo "=========================================="
|
|
17
|
+
echo ""
|
|
18
|
+
|
|
19
|
+
# Function to run individual test
|
|
20
|
+
run_test() {
|
|
21
|
+
local test_file="$1"
|
|
22
|
+
local test_name=$(basename "$test_file" .sh)
|
|
23
|
+
|
|
24
|
+
echo "----------------------------------------"
|
|
25
|
+
echo "Running: $test_name"
|
|
26
|
+
echo "----------------------------------------"
|
|
27
|
+
|
|
28
|
+
if "$SCRIPT_DIR/$test_file"; then
|
|
29
|
+
echo "✅ $test_name: PASSED"
|
|
30
|
+
PASSED_TESTS=$((PASSED_TESTS + 1))
|
|
31
|
+
else
|
|
32
|
+
echo "❌ $test_name: FAILED"
|
|
33
|
+
FAILED_TESTS=$((FAILED_TESTS + 1))
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
TOTAL_TESTS=$((TOTAL_TESTS + 1))
|
|
37
|
+
echo ""
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# Run all individual tests
|
|
41
|
+
run_test "mlgym_auth_login_test.sh"
|
|
42
|
+
run_test "mlgym_user_create_test.sh"
|
|
43
|
+
run_test "mlgym_auth_logout_test.sh"
|
|
44
|
+
run_test "mlgym_project_init_test.sh"
|
|
45
|
+
run_test "mlgym_projects_list_test.sh"
|
|
46
|
+
run_test "mlgym_projects_get_test.sh"
|
|
47
|
+
|
|
48
|
+
# Summary
|
|
49
|
+
echo "=========================================="
|
|
50
|
+
echo "TEST SUMMARY"
|
|
51
|
+
echo "=========================================="
|
|
52
|
+
echo "Total test suites: $TOTAL_TESTS"
|
|
53
|
+
echo "Passed: $PASSED_TESTS"
|
|
54
|
+
echo "Failed: $FAILED_TESTS"
|
|
55
|
+
echo "=========================================="
|
|
56
|
+
|
|
57
|
+
if [ $FAILED_TESTS -eq 0 ]; then
|
|
58
|
+
echo "✅ ALL TEST SUITES PASSED"
|
|
59
|
+
exit 0
|
|
60
|
+
else
|
|
61
|
+
echo "❌ SOME TEST SUITES FAILED"
|
|
62
|
+
exit 1
|
|
63
|
+
fi
|