一纸,寄万千。
纸鹊 Magpie 用于 HTML、Markdown 与 ZIP 的上传、预览和分享,使用 MIT 许可证。
@enderchen/magpie@1.6.7 已公开发布,可通过 npm 安装 CLI。生产服务地址为 https://magpiesend.site,通过 MAGPIE_BASE 或 --base 配置;本地开发默认地址仍为 http://localhost:8858。插件源码保留用于开发,网页暂不提供插件入口。
English | 中文
纸鹊 Magpie是一个零配置的 HTML / Markdown 即时预览与分享工具。把写好的文档拖进来,立刻获得一个干净的在线页面——无需部署流程,无需服务器知识。特别适合 AI 生成内容的一键分享。
- 即时预览 — 上传 HTML 或 Markdown 文件,秒级生成在线渲染页面
- Markdown 增强渲染 — 代码高亮(highlight.js)、数学公式(KaTeX)、Mermaid 图表,深色/浅色主题自动切换
- 源码查看 — 渲染 / 源码双模式切换,方便对照
- 短链接 — 每个文件自动生成 8 位短链(
/s/xxxxxxxx),分享更简洁 - 文件管理 — 重命名、删除、下载、公开/私有切换,操作简单直观
- 拖拽上传 — 支持点击选择和拖拽两种方式,单文件最大 50MB
- 版本历史 — 覆盖上传自动保留历史版本,可随时回滚
- 响应式设计 — 桌面端与移动端自适应,深色模式自动跟随系统
- 标签系统 — 为文件打标签,多维度分类检索
- 分类管理 — 创建分类归属文件,层级清晰
- 收藏功能 — 一键收藏常用文件,快速访问
- 多用户支持 — admin 可创建和管理多个用户,普通用户只能访问自己的文件和公开文件
- 开放注册 — 通过
ALLOW_REGISTRATION=true开放用户自助注册,配合 SMTP 实现邮箱验证 - 会话鉴权 — Cookie + bcrypt 密码哈希
- API Token — 每用户可创建多个 API Token,适合脚本和 AI 工具调用
- 公开/私有文件 — 上传时可选是否公开,私有文件仅文件所有者和 admin 可访问
- API 限流 — 登录和上传接口均有频率限制,防止暴力破解和滥用
- MCP 协议支持 — 内置 MCP Streamable HTTP 端点,AI 工具可直接调用
- Skills 管理 — 自动发现
skills/目录下的 Claude Code/Desktop 技能包 - JSON 上传接口 —
/api/files/upload-json支持程序化上传,适合 AI 工作流
- 零依赖运行 — 单容器即可启动,SQLite 内置存储
- Docker 一键部署 — 多阶段构建,环境变量配置,数据卷持久化
- 数据库迁移 — 自动执行 schema 迁移,升级无需手动操作
- 后端: Node.js + Express + express-session(SQLite 会话存储),按域拆分的 Router 架构(routes/ + lib/ 共享层)
- 数据库: SQLite3(零配置,自动迁移)
- 前端: 原生 JavaScript(无框架依赖)
- 渲染: marked.js + highlight.js + KaTeX + Mermaid
- 安全: helmet + 分级 CSP(管理界面严格策略,渲染页 iframe sandbox 隔离 + 内容分级 CSP)
- 协议: MCP Streamable HTTP(@modelcontextprotocol/sdk)
- 测试: node:test + supertest(单元 + 集成),GitHub Actions CI
- 容器: Docker / Docker Compose
git clone https://github.com/enderchen/magpie.git magpie
cd magpie
cp .env.example .env # 编辑 .env 填入 ADMIN_PASSWORD 和 SESSION_SECRET
docker-compose up -d访问 http://localhost:8858,浏览器会跳到登录页。
npm install
ADMIN_USER=admin ADMIN_PASSWORD=test1234 SESSION_SECRET=dev-secret npm start开发模式(热重载):
npm run devnpm test # 单元 + 集成测试(node:test + supertest)
npm run test:unit # 仅单元测试
npm run build # 构建前端产物(esbuild → public/dist)端到端 / 性能基准(需先 `=8000# npm start= 起服务):
node test/perf-harness.js 8858 # 核心流程 e2e(登录/上传/渲染/短链/标签)
node test/mcp-harness.js 8858 # MCP 端点
node test/perf-bench.js 8858 # 渲染/列表/缓存延迟基准纸鹊 Magpie随包提供 magpie 命令行工具,可通过 REST API 上传 / 列出 / 管理文件,对大文件和 ZIP 走 multipart 二进制流式上传(比 MCP 的 base64 进 token 流更快更省):
使用 Node.js ≥ 22.13.0 安装已发布的 @enderchen/magpie@1.6.7(支持 Node 22 / 24):
npm install -g @enderchen/magpie@1.6.7
export MAGPIE_BASE=https://magpiesend.site
# 在工作台设置中创建个人 API Token 后,配置 MAGPIE_TOKEN
magpie --version
magpie --help本地开发可使用源码安装;以下示例连接本机服务:
npm install
npm link # 在本项目源码目录执行,注册 magpie 命令
export MAGPIE_BASE=http://localhost:8858 # 本地开发;生产接入用 https://magpiesend.site
magpie upload ./report.html --public --token '<你的 token>'
magpie ls --kw 季度
magpie cat 8
magpie --helpmagpie 与 MCP 是对称的两个客户端入口,都架在同一套 REST API 之上。详见 magpie --help。
magpie update --check 查询 @enderchen/magpie 的版本;magpie update 更新同一包名。--check 仅查询,不安装。服务器的 APP_URL 不会自动配置客户端的 MAGPIE_BASE;CLI 根地址不加 /mcp。维护者打包与后续版本发布步骤见下方指南。
维护者打包与后续发布指南见 docs/RELEASING.md。
纸鹊 Magpie支持多用户体系。admin 可管理全部用户和文件,普通用户只能操作自己的文件和公开文件。
内容安全(CSP):通过 helmet + 分级策略加固——管理界面下发严格 CSP(仅放行同源 script),用户内容渲染页用 iframe sandbox(无 allow-same-origin,阻断对父窗口的访问)隔离,其中 Markdown 页套严格 CSP(内联 mermaid 脚本靠 nonce 放行),HTML 页用宽松 CSP + sandbox 兜底(用户 HTML 常含合法 script)。分享链接(/api/files/:id/render、/s/:key、下载、源码)在文件标记为公开时可匿名访问;上传时取消勾选「公开访问」可让该文件仅所有者和 admin 可见。
API 和 MCP 端点支持三种认证方式:
- Session Cookie — 登录后获得
magpie.sid,适合浏览器访问 - API Token — 用户在设置中创建
mg_前缀的 Token,适合脚本调用 - MCP Token — 环境变量
MCP_TOKEN,适合 AI 工具连接(向后兼容)
| 变量 | 必填 | 说明 |
|---|---|---|
ADMIN_USER |
否 | 首次启动、users 表为空时使用的管理员用户名;留空默认 admin |
ADMIN_PASSWORD |
否 | 首次启动、users 表为空时使用的管理员密码(≥8 位);留空则自动生成 16 位随机密码并打到启动日志 |
SESSION_SECRET |
生产必填 | 加密会话 Cookie;缺失时开发模式自动生成临时密钥,重启会失效 |
NODE_ENV |
否 | production 时 Cookie 仅 HTTPS 下发送,SESSION_SECRET 缺失会拒绝启动 |
PORT |
否 | 默认 8858 |
MCP_TOKEN |
否 | /mcp 端点的全局 Bearer token(向后兼容);未设置时仍可用用户级 API Token(mg_ 前缀)访问 MCP |
ALLOW_REGISTRATION |
否 | 设为 true 开放用户自助注册;默认关闭,仅 admin 可创建用户 |
SMTP_HOST |
否 | SMTP 服务器地址(如 smtp.qq.com),配置后支持邮箱验证 |
SMTP_PORT |
否 | SMTP 端口(如 465) |
SMTP_SECURE |
否 | 是否使用 SSL(true/false) |
SMTP_USER |
否 | SMTP 登录用户名 |
SMTP_PASS |
否 | SMTP 登录密码或授权码 |
SMTP_FROM |
否 | 发件人地址(如 "纸鹊 Magpie <user@example.com>") |
APP_URL |
否 | 应用外部访问地址,用于拼接验证链接(如 http://localhost:8858) |
FEEDBACK_EMAIL |
否 | 问题反馈邮件接收地址;留空时回退到首个管理员邮箱 → SMTP_FROM |
GOOGLE_CLIENT_ID |
否 | Google Web 应用 OAuth Client ID;与 GOOGLE_CLIENT_SECRET 同时配置后启用 Google 登录 |
GOOGLE_CLIENT_SECRET |
否 | Google Web 应用 OAuth Client Secret;仅保存在服务端环境变量中 |
GOOGLE_HTTP_TIMEOUT_MS |
否 | Google Token 与 OIDC 公钥请求超时,范围 1000-60000 毫秒,默认 10000 |
GOOGLE_HTTPS_PROXY |
否 | 仅供 Google OAuth 出站请求使用的可信 HTTP CONNECT 代理,支持 http:// 或 https:// |
MAGPIE_DATA_DIR |
否 | 数据目录,默认 ./data |
COOKIE_SECURE |
否 | 设为 true 时 Cookie 仅 HTTPS 传输(生产推荐) |
MCP_IP |
否 | MCP 端点日志中显示的主机名,默认 localhost |
MCP_PROTOCOL |
否 | MCP 端点协议,默认 http |
TOKEN_ENCRYPTION_KEY |
否 | API Token 加密密钥(hex 32 字节);未设置时自动在数据目录生成 token-key.key |
MAX_FILE_VERSIONS |
否 | 单个文件保留的最大版本数,默认 20 |
BACKUP_CRON |
否 | 自动备份 cron 表达式(如 0 3 * * *) |
BACKUP_DIR |
否 | 自动备份目录,默认 <MAGPIE_DATA_DIR>/backups |
如果 ADMIN_USER 和 ADMIN_PASSWORD 都留空启动,首次初始化日志会提示已创建管理员,并输出生成的初始密码。复制日志里的密码登录,并妥善保存。
SESSION_SECRET 推荐生成方式:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"所有用户登录后可在设置中修改密码。admin 可在用户管理中重置其他用户密码。
手动方式(SQLite 命令行):
node -e "console.log(require('bcryptjs').hashSync('新密码', 10))"
sqlite3 data/database.sqlite "UPDATE users SET password_hash='<上面生成的hash>' WHERE username='admin';"magpie/
├── server.js # 入口:app 装配 + 中间件 + 启动编排(业务逻辑已拆分)
├── routes/ # 按域拆分的 Express Router
│ ├── auth.js # 登录/注册/邮箱验证
│ ├── users.js # 用户管理(admin)
│ ├── tokens.js # API Token
│ ├── files.js # 文件 CRUD/上传/渲染/版本/标签/收藏/统计
│ ├── tags.js # 标签
│ ├── categories.js # 分类 + 模板元数据
│ ├── content-templates.js # 内容模板市场
│ ├── admin.js # 备份导出/导入/统计
│ └── skills.js # Skills + MCP 配置
├── lib/ # 共享层(被 routes 复用)
│ ├── db.js # SQLite 访问(dbRun/dbGet/dbAll + PRAGMA)
│ ├── paths.js # 数据/上传目录常量
│ ├── util.js # now/shareKey/clientIp/decodeFilename 等纯函数
│ ├── csp.js # 分级 CSP 策略 + nonce
│ ├── auth-state.js # adminUserId 共享状态
│ ├── templates.js # 模板系统 + marked/hljs/KaTeX 渲染管线
│ ├── render.js # 文件 → HTML 渲染(含 CSP 下发)
│ ├── render-cache.js # 渲染结果 LRU 缓存
│ ├── fts.js # FTS5 全文索引
│ ├── categories.js # 分类名内存缓存
│ ├── view-counts.js # 浏览数缓冲批量回写
│ ├── zip.js # ZIP 上传(安全校验/解压/分类)
│ ├── dispatch.js # MCP 进程内请求分发(绕过 TCP 自调用)
│ ├── crypto.js # API Token 明文 AES-256-GCM 加密
│ ├── usage.js # 用户存储空间维护
│ └── middleware/ # 鉴权 + 文件加载 + 用量采集中间件
├── logger.js # 结构化 JSON Lines 日志
├── mailer.js # SMTP 邮件(验证码/验证链接)
├── mcp-server.js # MCP Streamable HTTP 端点(/mcp)
├── migrations.js # 数据库迁移 runner
├── migrations/ # 按序执行的 schema 迁移文件(001-022)
├── skills-registry.js # 扫描 skills/ 目录,提供 skill 列表/详情/zip 打包
├── templates/ # Markdown 渲染样式模板(default/github/academic/dark-pro)
├── package.json
├── build.js # esbuild 打包前端 → public/dist
├── Dockerfile
├── docker-compose.yml
├── .env.example # 环境变量示例
├── .mcp.json # MCP 客户端配置示例
├── docs/
│ ├── api.md # REST API 完整参考
│ └── design/ # 设计文档
├── skills/
│ └── magpie/ # Claude Code / Desktop 统一技能:上传、生成内容、幻灯片、模板市场
├── test/ # 单元 + 集成测试(node:test + supertest)+ e2e harness
├── data/ # SQLite 数据库、上传文件与会话存储(运行时自动创建)
└── public/ # 前端静态资源
├── index.html
├── css/style.css
├── js/ # 按页拆分的 ES 模块
└── dist/ # 构建产物(npm run build 生成,git 忽略)
端口 8858(PORT 可覆盖)。所有写入端点要求登录或 Bearer token。完整参考见 docs/api.md。
| 端点 | 方法 | 说明 |
|---|---|---|
/api/auth/me |
GET | 当前登录信息(返回 {id, username, email, emailVerified, role}) |
/api/auth/login |
POST | 登录({account, password} 或 {username, password},自动识别用户名或邮箱) |
/api/auth/register |
POST | 注册(需 ALLOW_REGISTRATION=true) |
/api/auth/logout |
POST | 登出 |
/api/auth/change-password |
POST | 修改密码(所有用户可用) |
/api/auth/profile |
POST | 编辑个人资料(用户名/邮箱) |
/api/auth/send-register-code |
POST | 发送注册验证码(需开放注册) |
/api/auth/verify-email |
GET | 验证邮箱 token |
/api/auth/smtp-status |
GET | SMTP 是否已配置 |
/api/auth/registration-status |
GET | 注册是否开放 |
| 端点 | 方法 | 说明 |
|---|---|---|
/api/users |
GET | 列出所有用户 |
/api/users |
POST | 创建用户 |
/api/users/:id |
PUT | 更新角色或重置密码 |
/api/users/:id |
DELETE | 删除用户,文件转交 admin |
| 端点 | 方法 | 说明 |
|---|---|---|
/api/tokens |
GET | 列出自己的 Token |
/api/tokens |
POST | 创建 Token(明文仅返回一次) |
/api/tokens/:id |
DELETE | 删除 Token |
| 端点 | 方法 | 说明 |
|---|---|---|
/api/files |
GET | 列出文件(admin 看全部,普通用户看自己的 + 公开的) |
/api/files/search |
GET | 全文 + 文件名搜索(分页、过滤) |
/api/files/upload |
POST | multipart 上传(支持 .html/.htm/.md/.markdown/.zip,50MB) |
/api/files/upload-json |
POST | JSON 上传({name, content, isPublic?}) |
/api/files/batch |
POST | 批量操作(删除/公开/私有/分类,≤200) |
/api/files/:id |
GET | 单文件元数据 |
/api/files/:id |
PUT | 重命名或切换公开/私有 |
/api/files/:id |
DELETE | 删除文件 |
/api/files/:id/content |
GET | 返回原始文本 |
/api/files/:id/render |
GET | 返回渲染后 HTML |
/api/files/:id/download |
GET | 流式下载文件(Bundle 以 ZIP 下载) |
/api/files/:id/asset/* |
GET | Bundle 资源文件访问 |
/api/files/:id/overwrite |
POST | 覆盖上传(自动版本备份) |
/api/files/:id/overwrite-zip-base64 |
POST | base64 bundle ZIP 显式覆盖 |
/api/files/:id/versions |
GET | 版本历史列表 |
/api/files/:id/versions/:ver/restore |
POST | 恢复到指定版本 |
/api/files/:id/versions/:ver/download |
GET | 下载历史版本(Bundle 以 ZIP 下载) |
/api/files/:id/stats |
GET | 访问统计(viewCount/daily7/daily30) |
/s/:key |
GET | 短链接渲染页面 |
| 端点 | 方法 | 说明 |
|---|---|---|
/api/tags |
GET | 列出所有标签(含 file_count) |
/api/tags |
POST | 创建标签 |
/api/tags/:id |
DELETE | 删除标签 |
/api/files/:id/tags |
PUT | 替换文件的标签列表 |
| 端点 | 方法 | 说明 |
|---|---|---|
/api/files/:id/star |
POST | 收藏文件 |
/api/files/:id/star |
DELETE | 取消收藏 |
| 端点 | 方法 | 说明 |
|---|---|---|
/api/categories |
GET | 列出分类(含 file_count) |
/api/categories |
POST | 创建分类 |
/api/categories/:id |
PUT | 重命名分类(仅 admin) |
/api/categories/:id |
DELETE | 删除分类(仅 admin) |
/api/files/:id/category |
PUT | 设置文件分类 |
| 端点 | 方法 | 说明 |
|---|---|---|
/api/content-templates/market |
GET | 公开模板列表(无需登录) |
/api/content-templates |
GET | 当前用户模板列表 |
/api/content-templates |
POST | 创建模板 |
/api/content-templates/:id |
PUT/DELETE | 更新/删除模板(仅所有者) |
/api/content-templates/:id/use |
POST | 记录模板使用计数 |
/api/templates |
GET | 样式模板(渲染皮肤) |
| 端点 | 方法 | 说明 |
|---|---|---|
/api/admin/export |
GET | 导出数据库备份 |
/api/admin/import |
POST | 导入备份 |
/api/admin/stats |
GET | 系统统计 |
| 端点 | 方法 | 说明 |
|---|---|---|
/api/skills |
GET | 列出已安装的 skill 包 |
/api/skills/:name |
GET | skill 详情 |
/api/skills/:name/download |
GET | ZIP 下载整个 skill 目录 |
| 端点 | 方法 | 说明 |
|---|---|---|
/api/feedback |
POST | 提交问题/功能建议(免登录,写入数据库并邮件通知管理员) |
完整 API 文档见 docs/api.md。
纸鹊 Magpie内置 MCP Streamable HTTP 端点,让 Claude Code、Claude Desktop 等 AI 工具能够直接上传、管理文件。
设置全局 MCP_TOKEN 环境变量,或使用任意用户级 API Token(mg_ 前缀)即可启用 /mcp。两者二选一:
MCP_TOKEN=your-secret-tokenHTTP 客户端 — 支持 mcpServers JSON 的客户端使用以下生产配置。<YOUR_TOKEN> 替换为工作台创建的个人 API Token;本地开发改用 http://localhost:8858/mcp:
{
"mcpServers": {
"magpie": {
"type": "http",
"url": "https://magpiesend.site/mcp",
"headers": {
"Authorization": "Bearer <YOUR_TOKEN>"
}
}
}
}stdio 桌面客户端 — 先安装 CLI,再使用 command: "magpie"、args: ["mcp"],设置 env.MAGPIE_BASE=https://magpiesend.site、env.MAGPIE_TOKEN=<YOUR_TOKEN>。GUI 找不到命令时填写已安装的 magpie 绝对路径;不要把 HTTP 配置粘贴到 stdio 配置中。
Tools(18 个):
| 工具 | 用途 |
|---|---|
upload_file |
上传 HTML 或 Markdown,返回预览链接 |
list_files |
列出所有文件 |
get_file_content |
读取文件原文 |
get_file_url |
获取文件预览 URL |
rename_file |
重命名文件 |
delete_file |
删除文件 |
list_file_versions |
查看文件版本历史 |
restore_file_version |
回滚到指定版本 |
list_tags |
列出标签 |
add_tags_to_file |
为文件添加标签 |
star_file |
收藏文件 |
unstar_file |
取消收藏 |
list_categories |
列出分类 |
create_category |
创建分类 |
set_file_category |
设置文件分类 |
list_content_templates |
列出内容模板市场作品 |
get_content_template |
获取内容模板详情 |
instantiate_content_template |
按模板在当前账户创建文件 |
Resources(2 个):
| URI | 说明 |
|---|---|
magpie://files |
所有文件元数据(JSON 列表) |
magpie://file/{id} |
单文件正文(≤ 256KB) |
仓库内 skills/magpie/SKILL.md 可安装到 Codex 等支持 Skill 的客户端。配置服务地址和个人 API Token 后,按 Skill 工作流使用 CLI 优先、MCP 兜底生成和上传内容,返回预览链接。
magpie skill install --dir ~/.agents/skills/magpie
magpie skill update --dir ~/.agents/skills/magpie登录后首页底部有 AI 技能 (Skills) 区块,可查看详情、下载 zip 包。新增 Skill 只需在 skills/<name>/SKILL.md 编写 frontmatter,重启服务即可自动发现。
npx -y @modelcontextprotocol/inspector http://localhost:8858/mcp- AI 生成内容分享 — Claude Code、Cursor 等工具生成的 HTML 报告、可视化页面,一键上传获得可分享链接
- 技术文档协作 — Markdown 笔记、会议纪要、项目报告,上传后自动渲染代码高亮、数学公式、流程图
- 静态页面托管 — 单页 HTML Demo、原型、落地页,无需配置服务器
- 临时文件分享 — 任何 HTML/Markdown 文件,拖入即得链接,无需注册账号
- 版本管理 — 迭代更新的文档自动保留历史版本,随时回滚
现有的方案要么太重(需要配置服务器、域名、CI),要么太封闭(绑定特定平台)。
纸鹊 Magpie只想做一件事:让静态内容的分享回归简单。拖入文件,得到一个链接。支持可选的多用户体系,但默认开箱即用——拖入文件即得链接,匿名也能分享公开文件,无需注册。
MIT