Add forgejo-mcp/server_wrapper.py
This commit is contained in:
parent
02d13c58c9
commit
03a88fc31e
1 changed files with 106 additions and 0 deletions
106
forgejo-mcp/server_wrapper.py
Normal file
106
forgejo-mcp/server_wrapper.py
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
"""
|
||||
Forgejo MCP Server Wrapper
|
||||
Runs the MCP server with HTTP transport on port 8400
|
||||
Compatible with MCP Gateway tool discovery
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
import uvicorn
|
||||
from starlette.applications import Starlette
|
||||
from starlette.responses import JSONResponse
|
||||
from starlette.routing import Route
|
||||
|
||||
from forgejo_mcp import server
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger("forgejo-mcp")
|
||||
|
||||
PORT = int(os.environ.get("PORT", "8400"))
|
||||
|
||||
|
||||
async def handle_list_tools(request):
|
||||
"""GET /tools - List available tools."""
|
||||
try:
|
||||
tools = await server.list_tools()
|
||||
return JSONResponse(tools)
|
||||
except Exception as e:
|
||||
logger.error(f"Error listing tools: {e}")
|
||||
return JSONResponse({"error": str(e)}, status_code=500)
|
||||
|
||||
|
||||
async def handle_call_tool(request):
|
||||
"""POST /call_tool - Call a specific tool."""
|
||||
try:
|
||||
data = await request.json()
|
||||
tool_name = data.get("name") or data.get("tool")
|
||||
arguments = data.get("arguments", {})
|
||||
|
||||
if not tool_name:
|
||||
return JSONResponse({"error": "Missing 'name' or 'tool' parameter"}, status_code=400)
|
||||
|
||||
logger.info(f"Calling tool: {tool_name} with args: {arguments}")
|
||||
result = await server.call_tool(tool_name, arguments)
|
||||
|
||||
return JSONResponse({
|
||||
"content": [{"type": "text", "text": r.text} for r in result]
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"Tool call error: {e}", exc_info=True)
|
||||
return JSONResponse({"error": str(e)}, status_code=500)
|
||||
|
||||
|
||||
async def handle_health(request):
|
||||
"""GET /health - Health check endpoint."""
|
||||
return JSONResponse({"status": "healthy"})
|
||||
|
||||
|
||||
async def handle_mcp_sse(request):
|
||||
"""POST /mcp - Handle MCP SSE protocol requests from gateway."""
|
||||
try:
|
||||
logger.info(f"MCP request: {request.method} {request.url.path}")
|
||||
|
||||
# For POST requests, parse the JSON body
|
||||
if request.method == "POST":
|
||||
try:
|
||||
data = await request.json()
|
||||
logger.info(f"MCP POST data: {data}")
|
||||
|
||||
# Check if this is a tool call request
|
||||
if "name" in data or "tool" in data:
|
||||
return await handle_call_tool(request)
|
||||
except Exception as e:
|
||||
logger.warning(f"Could not parse JSON: {e}")
|
||||
|
||||
# For GET requests or other cases, list tools
|
||||
return await handle_list_tools(request)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"MCP handler error: {e}", exc_info=True)
|
||||
return JSONResponse({"error": str(e)}, status_code=500)
|
||||
|
||||
|
||||
# Create Starlette app with routes
|
||||
app = Starlette(
|
||||
routes=[
|
||||
Route("/tools", handle_list_tools, methods=["GET"]),
|
||||
Route("/call_tool", handle_call_tool, methods=["POST"]),
|
||||
Route("/health", handle_health, methods=["GET"]),
|
||||
Route("/mcp", handle_mcp_sse, methods=["GET", "POST"]),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
logger.info(f"Starting Forgejo MCP server on port {PORT}")
|
||||
config = uvicorn.Config(
|
||||
app=app,
|
||||
host="0.0.0.0",
|
||||
port=PORT,
|
||||
log_level="info",
|
||||
)
|
||||
server_instance = uvicorn.Server(config)
|
||||
asyncio.run(server_instance.serve())
|
||||
Loading…
Reference in a new issue