Skip to main content
Glama
README.md
# local-code-agent

基于 FastMCP 开发的本地 MCP Server:让外部 AI(ChatGPT、Claude 等)通过 HTTP 远程操控本地工作区——文件读写/编辑、搜索、shell 命令、Git 操作——并提供沙盒隔离、敏感文件保护与审计日志。

本项目不含 AI/LLM 逻辑,仅包含工具层服务与安全控制。

## 环境要求

- Python 3.10+(FastMCP 硬性要求)
- `pip install -r requirements.txt`(fastmcp、pyyaml)

## 快速开始

### 方式一:图形界面(推荐)

```bash
python start.py
```

控制台窗口操作步骤:

1. **工作区文件夹**:点「选择…」指定一个文件夹。AI 的全部操作被限制在该文件夹内(沙盒),换文件夹即切换沙盒根。
2. **连接提示词**:窗口中部有「连接提示词」卡片,把里面的文字复制后发给网页端 AI,AI 即按其中配置绑定本 MCP 服务器(无需 Token)。
3. **端口**:默认 8000;如被占用可改。
4. **只读模式**:勾选后写/编辑/命令类工具全部被拒,运行中切换立即生效。
5. 点「启动服务」→ 状态栏显示版本、只读状态、工作区、运行时长,日志区实时输出服务日志。
6. 停止:点「停止服务」,或直接关闭窗口(会先询问)。

### 方式二:命令行

```bash
# 1. 安装依赖
pip install -r requirements.txt

# 2. 启动服务(默认监听 127.0.0.1:8000,MCP 路径 /mcp,无需 Token)
python server.py
```

可选参数:`--workspace D:\projects\my-project`(沙盒根目录)、`--host 0.0.0.0`(允许局域网访问)、`--port 9000`。停止用 Ctrl+C。

### 验证与健康检查

服务启动后访问:`GET http://127.0.0.1:8000/health`(免认证)。返回:

```json
{ "status": "ok", "service": "local-code-agent", "version": "0.1.0",
  "workspace": "D:\\projects\\my-project", "readonly": false,
  "uptime_seconds": 3 }
```

其余端点(含 `/mcp`)可直接访问,无需认证。

### 局域网访问

默认只监听 `127.0.0.1`,仅本机可连。同局域网其他设备访问:

```bash
python server.py --host 0.0.0.0
```

客户端连接地址:`http://<本机局域网IP>:8000/mcp`(本机 IP 用 `ipconfig` 查看)。暴露到局域网意味着同网段设备都能访问且无需认证,务必谨慎。

> 不建议直接暴露公网。如需公网访问,请自备反向代理方案(Nginx + TLS、frp 或其他隧道工具),并在反代层强制 HTTPS 与鉴权。

## 图形化界面(可选)

不写命令行也能用。tkinter 为 Python 标准库,无需额外安装。

```bash
python start.py
```

控制台功能:

- **工作区文件夹**:点「选择…」打开文件夹选择器。一次只能选一个文件夹,AI 的全部操作被限制在该文件夹(沙盒)内,换文件夹会替换当前选择。
- **连接提示词**:内置可编辑的提示词文本,点「复制提示词」一键复制,发给网页端 AI 即可完成 MCP 绑定。无需 Token。
- **端口 / 只读模式**:设置监听端口;勾选只读则禁用写入/编辑/命令工具。
- **启动 / 停止服务**:在 GUI 进程内启动 FastMCP(后台线程 + uvicorn),使用独立日志处理器,停止会等待服务线程完成。
- **运行中切换**:更换工作区或勾选只读会立即生效,无需重启。端口修改需重启服务。
- **状态栏**:轮询 `/health`,显示版本、只读状态、当前工作区、运行时长。
- **日志区**:实时显示服务输出,自动清理 ANSI 转义码,右键可复制,超 600 行自动裁短。

GUI 与命令行共用同一套沙盒、审计机制;对接方式相同。

## 客户端对接

本机客户端:URL 填 `http://127.0.0.1:8000/mcp`;局域网客户端用 `http://<本机局域网IP>:8000/mcp`(服务器需 `--host 0.0.0.0` 启动)。无需认证。

Claude Desktop 的 `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "local-code-agent": {
      "url": "http://127.0.0.1:8000/mcp"
    }
  }
}
```

## 工具清单

| 工具 | 参数 | 说明 |
|---|---|---|
| `read_file` | path, offset=0, limit=0 | limit 0 表示全部;offset 表示跳过的起始行数 |
| `write_file` | path, content | 自动创建父目录;敏感路径会被拒绝 |
| `edit_file` | path, old_text, new_text, dry_run=false | 文本精确匹配且必须唯一 |
| `run_command` | command, timeout=30 | 工作区内执行任意命令;SSE 流式输出 |

## 安全模型

- **沙盒**:所有路径经 `realpath` 解析,必须落在工作区根目录内(可拦截符号链接逃逸)。`../` 及绝对路径无法越界。
- **认证**:无 Token 认证。服务默认只监听本机 `127.0.0.1`;如需对外,请在反向代理层自行加鉴权。
- **敏感文件**:`.env`、`.env.*`、`*.pem`、`*.key`、`id_rsa`、`.ssh/`、`.aws/`、`credentials` 在任意路径层级都会被拦截。返回统一「access denied」,不暴露文件是否存在。
- **审计日志**:JSON 行格式,轮转 10MB × 5,记录时间、工具名、脱敏参数、结果、耗时。
- **只读模式**:`python server.py --readonly` 或 GUI 勾选。写/命令工具仍可见,调用时返回 `read-only mode`。运行中可切换。

## 配置优先级

工作区:`--workspace` > 环境变量 `MCP_WORKSPACE` > `config.yaml`(默认 `.`)。其余配置均来自 `config.yaml`(详见文件内默认值)。

## 项目结构

```
server.py                 # FastMCP 入口:配置、认证、/health
tool_registry.py          # 工具注册(与生命周期分离)
config.py / config.yaml   # 默认值 + YAML
sandbox.py                # 路径沙盒 + 敏感文件过滤
audit.py                  # 轮转 JSON 审计日志
tools/file_ops.py         # 读/写/编辑/列目录/搜索
tools/file_management.py  # 删/改名/复制/建目录/stat/tail/glob
tools/download.py         # HTTP(S) 下载(无域名白名单)
tools/command.py          # 同步 run_command(测试/非流式)
tools/git_ops.py          # status/diff/log/branch/commit
runtime.py                # 运行时只读标志
gui/                      # tkinter 控制台(进程内服务)
start.py                  # GUI 入口
tests/                    # test_core.py + test_extra.py
```

## 已知限制

- Python 3.8 无法运行本服务(fastmcp 需 3.10+);逻辑模块兼容 3.8,可用 `python tests/test_core.py` 自检。
- `run_command` 为 SSE 流式输出,总超时上限 3600 秒。
- 仅支持单工作区。多工作区切换与会话级上下文暂未实现(YAGNI)。