{"_id":"sharedoc-mcp","_rev":"7-26c1f8d4fef115c27700371be60decbe","name":"sharedoc-mcp","dist-tags":{"latest":"2.2.0"},"versions":{"1.0.0":{"name":"sharedoc-mcp","version":"1.0.0","author":{"name":"AugustusW"},"license":"MIT","_id":"sharedoc-mcp@1.0.0","maintainers":[{"name":"augustusw","email":"ashs93156@gmail.com"}],"bin":{"sharedoc-mcp":"dist/index.js"},"dist":{"shasum":"8b173849b11a5b4c8ae44e608a7f23b7a11b4a35","tarball":"https://registry.npmjs.org/sharedoc-mcp/-/sharedoc-mcp-1.0.0.tgz","fileCount":12,"integrity":"sha512-X8XS5reLHQt1TSW+hsd+77eXu0wVvHFHPUpQWkwr/ciPacMK1BKstHeKCTWMskgiU5s67uotUq5ozityqvkzGg==","signatures":[{"sig":"MEQCIBf9R7HGbpS85mJ2v+L0BI/HPw060FVzhEOnPYu56kXdAiAhdgTLYKGla/EBLA9L18q7C3BrLYxE1gVV0i2dTDBORQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49680},"main":"dist/index.js","type":"module","engines":{"node":">=22.13.0"},"gitHead":"2c792ab73f5eb500e34c93a64381acc70e0e57cf","scripts":{"test":"vitest run","build":"tsc","pretest":"npm run build","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"augustusw","email":"ashs93156@gmail.com"},"_npmVersion":"11.12.1","description":"Share agent-generated Markdown as links — GitHub gists today, your own server tomorrow. An MCP server.","directories":{},"_nodeVersion":"25.9.0","dependencies":{"zod":"^4.4.0","marked":"^18.0.7","bcryptjs":"^3.0.3","sanitize-html":"^2.17.6","@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.6.0","@types/node":"^22.10.0","@types/sanitize-html":"^2.16.1"},"_npmOperationalInternal":{"tmp":"tmp/sharedoc-mcp_1.0.0_1784965771122_0.48822284752301703","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"sharedoc-mcp","version":"2.0.0","author":{"name":"AugustusW"},"license":"MIT","_id":"sharedoc-mcp@2.0.0","maintainers":[{"name":"augustusw","email":"ashs93156@gmail.com"}],"bin":{"sharedoc-mcp":"dist/index.js"},"dist":{"shasum":"cfc76860a905849df2a827c735bb667076e7f2c1","tarball":"https://registry.npmjs.org/sharedoc-mcp/-/sharedoc-mcp-2.0.0.tgz","fileCount":12,"integrity":"sha512-FAQom5h+0/5d4PCGddUShw6w52gEwbU3UtrnlY7BN8XDnQWmEnPBdqGNFhHG6mc8vcZbRM9MbWtF+PCrd+DRbw==","signatures":[{"sig":"MEUCIQDVxOfahI6/WblKrst6F3x/jFyl+8r/98oUJD3Vl3UweQIgeQqExl6Gbuwug1PpsbEs7SU/lbF6+vwBMQn6sM3dpUQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67738},"main":"dist/index.js","type":"module","engines":{"node":">=22.13.0"},"gitHead":"7ce8653f19a1a5a5339630d1a74f871cee463f6c","scripts":{"test":"vitest run","build":"tsc","pretest":"npm run build","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"augustusw","email":"ashs93156@gmail.com"},"_npmVersion":"11.12.1","description":"Share agent-generated Markdown as links — GitHub gists today, your own server tomorrow. An MCP server.","directories":{},"_nodeVersion":"25.9.0","dependencies":{"zod":"^4.4.0","marked":"^18.0.7","bcryptjs":"^3.0.3","sanitize-html":"^2.17.6","@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.6.0","@types/node":"^22.10.0","@types/sanitize-html":"^2.16.1"},"_npmOperationalInternal":{"tmp":"tmp/sharedoc-mcp_2.0.0_1784971746217_0.7061566837306894","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"sharedoc-mcp","version":"2.1.0","author":{"name":"AugustusW"},"license":"MIT","_id":"sharedoc-mcp@2.1.0","maintainers":[{"name":"augustusw","email":"ashs93156@gmail.com"}],"bin":{"sharedoc-mcp":"dist/index.js"},"dist":{"shasum":"9472d6174d3694160765c83be88bb7c670eade3e","tarball":"https://registry.npmjs.org/sharedoc-mcp/-/sharedoc-mcp-2.1.0.tgz","fileCount":12,"integrity":"sha512-+RKSjbdnlXMVHtPmgFRo3C8T9lNgl6vt0swow6YDew8tJ5IrDa5jASwRKyFBlzokB7oKiIg8CBHN8SawVsJ2Qg==","signatures":[{"sig":"MEYCIQCyXsLEUxUIyz8LDE6/nK+z0Uwn2roqbAN6sXKjafDcNwIhALWjUduMgDSAIkVdYszxubAp+28Pu70OxmizEhzEls44","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":70150},"main":"dist/index.js","type":"module","engines":{"node":">=22.13.0"},"gitHead":"4b383539d0e31a0845ed8009241df391f59714f6","scripts":{"test":"vitest run","build":"tsc","pretest":"npm run build","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"augustusw","email":"ashs93156@gmail.com"},"overrides":{"@hono/node-server":"^2.0.5"},"_npmVersion":"11.12.1","description":"Share agent-generated Markdown as links — GitHub gists today, your own server tomorrow. An MCP server.","directories":{},"_nodeVersion":"25.9.0","dependencies":{"zod":"^4.4.0","marked":"^18.0.7","bcryptjs":"^3.0.3","sanitize-html":"^2.17.6","@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.6.0","@types/node":"^22.10.0","@types/sanitize-html":"^2.16.1"},"_npmOperationalInternal":{"tmp":"tmp/sharedoc-mcp_2.1.0_1784974299158_0.4371099939840699","host":"s3://npm-registry-packages-npm-production"}},"2.1.1":{"name":"sharedoc-mcp","version":"2.1.1","author":{"name":"AugustusW"},"license":"MIT","_id":"sharedoc-mcp@2.1.1","maintainers":[{"name":"augustusw","email":"ashs93156@gmail.com"}],"bin":{"sharedoc-mcp":"dist/index.js"},"dist":{"shasum":"7980f62efa197c5dbe2308685cd28d00baed20a7","tarball":"https://registry.npmjs.org/sharedoc-mcp/-/sharedoc-mcp-2.1.1.tgz","fileCount":12,"integrity":"sha512-UyTt2cluhsOh6kbLiCgOrOu5OQDZuaQ1NceOd5tmBySrV9dxnSTdxI6EwbUW6OB4SRyNxbfT7u02EvdCpCyzjQ==","signatures":[{"sig":"MEUCICXq0+VTZcgjIWhSCQJomnD4iJKKUKdfSA0MyZVvd9lDAiEAlXxcdqTzJ/2YlgQvxItQaO/3WfoSIagsNLMlAE6HmmQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":71335},"main":"dist/index.js","type":"module","engines":{"node":">=22.13.0"},"gitHead":"4ea656f4fda60633911ff5d380c2f3939b11c12f","scripts":{"test":"vitest run","build":"tsc","pretest":"npm run build","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"augustusw","email":"ashs93156@gmail.com"},"overrides":{"@hono/node-server":"^2.0.5"},"_npmVersion":"11.12.1","description":"Share agent-generated Markdown as links — GitHub gists today, your own server tomorrow. An MCP server.","directories":{},"_nodeVersion":"25.9.0","dependencies":{"zod":"^4.4.0","marked":"^18.0.7","bcryptjs":"^3.0.3","sanitize-html":"^2.17.6","@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.6.0","@types/node":"^22.10.0","@types/sanitize-html":"^2.16.1"},"_npmOperationalInternal":{"tmp":"tmp/sharedoc-mcp_2.1.1_1784989684250_0.544884195121019","host":"s3://npm-registry-packages-npm-production"}},"2.1.3":{"name":"sharedoc-mcp","version":"2.1.3","author":{"name":"AugustusW"},"license":"MIT","_id":"sharedoc-mcp@2.1.3","maintainers":[{"name":"augustusw","email":"ashs93156@gmail.com"}],"homepage":"https://github.com/AugustusW/sharedoc-mcp#readme","bugs":{"url":"https://github.com/AugustusW/sharedoc-mcp/issues"},"bin":{"sharedoc-mcp":"dist/index.js"},"dist":{"shasum":"67ea535f8adbceb9f61fecc7303bdaf830d68966","tarball":"https://registry.npmjs.org/sharedoc-mcp/-/sharedoc-mcp-2.1.3.tgz","fileCount":11,"integrity":"sha512-mQlu5LNoew3aJ++x+KQP8w8Ajvsze8H0AQko8hZBBz78V7+AXQJy6GvW6/7usweU0VbFMqZYe/7H4F9MpghTgw==","signatures":[{"sig":"MEUCIQCKcNCy7Ui2ycmQAzoqT6/Iespyd9YwYlYBaTBOBWD8pgIgMM2tnzXid7f0KX9xHBoWYfBmwem9fEcjtKVbWKnLCFQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/sharedoc-mcp@2.1.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":70399},"main":"dist/index.js","type":"module","engines":{"node":">=22.13.0"},"gitHead":"f98c681a4317f57d51a262333e37c882e202a748","mcpName":"io.github.augustusw/sharedoc-mcp","scripts":{"test":"vitest run","build":"tsc","pretest":"npm run build","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:94b264a5-e04f-4236-a50b-737ecb0431e3"}},"overrides":{"@hono/node-server":"^2.0.5"},"repository":{"url":"git+https://github.com/AugustusW/sharedoc-mcp.git","type":"git"},"_npmVersion":"12.0.2","description":"Share agent-generated Markdown as links — GitHub gists today, your own server tomorrow. An MCP server.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"zod":"^4.4.0","marked":"^18.0.7","bcryptjs":"^3.0.3","sanitize-html":"^2.17.6","@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.6.0","@types/node":"^22.10.0","@types/sanitize-html":"^2.16.1"},"_npmOperationalInternal":{"tmp":"tmp/sharedoc-mcp_2.1.3_1785762610356_0.04646988392135398","host":"s3://npm-registry-packages-npm-production"}},"2.1.4":{"name":"sharedoc-mcp","version":"2.1.4","author":{"name":"AugustusW"},"license":"MIT","_id":"sharedoc-mcp@2.1.4","maintainers":[{"name":"augustusw","email":"ashs93156@gmail.com"}],"homepage":"https://github.com/AugustusW/sharedoc-mcp#readme","bugs":{"url":"https://github.com/AugustusW/sharedoc-mcp/issues"},"bin":{"sharedoc-mcp":"dist/index.js"},"dist":{"shasum":"ba7c3708fa6a47cea423233c6b58315f720bb393","tarball":"https://registry.npmjs.org/sharedoc-mcp/-/sharedoc-mcp-2.1.4.tgz","fileCount":11,"integrity":"sha512-wHbDI1rvohOuHzUVpW22DR4bdotIzRHXireS9uqvr1cbX88/kLpgnYRz6DmXqUkjFdCpY313dE2EUgTXNCj6PQ==","signatures":[{"sig":"MEQCIBZ8MPrXdVcatPjVKQePD38yENoQvF6PN477BZUCJgFrAiBh0x6olBtOuYOQ1vz1GR1nzDUQ8aHxv6LEo5Pn2Y/xYQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/sharedoc-mcp@2.1.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":70399},"main":"dist/index.js","type":"module","engines":{"node":">=22.13.0"},"gitHead":"39f26ec5226fe5cb8c9d4259d56d24f3188ddd41","mcpName":"io.github.AugustusW/sharedoc-mcp","scripts":{"test":"vitest run","build":"tsc","pretest":"npm run build","prepublishOnly":"npm run build && npm test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:94b264a5-e04f-4236-a50b-737ecb0431e3"}},"overrides":{"@hono/node-server":"^2.0.5"},"repository":{"url":"git+https://github.com/AugustusW/sharedoc-mcp.git","type":"git"},"_npmVersion":"12.0.2","description":"Share agent-generated Markdown as links — GitHub gists today, your own server tomorrow. An MCP server.","directories":{},"_nodeVersion":"22.23.1","dependencies":{"zod":"^4.4.0","marked":"^18.0.7","bcryptjs":"^3.0.3","sanitize-html":"^2.17.6","@modelcontextprotocol/sdk":"^1.29.0"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.0.0","typescript":"^5.6.0","@types/node":"^22.10.0","@types/sanitize-html":"^2.16.1"},"_npmOperationalInternal":{"tmp":"tmp/sharedoc-mcp_2.1.4_1785762983042_0.45014340855268986","host":"s3://npm-registry-packages-npm-production"}},"2.2.0":{"name":"sharedoc-mcp","version":"2.2.0","mcpName":"io.github.AugustusW/sharedoc-mcp","description":"Share agent-generated Markdown as links — GitHub gists today, your own server tomorrow. An MCP server.","license":"MIT","author":{"name":"AugustusW"},"repository":{"type":"git","url":"git+https://github.com/AugustusW/sharedoc-mcp.git"},"type":"module","bin":{"sharedoc-mcp":"dist/index.js"},"main":"dist/index.js","engines":{"node":">=22.13.0"},"scripts":{"build":"tsc","pretest":"npm run build","test":"vitest run","prepublishOnly":"npm run build && npm test"},"dependencies":{"@modelcontextprotocol/sdk":"^1.29.0","bcryptjs":"^3.0.3","marked":"^18.0.7","sanitize-html":"^2.17.6","zod":"^4.4.0"},"devDependencies":{"@types/node":"^22.10.0","@types/sanitize-html":"^2.16.1","typescript":"^5.6.0","vitest":"^3.0.0"},"overrides":{"@hono/node-server":"^2.0.5"},"gitHead":"729c43270fcc56461776a4867fbbdef3914cde95","_id":"sharedoc-mcp@2.2.0","bugs":{"url":"https://github.com/AugustusW/sharedoc-mcp/issues"},"homepage":"https://github.com/AugustusW/sharedoc-mcp#readme","_nodeVersion":"22.23.1","_npmVersion":"12.0.2","dist":{"integrity":"sha512-zHvCyKKD2GN4ZwPLLZsvKIiv8s7UsjB2DKc1KRaPiaeUc6R4IY1aZYfWw5D+tM133cg0WRWKX3CLYE3FcUdtQA==","shasum":"0ecf87bbb9a86aa0f0bf1e23b60ef6bd8f85c156","tarball":"https://registry.npmjs.org/sharedoc-mcp/-/sharedoc-mcp-2.2.0.tgz","fileCount":11,"unpackedSize":85796,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/sharedoc-mcp@2.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIComM6t97GPlGFPXMDHRsjRxfItmSNd2cGaW9g59+b3/AiEA7/Rd987VkhW320tgxpSSKjK4L1mLfUdHbf88ypHMAF0="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:94b264a5-e04f-4236-a50b-737ecb0431e3"}},"directories":{},"maintainers":[{"name":"augustusw","email":"ashs93156@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sharedoc-mcp_2.2.0_1786408013951_0.25524693286441846"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-25T07:49:31.084Z","modified":"2026-08-11T00:26:54.429Z","1.0.0":"2026-07-25T07:49:31.270Z","2.0.0":"2026-07-25T09:29:06.379Z","2.1.0":"2026-07-25T10:11:39.302Z","2.1.1":"2026-07-25T14:28:04.389Z","2.1.3":"2026-08-03T13:10:10.499Z","2.1.4":"2026-08-03T13:16:23.173Z","2.2.0":"2026-08-11T00:26:54.107Z"},"bugs":{"url":"https://github.com/AugustusW/sharedoc-mcp/issues"},"author":{"name":"AugustusW"},"license":"MIT","homepage":"https://github.com/AugustusW/sharedoc-mcp#readme","repository":{"type":"git","url":"git+https://github.com/AugustusW/sharedoc-mcp.git"},"description":"Share agent-generated Markdown as links — GitHub gists today, your own server tomorrow. An MCP server.","maintainers":[{"name":"augustusw","email":"ashs93156@gmail.com"}],"readme":"# sharedoc-mcp\n\n> **Agent 產出的 Markdown → 一條可以交給任何人的連結。今天用 GitHub gist，明天用你自己的 server。**\n\n[English](./README.md) | 繁體中文\n\n[![npm](https://img.shields.io/npm/v/sharedoc-mcp?color=brightgreen)](https://www.npmjs.com/package/sharedoc-mcp)\n[![npm downloads](https://img.shields.io/npm/dm/sharedoc-mcp?color=brightgreen)](https://www.npmjs.com/package/sharedoc-mcp)\n[![MCP Registry](https://img.shields.io/badge/MCP_Registry-io.github.AugustusW%2Fsharedoc--mcp-orange)](https://registry.modelcontextprotocol.io/v0/servers?search=sharedoc)\n[![Release](https://img.shields.io/github/v/release/AugustusW/sharedoc-mcp?color=brightgreen)](https://github.com/AugustusW/sharedoc-mcp/releases)\n[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![Node](https://img.shields.io/badge/node-%E2%89%A522.13-blue.svg)](https://nodejs.org/)\n[![MCP](https://img.shields.io/badge/MCP-stdio%20server-orange.svg)](https://modelcontextprotocol.io/)\n[![Claude Code](https://img.shields.io/badge/Claude%20Code-compatible-orange.svg)](https://claude.com/claude-code)\n[![Codex](https://img.shields.io/badge/Codex-compatible-black.svg)](https://developers.openai.com/codex/)\n\n[![Add to Cursor](https://img.shields.io/badge/Cursor-Add_MCP_Server-1a1a1a?logo=cursor&logoColor=white)](https://cursor.com/install-mcp?name=sharedoc&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInNoYXJlZG9jLW1jcEBeMiJdfQ%3D%3D)\n[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_MCP_Server-0098FF?logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect/mcp/install?name=sharedoc&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22sharedoc-mcp%40%5E2%22%5D%7D)\n\n一個 [MCP](https://modelcontextprotocol.io/) stdio server——可用於 [Claude Code](https://claude.com/claude-code)、Codex CLI 與任何 MCP client——給你的 agent **9 個工具：發佈、更新、搜尋、撤銷分享文件**。同一組介面、兩個可切換後端：**gist**（零設定，搭你已登入的 `gh` CLI）與 **selfhost**（SQLite 存你機器上，支援密碼與強制期限）。\n\n> 後端不支援某參數時（如 gist 收到 `password`）會回明確錯誤，不會靜默忽略。\n\n## 為什麼？\n\nAI agent 整天在產 Markdown——報告、研究摘要、會議記錄。要交給另一個人，通常得把一大面文字牆貼進聊天視窗。\n\n```text\n沒有 sharedoc-mcp                     有 sharedoc-mcp\n─────────────────                     ────────────────\n複製一大段文字貼進聊天                  「把這個做成分享文件」\n每多一個人就再貼一次                    一條連結給所有人\n內容埋在聊天記錄裡                      事後可撤銷／延長／追加\n「可以加密碼嗎？」……不行                selfhost 後端：bcrypt + 期限\n```\n\n> 這些 Markdown 摘要哪來的？常常是另一個 skill 產的——例如\n> [audio-tldr](https://github.com/AugustusW/audio-tldr-skill) 把影片和 podcast 變成 Markdown 摘要，\n> sharedoc-mcp 再把摘要變成連結。\n\n## 特色\n\n- ✓ 9 個 MCP 工具：建立／追加／取代內容／延長／改密碼／改標題／撤銷／刪除／搜尋\n- ✓ `sharedoc-mcp serve` daemon 模式——MCP client 關掉後 selfhost 連結照樣活著\n- ✓ 內容搜尋：用文件裡寫了什麼找回舊連結，不只靠標題\n- ✓ `GET /healthz`——帶身分識別的健檢端點，外部監控／自動重啟直接掛\n- ✓ 兩個後端、同一組介面——一個環境變數切換，工具 schema 完全相同\n- ✓ **Gist 後端**（預設）：secret gist 走你已登入的 `gh` CLI——不用管 token、不用架任何東西\n- ✓ **Selfhost 後端**：文件留在你機器上（內建 `node:sqlite`——零原生模組）\n- ✓ Server 端密碼驗證（bcrypt）+ 錯誤嘗試限流——5 次/分鐘，HTTP 429，計數存 SQLite、重啟不歸零（selfhost）\n- ✓ 強制期限（410）與撤銷 7 天內容清除緩衝（selfhost）；惰性過期清理（gist）\n- ✓ Markdown 經 `marked` + `sanitize-html` 渲染——分享內容中的 script、事件屬性、`javascript:` 連結都會被剝除\n- ✓ Viewer **只 bind 127.0.0.1**，所有回應帶完整安全 headers（CSP `default-src 'none'`、nosniff、禁 iframe、no-referrer、no-store）——對外曝光交給你自己控制的 tunnel（食譜見下）\n- ✓ 本地索引支援 `search_shared_docs` 與建立去重（5 分鐘內相同的無保護重試回同一 URL；補加密碼/期限的重試一律建新文件）\n- ✓ `search_shared_docs` 支援 offset 分頁（回應含 `hasMore`），selfhost 另有瀏覽統計（`viewCount`/`lastViewedAt`，僅成功渲染才計入）\n- ✓ [Docker](#docker) 一行指令跑 standalone `serve` daemon，預設跟其他地方一樣只 bind 127.0.0.1\n- ✓ 兩個 MCP client 可共用同一資料目錄：SQLite WAL + busy timeout、埠衝突優雅共存\n- ✓ 105 個離線測試；乾淨 checkout `npm test` 直接綠\n\n## 安裝\n\n需要 Node.js ≥ 22.13.0。gist 後端另需已登入的 [GitHub CLI](https://cli.github.com)（`gh auth login`）。\n\n**方式 A — Claude Code（一行）：**\n\n```bash\nclaude mcp add sharedoc --scope user -- npx -y sharedoc-mcp@^2\n```\n\n**方式 B — Codex CLI**（`~/.codex/config.toml`）：\n\n```toml\n[mcp_servers.sharedoc]\ncommand = \"npx\"\nargs = [\"-y\", \"sharedoc-mcp@^2\"]\n```\n\n**方式 C — Cursor（一鍵）：**點 [**Add to Cursor**](https://cursor.com/install-mcp?name=sharedoc&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInNoYXJlZG9jLW1jcEBeMiJdfQ%3D%3D)，或把設定併進 `~/.cursor/mcp.json`：\n\n```json\n{ \"mcpServers\": { \"sharedoc\": { \"command\": \"npx\", \"args\": [\"-y\", \"sharedoc-mcp@^2\"] } } }\n```\n\n**方式 D — VS Code（一鍵）：**點 [**Install in VS Code**](https://vscode.dev/redirect/mcp/install?name=sharedoc&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22sharedoc-mcp%40%5E2%22%5D%7D)，或在終端機執行：\n\n```bash\ncode --add-mcp '{\"name\":\"sharedoc\",\"command\":\"npx\",\"args\":[\"-y\",\"sharedoc-mcp@^2\"]}'\n```\n\n**方式 E — 其他 MCP client：**以 stdio server 執行 `npx -y sharedoc-mcp@^2`。\n\n> **為什麼用 `@^2`？**裸的 `npx -y sharedoc-mcp` 每次冷啟動解析**最新已發佈版本**——未來的 3.0 可能在你不知情下改變行為（甚至移除工具）。`@^2` 跟得上 2.x 修正、但永不跨 breaking 大版；想零漂移就釘精確版本（`@2.1.0`）。\n\n## 選後端\n\n| | 🅰 `gist`（預設） | 🅱 `selfhost` |\n|---|---|---|\n| 設定 | 無——用你已登入的 `gh` CLI | 無額外設定——資料留在你機器上 |\n| 文件放在 | GitHub（secret gist） | 你的機器（SQLite） |\n| 連結可達性 | 任何地方、立即 | localhost——對外分享請接 tunnel |\n| 密碼 | ✗（secret URL 本身就是保護） | ✓ server 端驗證（bcrypt）+ 限流 |\n| 期限 | 惰性——過期 gist 於下次使用時刪除 | 強制——過期連結回 410 |\n| 撤銷 | gist 立即刪除、不可逆 | 立即 410，內容 7 天緩衝後清除 |\n| 瀏覽統計 | ✗（GitHub gist API 不提供瀏覽次數資料） | ✓ viewCount + lastViewedAt，僅成功渲染才計入 |\n\n### Gist 快速開始\n\n跟 agent 說「把這個做成分享文件」——它呼叫 `create_shared_doc` 回傳 secret gist URL。Secret gist 不會被公開列出、網址無法猜測，但**拿到連結的任何人都能讀**——這就是此後端的完整安全模型。需要密碼請用 `selfhost`。\n\n本地索引（`~/.config/sharedoc-mcp/index.json`）記錄分享過的內容，供搜尋與過期清理。此後端的期限是*惰性*的：過期 gist 於下次任一工具執行時刪除，不是到期那一刻。\n\n### Selfhost 快速開始\n\n```bash\nclaude mcp add sharedoc --scope user --env SHAREDOC_BACKEND=selfhost -- npx -y sharedoc-mcp@^2\n```\n\n文件存在 `~/.local/share/sharedoc-mcp/` 的 SQLite；viewer 於 `http://127.0.0.1:8377` 服務。要分享到機器之外，前面接一個 tunnel 並設定 `SHAREDOC_PUBLIC_URL`：\n\n> **讓連結活得比編輯器久：**MCP 模式下 viewer 跟著 MCP client 一起關——關掉 Claude Code，selfhost 連結就暫時打不開（資料安全存在 SQLite，下次開就恢復）。要連結全天候在線，跑獨立 daemon：\n>\n> ```bash\n> npx -y sharedoc-mcp@^2 serve   # 只跑 viewer、共用同一個 DB——用 launchd/systemd/tmux 常駐（Windows：工作排程器或 NSSM）\n> ```\n>\n> MCP client 偵測到 daemon 已佔埠就直接沿用它。\n>\n> **什麼時候該設：**第一次把連結交給別人的那一刻——跟 tunnel 一起設（兩者都該常駐，如 launchd/systemd）。在那之前 MCP 模式的 viewer 就夠用；gist 後端使用者則永遠不需要。\n\n| 食譜 | 適合 | 設定 |\n|---|---|---|\n| **Tailscale 私有連線**（推薦） | 收件人是自己的裝置／可邀進 tailnet 的人 | `tailscale serve --bg 8377` → `https://<機器>.<tailnet>.ts.net`，**只有 tailnet 內可達**——完全不暴露到公網 |\n| **Tailscale Funnel** | 要分享給任何人、沒網域 | `tailscale funnel 8377` → 同一條固定網址，但公開 |\n| **Cloudflare named tunnel** | 有自己的網域 | 網域掛 Cloudflare，`cloudflared tunnel create` + 主機名 route 到 `http://127.0.0.1:8377` |\n| **cloudflared quick tunnel** | 臨時分享 | `cloudflared tunnel --url http://127.0.0.1:8377` → 隨機網址，每次重啟會變 |\n\n#### 有自己的網域？Cloudflare named tunnel 逐步版\n\n品牌化的固定分享網址，例如 `https://docs.example.com/docs/<uuid>`——TLS 由 Cloudflare 處理、機器在 NAT 後面也通：\n\n```bash\n# 一次性設定（網域已掛進 Cloudflare——免費方案就夠）\ncloudflared tunnel login\ncloudflared tunnel create sharedoc\ncloudflared tunnel route dns sharedoc docs.example.com\n```\n\n`~/.cloudflared/config.yml`：\n\n```yaml\ntunnel: sharedoc\ncredentials-file: ~/.cloudflared/<tunnel-id>.json\ningress:\n  - hostname: docs.example.com\n    service: http://127.0.0.1:8377\n  - service: http_status:404\n```\n\n跑 `cloudflared tunnel run sharedoc`（要常駐就裝成 service），MCP 註冊時帶上公開網址：\n\n```bash\nclaude mcp add sharedoc --scope user \\\n  --env SHAREDOC_BACKEND=selfhost \\\n  --env SHAREDOC_PUBLIC_URL=https://docs.example.com \\\n  -- npx -y sharedoc-mcp\n```\n\n順帶解鎖：Cloudflare 的 DDoS 防護免費附送；可疊 WAF 規則，或在分享路徑以外套 [Cloudflare Access](https://www.cloudflare.com/zero-trust/products/access/)（SSO）——變成「內部走 SSO、對外分享靠密碼」的雙層結構。\n\n**另一種情境——不想依賴家裡機器常開：**把 sharedoc-mcp 跑在 VPS 上（agent 也在那執行），nginx/caddy 反代 `127.0.0.1:8377` 配網域與自動 TLS 即可，不需要 tunnel。\n\n#### Docker\n\n跟上面一樣是跑 standalone 的 `serve` daemon，只是包成容器：\n\n```bash\ndocker build -t sharedoc-mcp .\ndocker run -d --name sharedoc \\\n  -p 8377:8377 \\\n  -e SHAREDOC_BIND_HOST=0.0.0.0 \\\n  -v sharedoc-data:/data \\\n  sharedoc-mcp\n```\n\n- `-v sharedoc-data:/data` 把 `docs.db` 存進 named volume——容器重建文件不會不見。\n- **`SHAREDOC_BIND_HOST=0.0.0.0` 是連上容器的必要條件。** viewer 預設只 bind `127.0.0.1`——跟本文件其他部署方式一樣——但在容器內這代表透過 `docker run -p` 完全連不到，因為 `-p` 轉發到容器的網路介面，不是它的 loopback。沒設這個環境變數的話，`docker logs` 會顯示 viewer 正常在聽，但對外映射的 host port 會一律拒絕連線。\n- 設成 `0.0.0.0` 代表**任何連得到容器對外埠的人都連得到 viewer，光靠網路位置不做任何驗證**——跟在容器裡跑任何沒驗證機制的 app、卻沒在前面擋一層是一樣的風險。請像本文件其他 selfhost 情境一樣在前面加一層(host 上的 reverse proxy、Tailscale sidecar、Cloudflare tunnel)，不要直接把 `-p 8377:8377` 對外網公開。單篇文件的密碼保護(這個後端內建的功能)不能替代這一層。\n- 如果收件人實際會用的網址跟 `http://<host>:8377` 不同(reverse proxy、網域、tunnel)，記得也設 `SHAREDOC_PUBLIC_URL`——容器沒辦法自己推斷。\n- MCP stdio server 本身不適合跑在 Docker 裡——它需要一個綁定 MCP client stdin/stdout 的本機 process。MCP client 一樣照常指向 host 上的 `npx -y sharedoc-mcp`；只有 standalone viewer daemon 適合放進容器。\n\n環境變數：\n\n| 變數 | 預設 | 意義 |\n|---|---|---|\n| `SHAREDOC_BACKEND` | `gist` | `gist` 或 `selfhost` |\n| `SHAREDOC_PORT` | `8377` | viewer 埠（selfhost） |\n| `SHAREDOC_BIND_HOST` | `127.0.0.1` | viewer bind 位址（selfhost）——要從 Docker 容器外連進來設 `0.0.0.0`；改之前先看上面 [Docker](#docker) 段落的曝險取捨 |\n| `SHAREDOC_PUBLIC_URL` | `http://127.0.0.1:<port>` | 分享連結的網址前綴——設成你的 tunnel 主機名 |\n| `SHAREDOC_DATA_DIR` | `~/.local/share/sharedoc-mcp` | SQLite 位置（selfhost） |\n| `SHAREDOC_INDEX_PATH` | `~/.config/sharedoc-mcp/index.json` | 本地索引（gist） |\n| `MCP_CALLER` | — | 建立文件的預設作者歸因 |\n\n## 9 個工具\n\n| 工具 | 功能 |\n|---|---|\n| `create_shared_doc` | 標題 + Markdown（+ 選填密碼 / `expires_in_hours` / 作者）→ 分享 URL |\n| `append_to_shared_doc` | 尾端追加 Markdown（非冪等——重試會加兩次） |\n| `update_shared_doc_content` | 取代整份內容（標題/密碼/期限不變）——冪等，可安全重試 |\n| `extend_shared_doc` | 延長期限 N 小時 |\n| `reset_shared_doc_password` | 設定／更換／移除（null）密碼（僅 selfhost） |\n| `update_shared_doc_title` | 改標題 |\n| `revoke_shared_doc` | 撤銷連結、保留紀錄（語意見後端對照表） |\n| `delete_shared_doc` | 連結失效＋紀錄整個消失——不可逆；需帶 `confirm: true`（agent 應先取得使用者明確同意） |\n| `search_shared_docs` | 不帶參數＝列出最新連結；標題子字串、內文搜尋（selfhost 全文；gist 僅開頭摘要）、狀態篩選、offset 分頁（回應含 hasMore）、selfhost 瀏覽統計 |\n\n## 隱私\n\n各後端的資料流：\n\n- **Gist 後端**：文件內容以 secret gist 上傳到你 GitHub 帳號下——適用 GitHub 的條款與保存政策。本地索引留在 `~/.config/sharedoc-mcp/`——存標題、URL、時間戳與每份文件的前 200 字元（供本機內容搜尋）；不存完整內容。除了經你自己的 `gh` CLI 送 GitHub 之外，不送任何地方。\n- **Selfhost 後端**：內容不離開你的機器，除非你接了 tunnel——那之後就是「拿到連結的人 + 中繼流量的 tunnel 供應商」可及。密碼只以 bcrypt 雜湊儲存。\n- sharedoc-mcp 本身無遙測、不呼叫任何自己的第三方服務。\n\n## 安全語意（誠實版）\n\n- **Gist 連結即權限**：拿到 URL 就能讀。撤銷＝立即刪除 gist、不可逆。\n- Selfhost 密碼於 server 端驗證通過才吐內容；只有「錯誤」嘗試會計入限流（每來源+文件 5 次/分鐘；解鎖成功即清空計數），計數存 SQLite——重啟 server 不會歸零。**經 tunnel 時所有外部訪客共用同一來源位址**，實際效果是每份文件 5 次/分鐘——比逐訪客更嚴格；一個人打錯幾次會讓該文件對其他人短暫鎖定。\n- 刻意**沒有檔案分享工具**：可傳任意路徑的「分享這個檔案」工具是 prompt injection 的洩密面（`.env`、金鑰）——被劫持的 agent 可以直接把機敏檔發佈出去。與其做 allowlist 不如整個拿掉。\n- Viewer 永遠只 bind 127.0.0.1。它是否、如何觸及網際網路，完全由你的 tunnel 設定決定。\n\n## 開發\n\n```bash\ngit clone https://github.com/AugustusW/sharedoc-mcp.git\ncd sharedoc-mcp\nnpm install\nnpm test        # 先 build 再跑 105 個離線測試——gh CLI 以 mock 替身，HTTP 測試只打 127.0.0.1\n```\n\n版本規則：每次釋出 bump `package.json` 的 `version`、加一筆 [CHANGELOG](./CHANGELOG.md)、打 git tag 發 [GitHub Release](https://github.com/AugustusW/sharedoc-mcp/releases) + [npm](https://www.npmjs.com/package/sharedoc-mcp)。\n**想收到更新通知**：Watch 本 repo（Custom → Releases）。`npx -y` 每次冷啟動會抓最新已發佈版本；你的索引與文件 DB 都在套件外——更新永遠不會動到它們。\n\n## 狀態\n\nv2.1.0（[CHANGELOG](./CHANGELOG.md)）——核心邏輯有 105 個離線單元/整合測試（`gh` CLI 以 mock 模擬；HTTP 測試只打 127.0.0.1；不需網路）。完整流程於 2026-07-25 人工驗證（經 built server 走 stdio JSON-RPC 實建 secret gist 的建立/索引/刪除，以及 selfhost 密碼流程端到端——表單 → 錯密碼 401 → 對密碼 200 → 限流 429 → 撤銷 410——並以 `lsof` 確認僅 bind 127.0.0.1），環境：\n\n- macOS（Apple Silicon）、Node v25——gist + selfhost 兩後端\n\nTunnel 食譜依各工具的標準行為撰寫；Windows／Linux 與真實 tunnel 端到端**尚未驗證**——歡迎回報。\n\n## 授權\n\nMIT © AugustusW\n","readmeFilename":"README.zh-TW.md"}