Add MCP server management + fix OAuth
This commit is contained in:
parent
05397ceffc
commit
70a12093e9
1 changed files with 94 additions and 0 deletions
|
|
@ -623,6 +623,100 @@ async def auth_logout():
|
|||
return {"status": "error", "message": str(e)}
|
||||
|
||||
|
||||
# ============ MCP Server Management ============
|
||||
|
||||
@app.get("/api/mcp/servers")
|
||||
async def list_mcp_servers():
|
||||
"""List configured MCP servers"""
|
||||
try:
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
"claude", "mcp", "list",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=10)
|
||||
output = stdout.decode(errors="replace").strip()
|
||||
|
||||
# Parse the output — claude mcp list shows servers in a table or JSON
|
||||
servers = []
|
||||
if "No MCP servers configured" in output:
|
||||
return {"servers": [], "raw": output}
|
||||
|
||||
# Try JSON parse first
|
||||
try:
|
||||
import json as _json
|
||||
data = _json.loads(output)
|
||||
if isinstance(data, list):
|
||||
servers = data
|
||||
elif isinstance(data, dict):
|
||||
servers = list(data.values()) if data else []
|
||||
except Exception:
|
||||
# Parse text output line by line
|
||||
for line in output.split("\n"):
|
||||
line = line.strip()
|
||||
if line and not line.startswith("-") and not line.startswith("Name"):
|
||||
parts = line.split()
|
||||
if len(parts) >= 1:
|
||||
servers.append({"name": parts[0], "details": " ".join(parts[1:])})
|
||||
|
||||
return {"servers": servers, "raw": output}
|
||||
except Exception as e:
|
||||
return {"servers": [], "error": str(e)}
|
||||
|
||||
|
||||
class McpServerAdd(BaseModel):
|
||||
name: str
|
||||
server_type: str = "sse" # sse | stdio
|
||||
url: Optional[str] = None
|
||||
command: Optional[str] = None
|
||||
args: Optional[List[str]] = None
|
||||
|
||||
|
||||
@app.post("/api/mcp/servers")
|
||||
async def add_mcp_server(server: McpServerAdd):
|
||||
"""Add an MCP server"""
|
||||
try:
|
||||
cmd = ["claude", "mcp", "add", server.name]
|
||||
if server.server_type == "sse" and server.url:
|
||||
cmd.extend(["--transport", "sse", server.url])
|
||||
elif server.server_type == "stdio" and server.command:
|
||||
cmd.extend(["--transport", "stdio", server.command])
|
||||
if server.args:
|
||||
cmd.extend(server.args)
|
||||
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
*cmd,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=15)
|
||||
output = stdout.decode(errors="replace") + stderr.decode(errors="replace")
|
||||
|
||||
return {
|
||||
"status": "ok" if proc.returncode == 0 else "error",
|
||||
"message": output.strip(),
|
||||
"name": server.name
|
||||
}
|
||||
except Exception as e:
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
|
||||
@app.delete("/api/mcp/servers/{name}")
|
||||
async def remove_mcp_server(name: str):
|
||||
"""Remove an MCP server"""
|
||||
try:
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
"claude", "mcp", "remove", name,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=10)
|
||||
output = stdout.decode(errors="replace") + stderr.decode(errors="replace")
|
||||
return {"status": "ok" if proc.returncode == 0 else "error", "message": output.strip()}
|
||||
except Exception as e:
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
|
||||
# Serve static frontend
|
||||
app.mount("/", StaticFiles(directory="/app/frontend/dist", html=True), name="static")
|
||||
|
||||
|
|
|
|||
Reference in a new issue