The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Doc Manager listing page.
A zero-knowledge document vault backed by Azure Blob Storage, with a built-in MCP server so you can add, read and search your docs straight from a Claude conversation.
Talk to your docs through Claude — create from chat, see it in the vault instantly.
containerd + Kaniko in a homelab.The same Rust process exposes a Streamable-HTTP [Model Context Protocol]
(https://modelcontextprotocol.io) server at /mcp, gated by an OAuth 2.1
flow against an upstream identity provider (currently GitHub —
Auth0 reserved for a future round, the code is provider-shaped).
Encrypted documents stay private (their content is never returned to
Claude); plaintext documents become first-class citizens in the chat.
| Tool | What it does | Available in MCP_READ_ONLY |
|---|---|---|
list_documents | List every doc with id, title, encrypted flag, attachment info, size | yes |
get_document | Fetch one plaintext document by id; refuses encrypted ones | yes |
search_documents | Case-insensitive substring search over titles (always) and plaintext content | yes |
get_attachment | Fetch the file attached to a doc (filename, bytes, base64, UTF-8 if applicable) | yes |
create_document | Create a new plaintext document; returns the new id | no |
update_document | Replace content (and optionally title) of a plaintext document | no |
add_attachment | Attach a file (text or base64-encoded binary) to a doc; replaces any existing | no |
delete_document | Delete a document and all its blobs (main, title, attachment); irreversible | no |
delete_attachment | Delete only the attachment of a document, leaving the document itself intact | no |
Encrypted documents are surfaced to Claude with encrypted: true so it can
discover them by title, but their contents and writes are refused server-side.
That keeps the zero-knowledge guarantee intact: encrypted = "private to me",
plaintext = "shareable with Claude".
Claude.ai's custom-connector advanced settings accept an OAuth Client ID + Client Secret (only those two fields), so Claude.ai runs the full OAuth 2.1 + PKCE flow itself and our server only needs to (a) advertise the IdP via well-known metadata and (b) validate the resulting bearer.
https://claude.ai/api/mcp/auth_callbackOAUTH_ALLOWED_USERS is required — an empty allowlist refuses to
start, so a misconfiguration cannot silently let any GitHub user in.https://doc-manager.giuliohome.com/mcp, then
Advanced settings → paste the GitHub OAuth App's Client ID and
Client Secret. The first request triggers the OAuth dance: Claude.ai
sees the 401 + WWW-Authenticate from /mcp, fetches our
well-known metadata, walks you through github.com/login/oauth/authorize,
and forwards the resulting bearer on every subsequent call. The server
validates each request by calling https://api.github.com/user (5-min
cache, SHA-256-hashed token key).If OAUTH_PROVIDER is unset the endpoint replies 503 Service Unavailable,
so the MCP surface is fully opt-in.
containerd + Kaniko (homelab)| Env var | Required | Purpose |
|---|---|---|
AZURE_STORAGE_ACCOUNT | yes | Azure Storage account name (container documents is auto-created) |
AZURE_STORAGE_ACCESS_KEY | yes | Storage access key |
RUST_ROCKET_EXACT_ORIGIN | yes | CORS origin for the React frontend |
OAUTH_PROVIDER | no (enables MCP) | github (Auth0 reserved for future) |
OAUTH_PUBLIC_BASE_URL | with OAUTH_PROVIDER | Public base URL of this server, e.g. https://doc-manager.giuliohome.com |
OAUTH_ALLOWED_USERS | with OAUTH_PROVIDER | Comma-separated GitHub logins; must list at least one user — empty refuses to start |
MCP_READ_ONLY | no (default false) | When true/1/yes, hides create/update MCP tools |
MCP_PUBLIC_INTROSPECT | no (auto) | Opens /mcp for unauthenticated tools/list only (calls are 403'd) so registries like Glama can probe. Auto-on when both AZURE_STORAGE_ACCOUNT and OAUTH_PROVIDER are unset; set 0 to force-disable. |
MCP_STDIO | no (default false) | When true/1/yes (or pass --stdio), runs as a stdio MCP server (newline-delimited JSON-RPC on stdin/stdout) instead of starting the HTTP listener. Used by registries that wrap servers with mcp-proxy. |
See the e2e repo.