# 设计文档：DevMemory MCP Server

## 项目结构

```
devmemory/
├── __init__.py
├── __main__.py              # 入口：python -m devmemory
├── server.py                # MCP 协议层（JSON-RPC over stdio）
├── protocol.py              # JSON-RPC 消息解析与响应构建
├── tools/
│   ├── __init__.py
│   ├── remember.py          # 记忆存入
│   ├── recall.py            # 记忆回忆
│   ├── forget.py            # 记忆删除
│   ├── status.py            # 会话状态
│   ├── track.py             # 问题跟踪
│   └── digest.py            # 记忆整理
├── db/
│   ├── __init__.py
│   ├── connection.py        # SQLite 连接管理（WAL 模式、sqlite-vec 加载）
│   ├── schema.py            # 建表语句
│   ├── memory_repo.py       # memories + vec_memories 读写
│   ├── state_repo.py        # session_state 读写
│   └── issue_repo.py        # issues 读写
├── embedding/
│   ├── __init__.py
│   └── engine.py            # ONNX Runtime 推理（tokenize → 推理 → pooling → 归一化）
├── web/
│   ├── __init__.py
│   ├── app.py               # HTTP 服务（Python 标准库 http.server）
│   ├── api.py               # REST API 路由
│   └── static/
│       ├── index.html        # 单页应用
│       ├── style.css
│       └── app.js
├── config.py                # 配置：路径、默认值、模型名
└── errors.py                # 统一错误格式
pyproject.toml               # 包配置、依赖、入口点
```

## 架构设计

### 分层架构

```
┌─────────────────────────────────┐
│  MCP 协议层（server.py）         │  stdin/stdout JSON-RPC
├─────────────────────────────────┤
│  工具层（tools/*.py）            │  6 个工具的业务逻辑
├─────────────────────────────────┤
│  数据层（db/*.py）               │  SQLite + sqlite-vec
├─────────────────────────────────┤
│  Embedding 层（embedding/）      │  ONNX Runtime 推理
└─────────────────────────────────┘

┌─────────────────────────────────┐
│  Web 看板（web/*.py）            │  独立 HTTP 服务，复用数据层
└─────────────────────────────────┘
```

### MCP 协议层（server.py + protocol.py）

自实现 JSON-RPC 2.0 over stdio：

- `protocol.py`：消息解析（从 stdin 按行读取 JSON）、响应构建（JSON-RPC result/error）
- `server.py`：主循环，路由分发到对应 handler
  - `initialize` → 返回 server info + capabilities，递增 session_id
  - `tools/list` → 返回 6 个工具的 name + description + inputSchema（JSON Schema）
  - `tools/call` → 根据 tool name 分发到 tools/*.py

消息格式遵循 MCP 规范：
- 请求：`{"jsonrpc": "2.0", "id": N, "method": "tools/call", "params": {...}}`
- 响应：`{"jsonrpc": "2.0", "id": N, "result": {...}}`
- 错误：`{"jsonrpc": "2.0", "id": N, "error": {"code": N, "message": "..."}}`

日志输出到 stderr（不干扰 stdout 的 JSON-RPC 通信）。

### 数据层设计

#### 双数据库管理

- `ConnectionManager` 类管理两个数据库连接：
  - `user_db`：`~/.devmemory/memory.db`
  - `project_db`：`{project}/.devmemory/memory.db`
- 启动时自动创建目录和数据库文件
- 所有连接启用 WAL 模式（`PRAGMA journal_mode=WAL`）
- 所有连接加载 sqlite-vec 扩展

#### 表结构

```sql
-- memories 表（用户级和项目级各一份）
CREATE TABLE IF NOT EXISTS memories (
    id TEXT PRIMARY KEY,
    content TEXT NOT NULL,
    tags TEXT NOT NULL DEFAULT '[]',  -- JSON 数组
    scope TEXT NOT NULL DEFAULT 'project',
    session_id INTEGER NOT NULL DEFAULT 0,
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);

-- sqlite-vec 虚拟表
CREATE VIRTUAL TABLE IF NOT EXISTS vec_memories USING vec0(
    id TEXT PRIMARY KEY,
    embedding FLOAT[384]
);

-- session_state 表（仅项目级）
CREATE TABLE IF NOT EXISTS session_state (
    id INTEGER PRIMARY KEY DEFAULT 1,
    is_blocked INTEGER NOT NULL DEFAULT 0,
    block_reason TEXT NOT NULL DEFAULT '',
    next_step TEXT NOT NULL DEFAULT '',
    current_task TEXT NOT NULL DEFAULT '',
    progress TEXT NOT NULL DEFAULT '[]',      -- JSON 数组
    recent_changes TEXT NOT NULL DEFAULT '[]', -- JSON 数组
    pending TEXT NOT NULL DEFAULT '[]',        -- JSON 数组
    updated_at TEXT NOT NULL
);

-- issues 表（仅项目级）
CREATE TABLE IF NOT EXISTS issues (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    issue_number INTEGER NOT NULL,
    date TEXT NOT NULL,
    title TEXT NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending',
    content TEXT NOT NULL DEFAULT '',
    archive_content TEXT NOT NULL DEFAULT '',
    migrated_to TEXT NOT NULL DEFAULT '',
    created_at TEXT NOT NULL,
    updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_issues_date ON issues(date);
CREATE INDEX IF NOT EXISTS idx_issues_status ON issues(status);
```

#### Repository 模式

每个 repo 封装对应表的 CRUD：

- `MemoryRepo`：insert（含去重检查）、search_by_vector、delete、get_by_session_range
- `StateRepo`：get、upsert（部分更新）
- `IssueRepo`：create、update、migrate、archive、list_by_date

### Embedding 层设计

`EmbeddingEngine` 类，懒加载：

1. 首次调用时通过 `huggingface-hub` 下载 ONNX 模型到 `~/.cache/huggingface/`
2. 加载 `tokenizers` 分词器
3. 创建 `onnxruntime.InferenceSession`
4. 推理流程：text → tokenize → ONNX 推理 → mean pooling → L2 归一化 → 384 维 float 数组

去重逻辑：remember 时先算 Embedding，在 vec_memories 中查相似度 > 0.95 的记录，有则更新，无则插入。

### Web 看板设计

独立命令 `devmemory web --project-dir . --port 9080`：

- `app.py`：基于 `http.server.HTTPServer`，处理静态文件和 API 请求
- `api.py`：REST API 路由，前缀 `/api/`
  - `GET /api/memories` — 记忆列表（支持 query/tags/scope 参数）
  - `GET /api/memories/:id` — 记忆详情
  - `PUT /api/memories/:id` — 编辑记忆
  - `DELETE /api/memories/:id` — 删除记忆
  - `DELETE /api/memories` — 批量删除（body 传 ids）
  - `GET /api/status` — 会话状态
  - `PUT /api/status` — 更新状态
  - `GET /api/issues` — 问题列表（支持 date/status 参数）
  - `PUT /api/issues/:id` — 更新问题状态
  - `GET /api/stats` — 统计概览
- `static/`：纯 HTML + CSS + JS 单页应用

数据库连接：只读连接用于查询，写操作通过独立连接。

### 入口点设计

`pyproject.toml` 配置两个命令：

```toml
[project.scripts]
devmemory = "devmemory.__main__:main"
```

`__main__.py` 解析子命令：
- `devmemory`（无子命令）或 `devmemory serve`：启动 MCP Server（stdio 模式）
- `devmemory web`：启动 Web 看板

### session_id 管理

- `server.py` 维护一个内部计数器 `_session_id`
- 每次收到 `initialize` 请求时 +1
- 从项目级数据库 `memories` 表读取 `MAX(session_id)` 作为初始值
- 所有 `remember` 调用使用当前 `_session_id`

### 错误处理

统一错误格式：

```python
{"success": False, "error": "错误类型", "details": "详细信息"}
```

MCP 协议层将业务错误包装为 JSON-RPC error response（code: -32000）。
参数校验错误使用 JSON-RPC invalid params（code: -32602）。
