mcp_file_manager
Enables AI agents and users to upload and download files via MCP, generating shareable links and identifier codes. Files are automatically deleted after 24 hours.
README
mcp_file_manager
通过 mcp 服务实现用户/ai agent 上传/下载文件并生成对应链接,每次进行上传操作时都生成对应标识码供 ai 查找,文件 24 小时后自动删除。
一个开箱即用的文件中转 MCP 服务:AI 和人都可以把文件扔进来,拿到一个标识码和一个可直接分享的下载链接;之后只要报出标识码,AI 就能重新找到并读取这个文件。所有文件默认保留 24 小时,到期自动删除。
特点
- 双向可用:AI 用 MCP 工具上传/下载;人用浏览器页面上传/下载。两边共用同一套存储与标识码。
- 标识码友好:Crockford Base32(已剔除
I/L/O/U),展示为7K2QF-9XM4T;查找时大小写、连字符、0/O1/I/l混淆全都宽容。 - 24 小时自动清理:后台守护任务每 10 分钟扫一次,启动时也扫一次(覆盖停机期间到期的文件),同时回收无主文件与失效上传链接。
- 全流式写盘:边写盘边算 SHA-256 并计数,超限立即中断,不把整个文件读进内存。
- 四种上传源:base64 内容、纯文本、服务器本地路径、远程 URL。
- 两种传输:
stdio(供 Claude Desktop / Cursor 等客户端拉起)与无状态Streamable HTTP(供远程部署)。 - 零依赖存储:本地文件系统 + 原子写入的
index.json,不需要数据库或对象存储。
关于保留期:仓库最初的描述是 14 天,本实现按最新要求改为 24 小时。保留期完全可配(
FM_TTL_HOURS),如需恢复 14 天只需设为336。
快速开始
需要 Node.js >= 20.11。
npm install
cp .env.example .env # 可选,不改也能跑
npm run dev # 开发模式:stdio + 本地文件服务
npm run build && npm start
启动后浏览器打开 http://localhost:8787 即为上传页面。
作为远程 HTTP 服务部署:
FM_HOST=0.0.0.0 FM_API_TOKEN=你的强密钥 npm run start:http
# MCP 端点:POST http://<host>:8787/mcp
接入 MCP 客户端(stdio)
参见 examples/claude_desktop_config.json:
{
"mcpServers": {
"file-manager": {
"command": "node",
"args": ["/结对路径/mcp_file_manager/dist/index.js"],
"env": {
"FM_DATA_DIR": "/结对路径/mcp_file_manager/data",
"FM_PUBLIC_BASE_URL": "http://localhost:8787",
"FM_TTL_HOURS": "24"
}
}
}
}
stdio 模式下会同时启动本地文件 HTTP 服务,否则生成的下载链接没人响应。不需要时加
--no-http。 日志一律输出到 stderr,stdout 留给 MCP 的 JSON-RPC 通道。
前端页面
页面在 public/ 下,是三个普通静态文件(HTML + CSS + 原生 JS),无构建步骤、无前端依赖,由 Express 直接托管:
| 入口 | 用途 |
|---|---|
GET / |
完整上传页:自己传文件、拿标识码、反查旧标识码 |
GET /u/:ticket |
同一份页面的“一次性上传链接”形态,发给外部的人使用 |
GET /assets/* |
public/ 里的样式与脚本 |
功能:
- 三种选文件方式:拖拽、点击选择、
Ctrl / ⌘ + V直接粘贴文件或截图;支持多文件排队逐个上传。 - 真实上传进度:用 XHR 上传,逐文件显示百分比进度条,失败的条目会留在列表里可直接重试。
- 标识码是主角:上传完成后用大号等宽字体展示
7K2QF-9XM4T,点一下即复制;另外提供“复制链接”与“复制给 AI”(一次拿到标识码 + 文件名 + 下载地址 + 到期时间)。 - 到期倒计时:每张卡片把
expiresAt渲染为本地时间并满上“还剩 N 小时”,过期后变红并提示已被自动删除。 - 标识码反查:输入标识码即可重新拿回下载链接(走
GET /api/files/:code,大小写与连字符不敏感)。 - 本机历史:最近 20 次上传存在
localStorage(不上传服务器、到期自动消失),方便事后回查标识码。 - 高级选项:备注、标签、自定义保留小时数(上限受
FM_MAX_TTL_HOURS约束)。 - 自适应:页面启动时拉
GET /api/config,自动展示当前保留策略与单文件上限(超限文件在上传前就被拦住);仅当服务端设了FM_API_TOKEN时才显示 Token 输入框(保存在sessionStorage)。 - 适配手机屏幕,跟随系统浅色/深色主题。
部署时请让
public/与dist/一同发布(npm 包的files与 Dockerfile 都已包含);缺少时页面会直接提示而不是返回空白。
MCP 工具
| 工具 | 作用 | 关键参数 |
|---|---|---|
upload_file |
上传文件,返回标识码与链接 | content(base64) / text / path / url 四选一,name、tags、ttlHours |
download_file |
按标识码取回内容 | code、savePath、encoding(auto/utf-8/base64/none) |
get_file_info |
只看元数据与链接 | code |
list_files |
列表/搜索(忘记标识码时用) | query、tag、limit、sort |
delete_file |
不等到期,立即删除 | code |
extend_expiry |
重算为“从现在起再保留 N 小时” | code、hours |
create_upload_link |
生成给人用的临时上传页面 | note、expiresInMinutes、maxUses、fileTtlHours |
sweep_expired |
手动触发一次到期清理 | — |
get_storage_stats |
文件数、占用、保留策略、下一个到期时间 | — |
典型对话:
- 用户:“把这份报价单存一下。” → AI 调
upload_file→ 回复标识码7K2QF-9XM4T+ 下载链接 + “24 小时后自动删除”。 - 用户(稍后):“7K2QF-9XM4T 里的金额是多少?” → AI 调
download_file直接读内容。 - 需要用户提供文件时:AI 调
create_upload_link→ 发出一个/u/<ticket>链接 → 用户上传后页面直接展示标识码。
HTTP 接口
| 方法 | 路径 | 说明 | 需 Token |
|---|---|---|---|
| GET | / |
上传页面 | 否 |
| GET | /assets/* |
前端静态资源 | 否 |
| GET | /healthz |
健康检查 | 否 |
| GET | /api/config |
页面渲染用的公开配置(保留期、上限、是否需 Token) | 否 |
| POST | /api/upload |
multipart 上传(字段名 file) |
是 |
| GET | /f/:code · /f/:code/:filename |
下载(?inline 可在浏览器内预览) |
否(标识码即凭证) |
| GET | /api/files/:code |
单文件元数据 JSON | 否 |
| GET | /api/files |
列表/搜索 | 是 |
| DELETE | /api/files/:code |
删除 | 是 |
| POST | /api/files/:code/extend |
延期,体 {"hours":48} |
是 |
| GET | /api/stats · POST /api/sweep |
状态与手动清理 | 是 |
| GET/POST | /u/:ticket |
临时上传页面与提交 | 否(票据即凭证) |
| GET | /api/tickets/:ticket |
票据详情(页面用于判定链接是否还有效) | 否(票据即凭证) |
| POST | /mcp |
无状态 Streamable HTTP MCP 端点 | 是 |
鉴权方式(三者均可,仅在设置了 FM_API_TOKEN 时生效):Authorization: Bearer <token>、X-API-Token: <token>、?token=<token>。
# 上传
curl -X POST http://localhost:8787/api/upload \
-H "Authorization: Bearer $FM_API_TOKEN" \
-F "file=@./report.pdf" -F "tags=财务,Q3" -F "ttlHours=48"
# 下载
curl -OJ http://localhost:8787/f/7K2QF9XM4T
环境变量
| 变量 | 默认值 | 说明 |
|---|---|---|
FM_TTL_HOURS |
24 |
默认保留时长(小时),到期自动删除 |
FM_MAX_TTL_HOURS |
720 |
单次请求可申请的保留上限(30 天) |
FM_SWEEP_INTERVAL_MINUTES |
10 |
到期清理扫描间隔 |
FM_DATA_DIR |
./data |
数据目录(files/、tmp/、index.json) |
FM_HOST / FM_PORT |
127.0.0.1 / 8787 |
HTTP 监听地址 |
FM_PUBLIC_BASE_URL |
http://<host>:<port> |
拼接对外链接用,反代/域名下必须设置 |
FM_API_TOKEN |
空 | 写接口鉴权;非本机部署强烈建议设置 |
FM_MAX_UPLOAD_MB |
100 |
单文件上限 |
FM_MAX_INLINE_MB |
4 |
MCP 内联返回内容的上限,超过则只给链接 |
FM_ALLOW_REMOTE_FETCH |
1 |
是否允许 url 源上传 |
FM_ALLOW_LOCAL_PATH |
1 |
是否允许 path 源上传 |
FM_LOG_LEVEL |
info |
debug / info / warn / error |
保留与清理策略
- 每个文件写入时记录
expiresAt = 上传时间 + 24 小时。 - 三个时机会执行清理:服务启动时、每 10 分钟的守护任务、手动调用
sweep_expired。 - 另外,任何一次对已过期标识码的访问会返回
410 expired并顺手删除该文件,不依赖守护任务的时序。 - 清理同时回收:到期文件实体 + 元数据、用尽/过期的上传票据、失去元数据的孤儿文件。
- 需要保留更久:上传时传
ttlHours,或事后调extend_expiry;全局改默认值用FM_TTL_HOURS。
项目结构
public/
index.html 上传页(/ 与 /u/:ticket 共用这一份)
styles.css 样式(含深色模式与移动端适配)
app.js 原生 JS:拖拽/粘贴、进度条、标识码复制、反查、本机历史
src/
index.ts 启动入口(参数解析、传输选择、优雅退出)
service.ts 全部业务逻辑(上传/下载/列表/延期/清理/统计)
store.ts 元数据索引(串行写队列 + 临时文件原子 rename)
storage.ts 文件实体存储(标识码命名,彻底隔结路径穿越)
codes.ts 标识码生成 / 归一化 / 展示格式
retention.ts 24h 到期守护任务
config.ts errors.ts logger.ts mime.ts utils.ts version.ts
mcp/server.ts 9 个 MCP 工具定义
http/app.ts Express 路由 + 静态资源 + 无状态 MCP 端点
http/pages.ts 前端目录定位与页面下发
tests/service.test.ts
分层原则:FileManagerService 是唯一真相,MCP 层、HTTP 层与前端都只是它的薄封装,保证各入口的标识码、链接与保留期行为完全一致。
开发
npm run typecheck # tsc --noEmit
npm test # node --test(含“默认 24 小时”与清理行为的回归用例)
npm run build # 只编译 TypeScript;public/ 直接发布,无需构建
Docker
docker compose up -d --build
# 或
docker build -t mcp-file-manager . && docker run -p 8787:8787 -v "$PWD/data:/data" mcp-file-manager
安全提醒
- 标识码即凭证:拿到标识码即可下载(无需 Token),分享链接前请确认接收方。标识码空间为 32^10,无法枚举。
- 对外暴露时请务必设置
FM_API_TOKEN,并在反代层加上 HTTPS 与频率限制。 - 页面上的 Token 只存在当前浏览器会话(
sessionStorage),不会写入磁盘持久保存。 - 如无需让 AI 读写服务器本地文件或抓取外网,请设
FM_ALLOW_LOCAL_PATH=0、FM_ALLOW_REMOTE_FETCH=0。 - 上传的原始文件名只保存在元数据里,磁盘上使用“标识码 + 白名单扩展名”命名。
后续可做
- 可插拔存储后端(S3 / R2)与预签名直传
- 多负载部署时把元数据换成 SQLite / Redis
- 可选的服务端加密与病毒扫描钩子
- 按上传者维度的配额与审计日志
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.