dsh-momo-learning
墨墨背单词的 DeepSeek Harness 插件。它把你墨墨账号的学习数据同步到本机 SQLite,然后在本地出选择题考你:每天 20 题,一题一题弹窗问,错了记进错题本,答完写一份日报。
整个过程只读,不改你的墨墨账号。
装上之后会多出两样东西,19 个 MCP 工具(名字形如 mcp__maimemo__maimemo_auth_status)和一个叫 momo-daily-learning 的 Skill。
定位
墨墨 App 已经在做记忆这件事了,所以这里管得很窄:
- App 判定为「认识」的词不考
- 今天刚新学的词也不考,刚背完还在短期记忆里,考了没意义
- 只考那些学过一阵子、已经有点忘的词
不代替 App 复习。也不做账号写入——加词、改复习状态、云词本都没有对应工具。
前置条件
这个插件目前只在 Windows 上能用。凭证存进 Windows Credential Manager,镜像存到 %LOCALAPPDATA%\MomoLearning,没有 macOS / Linux 的凭证后端。
- Node.js
>=24.13.1 <25。Harness 跑在哪个 Node 上,MCP 服务就用哪个 Node 启动。 - DeepSeek Harness 本身。没装的话
npx @deepseek-ai/dsh web就能起来,从源码安装和 profile 的说明在官方仓库。 - 一个墨墨开放平台的只读凭证。墨墨背单词 App 里「我的 → 更多设置 → 实验功能 → 开放 API」能拿到,也可以去 https://open.maimemo.com/open/api/v1/tokens/openapi 申请。有频控,别外传。
安装
先装 MCP 服务的依赖。git clone 下来的 mcp-server/node_modules 是空的,不装的话 MCP 起不来,工具列表里也就不会有 mcp__maimemo__*:
cd dsh-momo-learning
npm run mcp:install
mcp-server/dist 是编译好的,随仓库一起提交,不用构建。
然后把它装进一个 profile:
dsh plugin --profile <profile> add ./dsh-momo-learning
dsh plugin 会初始化 profile(第一个 bundle 是 @deepseek-ai/dsh-base),用 pnpm 把本目录链接进去。因为这个包声明了 dsh.bundle,它同时会被追加到 dsh.profile.bundles。本包没有运行时依赖,这一步不联网。
配墨墨凭证。令牌不能写在配置文件里,只能通过交互式命令存进系统凭证库:
cd dsh-momo-learning
npm run credential -- set # 交互式输入
npm run credential -- status
npm run credential -- remove
存进去之后条目名是 dsh.momo-learning-mcp。
启动前先确认 patch 层合成进去了:
dsh --profile <profile> --dump-config # 应该能看到 momo-learning 和 momo-learning-mcp 两行
dsh --profile <profile>
不想常驻也可以用一次性 overlay,但包本身还是得先 dsh plugin add,不然行里的包名解析不到:
dsh --profile <profile> --patch ./dsh-momo-learning/cordis.patch.yml
从旧版本升级
早期版本的凭证服务名是 codex.maimemo-learning-mcp,数据目录是 %LOCALAPPDATA%\CodexMomoLearning。配过凭证或者同步过镜像的话,先停掉 DSH 再跑:
npm run migrate-legacy -- --yes
它只搬位置,不动账号数据,旧条目会留着让你确认。数据库如果被 DSH 占着会报错让你先停掉,凭证那部分不受影响。
示例
你:开始今天的
(弹窗,第 1/20 题)
The committee will ___ the remaining issues at next week's meeting.
○ address ○ dress ○ redress ○ regress
你选了 address
✓ 正确。address 这里是及物动词「处理、着手解决」,不是常见的名词「地址」。
搭配:address an issue / a problem / a concern
例句:The report addresses the risks of long-term debt.(这份报告论述了长期债务的风险。)
易错点:后面接 issue / problem / question 时读作「处理」,跟「地址」没关系。
(第 2/20 题…)
20 题答完:答对 17 / 答错 3。错题进了本地错题本,明天会优先出它们。
日报写到 reports/momo-2026-09-14.md。
每题都给中文释义,答对也给。答对不代表真会,释义写出来你才知道自己是不是蒙的。
出题范围
出题不看今天学了什么,看的是本地镜像里的整个词表。取词就一条命令:
maimemo_list_quiz_candidates({ limit: 20 })
排序写在 SQL 里:错题本里没消除的排最前,然后是墨墨打了 STICKING 标签的顽固词,再是今天复习时答错、答模糊的,最后是学得少的。同一档里,距上次学习越久的排越前。今天新学的词已经被排除,默认也只取距上次学习至少一天以上的(minDaysSinceStudy,默认 1)。每个词都带一个 reason,说明它为什么被选中。
每天 20 题,上限 50。候选池经常有几百个词,只取 20,不是有 n 个词就出 n 道题。
今天没排上的词不用管。墨墨的复习排程会继续把它们排进后面几天的词表,到时候带着新的作答结果重新进候选池。
题型
只出选择题,四选一。五种形态,都是英语考试里真实存在的:
- 语境选词:英文句子挖空,四个词里选一个
- 近义替换:句子里标出一个词,问哪个选项最接近它
- 搭配填空:空出搭配的一部分,比如
___ price - 形近辨析:给英文释义,问是哪个词
- 熟词僻义:句子里用的是生僻义项,问此处什么意思。干扰项里会放这个词最常见的那个意思
不出中英对译(给中文选英文、给英文选中文释义),也不出「给词根选变形」这种题。App 已经在考词义了,再考一遍没意义。题干里不出现中文。
形近选项由 maimemo_find_similar_words 提供,它在本地拼写里按编辑距离排。单词效果好(adapt / adopt),多词短语偏弱(stiff price 只能匹配到 soaring price),这类词就换同义或同词根的角度出。
一题一题问
用 ask_user_question 弹窗问,一次一题,等回答再出下一题,不会一次把 20 题列出来。答完先判对错,再给答案和解析。
错题和日报
答题过程不存流水。只有答错才写 quiz_mistake,一个词一行;再错就累加 miss_count,不新增行。答对且没错过的词不写任何东西;答对的是错题本里的词,就标记消除。
整批答完写一份日报到 <工作区>/reports/momo-YYYY-MM-DD.md,一天一个文件。里面有题数、对错、错词清单(带累计错了几次),以及从错词里归纳出的薄弱点。数据库留着可查的事实,日报留着给人看的过程记录。
镜像怎么保持最新
本地 SQLite 里的学习记录不是历史备份,是出题的取数来源。范围筛选全在本地做,出题不打墨墨的历史记录接口。
第一次用跑一次全量回填。maimemo_backfill_study_records 按 next_study_date 滑窗分页(上游单次最多 1000 条,没有游标),{as_count: true} 给总数,分页走完拿全部记录。只有走到的词数和上游总数相等时才标 complete,否则标 partial 并说明只覆盖了多少。
以后是增量。maimemo_sync_today_snapshot 存完当天词表会顺手刷新学习记录,也可以单独调 maimemo_refresh_study_records。两者都先看库里最新的 observed_at:
- 当天已经同步过,就只按
voc_ids刷当天那批词,一次调用 - 中间空了整天,就整体重走一遍计划
空了整天为什么不能只查个日期窗口?因为上游只能用 next_study_date 筛日期,而学一个词会把它推到未来。按「上次同步到今天」去查,窗口内到期的词可能是 0 个,而这段时间实际学过的词全在窗口外,因为学完就改期了。新词也一样,初学当天 next_study_date 就可能排到几十天后。墨墨也没有「按历史日期取当天词表」的接口,漏掉的那几天的词表事后补不回来。所以只有重走能证明完整;计划在 1000 词以内时,它和按词刷新一样只是一次调用。
本地查记录用 maimemo_query_local_records,可以按北京时间的日期范围(last_study_date / first_study_date / next_study_date / add_date)、标签 STICKING / WELL_FAMILIAR、学习次数区间筛,支持分页。
不漏、不重复
只有走到的词数对上上游 as_count 才标 complete。滑窗不前进或者撞到页数上限就停下,标 partial 并给警告,不会假装走完了。
mirror_word 和 study_record 都是一词一行,study_record 按 word_id upsert。today_item、study_window_member、todo_entry 都以(批次或会话, 词)为主键,所以同一批次里同一个词不可能出现两次。本地查询默认只取还在计划里的词。
today_item、study_window_member、mirror_sync 这三张历史表会随同步次数增长,查询取的都是当天最新的批次,结果不会重复。
出问题
工具列表里没有 mcp__maimemo__*:多半是没跑 npm run mcp:install。再不然看看启动日志里有没有「墨墨学习 MCP 已通过 stdio 启动。」这一行。
maimemo_auth_status 返回 configured: false:凭证没配,跑 npm run credential -- set。
同步回来 0 个词:先看凭证对应的账号对不对。我遇到过这种情况,凭证能用、接口也返回 200,但数据全是空的,换成平时刷的那个账号之后立刻就正常了。另一种可能是 App 里「自动同步」没开,服务端没数据,接口只能返回空。
查询提示只覆盖已验证范围:先跑一次 maimemo_backfill_study_records。
--dump-config 看不到两行:profile 没装上,或者包路径不对。看 $DSH_HOME/profiles/<profile>/package.json 里 dsh.profile.bundles 有没有 dsh-momo-learning。
改了 SKILL.md 不生效:Skill 正文是插件加载时读的,得重启 Harness。
开发
MCP 服务是 TypeScript,插件入口 index.js 是纯 JavaScript,只用 Node 内置模块,不 import 任何 harness 包。
npm run mcp:install
npm run mcp:build # tsc -> mcp-server/dist
npm run mcp:typecheck
npm run mcp:test
改完 mcp-server/src/ 记得 npm run mcp:build。插件跑的是 dist/,而 dist/ 是随仓库提交的,不重建等于没改。这一层的更多细节在 mcp-server/README.md。
目录
这是个 bundle。package.json 里声明了 dsh.bundle.patch,所以 dsh plugin --profile <n> add <本包> 会把它作为一层 patch 挂进 profile;它内部再提供插件行——index.js 导出 apply,cordis.patch.yml 把它挂起来。DSH 里 bundle 和 plugin 不是一回事:bundle 是能装进 profile 的一层,plugin 是被 cordis.yml 挂载的一行。
| 路径 | 作用 |
|---|---|
cordis.patch.yml |
这个 bundle 的 patch 层:插入本包的插件行,以及一行指向本包 MCP 服务的 @deepseek-ai/dsh-mcp-client |
index.js |
插件本体:注册 momo-daily-learning Skill,并把本包路径作为 momoLearningPaths 服务发布出去 |
skills/momo-daily-learning/SKILL.md |
Skill 原文 |
mcp-server/ |
MCP 服务本体,独立的 TypeScript 子项目,自带 package.json、测试和 README |
verify.mjs |
自检脚本 |
LICENSE |
MIT |
cordis.patch.yml 里两行的顺序不是加载顺序。第一行发布 momoLearningPaths,第二行用 inject 声明依赖它,Loader 会等注入就绪再求值第二行的 !!js 配置。所以 MCP 行拿到的是本包的真实安装路径,不是挂载点或 profile 目录。
验证
开个新会话,确认四件事:
- Skill 目录里有
momo-daily-learning,能加载出正文 - 工具列表里有 19 个
mcp__maimemo__* maimemo_auth_status返回configured: truemaimemo_get_learning_overview返回镜像概况(还没同步过会带「尚无本地学习镜像」的 warning,这是正常的空状态)
MCP 客户端在插件激活时就完成首次连接和工具发现,所以 3、4 两步在 Harness 起来之后就能用。
不想开会话也可以跑自检脚本。它会按 launcher 的方式合成 dsh-base 各层加本 bundle 层,真的启动一次,然后断言 Skill 和 19 个工具都在:
cp <bundle>/verify.mjs "$DSH_HOME/profiles/<profile>/"
cd "$DSH_HOME/profiles/<profile>"
node verify.mjs
通过打印 PASS,缺东西就逐条列出来,并以退出码 1 结束。
卸载
dsh plugin --profile <profile> remove dsh-momo-learning
依赖和 patch 层都会移除。镜像数据和凭证不会被删。要清镜像数据用 MCP 工具 maimemo_clear_local_learning_data(confirm: true)。
已知限制
- 不支持写墨墨账号,加词、改复习状态、云词本都没有工具
maimemo_sync_word_supplements在探针没确认用户自建内容端点前固定返回UNSUPPORTED_CAPABILITY- 改
SKILL.md要重启 Harness 才生效 - 插件声明了
inject: ['skills'],组合里得有@deepseek-ai/dsh-skill(dsh-base已经挂了)。精简组合缺它的话这一行会停在待激活 - MCP 服务要能 spawn 带管道的子进程。把 stdio 管道禁掉的受限沙箱里工具会连不上,正常启动的 Harness 没这个问题
- 逐题弹窗依赖
ask_user_question,没有 UI 的会话会退化成一次一题的普通消息提问 - 全量回填覆盖的是计划里的词。墨墨没有按历史日期取当天词表的接口,所以开始用之前的逐日清单补不回来,可靠的分日历史从开始每天存快照那天起积累
- 全量回填之后新加进计划的词,要等下次回填或者出现在某天词表里才会进镜像
find_similar_words对多词短语偏弱
免责声明
这是第三方工具,跟墨墨背单词没有隶属、合作或背书关系,也不代表 DeepSeek 官方。
它只调墨墨开放平台的公开只读接口,凭证需要你自己申请,使用时请遵守墨墨开放 API 的条款和频控(比如每 10 秒 20 次、每 5 小时 2000 次)。学习数据接口目前标注为公测,上游的端点和字段随时可能变,本项目不对可用性作承诺。
题目、解析、例句和日报都是模型生成的,不是墨墨账号原文。墨墨开放接口只给词 id、拼写、作答结果和学习记录,没有释义、例句和词书信息。
访问凭证只存在你本机的系统凭证库里,项目不上传、不转发、不记录。学习数据也只留在本机镜像文件里。
License
MIT,见 LICENSE。
No comments yet. Be the first to write one.