sarveshpatel commited on
Commit
7094811
Β·
verified Β·
1 Parent(s): 54054d3

Create app/main.py

Browse files
Files changed (1) hide show
  1. app/main.py +111 -0
app/main.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """FastAPI application entry point - MCP Code Executor."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import sys
7
+ from contextlib import asynccontextmanager
8
+
9
+ from fastapi import FastAPI, Request
10
+ from fastapi.middleware.cors import CORSMiddleware
11
+ from fastapi.responses import JSONResponse
12
+
13
+ from app.config import get_settings
14
+ from app.executor import get_executor
15
+ from app.routes import health, mcp, tools
16
+
17
+ # ─── Logging Configuration ────────────────────────────────────────
18
+
19
+ logging.basicConfig(
20
+ level=logging.INFO,
21
+ format="%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
22
+ datefmt="%Y-%m-%d %H:%M:%S",
23
+ stream=sys.stdout,
24
+ )
25
+ logger = logging.getLogger("mcp_code_executor")
26
+
27
+
28
+ # ─── Application Lifespan ─────────────────────────────────────────
29
+
30
+ @asynccontextmanager
31
+ async def lifespan(app: FastAPI):
32
+ """Startup and shutdown logic."""
33
+ settings = get_settings()
34
+ logger.info("=" * 60)
35
+ logger.info("MCP Code Executor starting up")
36
+ logger.info(" Environment: %s", settings.env_type.value)
37
+ logger.info(" Code storage: %s", settings.code_storage_dir)
38
+ logger.info(" Max concurrent: %d", settings.max_concurrent_executions)
39
+ logger.info(" Execution timeout: %ds", settings.execution_timeout)
40
+ logger.info(" Python executable: %s", settings.get_python_executable())
41
+ logger.info("=" * 60)
42
+
43
+ yield
44
+
45
+ # Shutdown: cleanup active processes
46
+ logger.info("Shutting down - cleaning up active processes...")
47
+ executor = get_executor()
48
+ await executor.cleanup()
49
+ logger.info("Shutdown complete")
50
+
51
+
52
+ # ─── FastAPI Application ──────────────────────────────────────────
53
+
54
+ app = FastAPI(
55
+ title="MCP Code Executor",
56
+ description=(
57
+ "An MCP server that allows LLMs to execute Python code within a "
58
+ "specified Python environment. Supports incremental code generation, "
59
+ "package management, and concurrent execution."
60
+ ),
61
+ version="1.0.0",
62
+ lifespan=lifespan,
63
+ docs_url="/docs",
64
+ redoc_url="/redoc",
65
+ openapi_url="/openapi.json",
66
+ )
67
+
68
+ # ─── CORS Middleware ───────────────────────────────────────────────
69
+
70
+ app.add_middleware(
71
+ CORSMiddleware,
72
+ allow_origins=["*"],
73
+ allow_credentials=True,
74
+ allow_methods=["*"],
75
+ allow_headers=["*"],
76
+ )
77
+
78
+
79
+ # ─── Global Exception Handler ─────────────────────────────────────
80
+
81
+ @app.exception_handler(Exception)
82
+ async def global_exception_handler(request: Request, exc: Exception):
83
+ logger.exception("Unhandled exception on %s %s", request.method, request.url.path)
84
+ return JSONResponse(
85
+ status_code=500,
86
+ content={
87
+ "error": "Internal server error",
88
+ "detail": str(exc),
89
+ },
90
+ )
91
+
92
+
93
+ # ─── Register Routes ──────────────────────────────────────────────
94
+
95
+ app.include_router(health.router)
96
+ app.include_router(mcp.router)
97
+ app.include_router(tools.router)
98
+
99
+
100
+ # ─── Direct Run (development) ─────────────────────────────────────
101
+
102
+ if __name__ == "__main__":
103
+ import uvicorn
104
+
105
+ uvicorn.run(
106
+ "app.main:app",
107
+ host="0.0.0.0",
108
+ port=7860,
109
+ reload=True,
110
+ log_level="info",
111
+ )