从旧版 PCS 到 MCP:百度网盘 API 这些年到底变了什么
最近翻旧代码,又碰到百度网盘 API。这个东西挺有年代感的:网上还能搜到很多 2020 年前后的脚本,里面一堆 PCS、xpan/file、分片上传、MD5、access_token。
问题是,这些脚本现在直接跑,经常会卡在奇怪的地方。不是 OAuth 过不去,就是上传流程对不上;好不容易能列目录了,文件操作又开始返回看不懂的错误码。
刚好看到官方出了 baidu-netdisk/mcp,把百度网盘封装成 MCP Server。它提供文件列表、文件详情、上传、复制、删除、移动、重命名、搜索、分享链接、用户信息、容量查询这些工具。也就是说,现在不用每次都自己拼 REST 请求了,可以把网盘当成一组工具来用。
所以这篇就简单记一下:旧脚本为什么容易坏,MCP 这层到底帮我们省了什么,以及如果要把旧代码救回来,我会怎么改。
旧脚本为什么容易坏
以前很多脚本大概都是这个套路:
- 申请应用,拿
access_token - 调
xpan/file或更早的 PCS 接口列目录 - 上传时自己算 MD5,自己走 precreate、分片上传、create
- copy/move/delete/rename 也都自己拼接口
- 搜索、分享、配额这些功能后面再补
这个写法当年没啥问题。脚本嘛,能跑就行。但几年过去以后,问题就来了:
- 有些旧 PCS 接口不太适合新应用了。
- 鉴权比以前严格,复制一个 token 长期跑不稳。
- 上传不是简单 POST 文件,分片、预上传、block list、创建文件一步都不能少。
- 路径编码很容易出事,中文路径尤其烦。
- 返回字段越来越业务化,
fs_id/fsid、path、isdir、缩略图、摘要这些字段在不同接口里不完全一样。 - 搜索也不只是文件名关键词了,现在还有语义搜索。
最麻烦的是,旧脚本坏起来通常不是坏一个点,而是一整条链都老了。你修好列目录,上传又挂;上传能跑了,路径编码又不对;路径对了,重名文件怎么处理又跟以前不一样。
MCP 更像一层工具封装
baidu-netdisk/mcp 里的工具大概可以分成几类:
| 类别 | MCP 工具 | 做什么 |
|---|---|---|
| 文件信息 | file_list、file_doc_list、file_image_list、file_video_list、file_meta | 列目录、按类型列文件、查文件详情 |
| 文件管理 | make_dir、file_copy、file_del、file_move、file_rename | 创建目录和基本文件操作 |
| 上传 | file_upload_stdio、file_upload_by_url、文本上传 | 本地文件、URL、文本内容上传 |
| 搜索 | file_keyword_search、file_semantics_search | 关键词搜索和语义搜索 |
| 分享 | file_sharelink_set | 创建分享链接 |
| 用户 | user_info、get_quota | 用户信息和容量 |
我觉得这个方向挺合理。以前你要知道哪个接口负责预上传,哪个接口负责创建文件,哪个参数控制重名策略。现在你只要说“列目录”“上传文件”“搜索文件”,底下那些细节先交给工具处理。
当然 MCP 也不是魔法。路径还是路径,冲突策略还是冲突策略,上传也还是上传。它只是把这些麻烦集中到工具层,不用散在业务代码里到处处理。
修旧代码时我会先做 adapter
如果有一份旧脚本,我不会一上来就逐行换 URL。那样很容易变成考古,而且改完还是一堆接口细节到处飞。
我会先把旧代码里真正需要的动作抽出来,比如:
async function listDir(path) {}
async function uploadFile(localPath, remotePath) {}
async function mkdir(path) {}
async function rename(path, newName) {}
async function remove(path) {}
然后改成一层 adapter:
const netdisk = {
async listDir(dir = '/') {
return callTool('file_list', { dir });
},
async uploadFile(local_file_path, remote_path) {
return callTool('file_upload_stdio', {
local_file_path,
remote_path,
});
},
async mkdir(path) {
return callTool('make_dir', {
path,
rtype: 1,
});
},
async rename(path, newname) {
return callTool('file_rename', {
async: 1,
ondup: 'newcopy',
filelist: [{ path, newname }],
});
},
};
这样旧业务逻辑可以先不动。以后 MCP 参数变了,或者你要换 SDK,也主要改 adapter,不用全项目到处搜百度网盘接口。
路径编码最容易坑
百度网盘路径一直有个老坑:路径要以 / 开头,中文路径还要注意 URL Encode。有些地方还会提到斜杠怎么编码。
最常见就是两种错:
// 错误:没处理中文
const dir = '/我的资源/课程';
// 也可能错误:编码了两次
const dir = encodeURIComponent(encodeURIComponent('/我的资源/课程'));
我的习惯是:业务层不要到处 encodeURIComponent。业务层就用正常路径,真正发请求的时候再统一处理。如果是 MCP 工具,就先按它 README 里的参数约定来;如果是自己打 REST API,就在 adapter 里集中编码。
function normalizeRemotePath(path) {
if (!path.startsWith('/')) {
throw new Error(`remote path must start with /: ${path}`);
}
return path.replace(/\/+/g, '/');
}
这个函数只做路径规范化,不做编码。编码和规范化最好分开,不然旧代码越改越绕。
上传别再硬拼旧流程
旧上传代码是最容易坏的。以前很多脚本会自己做:
- 算每个 block 的 MD5
- precreate
- superfile2 分片上传
- create
这套流程不是不能写,但很脆。接口细节一变,权限策略一变,错误码一变,就要重新查文档。
MCP 里有 file_upload_stdio。如果只是让自动化脚本把文件传上去,我会优先用它。除非你真的需要进度条、断点续传、秒传判断,否则没必要在脚本里维护一套上传 SDK。
迁移早期也别急着把上传结果包装得太漂亮。原始响应先留着,排错的时候很有用。
文件操作要写清楚冲突策略
复制、移动、删除、重命名这些操作,看起来简单,但最怕默认行为不清楚。
比如重命名或移动时,最好明确写 ondup:
{
"async": 1,
"ondup": "newcopy",
"filelist": [
{
"path": "/test/old.docx",
"dest": "/test/archive",
"newname": "old.docx"
}
]
}
我一般会默认用 newcopy。自动化脚本误覆盖网盘文件真的很烦,宁愿多出一个副本,也别悄悄把原文件盖了。真要覆盖,再显式传 overwrite。
删除也是一样。不要让 remove(path) 这种函数太黑盒,至少要知道它调的是哪个工具、是不是批量、失败时有没有原始响应。
搜索不只是文件名了
以前搜网盘,基本就是关键词搜文件名。现在 MCP 里有 file_keyword_search,也有 file_semantics_search。
这两个东西最好别混在一起。关键词搜索适合“我知道文件大概叫什么”;语义搜索适合“我记得内容大概是什么,但不记得文件名”。
可以简单做个兼容:
async function search(query, mode = 'keyword') {
if (mode === 'semantic') {
return callTool('file_semantics_search', { query });
}
return callTool('file_keyword_search', {
dir: '/',
keyword: query,
});
}
旧应用默认还是走关键词比较稳。等真的需要按内容找文件,再把语义搜索暴露出去。
我会怎么迁移
如果手里有一份 2020 年左右的百度网盘脚本,我大概会按这个顺序改:
- 把散落的 API URL 收到一个
netdisk adapter里 - 把列目录、查详情、创建目录、上传、删除、移动、重命名、搜索拆成独立方法
- 路径统一校验,编码只在请求边界做
- 上传优先换成
file_upload_stdio或官方封装 - 文件操作显式设置冲突策略
- 原始响应先留着,不要一开始就把错误包装没了
这类 API 不是特别难,主要是边界条件多。路径、权限、分页、文件类型、冲突策略、异步任务,哪个没处理好都可能让脚本看起来“差一点就能跑”。
小结
百度网盘 API 这几年的变化,不只是接口地址变了,而是调用方式变了。以前是脚本自己拼 HTTP 请求,现在更适合把网盘能力封装成工具来调用。baidu-netdisk/mcp 就是这个方向。
如果只是让 Agent 或自动化脚本管理网盘文件,MCP 这层会比旧 PCS 脚本舒服很多。旧代码要修的也不是某一个 URL,而是把路径、上传、文件操作、搜索这些能力从旧接口里拆出来。
这样以后接口再变,也不至于全项目一起陪着塌。
另外,我做了两个配套工具练练手:pan.n3m.org 可以用来浏览百度网盘,bduss.n3m.org 可以用来获取 BDUSS。