@@ -113,6 +115,33 @@ means full support (ARM: `grep -o asimddp /proc/cpuinfo`).
Full deployment guide (compose, Synology walkthrough, permissions, reverse proxy / HTTPS,
backup, limitations): [docs/server/README.md](docs/server/README.md).
+## MCP (let AI clients query your library)
+
+`vixel mcp` runs a **stdio MCP server** with read-only tools (`search_media` / `get_media` /
+`find_similar`), so Claude Desktop, Cursor or Claude Code can search your library **without
+any network service**. Results include `vixel://` deep links that open the item in the app
+(videos jump to the matched timestamp). It needs a source checkout (`npm install &&
+npm run build:cli`; models inside an installed Vixel.app are found automatically):
+
+```json
+{
+ "mcpServers": {
+ "vixel": {
+ "command": "/absolute/path/Vixel/node_modules/.bin/electron",
+ "args": ["/absolute/path/Vixel/dist/cli/cli/index.js", "mcp"],
+ "env": { "ELECTRON_RUN_AS_NODE": "1" }
+ }
+ }
+}
+```
+
+> Why Electron as the runtime: the repo's better-sqlite3 is compiled for Electron's ABI;
+> with `ELECTRON_RUN_AS_NODE=1` Electron behaves as plain Node and opens no window.
+
+No source checkout? The desktop app's Settings → General → **Local API** exposes the same
+tools over Streamable HTTP at `http://127.0.0.1:41721/mcp` (bearer token shown in Settings);
+the server edition enables it with `VIXEL_MCP_TOKEN` (see [docs/server/README.md](docs/server/README.md)).
+
## Build from source
Node.js 20+.
diff --git a/README.md b/README.md
index 4cac266..d4b22f8 100644
--- a/README.md
+++ b/README.md
@@ -92,6 +92,8 @@ SCRFD 人脸检测 + MobileFaceNet 512 维特征 + sqlite-vec 近邻索引。
- **HEIC / RAW** —— macOS 上通过系统 `sips` 解码 CR2 / CR3 / NEF / ARW / DNG / RAF / ORF / RW2,保留 EXIF。
- **快速查看** —— 空格预览,⌘1–5 切换 全部 / 图片 / 视频 / 音频 / 地图。
- **命令行** —— `vixel search "海边" --json`,方便脚本和 Agent 调用(见下文);结果里的 `matchedBy` 说明是画面、图中文字还是文件名命中。
+- **链接进笔记** —— 右键「拷贝链接 / 拷贝 Markdown 链接」得到 `vixel://` 深链接,贴进 Obsidian、备忘录等任意笔记,点击回到 Vixel 定位到那一项(视频 / 音频直接跳到时间点)。链接按内容哈希定位,清库重建、移动文件后仍然有效。
+- **本地接口(默认关闭)** —— 设置 → 通用 → 本地接口:在本机开出网页界面和 HTTP API,手机浏览器也能访问桌面的资料库(局域网访问必须设口令);同一服务的 `/mcp` 是给 AI 客户端的只读 MCP 接口(见下文)。
- **中英文界面** —— 跟随系统语言,也可在 设置 → 通用 里切换。
- **诊断** —— `vixel doctor` / `vixel bench` 体检和测速,`VIXEL_PROFILE=1` 打印慢操作,见 [docs/debugging.md](docs/debugging.md)。
@@ -252,9 +254,36 @@ npm run cli -- people
npm run cli -- stats
```
-支持 `search` · `info` · `similar` · `people` · `stats` · `caption` · `folders`,
+支持 `search` · `info` · `similar` · `people` · `stats` · `caption` · `folders` · `mcp`,
`--json` 输出便于脚本和 AI Agent 调用。需要先运行一次应用以创建照片库。
+### MCP(让 AI 客户端查你的库)
+
+`vixel mcp` 把同一套查询变成 **stdio 形态的 MCP 服务器**(工具全部只读:`search_media` /
+`get_media` / `find_similar`),Claude Desktop、Cursor、Claude Code 等本地 AI 客户端
+**不开任何网络服务**就能搜你的库;结果里的 `vixel://` 链接点开直接回到应用并定位(视频跳到时间点)。
+需要源码仓库(`npm install && npm run build:cli`;已安装的 Vixel.app 里的语义模型会被自动找到),
+客户端里这样配置(Claude Desktop 的 `claude_desktop_config.json`、Cursor 的 `mcp.json` 同形):
+
+```json
+{
+ "mcpServers": {
+ "vixel": {
+ "command": "/绝对路径/Vixel/node_modules/.bin/electron",
+ "args": ["/绝对路径/Vixel/dist/cli/cli/index.js", "mcp"],
+ "env": { "ELECTRON_RUN_AS_NODE": "1" }
+ }
+ }
+}
+```
+
+> 为什么用 Electron 当运行时:仓库的 better-sqlite3 按 Electron 的 ABI 构建,普通 `node` 加载不了;
+> `ELECTRON_RUN_AS_NODE=1` 下 Electron 就是一个纯 Node,不会弹窗口。
+
+不想碰源码:桌面应用 设置 → 通用 → **本地接口** 打开后,同样的工具在 `http://127.0.0.1:41721/mcp`
+(Streamable HTTP + Bearer 令牌,设置页里拷贝);服务器版设 `VIXEL_MCP_TOKEN` 同理,
+见 [docs/server/README.md](docs/server/README.md)。
+
## 开发
```
diff --git a/docs/server/README.md b/docs/server/README.md
index 9a6cdda..edc7fa1 100644
--- a/docs/server/README.md
+++ b/docs/server/README.md
@@ -119,6 +119,31 @@ volumes:
| `VIXEL_PORT` | `8080` | 容器内监听端口 |
| `VIXEL_COOKIE_SECURE` | 关 | `=1` 会话 cookie 永远带 `Secure`(全程 HTTPS 时用) |
| `VIXEL_TRUST_PROXY` | 关 | `=1` 信任反代头:`X-Forwarded-Proto` 为 https 时自动加 `Secure`,登录限速按 `X-Forwarded-For` 计 |
+| `VIXEL_MCP_TOKEN` | (不设 = 关闭) | 开启 `/mcp` 端点(AI 客户端的只读 MCP 接口)的 Bearer 令牌,≥ 16 位。生成:`openssl rand -base64 24` |
+
+## MCP(AI 客户端接口)
+
+设置 `VIXEL_MCP_TOKEN` 后,服务器在 `/mcp` 提供一个 [MCP](https://modelcontextprotocol.io)
+端点(Streamable HTTP),AI 客户端 / Agent 可以用自然语言查询媒体库。工具**全部只读**:
+`search_media`(语义 + 图内文字 + 文件名搜索,命中视频时间段,带 vixel:// 深链接和 http 媒体链接)、
+`get_media`(单项详情:OCR 文字、标签、人物等)、`find_similar`(找相似)。
+
+```yaml
+ environment:
+ VIXEL_MCP_TOKEN: "用 openssl rand -base64 24 生成"
+```
+
+客户端配置(以 Claude Desktop / Cursor 的远程 MCP 为例):URL `http://<主机>:8080/mcp`,
+HTTP 头 `Authorization: Bearer <令牌>`。验证:
+
+```bash
+curl -s http://<主机>:8080/mcp -H "Authorization: Bearer <令牌>" \
+ -H 'content-type: application/json' \
+ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
+```
+
+注意:搜索结果(文件名、路径、识别出的文字等)会发给你连接的那个 AI 客户端;令牌与登录口令
+相互独立,泄露任何一个都应立即更换。
## 反向代理 / HTTPS
@@ -251,6 +276,32 @@ search instant. Lower `VIXEL_THREADS` (e.g. `2`) for a gentler, slower index.
| `VIXEL_PORT` | `8080` | Port inside the container |
| `VIXEL_COOKIE_SECURE` | off | `=1` always sets `Secure` on the session cookie (all-HTTPS setups) |
| `VIXEL_TRUST_PROXY` | off | `=1` trusts proxy headers: `Secure` cookie when `X-Forwarded-Proto` is https, login rate limit keyed by `X-Forwarded-For` |
+| `VIXEL_MCP_TOKEN` | (unset = disabled) | Bearer token that enables the `/mcp` endpoint (read-only MCP interface for AI clients), min 16 chars. Generate: `openssl rand -base64 24` |
+
+## MCP (AI client interface)
+
+With `VIXEL_MCP_TOKEN` set, the server exposes an [MCP](https://modelcontextprotocol.io)
+endpoint (Streamable HTTP) at `/mcp`, so AI clients and agents can query the library in
+natural language. All tools are **read-only**: `search_media` (semantic + text-in-image +
+filename search, with matched video time ranges, a vixel:// deep link and an http media link),
+`get_media` (details of one item: OCR text, tags, people, …) and `find_similar`.
+
+```yaml
+ environment:
+ VIXEL_MCP_TOKEN: "generate with: openssl rand -base64 24"
+```
+
+Client setup (remote MCP in Claude Desktop / Cursor): URL `http://{t.localapi.note}
+ + {status?.enabled && ( +{u}
+ ))}
+ {t.localapi.passwordRequired}
+ )} +{t.localapi.lanNote}
+ +
+ {`http://127.0.0.1:${status.port}/mcp`}
+
+
+ {status.mcpToken}
+
+
+
+ {t.localapi.mcpNote}
+