Skip to content

Commit 9d668aa

Browse files
committed
fix: remove codebase reset call, and fix async bug
1 parent 61964af commit 9d668aa

File tree

1 file changed

+30
-16
lines changed
  • codegen-examples/examples/codegen-mcp-server

1 file changed

+30
-16
lines changed

codegen-examples/examples/codegen-mcp-server/server.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import asyncio
22
from dataclasses import dataclass, field
3-
from typing import Annotated, Optional, Dict, Any, List
3+
import json
4+
from types import coroutine
5+
from typing import Annotated, Coroutine, Optional, Dict, Any, List
46
from mcp.server.fastmcp import FastMCP
57
from codegen import Codebase
68

@@ -11,20 +13,16 @@ class CodebaseState:
1113

1214
parse_task: Optional[asyncio.Future] = None
1315
parsed_codebase: Optional[Codebase] = None
14-
codebase_path: Optional[str] = None
1516
log_buffer: List[str] = field(default_factory=list)
1617

17-
async def parse(self, path: str) -> Codebase:
18+
def parse(self, path: str) -> Codebase:
1819
"""Parse the codebase at the given path."""
1920
codebase = Codebase(path)
2021
self.parsed_codebase = codebase
21-
self.codebase_path = path
2222
return codebase
2323

2424
def reset(self) -> None:
2525
"""Reset the state."""
26-
if self.parsed_codebase:
27-
self.parsed_codebase.reset()
2826
self.log_buffer.clear()
2927

3028

@@ -44,13 +42,27 @@ def capture_output(*args, **kwargs) -> None:
4442
for arg in args:
4543
state.log_buffer.append(str(arg))
4644

45+
def update_codebase(future: asyncio.Future):
46+
try:
47+
result = future.result()
48+
if result is not None:
49+
state.parsed_codebase = result
50+
else:
51+
state.parsed_codebase = None
52+
except Exception as e:
53+
pass
54+
55+
4756

4857
@mcp.tool(name="parse_codebase", description="Initiate codebase parsing")
4958
async def parse_codebase(codebase_path: Annotated[str, "path to the codebase to be parsed"]) -> Dict[str, str]:
5059
if not state.parse_task or state.parse_task.done():
5160
state.parse_task = asyncio.get_event_loop().run_in_executor(None, lambda: state.parse(codebase_path))
52-
return {"message": "Codebase parsing initiated, this may take some time depending on the size of the codebase. Use the `check_parsing_status` tool to check if the parse has completed."}
53-
return {"message": "Codebase is already being parsed."}
61+
state.parse_task.add_done_callback(update_codebase)
62+
return {
63+
"message": "Codebase parsing initiated, this may take some time depending on the size of the codebase. Use the `check_parsing_status` tool to check if the parse has completed."
64+
}
65+
return {"message": "Codebase is already being parsed.", "status": "error"}
5466

5567

5668
@mcp.tool(name="check_parse_status", description="Check if codebase parsing has completed")
@@ -69,17 +81,19 @@ async def execute_codemod(codemod: Annotated[str, "The python codemod code to ex
6981

7082
try:
7183
await state.parse_task
72-
# TODO: Implement proper sandboxing for code execution
73-
context = {
74-
"codebase": state.parsed_codebase,
75-
"print": capture_output,
76-
}
77-
exec(codemod, context)
84+
if (state.parsed_codebase is None):
85+
return {"error": "Codebase path is not set."}
86+
else:
87+
# TODO: Implement proper sandboxing for code execution
88+
context = {
89+
"codebase": state.parsed_codebase,
90+
"print": capture_output,
91+
}
92+
exec(codemod, context)
7893

7994
logs = "\n".join(state.log_buffer)
80-
8195
state.reset()
82-
return {"message": "Codemod executed and codebase reset.", "logs": logs}
96+
return {"message": "Codemod executed, view the logs for any output and your source code for any resulting updates.", "logs": logs}
8397
except Exception as e:
8498
return {"error": f"Error executing codemod: {str(e)}", "details": {"type": type(e).__name__, "message": str(e)}}
8599

0 commit comments

Comments
 (0)