ai-coding-gym-mcp 0.1.4__tar.gz → 0.1.6__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ai-coding-gym-mcp
3
- Version: 0.1.4
3
+ Version: 0.1.6
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ai-coding-gym-mcp
3
- Version: 0.1.4
3
+ Version: 0.1.6
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ai-coding-gym-mcp"
3
- version = "0.1.4"
3
+ version = "0.1.6"
4
4
  description = "MCP server for AI Coding Gym - fetch and submit coding challenges"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -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 Server
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
- async def configure(
118
+ @mcp.tool()
119
+ def configure(
194
120
  user_id: str,
195
- workspace_dir: Optional[str] = None
121
+ workspace_dir: str = None
196
122
  ) -> str:
197
- """Configure global settings for the MCP server."""
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
- async def fetch_problem(
180
+ @mcp.tool()
181
+ def fetch_problem(
244
182
  problem_id: str,
245
- user_id: Optional[str] = None,
246
- workspace_dir: Optional[str] = None
183
+ user_id: str = None,
184
+ workspace_dir: str = None
247
185
  ) -> str:
248
186
  """
249
- Fetch problem by cloning only the specific branch from the forked repository.
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
- async def submit_solution(
284
+ @mcp.tool()
285
+ def submit_solution(
337
286
  problem_id: str,
338
- user_id: Optional[str] = None,
339
- commit_message: Optional[str] = None
287
+ user_id: str = None,
288
+ commit_message: str = None
340
289
  ) -> str:
341
290
  """
342
- Submit solution by committing and pushing changes, then notify backend.
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,10 @@ 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
- )
395
+ def main():
396
+ """Entry point for the MCP server."""
397
+ mcp.run(transport='stdio')
487
398
 
488
399
 
489
400
  if __name__ == "__main__":
490
- asyncio.run(main())
401
+ main()
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setup(
7
7
  name="ai-coding-gym-mcp",
8
- version="0.1.4",
8
+ version="0.1.6",
9
9
  author="AICodingGym Team",
10
10
  author_email="datasmithlab@gmail.com",
11
11
  description="MCP server for AI Coding Gym - fetch and submit AI coding challenges",