SkillAgentSearch skills...

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-docstore

If the server publishes to npm under a different name, use that package instead — check the repo README.

About this skill
🔌

MCP Server

Model Context Protocol server

Quality Score

78/100

Supported Platforms

Claude Code
Claude Desktop

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.

Substance
30/30
Structure
20/20
Description
15/15
Adoption
3/20
Freshness
11/15

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 found

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.

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.

SkillScoreStarsUpdatedFormat
mcp-docstore (this skill)by Fishwaldo7834mo agoMCP Server
Agent-Reachby Panniantong100110.0ktodayCLAUDE.md
headroomby headroomlabs-ai10079.1ktodayCLAUDE.md
CowAgentby zhayujie10047.8k1d agoCLAUDE.md
Scraplingby D4Vinci10099.4k2d agoMCP 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.
<div align="center"> <img src="assets/icon-512.png" alt="MCP DocStore" width="160" height="160">

MCP 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.

License: MIT

</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) or private projects; documents with overview + markdown body + tags.
  • Sharing — share a project with individual users (by email) or with groups drawn from the token's groups claim; 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 with list_snapshots / get_snapshot / diff_versions and roll back with restore_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, and restore_snapshot are confirmation-guarded via MCP elicitation (with a confirm: true fallback 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 /mcp in 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:65532 the host directory first, or the server can't write to it.
  • With an external MySQL/Postgres backend, /data holds only the Bleve index (rebuildable via rebuild-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}/mcp as the connector URL. Dynamic client registration (RFC 7591) and PKCE handle the rest.
  • Claude Code:
    claude mcp add --transport http docstore https://docs.example.com/mcp
    
    No --client-id, --client-secret, or --callback-port flags — 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

View on GitHub
GitHub Stars3
CategoryContent
Updated4mo ago
Forks0

Languages

Go

Trust signals

90/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

1 low1 info
mcp-docstore — MCP Server: Install & Safety Check | SkillAgent