Files
hunjing/backend/app/api/v1/endpoints/mcp.py
T
2026-08-21 16:00:13 +08:00

174 lines
5.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""MCP server API(/tools/mcp-servers,skills-design §6)。
支持两种传输协议:streamable-http / stdio。
stdio 模式通过 /start、/stop、/restart 控制子进程生命周期。
"""
from fastapi import APIRouter, Depends, Query
from fastapi import status as http_status
from app.api.v1.deps import get_optional_tool_runtime
from app.application.tool_runtime.runtime import ToolRuntime
from app.integrations.mcp.process_manager import get_process_manager
from app.schemas.mcp import (
CreateMcpServerRequest,
McpServerResponse,
McpServerStatusResponse,
UpdateMcpServerRequest,
)
from app.services import mcp as mcp_service
router = APIRouter(prefix="/tools/mcp-servers", tags=["mcp"])
@router.post(
"",
response_model=McpServerResponse,
status_code=http_status.HTTP_201_CREATED,
)
async def register_mcp_server(
payload: CreateMcpServerRequest,
runtime: ToolRuntime | None = Depends(get_optional_tool_runtime),
) -> McpServerResponse:
"""注册 MCP server。
streamable-http:同步拉取工具清单并注册到运行时。
stdio:只存 DB,需后续调用 /start 启动子进程后拉取工具。
"""
return await mcp_service.register_mcp_server(
name=payload.name,
transport=payload.transport,
endpoint_url=payload.endpoint_url,
auth_token=payload.auth_token,
command=payload.command,
args_json=payload.args_json,
env_json=payload.env_json,
cwd=payload.cwd,
status=payload.status,
runtime=runtime,
process_manager=get_process_manager(),
)
@router.get("", response_model=list[McpServerResponse])
async def list_mcp_servers(
status: str | None = Query(default=None, description="按状态过滤:enabled/disabled"),
) -> list[McpServerResponse]:
"""列举 MCP server(含工具清单摘要)。"""
return await mcp_service.list_mcp_servers(status=status)
@router.patch(
"/{server_id}",
response_model=McpServerResponse,
)
async def update_mcp_server(
server_id: str,
payload: UpdateMcpServerRequest,
runtime: ToolRuntime | None = Depends(get_optional_tool_runtime),
) -> McpServerResponse:
"""更新 MCP server 字段(部分更新)。"""
return await mcp_service.update_mcp_server(
server_id,
status=payload.status,
endpoint_url=payload.endpoint_url,
auth_token=payload.auth_token,
command=payload.command,
args_json=payload.args_json,
env_json=payload.env_json,
cwd=payload.cwd,
runtime=runtime,
process_manager=get_process_manager(),
)
@router.delete("/{server_id}", status_code=http_status.HTTP_204_NO_CONTENT)
async def delete_mcp_server(
server_id: str,
runtime: ToolRuntime | None = Depends(get_optional_tool_runtime),
) -> None:
"""删除 MCP server(先 stop 子进程再删)。"""
await mcp_service.delete_mcp_server(
server_id,
runtime=runtime,
process_manager=get_process_manager(),
)
@router.post(
"/{server_id}/start",
response_model=McpServerStatusResponse,
)
async def start_mcp_server(
server_id: str,
runtime: ToolRuntime | None = Depends(get_optional_tool_runtime),
) -> McpServerStatusResponse:
"""启动 stdio MCP server 子进程,拉取工具并注册。"""
return await mcp_service.start_mcp_server(
server_id,
runtime=runtime,
process_manager=get_process_manager(),
)
@router.post(
"/{server_id}/stop",
response_model=McpServerStatusResponse,
)
async def stop_mcp_server(
server_id: str,
runtime: ToolRuntime | None = Depends(get_optional_tool_runtime),
) -> McpServerStatusResponse:
"""停止 stdio MCP server 子进程,注销工具。"""
return await mcp_service.stop_mcp_server(
server_id,
runtime=runtime,
process_manager=get_process_manager(),
)
@router.post(
"/{server_id}/restart",
response_model=McpServerStatusResponse,
)
async def restart_mcp_server(
server_id: str,
runtime: ToolRuntime | None = Depends(get_optional_tool_runtime),
) -> McpServerStatusResponse:
"""重启 stdio MCP server。"""
return await mcp_service.restart_mcp_server(
server_id,
runtime=runtime,
process_manager=get_process_manager(),
)
@router.get(
"/{server_id}/status",
response_model=McpServerStatusResponse,
)
async def get_mcp_server_status(
server_id: str,
) -> McpServerStatusResponse:
"""查询 MCP server 进程状态。"""
return await mcp_service.get_mcp_server_status(
server_id,
process_manager=get_process_manager(),
)
@router.post(
"/{server_id}/refresh",
response_model=McpServerResponse,
)
async def refresh_mcp_server_tools(
server_id: str,
runtime: ToolRuntime | None = Depends(get_optional_tool_runtime),
) -> McpServerResponse:
"""重新拉取 MCP server 工具清单并注册到运行时。"""
return await mcp_service.refresh_mcp_server_tools(
server_id,
runtime=runtime,
process_manager=get_process_manager(),
)