| """ |
| 沙盒MCP插件 MCP工具定义 |
| """ |
|
|
| from app.mcp.decorators import mcp_tool |
| from pydantic import BaseModel, Field |
| from typing import List |
|
|
| from .main import plugin |
| from .sandbox.security import SecurityController |
| from .sandbox.file_ops import FileOperations |
| from .sandbox.command_exec import CommandExecutor |
|
|
|
|
| class ReadFileInput(BaseModel): |
| """文件读取工具输入参数""" |
| path: str = Field(description="文件相对路径(相对于沙盒根目录)") |
| encoding: str = Field(default="utf-8", description="文件编码") |
|
|
|
|
| class ReadFileOutput(BaseModel): |
| """文件读取工具输出结果""" |
| success: bool = Field(description="操作是否成功") |
| content: str | None = Field(default=None, description="文件内容") |
| size: int | None = Field(default=None, description="文件大小(字节)") |
| error: str | None = Field(default=None, description="错误信息") |
|
|
|
|
| class WriteFileInput(BaseModel): |
| """文件写入工具输入参数""" |
| path: str = Field(description="文件相对路径(相对于沙盒根目录)") |
| content: str = Field(description="文件内容") |
| mode: str = Field(default="write", description="写入模式:write 或 append") |
|
|
|
|
| class WriteFileOutput(BaseModel): |
| """文件写入工具输出结果""" |
| success: bool = Field(description="操作是否成功") |
| path: str | None = Field(default=None, description="写入的文件路径") |
| size: int | None = Field(default=None, description="文件大小(字节)") |
| error: str | None = Field(default=None, description="错误信息") |
|
|
|
|
| class ListFilesInput(BaseModel): |
| """文件列表工具输入参数""" |
| path: str = Field(default="", description="目录相对路径(空表示沙盒根目录)") |
| pattern: str = Field(default="*", description="匹配模式(glob pattern)") |
|
|
|
|
| class ListFilesOutput(BaseModel): |
| """文件列表工具输出结果""" |
| success: bool = Field(description="操作是否成功") |
| files: List[dict] | None = Field(default=None, description="文件列表") |
| error: str | None = Field(default=None, description="错误信息") |
|
|
|
|
| class ExecuteInput(BaseModel): |
| """命令执行工具输入参数""" |
| command: str = Field(description="要执行的命令") |
| timeout: int = Field(default=30, description="超时时间(秒)") |
| cwd: str = Field(default="", description="工作目录(相对路径)") |
|
|
|
|
| class ExecuteOutput(BaseModel): |
| """命令执行工具输出结果""" |
| success: bool = Field(description="操作是否成功") |
| stdout: str = Field(default="", description="标准输出") |
| stderr: str = Field(default="", description="标准错误") |
| exit_code: int = Field(default=-1, description="退出码") |
| error: str | None = Field(default=None, description="错误信息") |
|
|
|
|
| @mcp_tool( |
| name="sandbox-read", |
| title="沙盒文件读取", |
| description="从沙盒目录读取文件内容", |
| annotations={ |
| "readOnlyHint": True, |
| "destructiveHint": False, |
| } |
| ) |
| async def sandbox_read(path: str, encoding: str = "utf-8") -> ReadFileOutput: |
| """从沙盒目录读取文件内容。 |
| |
| Args: |
| params: 包含文件路径和编码参数 |
| |
| Returns: |
| ReadFileOutput: 文件内容和相关信息 |
| """ |
| security = SecurityController() |
| file_ops = FileOperations(security) |
|
|
| result = file_ops.read_file(path, encoding) |
|
|
| return ReadFileOutput( |
| success=result.get("success", False), |
| content=result.get("content"), |
| size=result.get("size"), |
| error=result.get("error"), |
| ) |
|
|
|
|
| @mcp_tool( |
| name="sandbox-write", |
| title="沙盒文件写入", |
| description="向沙盒目录写入文件内容", |
| annotations={ |
| "readOnlyHint": False, |
| "destructiveHint": False, |
| } |
| ) |
| async def sandbox_write( |
| content: str, |
| path: str | None = None, |
| filename: str | None = None, |
| mode: str = "write", |
| ) -> WriteFileOutput: |
| """向沙盒目录写入文件内容。 |
| |
| Args: |
| params: 包含文件路径、内容和写入模式参数 |
| |
| Returns: |
| WriteFileOutput: 写入结果 |
| """ |
| security = SecurityController() |
| file_ops = FileOperations(security) |
|
|
| target_path = path or filename |
| if not target_path: |
| return WriteFileOutput( |
| success=False, |
| error="缺少文件路径,请传入 path 或 filename", |
| ) |
|
|
| result = file_ops.write_file(target_path, content, mode) |
|
|
| return WriteFileOutput( |
| success=result.get("success", False), |
| path=result.get("path"), |
| size=result.get("size"), |
| error=result.get("error"), |
| ) |
|
|
|
|
| @mcp_tool( |
| name="sandbox-list", |
| title="沙盒文件列表", |
| description="列出沙盒目录中的文件和目录", |
| annotations={ |
| "readOnlyHint": True, |
| "destructiveHint": False, |
| } |
| ) |
| async def sandbox_list(path: str = "", pattern: str = "*") -> ListFilesOutput: |
| """列出沙盒目录中的文件和目录。 |
| |
| Args: |
| params: 包含目录路径和匹配模式参数 |
| |
| Returns: |
| ListFilesOutput: 文件列表 |
| """ |
| security = SecurityController() |
| file_ops = FileOperations(security) |
|
|
| result = file_ops.list_files(path, pattern) |
|
|
| return ListFilesOutput( |
| success=result.get("success", False), |
| files=result.get("files"), |
| error=result.get("error"), |
| ) |
|
|
|
|
| @mcp_tool( |
| name="sandbox-exec", |
| title="沙盒命令执行", |
| description="在沙盒环境中安全执行命令", |
| annotations={ |
| "readOnlyHint": False, |
| "destructiveHint": True, |
| } |
| ) |
| async def sandbox_exec(command: str, timeout: int = 30, cwd: str = "") -> ExecuteOutput: |
| """在沙盒环境中安全执行命令。 |
| |
| Args: |
| params: 包含命令、超时时间和工作目录参数 |
| |
| Returns: |
| ExecuteOutput: 命令执行结果 |
| """ |
| security = SecurityController() |
| cmd_exec = CommandExecutor(security) |
|
|
| result = await cmd_exec.execute(command, timeout, cwd) |
|
|
| return ExecuteOutput( |
| success=result.get("success", False), |
| stdout=result.get("stdout", ""), |
| stderr=result.get("stderr", ""), |
| exit_code=result.get("exit_code", -1), |
| error=result.get("error"), |
| ) |
|
|