Monash Study Kit 把你自己的 Moodle 和 Ed 同步到电脑上,让 AI 软件通过 MCP 去搜。Claude Desktop 和 Claude Code 是在本机把它当程序启动,用 stdio 通信。ChatGPT 和网页版、手机上的 Claude 做不到这一点,它们跑在别人的服务器上,只能去调一个 HTTPS 地址。
10 月 30 日发布的 1.4.0 加了一个可选的 monash remote 模式来解决这个问题。这篇讲它是怎么锁住的,因为一个能读你 Moodle 的公网地址,出错的代价很大。
只给一个人,只读自己的数据
我之前就决定不替所有人托管 Study Kit。那样我的服务器上会存着每个同学的 Moodle 登录和 Ed 令牌,被攻破一次就全部泄露。文档里也是这么解释的。
所以远程模式只给数据的主人自己用。你在自己的服务器上跑,或者在自己电脑上开一个 Cloudflare 免费的临时隧道,它把你同步好的资料提供给你自己的 AI 软件。setup 不会启动它,安装和更新也不会开任何端口。只有你自己运行 monash remote serve,它才开始监听。
服务器还拒绝绑定在本机回环以外的地址:
def make_server(addr, con):
if addr[0] not in {"127.0.0.1", "localhost"}:
raise ValueError("Bind remote MCP on loopback behind an HTTPS reverse proxy")
HTTPS 由前面的 nginx 或隧道负责。每个请求都会检查 Host 和 Origin 是否和你给的公网地址一致,所以别的网页把自己的域名指到你机器上(DNS rebinding)会直接拿到 403。
用配对码代替密码
ChatGPT 和 Claude 用 OAuth 连接,通常意味着要有一个输密码的登录页。一个只有一个人用的工具,我不想为它做账号系统。所以登录页要的是你在自己终端里拿到的码:
$ monash remote pair
Pairing code: 3F9A-0C21-B7E4
Valid for 10 minutes, single use.
数据库里只存它的 SHA-256 哈希。输对一次就作废。输错五次窗口就关掉,要重新运行 pair。没有打开的窗口时,页面会直接提示,什么都不接受。别人就算知道了你的地址,不在十分钟内坐在你的电脑前也进不来。
谁可以连进来
MCP 软件在登录之前会先自己注册,协议规定注册不需要登录。也就是说谁都能注册。有两点让这件事不要紧。
第一,只有回调地址全部在白名单上,注册才会被接受:claude.ai、claude.com 和 chatgpt.com 上那几条固定的 OAuth 回调路径,整个主机名完全匹配,不能带端口、查询串或片段。想把授权码发到别处的客户端在注册时就被拒了,所以就算授权码被截到,也只能回到 Claude 或 ChatGPT。可以用参数额外加一个精确的地址,但不能写通配。
第二,注册的客户端最多 50 个。满了以后,会清掉注册超过一小时、从来没换到过令牌的客户端。真正在用的客户端一定有刷新令牌,所以不会被清掉。
剩下的是公开客户端的标准 OAuth:
- 必须用 PKCE(S256)。只有 verifier 算出来的哈希和登录时的 challenge 一致,授权码才能换令牌。
- 访问令牌一小时过期。刷新令牌 30 天过期,每用一次就换新的,旧的立刻失效。
- 令牌以哈希形式存在
secrets/remote-mcp.db,文件创建时权限就是 0600。 monash remote revoke --all删掉所有客户端、授权码和令牌,并关掉还开着的配对窗口。
远程只开放读的工具
本地的 Study Kit 有 18 个工具。其中两个会启动 Moodle 登录或同步,这需要在那台机器上开浏览器、输密码。远程模式把它们从工具列表里去掉,就算软件硬要按名字调用,也会被拒绝:
if spec and len(spec) > 3 and not spec[3]:
return {"jsonrpc": "2.0", "id": msg.get("id"), "error": {
"code": -32602, "message": "Run login or sync on the server's own terminal"}}
所以令牌能碰到的只有 16 个查询工具。令牌被偷的话,在它过期或被你撤销之前,对方能读你的课件,这当然不好,但他没法用你的身份登录,也改不了 Moodle 或 Ed 上的任何东西。不管本地还是远程,Study Kit 都没有提交作业、发帖或做测验的工具。
怎么验证的
tests/test_remote.py 里有 22 个测试,用编造的数据在一台机器上走完整个流程:从 401 开始的服务发现、注册、配对、PKCE、令牌过期和轮换、撤销、回调白名单、错误的 Host 和 Origin,以及拒绝登录和同步。有一个测试专门打开旧格式的数据库(令牌还没和服务器地址绑定的时候),确认升级以后之前存的令牌还能用。
10 月 30 日,PyPI 上的 1.4.0 包也在干净环境里用 Claude 和 ChatGPT 真实的回调地址走了一遍同样的登录和查询流程。那次测试没有公网域名。用我自己的域名和服务器,ChatGPT Plus 可以查我的 Moodle 和 Ed。具体步骤在自己托管。
小结
- 个人工具的远程模式就应该一直是个人的。一个主人,只有他自己的数据,不替别人启动任何东西。
- 只有一个用户的时候,一个从自己终端拿的码就能代替整套账号系统。
- 回调地址在客户端注册时就查清楚,后面每一步都能放心用。
- 想清楚哪些工具可以离开这台机器。会登录或会写东西的,都留在本地。