@runhuman/mcp-server 2.0.4 → 2.0.5
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/.env.example +12 -12
- package/README.md +243 -243
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp-server-factory.js +1 -1
- package/dist/tools/create-job.tool.d.ts.map +1 -1
- package/dist/tools/create-job.tool.js +52 -47
- package/dist/tools/create-job.tool.js.map +1 -1
- package/dist/tools/wait-for-result.tool.d.ts.map +1 -1
- package/dist/tools/wait-for-result.tool.js +99 -64
- package/dist/tools/wait-for-result.tool.js.map +1 -1
- package/dist/types.d.ts +3 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +78 -78
package/.env.example
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
# API Base URL
|
|
4
|
-
# For local development, use http://localhost:3400
|
|
5
|
-
# For production, use your deployed API URL
|
|
6
|
-
RUNHUMAN_API_URL=http://localhost:3400
|
|
7
|
-
|
|
8
|
-
# API Key
|
|
9
|
-
# Get this from the API dashboard at http://localhost:3400/app.html
|
|
10
|
-
# Or use the default test key below for local development
|
|
11
|
-
# Format: qa_live_xxxxxxxxxxxxxxxxxxxxx
|
|
12
|
-
RUNHUMAN_API_KEY=qa_live_test_key_for_demo_purposes_only_12345
|
|
1
|
+
# Runhuman API Configuration
|
|
2
|
+
|
|
3
|
+
# API Base URL
|
|
4
|
+
# For local development, use http://localhost:3400
|
|
5
|
+
# For production, use your deployed API URL
|
|
6
|
+
RUNHUMAN_API_URL=http://localhost:3400
|
|
7
|
+
|
|
8
|
+
# API Key
|
|
9
|
+
# Get this from the API dashboard at http://localhost:3400/app.html
|
|
10
|
+
# Or use the default test key below for local development
|
|
11
|
+
# Format: qa_live_xxxxxxxxxxxxxxxxxxxxx
|
|
12
|
+
RUNHUMAN_API_KEY=qa_live_test_key_for_demo_purposes_only_12345
|
package/README.md
CHANGED
|
@@ -1,243 +1,243 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
A Model Context Protocol (MCP) server that allows AI agents to interact with the
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
This MCP server provides tools for creating and managing human QA jobs through the
|
|
8
|
-
|
|
9
|
-
- Create new QA jobs with custom schemas
|
|
10
|
-
- Check the status of running jobs
|
|
11
|
-
- Retrieve completed job results
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
### For Claude Desktop (Recommended)
|
|
16
|
-
|
|
17
|
-
1. Get your API key at: https://runhuman.com/dashboard/api-keys
|
|
18
|
-
|
|
19
|
-
2. Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on Mac):
|
|
20
|
-
|
|
21
|
-
```json
|
|
22
|
-
{
|
|
23
|
-
"mcpServers": {
|
|
24
|
-
"runhuman": {
|
|
25
|
-
"command": "npx",
|
|
26
|
-
"args": ["-y", "@runhuman/mcp-server", "--api-key=qa_live_xxxxxxxxxxxxx"]
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
3. Restart Claude Desktop
|
|
33
|
-
|
|
34
|
-
That's it! The server will be automatically downloaded and run by Claude.
|
|
35
|
-
|
|
36
|
-
### For Development
|
|
37
|
-
|
|
38
|
-
From the monorepo root:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npm install
|
|
42
|
-
npm run build --workspace=@runhuman/mcp-server
|
|
43
|
-
|
|
44
|
-
# Run with API key
|
|
45
|
-
node packages/mcp-server/dist/index.js --api-key=qa_live_xxxxx
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Available Tools
|
|
49
|
-
|
|
50
|
-
#### `create_job`
|
|
51
|
-
Create a new QA job with human testers.
|
|
52
|
-
|
|
53
|
-
**Parameters:**
|
|
54
|
-
- `url` (string): The URL to test
|
|
55
|
-
- `description` (string): Instructions for the human tester describing what to test
|
|
56
|
-
- `schema` (object): Expected result schema that the tester response will be extracted into
|
|
57
|
-
- `targetDurationMinutes` (number, optional): Time limit for tester (default: 5, range: 1-60)
|
|
58
|
-
|
|
59
|
-
#### `wait_for_result`
|
|
60
|
-
Check status, wait, and retrieve results for a QA job in a single convenient call.
|
|
61
|
-
|
|
62
|
-
**Parameters:**
|
|
63
|
-
- `jobId` (string): The ID of the job to check
|
|
64
|
-
- `waitSeconds` (number, optional): How long to wait before checking again (default: 30, range: 1-300)
|
|
65
|
-
|
|
66
|
-
**Behavior:**
|
|
67
|
-
- Checks status BEFORE waiting (returns immediately if already complete)
|
|
68
|
-
- Waits for the specified duration
|
|
69
|
-
- Checks status AFTER waiting
|
|
70
|
-
- Returns results if complete, otherwise suggests calling again with longer wait time
|
|
71
|
-
|
|
72
|
-
**Usage Pattern:**
|
|
73
|
-
```javascript
|
|
74
|
-
// After creating a job, call repeatedly with increasing wait times:
|
|
75
|
-
let result = await wait_for_result(jobId, { waitSeconds: 30 });
|
|
76
|
-
if (result.status !== 'completed') {
|
|
77
|
-
result = await wait_for_result(jobId, { waitSeconds: 45 });
|
|
78
|
-
}
|
|
79
|
-
if (result.status !== 'completed') {
|
|
80
|
-
result = await wait_for_result(jobId, { waitSeconds: 60 });
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
**Returns:**
|
|
85
|
-
- `result`: Structured test results extracted from tester's response
|
|
86
|
-
- `status`: Job status (completed, failed, timeout, pending, claimed, in_progress)
|
|
87
|
-
- `costUsd`: Exact cost in USD with full precision (e.g., 0.396)
|
|
88
|
-
- `testDurationSeconds`: Time spent by tester in seconds (rounded up)
|
|
89
|
-
- `testerResponse`: Raw natural language feedback from the human tester
|
|
90
|
-
- `testerAlias`: Anonymized tester name (e.g., "Tester Alpha")
|
|
91
|
-
- `testerAvatarUrl`: Avatar image URL for UI display
|
|
92
|
-
- `testerColor`: Hex color code for theming (e.g., "#4A90E2")
|
|
93
|
-
- Additional metadata (timestamps, etc.)
|
|
94
|
-
|
|
95
|
-
**Cost Calculation:**
|
|
96
|
-
- Costs are calculated as: `duration × $0.0018/second` (general-use tier)
|
|
97
|
-
- Duration is always rounded UP using Math.ceil (any partial second counts)
|
|
98
|
-
- Costs are never $0 unless the tester never actually worked on it
|
|
99
|
-
- Full precision maintained (not rounded to cents)
|
|
100
|
-
|
|
101
|
-
## Configuration
|
|
102
|
-
|
|
103
|
-
The MCP server needs to be configured with your
|
|
104
|
-
|
|
105
|
-
### 1. Get an API Key
|
|
106
|
-
|
|
107
|
-
**Option A: Via Dashboard**
|
|
108
|
-
1. Start the API server: `npm run dev --workspace=@runhuman/api`
|
|
109
|
-
2. Open http://localhost:3400/api-keys
|
|
110
|
-
3. Click "Create API Key"
|
|
111
|
-
4. Copy the key (starts with `qa_live_`)
|
|
112
|
-
|
|
113
|
-
**Option B: Use Default Test Key**
|
|
114
|
-
- For local development, you can use: `qa_live_test_key_123`
|
|
115
|
-
- This key exists in `packages/api/data/api-keys.json`
|
|
116
|
-
|
|
117
|
-
### 2. Configure Environment Variables
|
|
118
|
-
|
|
119
|
-
Create a `.env` file in the MCP server directory:
|
|
120
|
-
|
|
121
|
-
```bash
|
|
122
|
-
# For local development
|
|
123
|
-
RUNHUMAN_API_URL=http://localhost:3400
|
|
124
|
-
RUNHUMAN_API_KEY=qa_live_test_key_123
|
|
125
|
-
|
|
126
|
-
# For production
|
|
127
|
-
RUNHUMAN_API_URL=https://api.runhuman.com
|
|
128
|
-
RUNHUMAN_API_KEY=qa_live_xxxxxxxxxxxxxxxxxxxxx
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
**Important:** Never commit `.env` files to git! They're already in `.gitignore`.
|
|
132
|
-
|
|
133
|
-
### 3. Verify Configuration
|
|
134
|
-
|
|
135
|
-
Test your API key works:
|
|
136
|
-
|
|
137
|
-
```bash
|
|
138
|
-
curl http://localhost:3400/api/jobs \
|
|
139
|
-
-H "Authorization: Bearer qa_live_test_key_123" \
|
|
140
|
-
-H "Content-Type: application/json" \
|
|
141
|
-
-d '{"url":"https://example.com","description":"test","outputSchema":{}}'
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
Should return a job ID if authentication works.
|
|
145
|
-
|
|
146
|
-
For more details, see [docs/API-AUTHENTICATION.md](docs/API-AUTHENTICATION.md)
|
|
147
|
-
|
|
148
|
-
## Testing
|
|
149
|
-
|
|
150
|
-
The MCP server includes automated tests to verify it's working correctly:
|
|
151
|
-
|
|
152
|
-
```bash
|
|
153
|
-
# Build first
|
|
154
|
-
npm run build --workspace=@runhuman/mcp-server
|
|
155
|
-
|
|
156
|
-
# Run simple automated test
|
|
157
|
-
npm run test --workspace=@runhuman/mcp-server
|
|
158
|
-
|
|
159
|
-
# Or use the MCP Inspector (interactive testing)
|
|
160
|
-
npm run test:inspector --workspace=@runhuman/mcp-server
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
The test script will:
|
|
164
|
-
1. ✅ Initialize a connection to the MCP server
|
|
165
|
-
2. ✅ List all available tools (create_job, wait_for_result)
|
|
166
|
-
3. ✅ Test calling the create_job tool
|
|
167
|
-
|
|
168
|
-
### Expected Test Output
|
|
169
|
-
|
|
170
|
-
```
|
|
171
|
-
✅ Server initialized successfully
|
|
172
|
-
✅ Tools listed: create_job, wait_for_result
|
|
173
|
-
✅ create_job tool called successfully
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## Development
|
|
177
|
-
|
|
178
|
-
```bash
|
|
179
|
-
# Watch mode (auto-rebuild on changes)
|
|
180
|
-
npm run dev --workspace=@runhuman/mcp-server
|
|
181
|
-
|
|
182
|
-
# Build
|
|
183
|
-
npm run build --workspace=@runhuman/mcp-server
|
|
184
|
-
|
|
185
|
-
# Test after building
|
|
186
|
-
npm run test --workspace=@runhuman/mcp-server
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
## Integration with Claude Desktop
|
|
190
|
-
|
|
191
|
-
To use this MCP server with Claude Desktop, add it to your configuration:
|
|
192
|
-
|
|
193
|
-
```json
|
|
194
|
-
{
|
|
195
|
-
"mcpServers": {
|
|
196
|
-
"runhuman": {
|
|
197
|
-
"command": "node",
|
|
198
|
-
"args": ["/path/to/qa-experiment/packages/mcp-server/dist/index.js"]
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
## Example Usage
|
|
205
|
-
|
|
206
|
-
Once connected to an AI agent (like Claude), the agent can use these tools naturally:
|
|
207
|
-
|
|
208
|
-
**User:** "Can someone test my checkout page at https://myapp.com/checkout?"
|
|
209
|
-
|
|
210
|
-
**Agent uses create_job:**
|
|
211
|
-
```
|
|
212
|
-
✅ Job created successfully!
|
|
213
|
-
Job ID: job_abc123
|
|
214
|
-
Status: pending
|
|
215
|
-
...
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
**Agent calls wait_for_result repeatedly until complete:**
|
|
219
|
-
```
|
|
220
|
-
⏳ Job Status: in_progress
|
|
221
|
-
Waited 30s, job not complete yet.
|
|
222
|
-
💡 Suggestion: Call wait_for_result again with waitSeconds: 45
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
**Finally:**
|
|
226
|
-
```
|
|
227
|
-
✅ Test completed!
|
|
228
|
-
Results Summary:
|
|
229
|
-
- Checkout Flow: ✅ Working
|
|
230
|
-
- Payment Processing: ✅ Successful
|
|
231
|
-
...
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
## Developer Documentation
|
|
235
|
-
|
|
236
|
-
For developers working on this MCP server:
|
|
237
|
-
- [docs/HOW-AGENTS-USE-MCP.md](docs/HOW-AGENTS-USE-MCP.md) - How AI agents discover and use MCP servers
|
|
238
|
-
- [docs/TOOL-RESPONSE-BEST-PRACTICES.md](docs/TOOL-RESPONSE-BEST-PRACTICES.md) - Best practices for tool responses
|
|
239
|
-
|
|
240
|
-
## Learn More
|
|
241
|
-
|
|
242
|
-
- [Model Context Protocol Documentation](https://modelcontextprotocol.io/)
|
|
243
|
-
- [
|
|
1
|
+
# Runhuman MCP Server
|
|
2
|
+
|
|
3
|
+
A Model Context Protocol (MCP) server that allows AI agents to interact with the Runhuman QA testing service.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This MCP server provides tools for creating and managing human QA jobs through the Runhuman API. AI agents can use this server to:
|
|
8
|
+
|
|
9
|
+
- Create new QA jobs with custom schemas
|
|
10
|
+
- Check the status of running jobs
|
|
11
|
+
- Retrieve completed job results
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
### For Claude Desktop (Recommended)
|
|
16
|
+
|
|
17
|
+
1. Get your API key at: https://runhuman.com/dashboard/api-keys
|
|
18
|
+
|
|
19
|
+
2. Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on Mac):
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"runhuman": {
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "@runhuman/mcp-server", "--api-key=qa_live_xxxxxxxxxxxxx"]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
3. Restart Claude Desktop
|
|
33
|
+
|
|
34
|
+
That's it! The server will be automatically downloaded and run by Claude.
|
|
35
|
+
|
|
36
|
+
### For Development
|
|
37
|
+
|
|
38
|
+
From the monorepo root:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install
|
|
42
|
+
npm run build --workspace=@runhuman/mcp-server
|
|
43
|
+
|
|
44
|
+
# Run with API key
|
|
45
|
+
node packages/mcp-server/dist/index.js --api-key=qa_live_xxxxx
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Available Tools
|
|
49
|
+
|
|
50
|
+
#### `create_job`
|
|
51
|
+
Create a new QA job with human testers.
|
|
52
|
+
|
|
53
|
+
**Parameters:**
|
|
54
|
+
- `url` (string): The URL to test
|
|
55
|
+
- `description` (string): Instructions for the human tester describing what to test
|
|
56
|
+
- `schema` (object): Expected result schema that the tester response will be extracted into
|
|
57
|
+
- `targetDurationMinutes` (number, optional): Time limit for tester (default: 5, range: 1-60)
|
|
58
|
+
|
|
59
|
+
#### `wait_for_result`
|
|
60
|
+
Check status, wait, and retrieve results for a QA job in a single convenient call.
|
|
61
|
+
|
|
62
|
+
**Parameters:**
|
|
63
|
+
- `jobId` (string): The ID of the job to check
|
|
64
|
+
- `waitSeconds` (number, optional): How long to wait before checking again (default: 30, range: 1-300)
|
|
65
|
+
|
|
66
|
+
**Behavior:**
|
|
67
|
+
- Checks status BEFORE waiting (returns immediately if already complete)
|
|
68
|
+
- Waits for the specified duration
|
|
69
|
+
- Checks status AFTER waiting
|
|
70
|
+
- Returns results if complete, otherwise suggests calling again with longer wait time
|
|
71
|
+
|
|
72
|
+
**Usage Pattern:**
|
|
73
|
+
```javascript
|
|
74
|
+
// After creating a job, call repeatedly with increasing wait times:
|
|
75
|
+
let result = await wait_for_result(jobId, { waitSeconds: 30 });
|
|
76
|
+
if (result.status !== 'completed') {
|
|
77
|
+
result = await wait_for_result(jobId, { waitSeconds: 45 });
|
|
78
|
+
}
|
|
79
|
+
if (result.status !== 'completed') {
|
|
80
|
+
result = await wait_for_result(jobId, { waitSeconds: 60 });
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Returns:**
|
|
85
|
+
- `result`: Structured test results extracted from tester's response
|
|
86
|
+
- `status`: Job status (completed, failed, timeout, pending, claimed, in_progress)
|
|
87
|
+
- `costUsd`: Exact cost in USD with full precision (e.g., 0.396)
|
|
88
|
+
- `testDurationSeconds`: Time spent by tester in seconds (rounded up)
|
|
89
|
+
- `testerResponse`: Raw natural language feedback from the human tester
|
|
90
|
+
- `testerAlias`: Anonymized tester name (e.g., "Tester Alpha")
|
|
91
|
+
- `testerAvatarUrl`: Avatar image URL for UI display
|
|
92
|
+
- `testerColor`: Hex color code for theming (e.g., "#4A90E2")
|
|
93
|
+
- Additional metadata (timestamps, etc.)
|
|
94
|
+
|
|
95
|
+
**Cost Calculation:**
|
|
96
|
+
- Costs are calculated as: `duration × $0.0018/second` (general-use tier)
|
|
97
|
+
- Duration is always rounded UP using Math.ceil (any partial second counts)
|
|
98
|
+
- Costs are never $0 unless the tester never actually worked on it
|
|
99
|
+
- Full precision maintained (not rounded to cents)
|
|
100
|
+
|
|
101
|
+
## Configuration
|
|
102
|
+
|
|
103
|
+
The MCP server needs to be configured with your Runhuman API credentials.
|
|
104
|
+
|
|
105
|
+
### 1. Get an API Key
|
|
106
|
+
|
|
107
|
+
**Option A: Via Dashboard**
|
|
108
|
+
1. Start the API server: `npm run dev --workspace=@runhuman/api`
|
|
109
|
+
2. Open http://localhost:3400/api-keys
|
|
110
|
+
3. Click "Create API Key"
|
|
111
|
+
4. Copy the key (starts with `qa_live_`)
|
|
112
|
+
|
|
113
|
+
**Option B: Use Default Test Key**
|
|
114
|
+
- For local development, you can use: `qa_live_test_key_123`
|
|
115
|
+
- This key exists in `packages/api/data/api-keys.json`
|
|
116
|
+
|
|
117
|
+
### 2. Configure Environment Variables
|
|
118
|
+
|
|
119
|
+
Create a `.env` file in the MCP server directory:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
# For local development
|
|
123
|
+
RUNHUMAN_API_URL=http://localhost:3400
|
|
124
|
+
RUNHUMAN_API_KEY=qa_live_test_key_123
|
|
125
|
+
|
|
126
|
+
# For production
|
|
127
|
+
RUNHUMAN_API_URL=https://api.runhuman.com
|
|
128
|
+
RUNHUMAN_API_KEY=qa_live_xxxxxxxxxxxxxxxxxxxxx
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Important:** Never commit `.env` files to git! They're already in `.gitignore`.
|
|
132
|
+
|
|
133
|
+
### 3. Verify Configuration
|
|
134
|
+
|
|
135
|
+
Test your API key works:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
curl http://localhost:3400/api/jobs \
|
|
139
|
+
-H "Authorization: Bearer qa_live_test_key_123" \
|
|
140
|
+
-H "Content-Type: application/json" \
|
|
141
|
+
-d '{"url":"https://example.com","description":"test","outputSchema":{}}'
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Should return a job ID if authentication works.
|
|
145
|
+
|
|
146
|
+
For more details, see [docs/API-AUTHENTICATION.md](docs/API-AUTHENTICATION.md)
|
|
147
|
+
|
|
148
|
+
## Testing
|
|
149
|
+
|
|
150
|
+
The MCP server includes automated tests to verify it's working correctly:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Build first
|
|
154
|
+
npm run build --workspace=@runhuman/mcp-server
|
|
155
|
+
|
|
156
|
+
# Run simple automated test
|
|
157
|
+
npm run test --workspace=@runhuman/mcp-server
|
|
158
|
+
|
|
159
|
+
# Or use the MCP Inspector (interactive testing)
|
|
160
|
+
npm run test:inspector --workspace=@runhuman/mcp-server
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
The test script will:
|
|
164
|
+
1. ✅ Initialize a connection to the MCP server
|
|
165
|
+
2. ✅ List all available tools (create_job, wait_for_result)
|
|
166
|
+
3. ✅ Test calling the create_job tool
|
|
167
|
+
|
|
168
|
+
### Expected Test Output
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
✅ Server initialized successfully
|
|
172
|
+
✅ Tools listed: create_job, wait_for_result
|
|
173
|
+
✅ create_job tool called successfully
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Development
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Watch mode (auto-rebuild on changes)
|
|
180
|
+
npm run dev --workspace=@runhuman/mcp-server
|
|
181
|
+
|
|
182
|
+
# Build
|
|
183
|
+
npm run build --workspace=@runhuman/mcp-server
|
|
184
|
+
|
|
185
|
+
# Test after building
|
|
186
|
+
npm run test --workspace=@runhuman/mcp-server
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Integration with Claude Desktop
|
|
190
|
+
|
|
191
|
+
To use this MCP server with Claude Desktop, add it to your configuration:
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{
|
|
195
|
+
"mcpServers": {
|
|
196
|
+
"runhuman": {
|
|
197
|
+
"command": "node",
|
|
198
|
+
"args": ["/path/to/qa-experiment/packages/mcp-server/dist/index.js"]
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Example Usage
|
|
205
|
+
|
|
206
|
+
Once connected to an AI agent (like Claude), the agent can use these tools naturally:
|
|
207
|
+
|
|
208
|
+
**User:** "Can someone test my checkout page at https://myapp.com/checkout?"
|
|
209
|
+
|
|
210
|
+
**Agent uses create_job:**
|
|
211
|
+
```
|
|
212
|
+
✅ Job created successfully!
|
|
213
|
+
Job ID: job_abc123
|
|
214
|
+
Status: pending
|
|
215
|
+
...
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**Agent calls wait_for_result repeatedly until complete:**
|
|
219
|
+
```
|
|
220
|
+
⏳ Job Status: in_progress
|
|
221
|
+
Waited 30s, job not complete yet.
|
|
222
|
+
💡 Suggestion: Call wait_for_result again with waitSeconds: 45
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**Finally:**
|
|
226
|
+
```
|
|
227
|
+
✅ Test completed!
|
|
228
|
+
Results Summary:
|
|
229
|
+
- Checkout Flow: ✅ Working
|
|
230
|
+
- Payment Processing: ✅ Successful
|
|
231
|
+
...
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Developer Documentation
|
|
235
|
+
|
|
236
|
+
For developers working on this MCP server:
|
|
237
|
+
- [docs/HOW-AGENTS-USE-MCP.md](docs/HOW-AGENTS-USE-MCP.md) - How AI agents discover and use MCP servers
|
|
238
|
+
- [docs/TOOL-RESPONSE-BEST-PRACTICES.md](docs/TOOL-RESPONSE-BEST-PRACTICES.md) - Best practices for tool responses
|
|
239
|
+
|
|
240
|
+
## Learn More
|
|
241
|
+
|
|
242
|
+
- [Model Context Protocol Documentation](https://modelcontextprotocol.io/)
|
|
243
|
+
- [Runhuman API Documentation](../api/README.md)
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Runhuman MCP Server - stdio entry point
|
|
4
4
|
*
|
|
5
5
|
* This is the CLI entry point for npx @runhuman/mcp-server.
|
|
6
6
|
* It uses stdio transport for communication with MCP clients like Claude Desktop.
|
|
@@ -21,7 +21,7 @@ const apiUrlArg = args.find(arg => arg.startsWith('--api-url='))?.split('=')[1];
|
|
|
21
21
|
const API_URL = apiUrlArg || process.env.RUNHUMAN_API_URL || 'https://qa-experiment.fly.dev';
|
|
22
22
|
const API_KEY = apiKeyArg || process.env.RUNHUMAN_API_KEY;
|
|
23
23
|
if (!API_KEY) {
|
|
24
|
-
console.error('
|
|
24
|
+
console.error('Error: API key is required');
|
|
25
25
|
console.error('');
|
|
26
26
|
console.error('For Claude Desktop, add to your config:');
|
|
27
27
|
console.error('{');
|
|
@@ -36,8 +36,8 @@ if (!API_KEY) {
|
|
|
36
36
|
console.error('Get your API key at: https://qa-experiment.fly.dev/app.html');
|
|
37
37
|
process.exit(1);
|
|
38
38
|
}
|
|
39
|
-
console.error(
|
|
40
|
-
console.error(
|
|
39
|
+
console.error(`Connected to Runhuman API at: ${API_URL}`);
|
|
40
|
+
console.error(`Using API key: ${API_KEY.substring(0, 12)}...`);
|
|
41
41
|
// Create the MCP server with configuration
|
|
42
42
|
const server = createMcpServer({
|
|
43
43
|
apiUrl: API_URL,
|
|
@@ -49,7 +49,7 @@ const server = createMcpServer({
|
|
|
49
49
|
async function main() {
|
|
50
50
|
const transport = new StdioServerTransport();
|
|
51
51
|
await server.connect(transport);
|
|
52
|
-
console.error('
|
|
52
|
+
console.error('Runhuman MCP server running on stdio');
|
|
53
53
|
}
|
|
54
54
|
main().catch((error) => {
|
|
55
55
|
console.error('Server error:', error);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,iEAAiE;AACjE,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,gBAAgB;AAChB,2CAA2C;AAC3C,0EAA0E;AAC1E,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAChF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhF,MAAM,OAAO,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,+BAA+B,CAAC;AAC7F,MAAM,OAAO,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAE1D,IAAI,CAAC,OAAO,EAAE,CAAC;IACb,OAAO,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;GAOG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,iEAAiE;AACjE,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,gBAAgB;AAChB,2CAA2C;AAC3C,0EAA0E;AAC1E,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAChF,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhF,MAAM,OAAO,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,+BAA+B,CAAC;AAC7F,MAAM,OAAO,GAAG,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAE1D,IAAI,CAAC,OAAO,EAAE,CAAC;IACb,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC5C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClB,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACzD,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACnC,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACnC,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACzC,OAAO,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;IACzF,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClB,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;IAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,CAAC,KAAK,CAAC,iCAAiC,OAAO,EAAE,CAAC,CAAC;AAC1D,OAAO,CAAC,KAAK,CAAC,kBAAkB,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AAE/D,2CAA2C;AAC3C,MAAM,MAAM,GAAG,eAAe,CAAC;IAC7B,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,OAAO;CAChB,CAAC,CAAC;AAEH;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;AACxD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -22,7 +22,7 @@ export function createMcpServer(config) {
|
|
|
22
22
|
prompts: [
|
|
23
23
|
{
|
|
24
24
|
name: 'explain_runhuman',
|
|
25
|
-
description: 'Get an explanation of how to use
|
|
25
|
+
description: 'Get an explanation of how to use Runhuman for QA testing',
|
|
26
26
|
},
|
|
27
27
|
],
|
|
28
28
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-job.tool.d.ts","sourceRoot":"","sources":["../../src/tools/create-job.tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAqB,MAAM,aAAa,CAAC;AAErF,eAAO,MAAM,uBAAuB,EAAE,
|
|
1
|
+
{"version":3,"file":"create-job.tool.d.ts","sourceRoot":"","sources":["../../src/tools/create-job.tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAqB,MAAM,aAAa,CAAC;AAErF,eAAO,MAAM,uBAAuB,EAAE,IAqDrC,CAAC;AAEF,wBAAsB,eAAe,CACnC,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAiFhF"}
|
|
@@ -3,22 +3,22 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const createJobToolDefinition = {
|
|
5
5
|
name: 'create_job',
|
|
6
|
-
description:
|
|
7
|
-
|
|
8
|
-
Creates a QA job that will be performed by a REAL HUMAN tester (not AI). The human will manually test your application, describe findings in natural language, and GPT-4o will extract structured data from their response.
|
|
9
|
-
|
|
10
|
-
Use this when you need human verification of:
|
|
11
|
-
- UI/UX functionality that's hard to automate
|
|
12
|
-
- Visual issues, accessibility problems
|
|
13
|
-
- Complex user flows (login, checkout, forms)
|
|
14
|
-
- Cross-browser compatibility
|
|
15
|
-
- Real user experience feedback
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
1. create_job → Returns jobId (job is now QUEUED, not complete!)
|
|
19
|
-
2. wait_for_result → Checks status, waits, and retrieves results (takes 2-10 min total)
|
|
20
|
-
3. If not complete, call wait_for_result again with longer wait time
|
|
21
|
-
|
|
6
|
+
description: `IMPORTANT: This ONLY creates and queues a job. It does NOT perform the test or return results. You MUST follow up with wait_for_result.
|
|
7
|
+
|
|
8
|
+
Creates a QA job that will be performed by a REAL HUMAN tester (not AI). The human will manually test your application, describe findings in natural language, and GPT-4o will extract structured data from their response.
|
|
9
|
+
|
|
10
|
+
Use this when you need human verification of:
|
|
11
|
+
- UI/UX functionality that's hard to automate
|
|
12
|
+
- Visual issues, accessibility problems
|
|
13
|
+
- Complex user flows (login, checkout, forms)
|
|
14
|
+
- Cross-browser compatibility
|
|
15
|
+
- Real user experience feedback
|
|
16
|
+
|
|
17
|
+
REQUIRED WORKFLOW (do NOT skip steps):
|
|
18
|
+
1. create_job → Returns jobId (job is now QUEUED, not complete!)
|
|
19
|
+
2. wait_for_result → Checks status, waits, and retrieves results (takes 2-10 min total)
|
|
20
|
+
3. If not complete, call wait_for_result again with longer wait time
|
|
21
|
+
|
|
22
22
|
DO NOT treat job creation as completion. You MUST wait for and retrieve results.`,
|
|
23
23
|
inputSchema: {
|
|
24
24
|
type: 'object',
|
|
@@ -47,6 +47,10 @@ DO NOT treat job creation as completion. You MUST wait for and retrieve results.
|
|
|
47
47
|
type: ['number', 'boolean'],
|
|
48
48
|
description: 'Maximum additional minutes allowed for extension. Set to false for unlimited. Default: false (unlimited). Range: 1-60 if number.',
|
|
49
49
|
},
|
|
50
|
+
additionalValidationInstructions: {
|
|
51
|
+
type: 'string',
|
|
52
|
+
description: 'Optional custom instructions for the AI when validating test results. Use this to specify what to focus on, what to ignore, or how to interpret specific scenarios. Example: "Ignore minor UI glitches in the header. Only mark as failed if the core checkout functionality does not work."',
|
|
53
|
+
},
|
|
50
54
|
},
|
|
51
55
|
required: ['url', 'description', 'schema'],
|
|
52
56
|
},
|
|
@@ -67,6 +71,7 @@ export async function handleCreateJob(args, config) {
|
|
|
67
71
|
targetDurationMinutes: args.targetDurationMinutes,
|
|
68
72
|
allowDurationExtension: args.allowDurationExtension,
|
|
69
73
|
maxExtensionMinutes: args.maxExtensionMinutes,
|
|
74
|
+
additionalValidationInstructions: args.additionalValidationInstructions,
|
|
70
75
|
}),
|
|
71
76
|
});
|
|
72
77
|
if (!response.ok) {
|
|
@@ -74,14 +79,14 @@ export async function handleCreateJob(args, config) {
|
|
|
74
79
|
return {
|
|
75
80
|
content: [{
|
|
76
81
|
type: 'text',
|
|
77
|
-
text:
|
|
78
|
-
|
|
79
|
-
Error: ${error.error || error.message || response.statusText}
|
|
80
|
-
Status: ${response.status}
|
|
81
|
-
|
|
82
|
-
Please check:
|
|
83
|
-
- Your RUNHUMAN_API_KEY is valid
|
|
84
|
-
- The API server is running at ${apiUrl}
|
|
82
|
+
text: `Failed to create job
|
|
83
|
+
|
|
84
|
+
Error: ${error.error || error.message || response.statusText}
|
|
85
|
+
Status: ${response.status}
|
|
86
|
+
|
|
87
|
+
Please check:
|
|
88
|
+
- Your RUNHUMAN_API_KEY is valid
|
|
89
|
+
- The API server is running at ${apiUrl}
|
|
85
90
|
- Your API key has permission to create jobs`,
|
|
86
91
|
}],
|
|
87
92
|
isError: true,
|
|
@@ -92,22 +97,22 @@ Please check:
|
|
|
92
97
|
return {
|
|
93
98
|
content: [{
|
|
94
99
|
type: 'text',
|
|
95
|
-
text:
|
|
96
|
-
|
|
97
|
-
Job ID: ${data.jobId}
|
|
98
|
-
Status: ${data.status}
|
|
99
|
-
URL: ${args.url}
|
|
100
|
-
Time limit: ${duration} minutes
|
|
101
|
-
|
|
102
|
-
The test has been queued for a HUMAN tester. It is NOT complete yet.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
1. Call wait_for_result(jobId: "${data.jobId}", waitSeconds: 30)
|
|
106
|
-
2. If not complete, call wait_for_result again with waitSeconds: 45
|
|
107
|
-
3. Continue with increasing wait times (60, 90, etc.) until complete
|
|
108
|
-
|
|
109
|
-
Typical completion time: 2-10 minutes total.
|
|
110
|
-
|
|
100
|
+
text: `Job QUEUED (not complete yet!)
|
|
101
|
+
|
|
102
|
+
Job ID: ${data.jobId}
|
|
103
|
+
Status: ${data.status}
|
|
104
|
+
URL: ${args.url}
|
|
105
|
+
Time limit: ${duration} minutes
|
|
106
|
+
|
|
107
|
+
The test has been queued for a HUMAN tester. It is NOT complete yet.
|
|
108
|
+
|
|
109
|
+
REQUIRED NEXT STEPS:
|
|
110
|
+
1. Call wait_for_result(jobId: "${data.jobId}", waitSeconds: 30)
|
|
111
|
+
2. If not complete, call wait_for_result again with waitSeconds: 45
|
|
112
|
+
3. Continue with increasing wait times (60, 90, etc.) until complete
|
|
113
|
+
|
|
114
|
+
Typical completion time: 2-10 minutes total.
|
|
115
|
+
|
|
111
116
|
DO NOT consider this task done until you have retrieved the results!`,
|
|
112
117
|
}],
|
|
113
118
|
};
|
|
@@ -116,13 +121,13 @@ DO NOT consider this task done until you have retrieved the results!`,
|
|
|
116
121
|
return {
|
|
117
122
|
content: [{
|
|
118
123
|
type: 'text',
|
|
119
|
-
text:
|
|
120
|
-
|
|
121
|
-
${error instanceof Error ? error.message : 'Unknown error'}
|
|
122
|
-
|
|
123
|
-
Please check:
|
|
124
|
-
- The API server is running at ${apiUrl}
|
|
125
|
-
- Your network connection
|
|
124
|
+
text: `Error creating job
|
|
125
|
+
|
|
126
|
+
${error instanceof Error ? error.message : 'Unknown error'}
|
|
127
|
+
|
|
128
|
+
Please check:
|
|
129
|
+
- The API server is running at ${apiUrl}
|
|
130
|
+
- Your network connection
|
|
126
131
|
- Your .env file configuration`,
|
|
127
132
|
}],
|
|
128
133
|
isError: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-job.tool.js","sourceRoot":"","sources":["../../src/tools/create-job.tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,CAAC,MAAM,uBAAuB,GAAS;IAC3C,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE;;;;;;;;;;;;;;;;iFAgBkE;IAC/E,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,GAAG,EAAE;gBACH,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,sFAAsF;aACpG;YACD,WAAW,EAAE;gBACX,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,6PAA6P;aAC3Q;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,mRAAmR;aACjS;YACD,qBAAqB,EAAE;gBACrB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,4GAA4G;aAC1H;YACD,sBAAsB,EAAE;gBACtB,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE,mGAAmG;aACjH;YACD,mBAAmB,EAAE;gBACnB,IAAI,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;gBAC3B,WAAW,EAAE,kIAAkI;aAChJ;SACF;QACD,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,CAAC;KAC3C;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAmB,EACnB,MAAuB;IAEvB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAElC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,WAAW,EAAE;YACjD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,MAAM,EAAE;gBACnC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,YAAY,EAAE,IAAI,CAAC,MAAM;gBACzB,qBAAqB,EAAE,IAAI,CAAC,qBAAqB;gBACjD,sBAAsB,EAAE,IAAI,CAAC,sBAAsB;gBACnD,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;
|
|
1
|
+
{"version":3,"file":"create-job.tool.js","sourceRoot":"","sources":["../../src/tools/create-job.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait-for-result.tool.d.ts","sourceRoot":"","sources":["../../src/tools/wait-for-result.tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAe,MAAM,aAAa,CAAC;AAEnF,eAAO,MAAM,2BAA2B,EAAE,
|
|
1
|
+
{"version":3,"file":"wait-for-result.tool.d.ts","sourceRoot":"","sources":["../../src/tools/wait-for-result.tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAe,MAAM,aAAa,CAAC;AAEnF,eAAO,MAAM,2BAA2B,EAAE,IAwCzC,CAAC;AAyFF,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAiHhF"}
|
|
@@ -3,22 +3,27 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const waitForResultToolDefinition = {
|
|
5
5
|
name: 'wait_for_result',
|
|
6
|
-
description: `Check status, wait, and retrieve results for a QA job in a single call.
|
|
7
|
-
|
|
8
|
-
This tool combines status checking, waiting, and result retrieval into one convenient function:
|
|
9
|
-
- Checks status BEFORE waiting (returns immediately if already complete)
|
|
10
|
-
- Polls status every 5 seconds during the wait period
|
|
11
|
-
- Returns immediately when job completes (no need to wait full duration)
|
|
12
|
-
- Returns results if complete, otherwise suggests calling again with longer wait
|
|
13
|
-
|
|
14
|
-
Jobs progress through states: pending →
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
6
|
+
description: `Check status, wait, and retrieve results for a QA job in a single call.
|
|
7
|
+
|
|
8
|
+
This tool combines status checking, waiting, and result retrieval into one convenient function:
|
|
9
|
+
- Checks status BEFORE waiting (returns immediately if already complete)
|
|
10
|
+
- Polls status every 5 seconds during the wait period
|
|
11
|
+
- Returns immediately when job completes (no need to wait full duration)
|
|
12
|
+
- Returns results if complete, otherwise suggests calling again with longer wait
|
|
13
|
+
|
|
14
|
+
Jobs progress through states: pending → waiting → working → completed (or incomplete/abandoned/error)
|
|
15
|
+
- pending: Job is being prepared
|
|
16
|
+
- waiting: Job posted to Slack, waiting for a tester to claim it
|
|
17
|
+
- working: Tester has claimed the job and is actively testing
|
|
18
|
+
- completed/incomplete/abandoned/error: Terminal states
|
|
19
|
+
|
|
20
|
+
Typical completion time: 2-10 minutes total
|
|
21
|
+
|
|
22
|
+
Use this tool repeatedly with increasing wait times until you get results:
|
|
23
|
+
- First call: wait_for_result(jobId, { waitSeconds: 30 })
|
|
24
|
+
- If not complete: wait_for_result(jobId, { waitSeconds: 45 })
|
|
25
|
+
- If still not complete: wait_for_result(jobId, { waitSeconds: 60 })
|
|
26
|
+
|
|
22
27
|
Returns immediately if job is already complete (no waiting needed).`,
|
|
23
28
|
inputSchema: {
|
|
24
29
|
type: 'object',
|
|
@@ -56,10 +61,10 @@ function formatCompletedResult(job) {
|
|
|
56
61
|
content: [
|
|
57
62
|
{
|
|
58
63
|
type: 'text',
|
|
59
|
-
text:
|
|
60
|
-
|
|
61
|
-
Job ID: ${job.id}
|
|
62
|
-
|
|
64
|
+
text: `Test completed!
|
|
65
|
+
|
|
66
|
+
Job ID: ${job.id}
|
|
67
|
+
|
|
63
68
|
**Test Results:**`,
|
|
64
69
|
},
|
|
65
70
|
{
|
|
@@ -76,27 +81,43 @@ Job ID: ${job.id}
|
|
|
76
81
|
],
|
|
77
82
|
};
|
|
78
83
|
}
|
|
79
|
-
function
|
|
84
|
+
function formatIncompleteResult(job) {
|
|
80
85
|
return {
|
|
81
86
|
content: [{
|
|
82
87
|
type: 'text',
|
|
83
|
-
text:
|
|
84
|
-
|
|
85
|
-
Job ID: ${job.id}
|
|
86
|
-
|
|
88
|
+
text: `Test completed with incomplete data
|
|
89
|
+
|
|
90
|
+
Job ID: ${job.id}
|
|
91
|
+
|
|
92
|
+
The test was completed but some required data was missing or incomplete.
|
|
93
|
+
${job.error ? `\nDetails: ${job.error}` : ''}`,
|
|
94
|
+
}],
|
|
95
|
+
isError: true,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function formatAbandonedResult(job) {
|
|
99
|
+
return {
|
|
100
|
+
content: [{
|
|
101
|
+
type: 'text',
|
|
102
|
+
text: `Test abandoned
|
|
103
|
+
|
|
104
|
+
Job ID: ${job.id}
|
|
105
|
+
|
|
106
|
+
The tester abandoned this test.
|
|
107
|
+
${job.error ? `\nReason: ${job.error}` : ''}`,
|
|
87
108
|
}],
|
|
88
109
|
isError: true,
|
|
89
110
|
};
|
|
90
111
|
}
|
|
91
|
-
function
|
|
112
|
+
function formatErrorResult(job) {
|
|
92
113
|
return {
|
|
93
114
|
content: [{
|
|
94
115
|
type: 'text',
|
|
95
|
-
text:
|
|
96
|
-
|
|
97
|
-
Job ID: ${job.id}
|
|
98
|
-
|
|
99
|
-
|
|
116
|
+
text: `Test failed due to system error
|
|
117
|
+
|
|
118
|
+
Job ID: ${job.id}
|
|
119
|
+
|
|
120
|
+
Error: ${job.error || 'Unknown error'}`,
|
|
100
121
|
}],
|
|
101
122
|
isError: true,
|
|
102
123
|
};
|
|
@@ -113,13 +134,17 @@ export async function handleWaitForResult(args, config) {
|
|
|
113
134
|
console.error(`[wait_for_result] Job already completed`);
|
|
114
135
|
return formatCompletedResult(job);
|
|
115
136
|
}
|
|
116
|
-
if (job.status === '
|
|
117
|
-
console.error(`[wait_for_result] Job already
|
|
118
|
-
return
|
|
137
|
+
if (job.status === 'incomplete') {
|
|
138
|
+
console.error(`[wait_for_result] Job already completed with incomplete data`);
|
|
139
|
+
return formatIncompleteResult(job);
|
|
140
|
+
}
|
|
141
|
+
if (job.status === 'abandoned') {
|
|
142
|
+
console.error(`[wait_for_result] Job already abandoned`);
|
|
143
|
+
return formatAbandonedResult(job);
|
|
119
144
|
}
|
|
120
|
-
if (job.status === '
|
|
121
|
-
console.error(`[wait_for_result] Job already
|
|
122
|
-
return
|
|
145
|
+
if (job.status === 'error') {
|
|
146
|
+
console.error(`[wait_for_result] Job already failed with error`);
|
|
147
|
+
return formatErrorResult(job);
|
|
123
148
|
}
|
|
124
149
|
// Job not complete yet, poll periodically during the wait period
|
|
125
150
|
console.error(`[wait_for_result] Job status: ${job.status}. Polling every ${pollIntervalSeconds}s for up to ${waitSeconds}s...`);
|
|
@@ -139,44 +164,54 @@ export async function handleWaitForResult(args, config) {
|
|
|
139
164
|
// Check status
|
|
140
165
|
console.error(`[wait_for_result] Polling status (${elapsedSeconds}s elapsed)...`);
|
|
141
166
|
job = await checkJobStatus(args.jobId, config);
|
|
142
|
-
// Check if
|
|
167
|
+
// Check if in terminal state now
|
|
143
168
|
if (job.status === 'completed') {
|
|
144
169
|
console.error(`[wait_for_result] Job completed after ${elapsedSeconds}s`);
|
|
145
170
|
return formatCompletedResult(job);
|
|
146
171
|
}
|
|
147
|
-
if (job.status === '
|
|
148
|
-
console.error(`[wait_for_result] Job
|
|
149
|
-
return
|
|
172
|
+
if (job.status === 'incomplete') {
|
|
173
|
+
console.error(`[wait_for_result] Job completed with incomplete data after ${elapsedSeconds}s`);
|
|
174
|
+
return formatIncompleteResult(job);
|
|
150
175
|
}
|
|
151
|
-
if (job.status === '
|
|
152
|
-
console.error(`[wait_for_result] Job
|
|
153
|
-
return
|
|
176
|
+
if (job.status === 'abandoned') {
|
|
177
|
+
console.error(`[wait_for_result] Job abandoned after ${elapsedSeconds}s`);
|
|
178
|
+
return formatAbandonedResult(job);
|
|
179
|
+
}
|
|
180
|
+
if (job.status === 'error') {
|
|
181
|
+
console.error(`[wait_for_result] Job failed with error after ${elapsedSeconds}s`);
|
|
182
|
+
return formatErrorResult(job);
|
|
154
183
|
}
|
|
155
184
|
console.error(`[wait_for_result] Job still ${job.status}, continuing to poll...`);
|
|
156
185
|
}
|
|
157
186
|
// Reached max wait time without completion
|
|
158
|
-
const statusEmoji = {
|
|
159
|
-
pending: '⏳',
|
|
160
|
-
claimed: '👤',
|
|
161
|
-
in_progress: '🔄',
|
|
162
|
-
};
|
|
163
|
-
const emoji = statusEmoji[job.status] || '📊';
|
|
164
187
|
const nextWait = Math.min(waitSeconds + 15, 120);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
188
|
+
// Determine appropriate status message based on job state
|
|
189
|
+
let statusMessage;
|
|
190
|
+
if (job.status === 'pending') {
|
|
191
|
+
statusMessage = 'Your test is being prepared and will be posted to testers shortly...';
|
|
192
|
+
}
|
|
193
|
+
else if (job.status === 'waiting') {
|
|
194
|
+
statusMessage = 'Waiting for a tester to claim your test...';
|
|
195
|
+
}
|
|
196
|
+
else if (job.status === 'working') {
|
|
197
|
+
statusMessage = 'The tester is working on your test...';
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
// Fallback for any unexpected status
|
|
201
|
+
statusMessage = `Job is in ${job.status} state...`;
|
|
202
|
+
}
|
|
168
203
|
return {
|
|
169
204
|
content: [{
|
|
170
205
|
type: 'text',
|
|
171
|
-
text:
|
|
172
|
-
|
|
173
|
-
Job ID: ${job.id}
|
|
174
|
-
|
|
175
|
-
${statusMessage}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
206
|
+
text: `Job Status: ${job.status}
|
|
207
|
+
|
|
208
|
+
Job ID: ${job.id}
|
|
209
|
+
|
|
210
|
+
${statusMessage}
|
|
211
|
+
|
|
212
|
+
Waited ${waitSeconds}s (polling every ${pollIntervalSeconds}s), job not complete yet.
|
|
213
|
+
|
|
214
|
+
Suggestion: Call wait_for_result again with waitSeconds: ${nextWait}
|
|
180
215
|
Typical completion time: 2-10 minutes total.`,
|
|
181
216
|
}],
|
|
182
217
|
};
|
|
@@ -185,8 +220,8 @@ Typical completion time: 2-10 minutes total.`,
|
|
|
185
220
|
return {
|
|
186
221
|
content: [{
|
|
187
222
|
type: 'text',
|
|
188
|
-
text:
|
|
189
|
-
|
|
223
|
+
text: `Error waiting for result
|
|
224
|
+
|
|
190
225
|
${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
191
226
|
}],
|
|
192
227
|
isError: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wait-for-result.tool.js","sourceRoot":"","sources":["../../src/tools/wait-for-result.tool.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,CAAC,MAAM,2BAA2B,GAAS;IAC/C,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE
|
|
1
|
+
{"version":3,"file":"wait-for-result.tool.js","sourceRoot":"","sources":["../../src/tools/wait-for-result.tool.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* MCP Server Configuration Types
|
|
3
3
|
*/
|
|
4
4
|
export interface McpServerConfig {
|
|
5
|
-
/** Base URL of the
|
|
5
|
+
/** Base URL of the Runhuman API */
|
|
6
6
|
apiUrl: string;
|
|
7
7
|
/** API key for authentication */
|
|
8
8
|
apiKey: string;
|
|
@@ -14,6 +14,8 @@ export interface CreateJobArgs {
|
|
|
14
14
|
targetDurationMinutes?: number;
|
|
15
15
|
allowDurationExtension?: boolean;
|
|
16
16
|
maxExtensionMinutes?: number | boolean;
|
|
17
|
+
/** Custom instructions for the AI when validating test results */
|
|
18
|
+
additionalValidationInstructions?: string;
|
|
17
19
|
}
|
|
18
20
|
export interface WaitForResultArgs {
|
|
19
21
|
jobId: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACvC,kEAAkE;IAClE,gCAAgC,CAAC,EAAE,MAAM,CAAC;CAC3C;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE;QACX,mBAAmB,EAAE,MAAM,CAAC;QAC5B,eAAe,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC7E,eAAe,EAAE,KAAK,CAAC;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC5F,MAAM,EAAE,KAAK,CAAC;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QAC7E,WAAW,EAAE,MAAM,EAAE,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB"}
|
package/package.json
CHANGED
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@runhuman/mcp-server",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "Model Context Protocol (MCP) server for
|
|
5
|
-
"main": "dist/lib.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"import": "./dist/lib.js",
|
|
10
|
-
"require": "./dist/lib.js",
|
|
11
|
-
"types": "./dist/lib.d.ts"
|
|
12
|
-
},
|
|
13
|
-
"./factory": {
|
|
14
|
-
"import": "./dist/mcp-server-factory.js",
|
|
15
|
-
"types": "./dist/mcp-server-factory.d.ts"
|
|
16
|
-
},
|
|
17
|
-
"./types": {
|
|
18
|
-
"import": "./dist/types.js",
|
|
19
|
-
"types": "./dist/types.d.ts"
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
"bin": {
|
|
23
|
-
"runhuman-mcp": "dist/index.js"
|
|
24
|
-
},
|
|
25
|
-
"files": [
|
|
26
|
-
"dist",
|
|
27
|
-
"README.md",
|
|
28
|
-
".env.example"
|
|
29
|
-
],
|
|
30
|
-
"scripts": {
|
|
31
|
-
"build": "tsc",
|
|
32
|
-
"dev": "tsx watch src/index.ts",
|
|
33
|
-
"start": "node dist/index.js",
|
|
34
|
-
"prepublishOnly": "npm run build",
|
|
35
|
-
"type-check": "tsc",
|
|
36
|
-
"test": "node test-simple.cjs",
|
|
37
|
-
"test:all": "node test-all-tools.cjs",
|
|
38
|
-
"test:routes": "node test-route-fix.cjs",
|
|
39
|
-
"test:endpoints": "node test-api-endpoints.cjs",
|
|
40
|
-
"test:ci": "npm run test:endpoints && npm run test:routes",
|
|
41
|
-
"test:inspector": "npx @modelcontextprotocol/inspector node dist/index.js"
|
|
42
|
-
},
|
|
43
|
-
"keywords": [
|
|
44
|
-
"mcp",
|
|
45
|
-
"model-context-protocol",
|
|
46
|
-
"qa",
|
|
47
|
-
"testing",
|
|
48
|
-
"human-in-the-loop",
|
|
49
|
-
"ai-agent",
|
|
50
|
-
"claude",
|
|
51
|
-
"anthropic",
|
|
52
|
-
"qa-testing",
|
|
53
|
-
"manual-testing"
|
|
54
|
-
],
|
|
55
|
-
"author": "
|
|
56
|
-
"repository": {
|
|
57
|
-
"type": "git",
|
|
58
|
-
"url": "git+https://github.com/yueranyuan/qa-experiment.git",
|
|
59
|
-
"directory": "packages/mcp-server"
|
|
60
|
-
},
|
|
61
|
-
"homepage": "https://runhuman.com",
|
|
62
|
-
"bugs": {
|
|
63
|
-
"url": "https://github.com/yueranyuan/qa-experiment/issues"
|
|
64
|
-
},
|
|
65
|
-
"license": "ISC",
|
|
66
|
-
"engines": {
|
|
67
|
-
"node": ">=18.0.0"
|
|
68
|
-
},
|
|
69
|
-
"dependencies": {
|
|
70
|
-
"@modelcontextprotocol/sdk": "latest",
|
|
71
|
-
"dotenv": "^17.2.3"
|
|
72
|
-
},
|
|
73
|
-
"devDependencies": {
|
|
74
|
-
"@types/node": "^20.11.17",
|
|
75
|
-
"tsx": "^4.7.1",
|
|
76
|
-
"typescript": "^5.3.3"
|
|
77
|
-
}
|
|
78
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@runhuman/mcp-server",
|
|
3
|
+
"version": "2.0.5",
|
|
4
|
+
"description": "Model Context Protocol (MCP) server for Runhuman - Human-powered QA testing for AI agents",
|
|
5
|
+
"main": "dist/lib.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/lib.js",
|
|
10
|
+
"require": "./dist/lib.js",
|
|
11
|
+
"types": "./dist/lib.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./factory": {
|
|
14
|
+
"import": "./dist/mcp-server-factory.js",
|
|
15
|
+
"types": "./dist/mcp-server-factory.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./types": {
|
|
18
|
+
"import": "./dist/types.js",
|
|
19
|
+
"types": "./dist/types.d.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"bin": {
|
|
23
|
+
"runhuman-mcp": "dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"README.md",
|
|
28
|
+
".env.example"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc",
|
|
32
|
+
"dev": "tsx watch src/index.ts",
|
|
33
|
+
"start": "node dist/index.js",
|
|
34
|
+
"prepublishOnly": "npm run build",
|
|
35
|
+
"type-check": "tsc",
|
|
36
|
+
"test": "node test-simple.cjs",
|
|
37
|
+
"test:all": "node test-all-tools.cjs",
|
|
38
|
+
"test:routes": "node test-route-fix.cjs",
|
|
39
|
+
"test:endpoints": "node test-api-endpoints.cjs",
|
|
40
|
+
"test:ci": "npm run test:endpoints && npm run test:routes",
|
|
41
|
+
"test:inspector": "npx @modelcontextprotocol/inspector node dist/index.js"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"mcp",
|
|
45
|
+
"model-context-protocol",
|
|
46
|
+
"qa",
|
|
47
|
+
"testing",
|
|
48
|
+
"human-in-the-loop",
|
|
49
|
+
"ai-agent",
|
|
50
|
+
"claude",
|
|
51
|
+
"anthropic",
|
|
52
|
+
"qa-testing",
|
|
53
|
+
"manual-testing"
|
|
54
|
+
],
|
|
55
|
+
"author": "Runhuman <hey@runhuman.com>",
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "git+https://github.com/yueranyuan/qa-experiment.git",
|
|
59
|
+
"directory": "packages/mcp-server"
|
|
60
|
+
},
|
|
61
|
+
"homepage": "https://runhuman.com",
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/yueranyuan/qa-experiment/issues"
|
|
64
|
+
},
|
|
65
|
+
"license": "ISC",
|
|
66
|
+
"engines": {
|
|
67
|
+
"node": ">=18.0.0"
|
|
68
|
+
},
|
|
69
|
+
"dependencies": {
|
|
70
|
+
"@modelcontextprotocol/sdk": "latest",
|
|
71
|
+
"dotenv": "^17.2.3"
|
|
72
|
+
},
|
|
73
|
+
"devDependencies": {
|
|
74
|
+
"@types/node": "^20.11.17",
|
|
75
|
+
"tsx": "^4.7.1",
|
|
76
|
+
"typescript": "^5.3.3"
|
|
77
|
+
}
|
|
78
|
+
}
|