ai-coding-gym-mcp 0.1.4__py3-none-any.whl → 0.1.5__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.4.dist-info → ai_coding_gym_mcp-0.1.5.dist-info}/METADATA +1 -1
- ai_coding_gym_mcp-0.1.5.dist-info/RECORD +6 -0
- server.py +51 -144
- ai_coding_gym_mcp-0.1.4.dist-info/RECORD +0 -6
- {ai_coding_gym_mcp-0.1.4.dist-info → ai_coding_gym_mcp-0.1.5.dist-info}/WHEEL +0 -0
- {ai_coding_gym_mcp-0.1.4.dist-info → ai_coding_gym_mcp-0.1.5.dist-info}/entry_points.txt +0 -0
- {ai_coding_gym_mcp-0.1.4.dist-info → ai_coding_gym_mcp-0.1.5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
server.py,sha256=EpEFN-XHdE0x2GFMMaA9SYuTY6ulSFezI8i7A_g8gB0,13980
|
|
2
|
+
ai_coding_gym_mcp-0.1.5.dist-info/METADATA,sha256=7M0rJOZdNzyWJ0nCEshptavra2hi41_ec2AnFa6IXPc,6526
|
|
3
|
+
ai_coding_gym_mcp-0.1.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
4
|
+
ai_coding_gym_mcp-0.1.5.dist-info/entry_points.txt,sha256=8RFDakwz8EhbAs4nFxFMAFuiH2NBJsZygTNgWIs-nV4,82
|
|
5
|
+
ai_coding_gym_mcp-0.1.5.dist-info/top_level.txt,sha256=StKOSmRhvWS5IPcvhsDRbtxUTEofJgYFGOu5AAJdSWo,7
|
|
6
|
+
ai_coding_gym_mcp-0.1.5.dist-info/RECORD,,
|
server.py
CHANGED
|
@@ -4,23 +4,20 @@ MCP Server for AI Coding Gym
|
|
|
4
4
|
Provides /fetch and /submit tools for local problem solving workflow
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
import asyncio
|
|
8
|
-
import json
|
|
9
7
|
import os
|
|
10
8
|
import subprocess
|
|
11
|
-
import tempfile
|
|
12
9
|
from datetime import datetime
|
|
13
10
|
from pathlib import Path
|
|
14
11
|
from typing import Any, Dict, Optional
|
|
15
12
|
import requests
|
|
16
13
|
|
|
17
|
-
from mcp.server import
|
|
18
|
-
from mcp.types import Tool, TextContent, ErrorData
|
|
19
|
-
import mcp.server.stdio
|
|
14
|
+
from mcp.server.fastmcp import FastMCP
|
|
20
15
|
|
|
21
16
|
|
|
17
|
+
# Initialize FastMCP server
|
|
18
|
+
mcp = FastMCP("ai-coding-gym")
|
|
19
|
+
|
|
22
20
|
# Global state
|
|
23
|
-
app = Server("ai-coding-gym")
|
|
24
21
|
credentials_store: Dict[str, Dict[str, Any]] = {} # problem_id -> {deploy_key, repo_url, branch, etc}
|
|
25
22
|
config_store: Dict[str, str] = {} # Global config: user_id, server_url, api_key
|
|
26
23
|
|
|
@@ -28,78 +25,6 @@ config_store: Dict[str, str] = {} # Global config: user_id, server_url, api_key
|
|
|
28
25
|
DEFAULT_SERVER_URL = "http://ai-coding-gym.cis240515.projects.jetstream-cloud.org:4000"
|
|
29
26
|
|
|
30
27
|
|
|
31
|
-
# Tool definitions
|
|
32
|
-
CONFIGURE_TOOL = Tool(
|
|
33
|
-
name="configure",
|
|
34
|
-
description="Configure global settings for the MCP server. Generates an SSH key pair locally, "
|
|
35
|
-
"sends the public key to the server, and receives your repository name. "
|
|
36
|
-
"Set your user_id once. "
|
|
37
|
-
"These values will be used as defaults for all fetch and submit operations.",
|
|
38
|
-
inputSchema={
|
|
39
|
-
"type": "object",
|
|
40
|
-
"properties": {
|
|
41
|
-
"user_id": {
|
|
42
|
-
"type": "string",
|
|
43
|
-
"description": "Your user ID for authentication with the backend server"
|
|
44
|
-
},
|
|
45
|
-
"workspace_dir": {
|
|
46
|
-
"type": "string",
|
|
47
|
-
"description": "Default workspace directory for cloning repositories (optional)"
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
"required": ["user_id"]
|
|
51
|
-
}
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
FETCH_TOOL = Tool(
|
|
55
|
-
name="fetch",
|
|
56
|
-
description="Fetch a coding problem from the server and clone the repository locally. "
|
|
57
|
-
"Uses your SSH key from /configure to access the repository.",
|
|
58
|
-
inputSchema={
|
|
59
|
-
"type": "object",
|
|
60
|
-
"properties": {
|
|
61
|
-
"problem_id": {
|
|
62
|
-
"type": "string",
|
|
63
|
-
"description": "The unique identifier for the problem (e.g., 'django__django-10097')"
|
|
64
|
-
},
|
|
65
|
-
"user_id": {
|
|
66
|
-
"type": "string",
|
|
67
|
-
"description": "Your user ID (optional if configured globally via /configure)"
|
|
68
|
-
},
|
|
69
|
-
"workspace_dir": {
|
|
70
|
-
"type": "string",
|
|
71
|
-
"description": "Local directory to clone the repository into (optional)"
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
"required": ["problem_id"]
|
|
75
|
-
}
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
SUBMIT_TOOL = Tool(
|
|
79
|
-
name="submit",
|
|
80
|
-
description="Submit your solution by committing all changes and pushing to the remote repository. "
|
|
81
|
-
"Notifies the backend server that a submission has been made.",
|
|
82
|
-
inputSchema={
|
|
83
|
-
"type": "object",
|
|
84
|
-
"properties": {
|
|
85
|
-
"problem_id": {
|
|
86
|
-
"type": "string",
|
|
87
|
-
"description": "The unique identifier for the problem"
|
|
88
|
-
},
|
|
89
|
-
"user_id": {
|
|
90
|
-
"type": "string",
|
|
91
|
-
"description": "Your user ID (optional if configured globally via /configure)"
|
|
92
|
-
},
|
|
93
|
-
"commit_message": {
|
|
94
|
-
"type": "string",
|
|
95
|
-
"description": "Custom commit message (optional)"
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
"required": ["problem_id"]
|
|
99
|
-
}
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
|
|
103
28
|
# Helper functions for Git SSH key management
|
|
104
29
|
def infer_user_id_from_keys() -> Optional[str]:
|
|
105
30
|
"""
|
|
@@ -190,11 +115,23 @@ def run_git_command(cmd: str, cwd: str, key_path: Optional[Path] = None) -> subp
|
|
|
190
115
|
|
|
191
116
|
|
|
192
117
|
# Tool implementations
|
|
193
|
-
|
|
118
|
+
@mcp.tool()
|
|
119
|
+
def configure(
|
|
194
120
|
user_id: str,
|
|
195
|
-
workspace_dir:
|
|
121
|
+
workspace_dir: str = None
|
|
196
122
|
) -> str:
|
|
197
|
-
"""
|
|
123
|
+
"""
|
|
124
|
+
Configure global settings for the MCP server. Generates an SSH key pair locally,
|
|
125
|
+
sends the public key to the server, and receives your repository name.
|
|
126
|
+
Set your user_id once. These values will be used as defaults for all fetch and submit operations.
|
|
127
|
+
|
|
128
|
+
:param user_id: Your user ID for authentication with the backend server
|
|
129
|
+
:type user_id: str
|
|
130
|
+
:param workspace_dir: Default workspace directory for cloning repositories (optional)
|
|
131
|
+
:type workspace_dir: str
|
|
132
|
+
:return: Configuration status message
|
|
133
|
+
:rtype: str
|
|
134
|
+
"""
|
|
198
135
|
server_url = DEFAULT_SERVER_URL
|
|
199
136
|
try:
|
|
200
137
|
# Generate SSH key pair
|
|
@@ -240,13 +177,24 @@ You can now use /fetch and /submit without passing these parameters.
|
|
|
240
177
|
return f"Error: Configuration failed: {str(e)}"
|
|
241
178
|
|
|
242
179
|
|
|
243
|
-
|
|
180
|
+
@mcp.tool()
|
|
181
|
+
def fetch_problem(
|
|
244
182
|
problem_id: str,
|
|
245
|
-
user_id:
|
|
246
|
-
workspace_dir:
|
|
183
|
+
user_id: str = None,
|
|
184
|
+
workspace_dir: str = None
|
|
247
185
|
) -> str:
|
|
248
186
|
"""
|
|
249
|
-
Fetch
|
|
187
|
+
Fetch a coding problem from the server and clone the repository locally.
|
|
188
|
+
Uses your SSH key from /configure to access the repository.
|
|
189
|
+
|
|
190
|
+
:param problem_id: The unique identifier for the problem (e.g., 'django__django-10097')
|
|
191
|
+
:type problem_id: str
|
|
192
|
+
:param user_id: Your user ID (optional if configured globally via /configure)
|
|
193
|
+
:type user_id: str
|
|
194
|
+
:param workspace_dir: Local directory to clone the repository into (optional)
|
|
195
|
+
:type workspace_dir: str
|
|
196
|
+
:return: Fetch status message
|
|
197
|
+
:rtype: str
|
|
250
198
|
"""
|
|
251
199
|
try:
|
|
252
200
|
# Use configured values if not provided
|
|
@@ -333,13 +281,24 @@ You can now start working on the solution!
|
|
|
333
281
|
return f"Error: Unexpected error: {str(e)}"
|
|
334
282
|
|
|
335
283
|
|
|
336
|
-
|
|
284
|
+
@mcp.tool()
|
|
285
|
+
def submit_solution(
|
|
337
286
|
problem_id: str,
|
|
338
|
-
user_id:
|
|
339
|
-
commit_message:
|
|
287
|
+
user_id: str = None,
|
|
288
|
+
commit_message: str = None
|
|
340
289
|
) -> str:
|
|
341
290
|
"""
|
|
342
|
-
Submit solution by committing and pushing
|
|
291
|
+
Submit your solution by committing all changes and pushing to the remote repository.
|
|
292
|
+
Notifies the backend server that a submission has been made.
|
|
293
|
+
|
|
294
|
+
:param problem_id: The unique identifier for the problem
|
|
295
|
+
:type problem_id: str
|
|
296
|
+
:param user_id: Your user ID (optional if configured globally via /configure)
|
|
297
|
+
:type user_id: str
|
|
298
|
+
:param commit_message: Custom commit message (optional)
|
|
299
|
+
:type commit_message: str
|
|
300
|
+
:return: Submission status message
|
|
301
|
+
:rtype: str
|
|
343
302
|
"""
|
|
344
303
|
try:
|
|
345
304
|
# Use configured values if not provided
|
|
@@ -433,58 +392,6 @@ Your solution has been submitted for evaluation!
|
|
|
433
392
|
return f"Error: Unexpected error: {str(e)}"
|
|
434
393
|
|
|
435
394
|
|
|
436
|
-
# MCP Server handlers
|
|
437
|
-
@app.list_tools()
|
|
438
|
-
async def list_tools() -> list[Tool]:
|
|
439
|
-
"""List available tools."""
|
|
440
|
-
return [CONFIGURE_TOOL, FETCH_TOOL, SUBMIT_TOOL]
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
@app.call_tool()
|
|
444
|
-
async def call_tool(name: str, arguments: Any) -> list[TextContent]:
|
|
445
|
-
"""Handle tool calls."""
|
|
446
|
-
try:
|
|
447
|
-
if name == "configure":
|
|
448
|
-
result = await configure(
|
|
449
|
-
user_id=arguments["user_id"],
|
|
450
|
-
workspace_dir=arguments.get("workspace_dir")
|
|
451
|
-
)
|
|
452
|
-
return [TextContent(type="text", text=result)]
|
|
453
|
-
|
|
454
|
-
elif name == "fetch":
|
|
455
|
-
result = await fetch_problem(
|
|
456
|
-
problem_id=arguments["problem_id"],
|
|
457
|
-
user_id=arguments.get("user_id"),
|
|
458
|
-
workspace_dir=arguments.get("workspace_dir")
|
|
459
|
-
)
|
|
460
|
-
return [TextContent(type="text", text=result)]
|
|
461
|
-
|
|
462
|
-
elif name == "submit":
|
|
463
|
-
result = await submit_solution(
|
|
464
|
-
problem_id=arguments["problem_id"],
|
|
465
|
-
user_id=arguments.get("user_id"),
|
|
466
|
-
commit_message=arguments.get("commit_message")
|
|
467
|
-
)
|
|
468
|
-
return [TextContent(type="text", text=result)]
|
|
469
|
-
|
|
470
|
-
else:
|
|
471
|
-
raise ValueError(f"Unknown tool: {name}")
|
|
472
|
-
|
|
473
|
-
except KeyError as e:
|
|
474
|
-
return [TextContent(type="text", text=f"Error: Missing required parameter: {str(e)}")]
|
|
475
|
-
except Exception as e:
|
|
476
|
-
return [TextContent(type="text", text=f"Error: Error executing tool: {str(e)}")]
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
async def main():
|
|
480
|
-
"""Run the MCP server."""
|
|
481
|
-
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
|
|
482
|
-
await app.run(
|
|
483
|
-
read_stream,
|
|
484
|
-
write_stream,
|
|
485
|
-
app.create_initialization_options()
|
|
486
|
-
)
|
|
487
|
-
|
|
488
|
-
|
|
489
395
|
if __name__ == "__main__":
|
|
490
|
-
|
|
396
|
+
# Initialize and run the server
|
|
397
|
+
mcp.run(transport='stdio')
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
server.py,sha256=CPUOvS60mwvBa7iSFGkUhFvfi2sB8DAJr1eHqB1MJYQ,16939
|
|
2
|
-
ai_coding_gym_mcp-0.1.4.dist-info/METADATA,sha256=36X6NU8ecK7txC6d8KxQkkQExz-0t0_6RszSgoayJgw,6526
|
|
3
|
-
ai_coding_gym_mcp-0.1.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
4
|
-
ai_coding_gym_mcp-0.1.4.dist-info/entry_points.txt,sha256=8RFDakwz8EhbAs4nFxFMAFuiH2NBJsZygTNgWIs-nV4,82
|
|
5
|
-
ai_coding_gym_mcp-0.1.4.dist-info/top_level.txt,sha256=StKOSmRhvWS5IPcvhsDRbtxUTEofJgYFGOu5AAJdSWo,7
|
|
6
|
-
ai_coding_gym_mcp-0.1.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|