Owl 是一个自托管的 MDX / MDD Web 词典。它面向个人查词、公开词典共享、用户私有词典管理,以及 AI 客户端通过 MCP 查询词典的场景。
- 在浏览器中直接查询 MDX 词典。
- 未登录用户可以查询已启用的公开词典。
- 登录用户可以查询公开词典,以及自己上传的私有词典。
- 支持查询全部可用词典,也可以筛选到某一本词典。
- 支持搜索建议和键盘导航。
- 支持点击词条内部链接,继续跳转查询相关词。
- 支持渲染 MDX 返回的 HTML 内容。
- 支持通过后端读取配套 MDD 中的图片、音频、CSS、字体和其他媒体资源。
- 词条中有音频资源时可以直接播放。
- 支持复制纯文本释义,方便粘贴到笔记或其他工具中。
- 支持最近搜索,保留数量可以在管理界面配置。
- 查询页面同时适配桌面端和移动端。
- 移动端提供更紧凑的词典筛选控件。
- 移动端搜索后会直接定位到结果区域,避免最近搜索挡住结果。
- 最佳匹配结果会被突出显示,其他匹配结果在下方继续展示。
- 查询结果会显示公开 / 私有来源标识。
- 支持多种主题,包括复古风格、深色主题、黑白主题等。
- 阅读字体可以切换为 sans / serif / mono / 自定义字体。
- 切换界面语言:简体中文 / English。
- 切换视觉主题。
- 设置阅读字体模式。
- 上传并使用共享自定义字体。
- 设置显示名称和头像。
- 设置最近搜索保留数量。
- 在网页中上传
.mdx文件和可选的.mdd文件。 - 刷新单本词典,用于重新加载或补齐资源。
- 刷新整个词典库,用于重新扫描挂载目录。
- 启用 / 停用词典。
- 设置词典为公开 / 私有。
- 删除词典。
- 在界面中查看词典文件状态:
okmissing_mdxmissing_mddmissing_all
- 查看结构化刷新报告:
- discovered
- updated
- skipped
- failed
- 同 basename 的
.mdx + .mdd会被视为同一套词典。 - 如果先上传 MDX,之后再补充同名 MDD,可以通过刷新重新发现资源。
- 挂载的词典目录会被递归扫描。
- 如果不挂载外部目录,也可以只使用网页上传模式。
管理员可以设置:
- 是否开放新用户注册。
- 网站 footer 额外信息。
- 版权信息。
默认情况下,footer 信息为空时不会显示。
Owl 内置基于 SSE 的 MCP 服务,方便 AI 客户端调用词典。
/api/mcp/sse
认证方式是每个用户自己的 MCP Token:
Authorization: Bearer <MCP_TOKEN>
临时测试也可以使用 URL 参数:
/api/mcp/sse?token=<MCP_TOKEN>
初次 SSE 连接必须携带 Token;连接建立后,SDK 后续 POST 请求会通过 MCP session 继续通信。
-
list_dictionaries- 列出当前 token 用户可访问的词典。
- 范围:已启用的公开词典 + 当前用户自己的私有词典。
-
search_dictionary- 查询当前 token 用户可访问的词典。
- 必填:
query - 可选:
dictionary_id或dictionary_name - 可选:
format=markdown会让 MCP 响应的文本内容以 Markdown 输出;不传format时保持默认 JSON 文本输出。 - 如果不指定词典,则按 Web 查询相同范围搜索全部可访问词典。
每个用户都可以在管理界面维护自己的 MCP Token:
- 保存自定义 Token
- 生成随机 Token
- 删除 / 撤销 Token
- 打开使用说明弹窗查看接入方式
Token 只会以 hash 形式存储。生成后请立即复制,之后界面只显示首尾提示。
- 后端:Go + Echo v5 + ent
- 数据库:默认 SQLite,也支持通过 driver/DSN 配置 PostgreSQL、MySQL
- 词典引擎:
github.com/lib-x/mdx - MCP 服务:
github.com/modelcontextprotocol/go-sdk - 前端:React + Vite + TypeScript
- 搜索索引:默认使用数据库持久索引;可选 Redis + RediSearch
- 部署方式:单 Go 服务 / 单 Docker 镜像
- 前端生产资源:通过
go:embed嵌入 Go 服务 - 自动化:GitHub Actions 构建 CI、发布二进制和 Docker 镜像
Owl 可以不依赖 Redis 运行,此时会把导出的 MDX 搜索索引写入已配置数据库,只在需要渲染命中释义时才加载完整词典对象。
配置 Redis 后:
- exact / prefix 索引可以写入 Redis
- fuzzy 查询可以使用 RediSearch
- 自动补全结果由后端聚合
- 如果 RediSearch 不可用,会自动回退到前缀索引搜索
仓库提供四个 Docker Compose 文件:
docker-compose.yml:最简单部署,SQLite,不启用 Redisdocker-compose.redis.yml:SQLite + Redis + RediSearchdocker-compose.postgres.yml:PostgreSQL,不启用 Redisdocker-compose.mysql.yml:MySQL,不启用 Redis
cp .env.example .env
# 先修改 OWL_JWT_SECRET 和管理员账号密码
docker compose -f docker-compose.yml pull
docker compose -f docker-compose.yml up -d默认地址:
http://localhost:8080
该模式会启动:
- Owl:
http://localhost:8080 - SQLite:保存在持久化 volume
owl_data中 - 上传词典:保存在
/app/data/uploads - 不依赖 Redis
如果你希望启用 Redis 前缀 / 精确索引和 RediSearch 模糊查询,可以使用:
cp .env.example .env
# 先修改 OWL_JWT_SECRET 和管理员账号密码
docker compose -f docker-compose.redis.yml pull
docker compose -f docker-compose.redis.yml up -d该模式会启动:
- Owl:
http://localhost:8080 - Redis Stack Server,用于 Redis + RediSearch
- SQLite 数据库和上传文件保存在
owl_data - Redis 数据保存在
owl_redis
如果你希望 Owl 的元数据使用 PostgreSQL 而不是 SQLite,可以使用这个方案。上传的词典文件仍然保存在 owl_data;变化的是关系数据库。
cp .env.example .env
# 修改 OWL_JWT_SECRET 和管理员账号密码
docker compose -f docker-compose.postgres.yml pull
docker compose -f docker-compose.postgres.yml up -d该 compose 会启动内置 owl 数据库 / 用户的 PostgreSQL,并设置:
OWL_DB_TYPE=postgres
OWL_DB_DSN=postgres://...
如果你希望 Owl 的元数据使用 MySQL 而不是 SQLite,可以使用这个方案。上传的词典文件仍然保存在 owl_data;变化的是关系数据库。
cp .env.example .env
# 修改 OWL_JWT_SECRET 和管理员账号密码
docker compose -f docker-compose.mysql.yml pull
docker compose -f docker-compose.mysql.yml up -d该 compose 会启动内置 owl 数据库 / 用户的 MySQL,并设置:
OWL_DB_TYPE=mysql
OWL_DB_DSN=owl:...@tcp(mysql:3306)/owl?parseTime=true&charset=utf8mb4&loc=Local
Compose 文件默认使用发布镜像:czyt/owl:latest。
如果你本机已经有很多 .mdx / .mdd 文件,可以把宿主机目录挂载到 OWL_LIBRARY_DIR。
示例覆盖:
services:
owl:
environment:
OWL_LIBRARY_DIR: /app/library
volumes:
- owl_data:/app/data
- ./dicts:/app/library启动后:
- 登录
- 打开 管理
- 点击 刷新词典库
Owl 会递归扫描目录,并自动把 name.mdx 和 name.mdd 识别为同一套词典。
如果你不想挂载外部词典目录,可以保持:
OWL_LIBRARY_DIR=/app/data/uploads
这样词典就可以完全通过网页上传和管理。
- 打开
http://localhost:8080。 - 使用初始化管理员账号登录。
- 上传一本测试词典,或挂载词典目录后刷新词典库。
- 根据需要设置词典公开 / 私有。
- 回到首页确认可以正常查词。
- 可选:配置注册开关、footer、字体和 MCP Token。
升级 Owl 时,请使用与你启动时相同的 compose 文件。
不启用 Redis:
git pull
docker compose -f docker-compose.yml down
docker compose -f docker-compose.yml pull
docker compose -f docker-compose.yml up -d启用 Redis:
git pull
docker compose -f docker-compose.redis.yml down
docker compose -f docker-compose.redis.yml pull
docker compose -f docker-compose.redis.yml up -dSQLite / PostgreSQL / MySQL 数据、上传词典和 Redis 数据都会保留在 Docker volume 中,除非你手动删除 volume。
cd backend
GOPROXY=https://goproxy.cn,direct GOSUMDB=off go test ./...
GOPROXY=https://goproxy.cn,direct GOSUMDB=off go vet ./...
GOPROXY=https://goproxy.cn,direct GOSUMDB=off go run ./cmd/server后端默认地址:
http://localhost:8080
cd frontend
pnpm install
pnpm lint
pnpm build
pnpm dev前端开发地址:
http://localhost:3000
生产风格本地运行时,pnpm build 会把前端构建产物写入 backend/web/dist,Go 服务通过嵌入资源提供页面。Vite 开发服务会把 /api 代理到后端。
完整列表见 .env.example。
OWL_PORTOWL_FRONTEND_ORIGINOWL_JWT_SECRETOWL_DATA_DIROWL_UPLOADS_DIROWL_LIBRARY_DIROWL_WARM_DICTIONARIES:默认false。设为true会在启动时预加载所有已启用词典;大词典库建议保持关闭,避免重启慢和基础内存占用过高。OWL_MAX_LOADED_DICTIONARIES:进程内最多保留的完整已加载词典数量。默认0(不限制),避免全局搜索反复冷加载;内存受限的部署可设为正整数。
OWL_DB_TYPE:默认sqlite;也支持postgres/postgresql和mysql/mariadbOWL_DB_DSN:数据库连接字符串;SQLite 默认可留空,由OWL_DB_PATH自动生成OWL_DB_PATH:SQLite 数据库路径
使用 SQLite 且 OWL_DB_DSN 为空时,Owl 会自动生成包含 shared cache、外键、WAL 日志模式、NORMAL 同步模式和 10 秒 busy timeout 的 DSN,用于改善 SQLite 下的并发读写体验,同时保留简单部署方式。
示例:
# SQLite 默认:DSN 留空,由 OWL_DB_PATH 自动生成。
OWL_DB_TYPE=sqlite
OWL_DB_DSN=
# SQLite 显式 DSN,等价于默认生成格式。
OWL_DB_TYPE=sqlite
OWL_DB_DSN=file:/app/data/data.db?cache=shared&_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)&_pragma=synchronous(NORMAL)&_pragma=busy_timeout(10000)
OWL_DB_TYPE=postgres
OWL_DB_DSN=postgres://owl:secret@postgres:5432/owl?sslmode=disable
OWL_DB_TYPE=mysql
OWL_DB_DSN=owl:secret@tcp(mysql:3306)/owl?parseTime=true&charset=utf8mb4&loc=Local
OWL_BOOTSTRAP_ADMINOWL_ADMIN_USERNAMEOWL_ADMIN_PASSWORDOWL_ALLOW_REGISTER
OWL_REDIS_ADDROWL_REDIS_PASSWORDOWL_REDIS_DBOWL_REDIS_KEY_PREFIXOWL_REDIS_PREFIX_MAX_LENOWL_REDIS_SEARCH_ENABLEDOWL_REDIS_SEARCH_KEY_PREFIX
OWL_AUDIO_CACHE_DIRFFMPEG_BIN
游客范围:
curl http://localhost:8080/api/public/search-backends登录范围:
curl -H 'Authorization: Bearer <token>' http://localhost:8080/api/debug/search-backends重点字段含义:
fuzzy_backend: redisearch:正在使用 RediSearchfuzzy_backend: sql-index:正在使用本地数据库索引fuzzy_backend: memory-fuzzy:处于回退模式prefix_backend: redis-prefix:Redis 前缀索引已生效prefix_backend: sql-prefix:本地数据库前缀索引已生效