mcp-docstore
Multi-tenant Model Context Protocol (MCP) server that gives AI agents a persistent, searchable, version-controlled document store — save in one session, retrieve and edit in another.
Install / Use
claude mcp add Fishwaldo -- npx -y github:Fishwaldo/mcp-docstoreIf the server publishes to npm under a different name, use that package instead — check the repo README.
MCP Server
Model Context Protocol server
Quality Score
Category
Content & MediaSupported Platforms
Our assessment of mcp-docstore
mcp-docstore scores 78/100 on our quality scale, 1052nd of 1,179 Content & Media skills we index.
Its MCP Server is 21 KB long, well organised into 19 sections with 9 code examples: a thorough specification that gives an agent plenty to work with.
It has 3 GitHub stars, so there is little community track record yet; judge it on its content.
Maintenance, license and trust
- The repository was last updated about 4 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
- Our last check on 2026-09-23 found the source still online.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 90/100, with 1 caution from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
Safety scan
No issues foundOur scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful.
AI review by kimi-k2.7-code on 2026-10-06. Automated pattern scan on 2026-10-06. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.
mcp-docstore compared with similar skills
All 4 of these similar skills score higher than mcp-docstore; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| mcp-docstore (this skill)by Fishwaldo | 78 | 3 | 4mo ago | MCP Server |
| Agent-Reachby Panniantong | 100 | 110.0k | today | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 79.1k | today | CLAUDE.md |
| CowAgentby zhayujie | 100 | 47.8k | 1d ago | CLAUDE.md |
| Scraplingby D4Vinci | 100 | 99.4k | 2d ago | MCP Server |
Frequently asked questions
- How do I install mcp-docstore?
- Run
claude mcp add Fishwaldo -- npx -y github:Fishwaldo/mcp-docstore. The install tabs above show the steps for each supported agent. - Which AI agents does mcp-docstore work with?
- It is written for Claude Code and Claude Desktop, as a MCP Server file. Other agents that read the same format can often use it too.
- Is mcp-docstore safe to use?
- Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful. It is MIT-licensed and scores 90/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is mcp-docstore still maintained?
- The repository was last updated about 4 months ago. That is recent enough to be usable, but agent tooling moves fast, so check the instructions against your agent's current version.
Skill content
View source on GitHubMCP DocStore
A multi-tenant Model Context Protocol server for persistent documents — so AI agents can save, find, and edit work that survives across sessions and tools.
</div>What it is
MCP DocStore gives AI agents a shared, durable place to keep documents. An agent in one session (say, a Claude.ai artifact) writes a document; an agent in another (say, Claude Code) retrieves and edits it later. Documents live in projects, each document carries a short overview for quick scanning plus a longer markdown body, and every edit is versioned so nothing is lost.
It is its own OAuth 2.1 authorization server: it federates login to your existing identity provider (Okta, or any OIDC IdP), mints its own audience-bound access tokens, and resolves each caller to a tenant by email domain or address. Data is isolated per tenant, with org-wide, private, and shared projects. Connecting an MCP client is paste-a-URL — no per-client OAuth app to register on your IdP.
Features
- Projects & documents —
org(whole-tenant) orprivateprojects; documents with overview + markdown body + tags. - Sharing — share a project with individual users (by email) or with groups drawn from
the token's
groupsclaim; read or write. - Versioned edits — full-replace, section (markdown heading) edits, append, and section
delete. Mutating edits use optimistic concurrency (
base_version); every edit snapshots the prior version. Inspect history withlist_snapshots/get_snapshot/diff_versionsand roll back withrestore_snapshot. - Full-text search — keyword search (powered by Bleve) scoped to exactly what the caller may see; no query syntax to learn.
- Archiving — archive/unarchive projects to hide them from lists and search while keeping them reachable by id.
- Safe destructive ops —
delete_project,delete_document, andrestore_snapshotare confirmation-guarded via MCP elicitation (with aconfirm: truefallback for clients that can't prompt). - Multi-tenant & config-seeded — tenants and their admins are declared in config; a user belongs to exactly one tenant.
Tool surface
| Group | Tools |
|---|---|
| Projects | list_projects, create_project, get_project, update_project, archive_project, unarchive_project, delete_project |
| Sharing | share_project, unshare_project, list_project_shares |
| Documents | list_documents, create_document, get_document, get_section, edit_document, append_document, delete_section, delete_document |
| History | list_snapshots, get_snapshot, diff_versions, restore_snapshot |
| Search | search_documents |
Each tool is annotated with read-only / destructive / closed-world hints so clients can reason about safety.
Configuration
Copy config.example.yaml — it is the fully-commented reference — and
edit it. Every key with a listed default may be omitted. The complete surface:
listen_addr: ":8080" # HTTP listen address (default ":8080")
public_url: "https://docs.example.com" # public base URL; the OAuth issuer + resource identifier.
# Used in discovery/protected-resource metadata, WWW-Authenticate, and icon URLs
snapshot_retention: 10 # versions kept per document (default 10)
bleve_index_path: "./data/index.bleve" # required; full-text index location
session_timeout: 2m # reap idle Streamable HTTP MCP sessions (default 2m; must be positive)
max_request_bytes: 4194304 # cap MCP request body bytes (default 4 MiB)
logging:
level: info # debug | info | warn | error (default info)
format: json # json | text (default json)
client_ip_header: "" # e.g. "X-Forwarded-For" behind a proxy; empty = connection RemoteAddr
database:
driver: sqlite # sqlite | mysql | postgres
# sqlite REQUIRES _pragma=foreign_keys(1) in the DSN — the server fails fast at startup without it
dsn: "file:./data/docstore.db?_pragma=foreign_keys(1)"
oidc: # the UPSTREAM identity provider — login-federation leg ONLY.
# This server is its own OAuth issuer (see oauth: below).
issuer: "https://idp.example.com"
client_id: "docstore-upstream-client-id" # the ONE confidential client you register on your IdP
client_secret: "docs…[redacted]" # redirect URI: {public_url}/oauth/callback
scopes: ["openid", "profile", "email", "groups", "offline_access"] # default; offline_access is REQUIRED for refresh
discovery_timeout: 15s # bounds OIDC discovery + JWKS refresh calls (default 15s)
# allow_private_ip: false # true ONLY for an internal IdP resolving to an RFC-1918/loopback address
# (relaxes SSRF protection on IdP calls; logged as a startup warning)
# root_ca: "/etc/mcp-docstore/idp-ca.pem" # extra CA PEM to trust for an internal IdP's TLS certificate
oauth: # the embedded OAuth 2.1 authorization server (always on)
access_token_ttl: 15m # issued access-token lifetime (default 15m)
refresh_token_ttl: 168h # issued refresh-token lifetime (default 168h / 7 days)
registration: "open" # "open" (default; any client may dynamically register) | "allowlist"
# registration_allowlist: # required (>=1 https:// entry) when registration is "allowlist"
# - "https://client.example.com/callback"
cookie_secure: true # HTTPS-only consent cookie (default true); set false ONLY for local http dev
sweep_interval: 1h # reap expired oauth rows: auth codes, refresh tokens, revocations (default 1h)
trust_proxy: false # trust proxy X-Forwarded-* headers for client IP/scheme (default false)
trusted_proxy_count: 1 # proxy hops to peel off when trust_proxy is true (default 1)
web: # optional web UI + REST API; omit or set enabled: false to disable
enabled: true # serves the SPA at "/", bearer-authenticated /api/*, and public /openapi.json + /docs
tenants:
- key: acme
name: "Acme Corp"
match:
domains: ["acme.com", "acme.io"] # a caller's email domain
emails: ["contractor@gmail.com"] # or exact email
admins: ["alice@acme.com"] # tenant admins (declarative; reconciled at login)
Tenant admins have full read/write over every project in their own tenant. The admins list
is the single source of truth and is reconciled on each login. See the Authentication
and Web UI and REST API sections below for what the oidc:, oauth:, and
web: blocks actually do.
Running
# build
go build -o mcp-docstore .
# serve (Streamable HTTP MCP endpoint at "/mcp", metadata at /.well-known/oauth-protected-resource)
./mcp-docstore --config config.yaml
# rebuild the search index from the database (after a schema change or index loss)
./mcp-docstore --config config.yaml rebuild-index
Breaking change: the MCP endpoint moved from
/to/mcpin v0.5.0. Existing MCP clients must repoint their server URL to<public_url>/mcp.
On first boot with an empty index, the server builds it from the database automatically.
Docker
Images are published to GHCR for linux/amd64 and linux/arm64: ghcr.io/fishwaldo/mcp-docstore (tags :X.Y.Z, :X.Y, :latest).
Persistent state — the SQLite database and the Bleve index — lives in the container at /data (a declared volume, owned by the non-root runtime user 65532). Point your config there and mount a volume so data survives restarts:
# config.yaml (paths under the mounted /data volume)
bleve_index_path: "/data/index.bleve"
database:
driver: sqlite
dsn: "file:/data/docstore.db?_pragma=foreign_keys(1)"
docker run -p 8080:8080 \
-v mcp-docstore-data:/data \
-v "$PWD/config.yaml:/etc/mcp-docstore/config.yaml:ro" \
ghcr.io/fishwaldo/mcp-docstore --config /etc/mcp-docstore/config.yaml
# rebuild the index in the same container/volume
docker run --rm \
-v mcp-docstore-data:/data \
-v "$PWD/config.yaml:/etc/mcp-docstore/config.yaml:ro" \
ghcr.io/fishwaldo/mcp-docstore --config /etc/mcp-docstore/config.yaml rebuild-index
Notes:
- The container runs as non-root (uid 65532). A Docker named volume (as above) is initialized with the right ownership automatically. If you use a bind mount instead (
-v $PWD/data:/data),chown 65532:65532the host directory first, or the server can't write to it. - With an external MySQL/Postgres backend,
/dataholds only the Bleve index (rebuildable viarebuild-index), not your documents.
Build it yourself:
docker build -t mcp-docstore .
Authentication
MCP DocStore is its own OAuth 2.1 authorization server (built on
mcp-oauth): it federates login to your upstream IdP
(the oidc: block) and mints its own short-lived, audience-bound access tokens, verified by one
shared pipeline for both /mcp and (when the web UI is enabled) /api. It
serves the full OAuth surface itself — /oauth/{authorize,callback,token,revoke,register} plus
/.well-known/{oauth-authorization-server,openid-configuration,oauth-protected-resource,jwks.json}
— so clients discover everything from the MCP URL alone; there is no separate Okta app per
client.
For users — connect an MCP client
No client registration, no client ID/secret to obtain. Just point your client at the server:
- claude.ai (custom connector): paste
{public_url}/mcpas the connector URL. Dynamic client registration (RFC 7591) and PKCE handle the rest. - Claude Code:
Noclaude mcp add --transport http docstore https://docs.example.com/mcp--client-id,--client-secret, or--callback-portflags — open dynamic registration plus RFC 8252 loopback redirects handle it.
The first time a given client connects, DocStore shows a one-time consent screen ("<client name> wants to sign you in through this server's identity provider") before forwarding to your
upstream IdP login. Approval is remembered (cookie-based, ~90 days); the first-party web UI is
exempt and never shows it.
For operators — deploy
You need exactly one confidential OIDC client registered on your upstream IdP (e.g. one Okta app), with a single redirect URI:
{public_url}/oauth/callback
That one upstream client is shared by every downstream MCP client and the web UI — none of them talk to the IdP directly. No API Access Management / custom-authorization-server product is required on the IdP side; DocStore issues its own tokens.
Grant the upstream app the offline_access scope (it is in the default oidc.scopes). The
IdP only returns a refresh token when this scope is granted, and DocStore needs that upstream
refresh token to renew its cached provider token as sessions rotate. Without it, refreshes fail
once the cached provider token lapses and clients are forced back through full login.
oidc:
issuer: "https://idp.example.com"
client_id: "docstore-upstream-client-id"
client_secret: "docs…[redacted]"
# allow_private_ip: true # only for an internal IdP resolving to an RFC-1918/loopback address
# root_ca: "/e
Truncated for display — read the full file on GitHub.
Related Skills
Agent-Reach
110.0kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
headroom
79.1kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
CowAgent
47.8kOpen-source personal AI assistant & Agent Harness. Plans tasks, runs tools and skills, self-evolves with memory and knowledge. Multi-agent, multi-model, multi-channel. Lightweight, extensible, one-line install.
Scrapling
99.4k🕷️ The BEST Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ and follow here for daily tips and tricks: https://x.com/Scrapling_dev
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
