ai-coding-gym-mcp 0.1.1__py3-none-any.whl → 0.1.3__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.
- {ai_coding_gym_mcp-0.1.1.dist-info → ai_coding_gym_mcp-0.1.3.dist-info}/METADATA +40 -37
- ai_coding_gym_mcp-0.1.3.dist-info/RECORD +6 -0
- server.py +1 -21
- ai_coding_gym_mcp-0.1.1.dist-info/RECORD +0 -6
- {ai_coding_gym_mcp-0.1.1.dist-info → ai_coding_gym_mcp-0.1.3.dist-info}/WHEEL +0 -0
- {ai_coding_gym_mcp-0.1.1.dist-info → ai_coding_gym_mcp-0.1.3.dist-info}/entry_points.txt +0 -0
- {ai_coding_gym_mcp-0.1.1.dist-info → ai_coding_gym_mcp-0.1.3.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ai-coding-gym-mcp
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: MCP server for AI Coding Gym - fetch and submit coding challenges
|
|
5
5
|
Home-page: https://github.com/yourusername/ai-coding-gym-mcp
|
|
6
6
|
Author: AICodingGym Team
|
|
@@ -63,10 +63,7 @@ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_
|
|
|
63
63
|
"mcpServers": {
|
|
64
64
|
"ai-coding-gym": {
|
|
65
65
|
"command": "python",
|
|
66
|
-
"args": ["-m", "server"]
|
|
67
|
-
"env": {
|
|
68
|
-
"AI_CODING_GYM_SERVER": "https://your-server-url.com"
|
|
69
|
-
}
|
|
66
|
+
"args": ["-m", "server"]
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
69
|
}
|
|
@@ -86,30 +83,48 @@ python server.py
|
|
|
86
83
|
|
|
87
84
|
Or configure it in your MCP client settings (e.g., Claude Desktop).
|
|
88
85
|
|
|
86
|
+
### Tool: `/configure`
|
|
87
|
+
|
|
88
|
+
Configure the MCP server with your user ID. This generates an SSH key pair and registers it with the server.
|
|
89
|
+
|
|
90
|
+
**Parameters:**
|
|
91
|
+
- `user_id` (required): Your user ID for authentication
|
|
92
|
+
- `workspace_dir` (optional): Default workspace directory (default: `"./workspace"`)
|
|
93
|
+
|
|
94
|
+
**Example:**
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"user_id": "user_123",
|
|
98
|
+
"workspace_dir": "./workspace"
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**What it does:**
|
|
103
|
+
1. Generates an SSH key pair locally (stored in `~/.mcp-keys/`)
|
|
104
|
+
2. Sends the public key to the server
|
|
105
|
+
3. Receives your repository name
|
|
106
|
+
4. Stores configuration for future use
|
|
107
|
+
|
|
89
108
|
### Tool: `/fetch`
|
|
90
109
|
|
|
91
110
|
Fetches a problem from the backend and clones the repository locally.
|
|
92
111
|
|
|
93
112
|
**Parameters:**
|
|
94
113
|
- `problem_id` (required): Problem identifier (e.g., `"django__django-10097"`)
|
|
95
|
-
- `user_id` (
|
|
96
|
-
- `server_url` (optional): Backend server URL (default: `"https://api.example.com"`)
|
|
114
|
+
- `user_id` (optional): Your user ID (uses configured value if not provided)
|
|
97
115
|
- `workspace_dir` (optional): Local workspace directory (default: `"./workspace"`)
|
|
98
116
|
|
|
99
117
|
**Example:**
|
|
100
118
|
```json
|
|
101
119
|
{
|
|
102
|
-
"problem_id": "django__django-10097"
|
|
103
|
-
"user_id": "user_123",
|
|
104
|
-
"server_url": "https://ai-coding-gym.example.com"
|
|
120
|
+
"problem_id": "django__django-10097"
|
|
105
121
|
}
|
|
106
122
|
```
|
|
107
123
|
|
|
108
124
|
**What it does:**
|
|
109
|
-
1.
|
|
110
|
-
2. Clones the
|
|
111
|
-
3.
|
|
112
|
-
4. Saves the problem statement to `PROBLEM_STATEMENT.md`
|
|
125
|
+
1. Uses your SSH key from `/configure` to access the repository
|
|
126
|
+
2. Clones only the specific problem branch (shallow clone)
|
|
127
|
+
3. Sets up the workspace at `workspace/{problem_id}/`
|
|
113
128
|
|
|
114
129
|
### Tool: `/submit`
|
|
115
130
|
|
|
@@ -117,15 +132,13 @@ Submits your solution by committing changes and pushing to the remote repository
|
|
|
117
132
|
|
|
118
133
|
**Parameters:**
|
|
119
134
|
- `problem_id` (required): Problem identifier
|
|
120
|
-
- `user_id` (
|
|
121
|
-
- `server_url` (optional): Backend server URL (default: `"https://api.example.com"`)
|
|
135
|
+
- `user_id` (optional): Your user ID (uses configured value if not provided)
|
|
122
136
|
- `commit_message` (optional): Custom commit message
|
|
123
137
|
|
|
124
138
|
**Example:**
|
|
125
139
|
```json
|
|
126
140
|
{
|
|
127
141
|
"problem_id": "django__django-10097",
|
|
128
|
-
"user_id": "user_123",
|
|
129
142
|
"commit_message": "Fixed the authentication bug"
|
|
130
143
|
}
|
|
131
144
|
```
|
|
@@ -138,25 +151,22 @@ Submits your solution by committing changes and pushing to the remote repository
|
|
|
138
151
|
|
|
139
152
|
## Backend API Endpoints
|
|
140
153
|
|
|
141
|
-
The MCP server
|
|
154
|
+
The MCP server connects to the hardcoded AI Coding Gym server and uses the following endpoints:
|
|
142
155
|
|
|
143
|
-
### POST `/api/
|
|
156
|
+
### POST `/api/configure`
|
|
144
157
|
|
|
145
158
|
**Request:**
|
|
146
159
|
```json
|
|
147
160
|
{
|
|
148
|
-
"
|
|
149
|
-
"
|
|
161
|
+
"user_id": "user_123",
|
|
162
|
+
"public_key": "ssh-rsa AAAAB3..."
|
|
150
163
|
}
|
|
151
164
|
```
|
|
152
165
|
|
|
153
166
|
**Response:**
|
|
154
167
|
```json
|
|
155
168
|
{
|
|
156
|
-
"
|
|
157
|
-
"branch": "django__django-10097-user_123",
|
|
158
|
-
"deploy_key": "-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----",
|
|
159
|
-
"problem_statement": "# Problem Description\n\n..."
|
|
169
|
+
"repo_name": "user_123-swebench"
|
|
160
170
|
}
|
|
161
171
|
```
|
|
162
172
|
|
|
@@ -183,23 +193,16 @@ The MCP server expects the following backend API endpoints:
|
|
|
183
193
|
|
|
184
194
|
## Security
|
|
185
195
|
|
|
186
|
-
-
|
|
187
|
-
- Keys are
|
|
196
|
+
- User SSH keys are stored in `~/.mcp-keys/` with 600 permissions
|
|
197
|
+
- Keys are generated locally and public key is shared with the server
|
|
188
198
|
- SSH host key checking is disabled for convenience (consider enabling in production)
|
|
189
|
-
-
|
|
190
|
-
|
|
191
|
-
## Configuration
|
|
192
|
-
|
|
193
|
-
Default server URL is `https://api.example.com`. You can override it by passing `server_url` parameter to each tool call, or set it via environment variable:
|
|
194
|
-
|
|
195
|
-
```bash
|
|
196
|
-
export AI_CODING_GYM_SERVER="https://your-server.com"
|
|
197
|
-
```
|
|
199
|
+
- Configuration is cached in memory during the MCP server session
|
|
198
200
|
|
|
199
201
|
## Troubleshooting
|
|
200
202
|
|
|
201
203
|
**"No credentials found for problem_id"**
|
|
202
|
-
- Run `/
|
|
204
|
+
- Run `/configure` first to set up your credentials
|
|
205
|
+
- Then run `/fetch` to download the problem
|
|
203
206
|
|
|
204
207
|
**"Git clone/push failed"**
|
|
205
208
|
- Check network connectivity
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
server.py,sha256=CPUOvS60mwvBa7iSFGkUhFvfi2sB8DAJr1eHqB1MJYQ,16939
|
|
2
|
+
ai_coding_gym_mcp-0.1.3.dist-info/METADATA,sha256=mf71-4IFxeRbyuRF8FyW--PmJ76-2i_95T5v6y4WAjU,6223
|
|
3
|
+
ai_coding_gym_mcp-0.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
4
|
+
ai_coding_gym_mcp-0.1.3.dist-info/entry_points.txt,sha256=O_Ya91fge6V-bwpf4oace2eFB2asJVEE4Oe3fWcL6dY,50
|
|
5
|
+
ai_coding_gym_mcp-0.1.3.dist-info/top_level.txt,sha256=StKOSmRhvWS5IPcvhsDRbtxUTEofJgYFGOu5AAJdSWo,7
|
|
6
|
+
ai_coding_gym_mcp-0.1.3.dist-info/RECORD,,
|
server.py
CHANGED
|
@@ -66,10 +66,6 @@ FETCH_TOOL = Tool(
|
|
|
66
66
|
"type": "string",
|
|
67
67
|
"description": "Your user ID (optional if configured globally via /configure)"
|
|
68
68
|
},
|
|
69
|
-
"server_url": {
|
|
70
|
-
"type": "string",
|
|
71
|
-
"description": "Backend server URL (optional if configured globally)"
|
|
72
|
-
},
|
|
73
69
|
"workspace_dir": {
|
|
74
70
|
"type": "string",
|
|
75
71
|
"description": "Local directory to clone the repository into (optional)"
|
|
@@ -94,10 +90,6 @@ SUBMIT_TOOL = Tool(
|
|
|
94
90
|
"type": "string",
|
|
95
91
|
"description": "Your user ID (optional if configured globally via /configure)"
|
|
96
92
|
},
|
|
97
|
-
"server_url": {
|
|
98
|
-
"type": "string",
|
|
99
|
-
"description": "Backend server URL (optional if configured globally)"
|
|
100
|
-
},
|
|
101
93
|
"commit_message": {
|
|
102
94
|
"type": "string",
|
|
103
95
|
"description": "Custom commit message (optional)"
|
|
@@ -225,7 +217,6 @@ async def configure(
|
|
|
225
217
|
|
|
226
218
|
# Store configuration
|
|
227
219
|
config_store["user_id"] = user_id
|
|
228
|
-
config_store["server_url"] = server_url
|
|
229
220
|
config_store["repo_name"] = repo_name
|
|
230
221
|
config_store["private_key_path"] = str(private_key_path)
|
|
231
222
|
|
|
@@ -235,7 +226,6 @@ async def configure(
|
|
|
235
226
|
return f"""Configuration saved successfully!
|
|
236
227
|
|
|
237
228
|
User ID: {user_id}
|
|
238
|
-
Server URL: {server_url}
|
|
239
229
|
Repository: {repo_name}
|
|
240
230
|
Workspace: {workspace_dir or 'Default (./workspace)'}
|
|
241
231
|
SSH Key: {private_key_path}
|
|
@@ -253,7 +243,6 @@ You can now use /fetch and /submit without passing these parameters.
|
|
|
253
243
|
async def fetch_problem(
|
|
254
244
|
problem_id: str,
|
|
255
245
|
user_id: Optional[str] = None,
|
|
256
|
-
server_url: Optional[str] = None,
|
|
257
246
|
workspace_dir: Optional[str] = None
|
|
258
247
|
) -> str:
|
|
259
248
|
"""
|
|
@@ -262,7 +251,6 @@ async def fetch_problem(
|
|
|
262
251
|
try:
|
|
263
252
|
# Use configured values if not provided
|
|
264
253
|
user_id = user_id or config_store.get("user_id") or infer_user_id_from_keys()
|
|
265
|
-
server_url = server_url or config_store.get("server_url") or DEFAULT_SERVER_URL
|
|
266
254
|
workspace_dir = workspace_dir or config_store.get("workspace_dir", "./workspace")
|
|
267
255
|
repo_name = config_store.get("repo_name")
|
|
268
256
|
|
|
@@ -294,7 +282,6 @@ async def fetch_problem(
|
|
|
294
282
|
"repo_url": repo_url,
|
|
295
283
|
"branch": branch,
|
|
296
284
|
"user_id": user_id,
|
|
297
|
-
"server_url": server_url,
|
|
298
285
|
"private_key_path": private_key_path
|
|
299
286
|
}
|
|
300
287
|
|
|
@@ -349,7 +336,6 @@ You can now start working on the solution!
|
|
|
349
336
|
async def submit_solution(
|
|
350
337
|
problem_id: str,
|
|
351
338
|
user_id: Optional[str] = None,
|
|
352
|
-
server_url: Optional[str] = None,
|
|
353
339
|
commit_message: Optional[str] = None
|
|
354
340
|
) -> str:
|
|
355
341
|
"""
|
|
@@ -358,15 +344,11 @@ async def submit_solution(
|
|
|
358
344
|
try:
|
|
359
345
|
# Use configured values if not provided
|
|
360
346
|
user_id = user_id or config_store.get("user_id") or infer_user_id_from_keys()
|
|
361
|
-
server_url = server_url or config_store.get("server_url") or DEFAULT_SERVER_URL
|
|
362
347
|
commit_message = commit_message or ""
|
|
363
348
|
|
|
364
349
|
if not user_id:
|
|
365
350
|
return "Error: Could not determine user_id. Please run /configure first to set up your credentials."
|
|
366
351
|
|
|
367
|
-
if not server_url:
|
|
368
|
-
return "Error: server_url is required. Please run /configure first or pass it as a parameter."
|
|
369
|
-
|
|
370
352
|
# Check if we have cached credentials
|
|
371
353
|
if problem_id not in credentials_store:
|
|
372
354
|
return f"Error: No credentials found for {problem_id}. Please run /fetch first."
|
|
@@ -423,7 +405,7 @@ async def submit_solution(
|
|
|
423
405
|
return f"Error: Git push failed:\n{result.stderr}"
|
|
424
406
|
|
|
425
407
|
# Notify backend server
|
|
426
|
-
api_endpoint = f"{
|
|
408
|
+
api_endpoint = f"{DEFAULT_SERVER_URL}/api/submit"
|
|
427
409
|
payload = {
|
|
428
410
|
"problem_id": problem_id,
|
|
429
411
|
"user_id": user_id,
|
|
@@ -473,7 +455,6 @@ async def call_tool(name: str, arguments: Any) -> list[TextContent]:
|
|
|
473
455
|
result = await fetch_problem(
|
|
474
456
|
problem_id=arguments["problem_id"],
|
|
475
457
|
user_id=arguments.get("user_id"),
|
|
476
|
-
server_url=arguments.get("server_url"),
|
|
477
458
|
workspace_dir=arguments.get("workspace_dir")
|
|
478
459
|
)
|
|
479
460
|
return [TextContent(type="text", text=result)]
|
|
@@ -482,7 +463,6 @@ async def call_tool(name: str, arguments: Any) -> list[TextContent]:
|
|
|
482
463
|
result = await submit_solution(
|
|
483
464
|
problem_id=arguments["problem_id"],
|
|
484
465
|
user_id=arguments.get("user_id"),
|
|
485
|
-
server_url=arguments.get("server_url"),
|
|
486
466
|
commit_message=arguments.get("commit_message")
|
|
487
467
|
)
|
|
488
468
|
return [TextContent(type="text", text=result)]
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
server.py,sha256=wuol2aas5zY1-DP6c5JMfcve46xYPdX95ygo_pCCqEs,17875
|
|
2
|
-
ai_coding_gym_mcp-0.1.1.dist-info/METADATA,sha256=sGOqY3YC9Xwck1o0au2DeiQHsGM-puJnTGYzyEPg12Q,6377
|
|
3
|
-
ai_coding_gym_mcp-0.1.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
4
|
-
ai_coding_gym_mcp-0.1.1.dist-info/entry_points.txt,sha256=O_Ya91fge6V-bwpf4oace2eFB2asJVEE4Oe3fWcL6dY,50
|
|
5
|
-
ai_coding_gym_mcp-0.1.1.dist-info/top_level.txt,sha256=StKOSmRhvWS5IPcvhsDRbtxUTEofJgYFGOu5AAJdSWo,7
|
|
6
|
-
ai_coding_gym_mcp-0.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|