mcp-server-mturk 0.1.0__py3-none-any.whl
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.
- mcp_server_mturk-0.1.0.dist-info/METADATA +271 -0
- mcp_server_mturk-0.1.0.dist-info/RECORD +14 -0
- mcp_server_mturk-0.1.0.dist-info/WHEEL +4 -0
- mcp_server_mturk-0.1.0.dist-info/entry_points.txt +2 -0
- mcp_server_mturk-0.1.0.dist-info/licenses/LICENSE +21 -0
- mturk_mcp/__init__.py +3 -0
- mturk_mcp/client.py +75 -0
- mturk_mcp/server.py +75 -0
- mturk_mcp/tools/__init__.py +5 -0
- mturk_mcp/tools/account.py +109 -0
- mturk_mcp/tools/assignments.py +329 -0
- mturk_mcp/tools/hits.py +384 -0
- mturk_mcp/tools/qualifications.py +341 -0
- mturk_mcp/tools/workers.py +359 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: mcp-server-mturk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for Amazon Mechanical Turk - enables AI agents to create HITs, review assignments, manage workers, and access human intelligence
|
|
5
|
+
Project-URL: Homepage, https://github.com/davidmcsharry/mcp-server-mturk
|
|
6
|
+
Project-URL: Repository, https://github.com/davidmcsharry/mcp-server-mturk
|
|
7
|
+
Project-URL: Issues, https://github.com/davidmcsharry/mcp-server-mturk/issues
|
|
8
|
+
Author: David McSharry
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai-agents,amazon,crowdsourcing,human-intelligence,llm,mcp,mechanical-turk,model-context-protocol,mturk
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: boto3>=1.35.0
|
|
21
|
+
Requires-Dist: mcp>=1.0.0
|
|
22
|
+
Requires-Dist: pydantic>=2.0.0
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# mcp-server-mturk
|
|
26
|
+
|
|
27
|
+
An MCP (Model Context Protocol) server that enables AI agents to interact with Amazon Mechanical Turk. This allows AI systems to request human intelligence for surveys, data labeling, content moderation, and any other MTurk-supported task.
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
- **24 tools** covering the full MTurk API
|
|
32
|
+
- **HIT Management**: Create, list, update, and delete Human Intelligence Tasks
|
|
33
|
+
- **Assignment Workflow**: Review, approve, reject, and bulk-approve worker submissions
|
|
34
|
+
- **Qualification System**: Create custom qualifications to filter workers
|
|
35
|
+
- **Worker Management**: Block/unblock workers, send notifications, pay bonuses
|
|
36
|
+
- **Account Management**: Check balance, list reviewable HITs
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
### Using uvx (recommended)
|
|
41
|
+
|
|
42
|
+
No installation needed. Run directly:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
uvx mcp-server-mturk
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Using pip
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install mcp-server-mturk
|
|
52
|
+
python -m mturk_mcp.server
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
### Environment Variables
|
|
58
|
+
|
|
59
|
+
| Variable | Required | Description |
|
|
60
|
+
|----------|----------|-------------|
|
|
61
|
+
| `AWS_ACCESS_KEY_ID` | Yes | Your AWS access key with MTurk permissions |
|
|
62
|
+
| `AWS_SECRET_ACCESS_KEY` | Yes | Your AWS secret key |
|
|
63
|
+
| `MTURK_SANDBOX` | No | Set to `true` for sandbox mode (testing) |
|
|
64
|
+
|
|
65
|
+
### AWS Credentials Setup
|
|
66
|
+
|
|
67
|
+
1. Go to [AWS IAM Console](https://console.aws.amazon.com/iam/)
|
|
68
|
+
2. Create a new user with `AmazonMechanicalTurkFullAccess` policy
|
|
69
|
+
3. Generate access keys for the user
|
|
70
|
+
|
|
71
|
+
### MTurk Account Setup
|
|
72
|
+
|
|
73
|
+
1. Create an [MTurk Requester account](https://requester.mturk.com/)
|
|
74
|
+
2. For testing, also register for the [MTurk Sandbox](https://requestersandbox.mturk.com/)
|
|
75
|
+
|
|
76
|
+
## Usage with AI Clients
|
|
77
|
+
|
|
78
|
+
### Claude Code
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Sandbox mode (recommended for testing)
|
|
82
|
+
claude mcp add mturk-sandbox \
|
|
83
|
+
--env AWS_ACCESS_KEY_ID=your_key \
|
|
84
|
+
--env AWS_SECRET_ACCESS_KEY=your_secret \
|
|
85
|
+
--env MTURK_SANDBOX=true \
|
|
86
|
+
-- uvx mcp-server-mturk
|
|
87
|
+
|
|
88
|
+
# Production mode (uses real money!)
|
|
89
|
+
claude mcp add mturk \
|
|
90
|
+
--env AWS_ACCESS_KEY_ID=your_key \
|
|
91
|
+
--env AWS_SECRET_ACCESS_KEY=your_secret \
|
|
92
|
+
-- uvx mcp-server-mturk
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Claude Desktop
|
|
96
|
+
|
|
97
|
+
Add to your `claude_desktop_config.json`:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"mcpServers": {
|
|
102
|
+
"mturk-sandbox": {
|
|
103
|
+
"command": "uvx",
|
|
104
|
+
"args": ["mcp-server-mturk"],
|
|
105
|
+
"env": {
|
|
106
|
+
"AWS_ACCESS_KEY_ID": "your_key",
|
|
107
|
+
"AWS_SECRET_ACCESS_KEY": "your_secret",
|
|
108
|
+
"MTURK_SANDBOX": "true"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Config file locations:
|
|
116
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
117
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
118
|
+
|
|
119
|
+
### Cursor
|
|
120
|
+
|
|
121
|
+
Add to Cursor's MCP settings:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"mcpServers": {
|
|
126
|
+
"mturk": {
|
|
127
|
+
"command": "uvx",
|
|
128
|
+
"args": ["mcp-server-mturk"],
|
|
129
|
+
"env": {
|
|
130
|
+
"AWS_ACCESS_KEY_ID": "your_key",
|
|
131
|
+
"AWS_SECRET_ACCESS_KEY": "your_secret",
|
|
132
|
+
"MTURK_SANDBOX": "true"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Using pip instead of uvx
|
|
140
|
+
|
|
141
|
+
Replace `"command": "uvx", "args": ["mcp-server-mturk"]` with:
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"command": "python",
|
|
146
|
+
"args": ["-m", "mturk_mcp.server"]
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Available Tools
|
|
151
|
+
|
|
152
|
+
### HIT Operations (6 tools)
|
|
153
|
+
|
|
154
|
+
| Tool | Description |
|
|
155
|
+
|------|-------------|
|
|
156
|
+
| `create_hit` | Create a new Human Intelligence Task with HTML form |
|
|
157
|
+
| `get_hit` | Get details and status of a specific HIT |
|
|
158
|
+
| `list_hits` | List all HITs for your account |
|
|
159
|
+
| `delete_hit` | Delete a HIT (must have no pending assignments) |
|
|
160
|
+
| `update_hit_expiration` | Extend or expire a HIT |
|
|
161
|
+
| `create_additional_assignments` | Add more worker slots to an existing HIT |
|
|
162
|
+
|
|
163
|
+
### Assignment Management (5 tools)
|
|
164
|
+
|
|
165
|
+
| Tool | Description |
|
|
166
|
+
|------|-------------|
|
|
167
|
+
| `list_assignments` | Get all worker submissions for a HIT |
|
|
168
|
+
| `get_assignment` | Get details including worker's answer |
|
|
169
|
+
| `approve_assignment` | Approve and pay for completed work |
|
|
170
|
+
| `reject_assignment` | Reject unsatisfactory work (use sparingly) |
|
|
171
|
+
| `approve_all_submitted_assignments` | Bulk approve all pending assignments |
|
|
172
|
+
|
|
173
|
+
### Qualification Management (5 tools)
|
|
174
|
+
|
|
175
|
+
| Tool | Description |
|
|
176
|
+
|------|-------------|
|
|
177
|
+
| `create_qualification_type` | Create a custom worker qualification |
|
|
178
|
+
| `list_qualification_types` | List available qualifications |
|
|
179
|
+
| `assign_qualification` | Grant a qualification to a worker |
|
|
180
|
+
| `revoke_qualification` | Remove a qualification from a worker |
|
|
181
|
+
| `get_qualification_score` | Check a worker's qualification value |
|
|
182
|
+
|
|
183
|
+
### Worker Management (6 tools)
|
|
184
|
+
|
|
185
|
+
| Tool | Description |
|
|
186
|
+
|------|-------------|
|
|
187
|
+
| `block_worker` | Block a worker from all your HITs |
|
|
188
|
+
| `unblock_worker` | Remove a worker block |
|
|
189
|
+
| `list_blocked_workers` | List all blocked workers |
|
|
190
|
+
| `notify_workers` | Send email to workers |
|
|
191
|
+
| `send_bonus` | Send bonus payment to a worker |
|
|
192
|
+
| `list_bonus_payments` | List bonus payments made |
|
|
193
|
+
|
|
194
|
+
### Account & Utility (2 tools)
|
|
195
|
+
|
|
196
|
+
| Tool | Description |
|
|
197
|
+
|------|-------------|
|
|
198
|
+
| `get_account_balance` | Check your MTurk account balance |
|
|
199
|
+
| `list_reviewable_hits` | Find HITs with work ready for review |
|
|
200
|
+
|
|
201
|
+
## Example Prompts
|
|
202
|
+
|
|
203
|
+
Once connected, you can ask your AI assistant things like:
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
"Check my MTurk account balance"
|
|
207
|
+
|
|
208
|
+
"Create a survey HIT asking 100 people their favorite programming language, paying $0.10 each"
|
|
209
|
+
|
|
210
|
+
"List all my HITs and show which ones have pending assignments"
|
|
211
|
+
|
|
212
|
+
"Show me the submitted assignments for HIT abc123"
|
|
213
|
+
|
|
214
|
+
"Approve all submitted assignments for HIT abc123 with the message 'Thank you!'"
|
|
215
|
+
|
|
216
|
+
"Send a $0.50 bonus to worker xyz789 for their detailed response"
|
|
217
|
+
|
|
218
|
+
"Create a 'Trusted Worker' qualification and assign it to workers who did good work"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Sandbox vs Production
|
|
222
|
+
|
|
223
|
+
| Mode | Environment Variable | Use For |
|
|
224
|
+
|------|---------------------|---------|
|
|
225
|
+
| **Sandbox** | `MTURK_SANDBOX=true` | Testing, development, no real money |
|
|
226
|
+
| **Production** | `MTURK_SANDBOX=false` (or unset) | Real HITs, real workers, real payments |
|
|
227
|
+
|
|
228
|
+
**Always test with sandbox first!** Production mode uses real money and interacts with real workers.
|
|
229
|
+
|
|
230
|
+
## Development
|
|
231
|
+
|
|
232
|
+
### Running locally
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
# Clone and install
|
|
236
|
+
git clone https://github.com/davidmcsharry/mcp-server-mturk
|
|
237
|
+
cd mcp-server-mturk
|
|
238
|
+
uv sync
|
|
239
|
+
|
|
240
|
+
# Run the server
|
|
241
|
+
uv run python -m mturk_mcp.server
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Testing with MCP Inspector
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
npx @modelcontextprotocol/inspector uvx mcp-server-mturk
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Building
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
uv build
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Publishing to PyPI
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
uv publish
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## License
|
|
263
|
+
|
|
264
|
+
MIT
|
|
265
|
+
|
|
266
|
+
## Links
|
|
267
|
+
|
|
268
|
+
- [Model Context Protocol](https://modelcontextprotocol.io/)
|
|
269
|
+
- [MTurk API Documentation](https://docs.aws.amazon.com/AWSMechTurk/latest/AWSMturkAPI/Welcome.html)
|
|
270
|
+
- [MTurk Requester Portal](https://requester.mturk.com/)
|
|
271
|
+
- [MTurk Sandbox](https://requestersandbox.mturk.com/)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
mturk_mcp/__init__.py,sha256=XI0gVmk3eMl7PXwfwx33zLRuNp2K-0IL2rB3cxJY5ks,106
|
|
2
|
+
mturk_mcp/client.py,sha256=H4MGR8YbpaMhZr27ZBsCg9cLtJdcU4qqUvL0zUVbpIE,2635
|
|
3
|
+
mturk_mcp/server.py,sha256=SBZHvdf_8cByjdY1AmSJ-UEKmP3c0NL8E-fOj4bWCwY,2124
|
|
4
|
+
mturk_mcp/tools/__init__.py,sha256=Vc4VQLqJ1omADCP2BfqHWOni4yvluKIgO2Kui1Za6KU,194
|
|
5
|
+
mturk_mcp/tools/account.py,sha256=AApFAuOvopIWCyTJNeIkphEI2IASXOea5dBTs1FnzLg,5137
|
|
6
|
+
mturk_mcp/tools/assignments.py,sha256=ZFOAerNh7B14J8OeVx-A4y3kgVnETgbxaNntCXPc7O8,15382
|
|
7
|
+
mturk_mcp/tools/hits.py,sha256=lb9xY-XCQMyCu_GzE95xXvNuLm5DASyipeuVkoMrZQA,18951
|
|
8
|
+
mturk_mcp/tools/qualifications.py,sha256=iG9Kz5D34i8IinKMu1rP085zg64ZpbWkSVz7hwfXgCY,16577
|
|
9
|
+
mturk_mcp/tools/workers.py,sha256=4GLZlDFzyzyUMM9pT4IJv5pXmTHrG9CpDIx1IqxgHsg,15392
|
|
10
|
+
mcp_server_mturk-0.1.0.dist-info/METADATA,sha256=x81GIMAG5Ea2ShwPTxnGfr-ZcXroId6Y6vhu5VmpKGA,7665
|
|
11
|
+
mcp_server_mturk-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
12
|
+
mcp_server_mturk-0.1.0.dist-info/entry_points.txt,sha256=RgDOzQaUXCG-ocgo8GhKw7dzh3uKXO_2gE7LuP0P_GM,59
|
|
13
|
+
mcp_server_mturk-0.1.0.dist-info/licenses/LICENSE,sha256=IPe1EzjsFk59zmD6boPfdk5F0YQMtj9XafgjyMQFJBI,1071
|
|
14
|
+
mcp_server_mturk-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 David McSharry
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
mturk_mcp/__init__.py
ADDED
mturk_mcp/client.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""AWS MTurk client wrapper with environment-based configuration."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import boto3
|
|
6
|
+
from botocore.exceptions import ClientError, NoCredentialsError
|
|
7
|
+
|
|
8
|
+
_client = None
|
|
9
|
+
|
|
10
|
+
SANDBOX_ENDPOINT = "https://mturk-requester-sandbox.us-east-1.amazonaws.com"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_mturk_client():
|
|
14
|
+
"""Get or create the MTurk client singleton."""
|
|
15
|
+
global _client
|
|
16
|
+
if _client is None:
|
|
17
|
+
use_sandbox = os.environ.get("MTURK_SANDBOX", "false").lower() == "true"
|
|
18
|
+
endpoint_url = SANDBOX_ENDPOINT if use_sandbox else None
|
|
19
|
+
|
|
20
|
+
_client = boto3.client(
|
|
21
|
+
"mturk",
|
|
22
|
+
region_name="us-east-1",
|
|
23
|
+
endpoint_url=endpoint_url,
|
|
24
|
+
aws_access_key_id=os.environ.get("AWS_ACCESS_KEY_ID"),
|
|
25
|
+
aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY"),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# Log which environment we're using
|
|
29
|
+
env_name = "SANDBOX" if use_sandbox else "PRODUCTION"
|
|
30
|
+
print(f"[mturk-mcp] Connected to MTurk {env_name}", file=sys.stderr)
|
|
31
|
+
|
|
32
|
+
return _client
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def is_sandbox() -> bool:
|
|
36
|
+
"""Check if we're using the sandbox environment."""
|
|
37
|
+
return os.environ.get("MTURK_SANDBOX", "false").lower() == "true"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def wrap_html_question(html_content: str) -> str:
|
|
41
|
+
"""Wrap HTML content in MTurk's HTMLQuestion format."""
|
|
42
|
+
return f"""<?xml version="1.0" encoding="UTF-8"?>
|
|
43
|
+
<HTMLQuestion xmlns="http://mechanicalturk.amazonaws.com/AWSMechanicalTurkDataSchemas/2011-11-11/HTMLQuestion.xsd">
|
|
44
|
+
<HTMLContent><![CDATA[
|
|
45
|
+
<!DOCTYPE html>
|
|
46
|
+
<html>
|
|
47
|
+
<head>
|
|
48
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
|
49
|
+
<script type="text/javascript" src="https://s3.amazonaws.com/mturk-public/externalHIT_v1.js"></script>
|
|
50
|
+
</head>
|
|
51
|
+
<body>
|
|
52
|
+
<form name="mturk_form" method="post" id="mturk_form" action="https://www.mturk.com/mturk/externalSubmit">
|
|
53
|
+
<input type="hidden" name="assignmentId" id="assignmentId" value="">
|
|
54
|
+
{html_content}
|
|
55
|
+
<p><input type="submit" id="submitButton" value="Submit"></p>
|
|
56
|
+
</form>
|
|
57
|
+
<script>
|
|
58
|
+
turkSetAssignmentID();
|
|
59
|
+
</script>
|
|
60
|
+
</body>
|
|
61
|
+
</html>
|
|
62
|
+
]]></HTMLContent>
|
|
63
|
+
<FrameHeight>600</FrameHeight>
|
|
64
|
+
</HTMLQuestion>"""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def format_error(e: Exception) -> str:
|
|
68
|
+
"""Format AWS errors into user-friendly messages."""
|
|
69
|
+
if isinstance(e, NoCredentialsError):
|
|
70
|
+
return "AWS credentials not found. Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables."
|
|
71
|
+
if isinstance(e, ClientError):
|
|
72
|
+
error_code = e.response.get("Error", {}).get("Code", "Unknown")
|
|
73
|
+
error_msg = e.response.get("Error", {}).get("Message", str(e))
|
|
74
|
+
return f"MTurk API error ({error_code}): {error_msg}"
|
|
75
|
+
return f"Error: {str(e)}"
|
mturk_mcp/server.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""MTurk MCP Server - Main entry point."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
from mcp.server import Server
|
|
7
|
+
from mcp.server.stdio import stdio_server
|
|
8
|
+
from mcp.types import Tool, TextContent
|
|
9
|
+
|
|
10
|
+
from .client import get_mturk_client, format_error, wrap_html_question, is_sandbox
|
|
11
|
+
|
|
12
|
+
# Create server instance
|
|
13
|
+
server = Server("mturk")
|
|
14
|
+
|
|
15
|
+
# Import tool handlers
|
|
16
|
+
from .tools import hits, assignments, qualifications, workers, account
|
|
17
|
+
|
|
18
|
+
# Collect all tools from modules
|
|
19
|
+
ALL_TOOLS: list[Tool] = []
|
|
20
|
+
TOOL_HANDLERS: dict[str, callable] = {}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def register_tool(name: str, description: str, input_schema: dict, handler: callable):
|
|
24
|
+
"""Register a tool with its schema and handler."""
|
|
25
|
+
ALL_TOOLS.append(Tool(
|
|
26
|
+
name=name,
|
|
27
|
+
description=description,
|
|
28
|
+
inputSchema=input_schema,
|
|
29
|
+
))
|
|
30
|
+
TOOL_HANDLERS[name] = handler
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# Register all tools from modules
|
|
34
|
+
hits.register_tools(register_tool)
|
|
35
|
+
assignments.register_tools(register_tool)
|
|
36
|
+
qualifications.register_tools(register_tool)
|
|
37
|
+
workers.register_tools(register_tool)
|
|
38
|
+
account.register_tools(register_tool)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@server.list_tools()
|
|
42
|
+
async def handle_list_tools() -> list[Tool]:
|
|
43
|
+
"""Return all available MTurk tools."""
|
|
44
|
+
return ALL_TOOLS
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@server.call_tool()
|
|
48
|
+
async def handle_call_tool(name: str, arguments: dict) -> list[TextContent]:
|
|
49
|
+
"""Handle tool invocations."""
|
|
50
|
+
if name not in TOOL_HANDLERS:
|
|
51
|
+
return [TextContent(type="text", text=f"Unknown tool: {name}")]
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
handler = TOOL_HANDLERS[name]
|
|
55
|
+
result = await handler(arguments)
|
|
56
|
+
return result
|
|
57
|
+
except Exception as e:
|
|
58
|
+
return [TextContent(type="text", text=format_error(e))]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
async def run():
|
|
62
|
+
"""Run the MCP server with stdio transport."""
|
|
63
|
+
print("[mturk-mcp] Starting MTurk MCP server...", file=sys.stderr)
|
|
64
|
+
print(f"[mturk-mcp] Registered {len(ALL_TOOLS)} tools", file=sys.stderr)
|
|
65
|
+
async with stdio_server() as (read_stream, write_stream):
|
|
66
|
+
await server.run(read_stream, write_stream, server.create_initialization_options())
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def main():
|
|
70
|
+
"""Entry point for the MCP server."""
|
|
71
|
+
asyncio.run(run())
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
if __name__ == "__main__":
|
|
75
|
+
main()
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Account and utility tools for MTurk."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from mcp.types import TextContent
|
|
5
|
+
|
|
6
|
+
from ..client import get_mturk_client, format_error, is_sandbox
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def register_tools(register):
|
|
10
|
+
"""Register account-related tools."""
|
|
11
|
+
|
|
12
|
+
async def get_account_balance(args: dict) -> list[TextContent]:
|
|
13
|
+
"""Get the available balance in your MTurk requester account."""
|
|
14
|
+
try:
|
|
15
|
+
client = get_mturk_client()
|
|
16
|
+
response = client.get_account_balance()
|
|
17
|
+
result = {
|
|
18
|
+
"available_balance": response["AvailableBalance"],
|
|
19
|
+
"on_hold_balance": response.get("OnHoldBalance"),
|
|
20
|
+
"environment": "sandbox" if is_sandbox() else "production",
|
|
21
|
+
}
|
|
22
|
+
return [TextContent(type="text", text=json.dumps(result, indent=2))]
|
|
23
|
+
except Exception as e:
|
|
24
|
+
return [TextContent(type="text", text=format_error(e))]
|
|
25
|
+
|
|
26
|
+
register(
|
|
27
|
+
"get_account_balance",
|
|
28
|
+
"""Retrieves the current available balance in your Amazon Mechanical Turk requester account.
|
|
29
|
+
|
|
30
|
+
Use this tool to check how much money you have available before creating HITs, or to verify funds after making payments. The balance is returned in USD.
|
|
31
|
+
|
|
32
|
+
Returns two values:
|
|
33
|
+
- available_balance: Money you can spend on HITs and bonuses right now
|
|
34
|
+
- on_hold_balance: Money reserved for pending assignments (will be released when you approve/reject work)
|
|
35
|
+
|
|
36
|
+
Also indicates whether you're connected to the sandbox (testing) or production environment. In sandbox mode, the balance is fake money for testing purposes.
|
|
37
|
+
|
|
38
|
+
This tool takes no parameters and should be called whenever you need to verify you have sufficient funds for an operation.""",
|
|
39
|
+
{"type": "object", "properties": {}, "required": []},
|
|
40
|
+
get_account_balance,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
async def list_reviewable_hits(args: dict) -> list[TextContent]:
|
|
44
|
+
"""List HITs that have assignments ready for review."""
|
|
45
|
+
try:
|
|
46
|
+
client = get_mturk_client()
|
|
47
|
+
params = {
|
|
48
|
+
"Status": args.get("status", "Reviewable"),
|
|
49
|
+
"MaxResults": min(args.get("max_results", 100), 100),
|
|
50
|
+
}
|
|
51
|
+
if args.get("hit_type_id"):
|
|
52
|
+
params["HITTypeId"] = args["hit_type_id"]
|
|
53
|
+
|
|
54
|
+
response = client.list_reviewable_hits(**params)
|
|
55
|
+
hits = response.get("HITs", [])
|
|
56
|
+
result = {
|
|
57
|
+
"count": len(hits),
|
|
58
|
+
"hits": [
|
|
59
|
+
{
|
|
60
|
+
"hit_id": hit["HITId"],
|
|
61
|
+
"hit_type_id": hit.get("HITTypeId"),
|
|
62
|
+
"title": hit.get("Title"),
|
|
63
|
+
"creation_time": str(hit.get("CreationTime")),
|
|
64
|
+
}
|
|
65
|
+
for hit in hits
|
|
66
|
+
],
|
|
67
|
+
}
|
|
68
|
+
return [TextContent(type="text", text=json.dumps(result, indent=2))]
|
|
69
|
+
except Exception as e:
|
|
70
|
+
return [TextContent(type="text", text=format_error(e))]
|
|
71
|
+
|
|
72
|
+
register(
|
|
73
|
+
"list_reviewable_hits",
|
|
74
|
+
"""Finds HITs that have worker submissions waiting to be reviewed (approved or rejected).
|
|
75
|
+
|
|
76
|
+
Use this tool when you want to check if any workers have completed assignments that need your attention. This is typically the first step in the review workflow - call this to find HITs with pending work, then use list_assignments to see the actual submissions.
|
|
77
|
+
|
|
78
|
+
A HIT becomes 'Reviewable' when at least one worker has submitted an assignment that hasn't been approved or rejected yet. Once all assignments for a HIT are reviewed, it moves out of the reviewable state.
|
|
79
|
+
|
|
80
|
+
The status parameter filters results:
|
|
81
|
+
- 'Reviewable' (default): HITs with at least one submitted assignment awaiting review
|
|
82
|
+
- 'Reviewing': HITs you've marked as being actively reviewed (rarely used)
|
|
83
|
+
|
|
84
|
+
Returns basic HIT info including hit_id (needed for list_assignments), title, and creation time. Does not return the actual worker submissions - use list_assignments for that.""",
|
|
85
|
+
{
|
|
86
|
+
"type": "object",
|
|
87
|
+
"properties": {
|
|
88
|
+
"hit_type_id": {
|
|
89
|
+
"type": "string",
|
|
90
|
+
"description": "Optional filter to only show HITs of a specific type. HIT types group HITs with the same reward, duration, and qualifications. Omit to see all reviewable HITs."
|
|
91
|
+
},
|
|
92
|
+
"status": {
|
|
93
|
+
"type": "string",
|
|
94
|
+
"enum": ["Reviewable", "Reviewing"],
|
|
95
|
+
"description": "Filter by review status. 'Reviewable' (default) shows HITs with pending submissions. 'Reviewing' shows HITs marked as being actively reviewed.",
|
|
96
|
+
"default": "Reviewable"
|
|
97
|
+
},
|
|
98
|
+
"max_results": {
|
|
99
|
+
"type": "integer",
|
|
100
|
+
"description": "Maximum number of HITs to return, between 1 and 100. Defaults to 100. Use smaller values for faster responses when you only need a few results.",
|
|
101
|
+
"default": 100,
|
|
102
|
+
"minimum": 1,
|
|
103
|
+
"maximum": 100
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
"required": [],
|
|
107
|
+
},
|
|
108
|
+
list_reviewable_hits,
|
|
109
|
+
)
|