SkillAgentSearch skills...

bookstack-mcp

MCP server for BookStack — 56 tools covering the full API + semantic vector search. Rust/tokio/axum, dual transport (SSE + Streamable HTTP), OAuth 2.1, pluggable DB (SQLite/PostgreSQL+pgvector).

Install / Use

claude mcp add bees-roadhouse -- npx -y github:bees-roadhouse/bookstack-mcp

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

75/100

Supported Platforms

Claude Code
Claude Desktop

BookStack MCP Server

SafeSkill 50/100 An MCP (Model Context Protocol) server that gives Claude full access to a BookStack instance. Built in Rust with tokio/axum as a Cargo workspace with pluggable database backends and optional semantic vector search.

Features

  • Full CRUD on all core BookStack resources (shelves, books, chapters, pages, attachments)
  • Full-text search with BookStack query operators
  • Semantic vector search — natural language search across all content via embeddings (optional). Two modes on semantic_search: standard (default, vector + keyword + Markov-blanket blend) and precision (4-stage cascade — semantic → keyword → Markov-blanket → cross-encoder). An optional rerank: bool flag layers a cross-encoder pass on top of the standard top-N (v0.13.0; replaces the pre-v0.13.0 mode: "rerank"). Per-page access control enforced via BookStack's API on every result.
  • Settings UI (/settings) — browser-based admin configuration page (token-gated via the same /authorize flow). Surfaces only the global server fields the index worker needs (hive_shelf_id, user_journals_shelf_id).
  • Pluggable database — SQLite for simple deployments, PostgreSQL + pgvector for production
  • Separate embedder — background embedding service with pluggable backends (local ONNX, Ollama, OpenAI, Voyage)
  • Cross-encoder reranker (optional) — embedder exposes POST /rerank when BSMCP_RERANK_PROVIDER is configured. Three providers: local (in-process ONNX cross-encoder via fastembed, default BAAI/bge-reranker-v2-m3), voyage (Voyage's /v1/rerank), openai (any OpenAI-shape rerank endpoint — covers Voyage/Jina/Cohere-via-shim/self-hosted). Off by default; consumed by semantic_search's rerank: true flag (refinement on the standard mode) + mode: "precision" (cascade), and by search_content's rerank: true flag (v0.13.0).
  • Server-side markdown to HTML conversion — send markdown, server converts before sending to BookStack
  • Staging upload flow — upload local images and attachments through a two-step staging endpoint without exposing local paths to the container (see below)
  • OAuth 2.1 support — use as a Claude.ai or Claude Desktop custom connector without config files
  • Encrypted token storage — OAuth tokens encrypted at rest with AES-256-GCM
  • Dual transport — SSE (MCP 2024-11-05) and Streamable HTTP (MCP 2025-03-26)
  • Dynamic structure discovery — AI automatically learns your BookStack hierarchy on connect
  • Auto-migration — seamlessly migrate from SQLite to PostgreSQL on startup
  • Multi-user support via per-session BookStack API tokens
  • Multi-arch Docker images (amd64 + arm64)

Architecture

crates/
  bsmcp-common/       Shared types, traits, config, chunking, vector utils
  bsmcp-db-sqlite/    SQLite backend (rusqlite, bundled)
  bsmcp-db-postgres/  PostgreSQL + pgvector backend (sqlx)
  bsmcp-server/       MCP server binary (axum, no ONNX dependency)
  bsmcp-embedder/     Embedder + reconciliation worker (single binary, role-selected via --role flag)
                      — local ONNX / Ollama / OpenAI / Voyage embedding, job queue worker, HTTP /embed + optional /rerank
                      — reconciliation worker: initial walk + webhook/cron delta walk on the index_jobs queue

docker/
  Dockerfile.server       Lightweight server image (~35MB)
  Dockerfile.embedder     Embedder + worker image with ONNX Runtime (~45MB)
  docker-compose.yml      PostgreSQL deployment (production)
  docker-compose.sqlite.yml  SQLite deployment (simple)

The MCP server handles all client-facing protocol, OAuth, and search. The embedder runs separately, polling a database-backed job queue to embed pages and serving a /embed HTTP endpoint for query-time embedding (and /rerank when a reranker provider is configured). The embedder supports four embedding backends: local ONNX models (fastembed), Ollama, OpenAI-compatible APIs, and Voyage. The reconciliation worker (same binary, run with --role=worker) owns the index_jobs queue — runs the initial full walk on cold start, then consumes webhook + cron jobs and the periodic delta walk. Run as two compose services (separate embedder + worker) or as one with --role=both.

Available Tools (59 BookStack + 3 semantic = 62)

| Category | Tools | |----------|-------| | Search | search_content | | Semantic | semantic_search, reembed, embedding_status | | Shelves | list_shelves, get_shelf, create_shelf, update_shelf, delete_shelf | | Books | list_books, get_book, create_book, update_book, delete_book | | Chapters | list_chapters, get_chapter, create_chapter, update_chapter, delete_chapter | | Pages | list_pages, get_page, create_page, update_page, delete_page, edit_page, append_to_page, replace_section, insert_after | | Move | move_page, move_chapter, move_book_to_shelf | | Attachments | list_attachments, get_attachment, create_attachment, update_attachment, delete_attachment, upload_attachment | | Staging | prepare_upload (used with upload_image / upload_attachment for local file uploads) | | Exports | export_page, export_chapter, export_book (markdown, plaintext, html) | | Comments | list_comments, get_comment, create_comment, update_comment, delete_comment | | Recycle Bin | list_recycle_bin, restore_recycle_bin_item, destroy_recycle_bin_item | | Users | list_users, get_user | | Audit Log | list_audit_log | | System | get_system_info | | Images | list_images, get_image, upload_image, update_image, delete_image | | Permissions | get_content_permissions, update_content_permissions | | Roles | list_roles, get_role |

Semantic tools (semantic_search, reembed, embedding_status) only appear when BSMCP_SEMANTIC_SEARCH=true and an embedder is running. Without semantic search: 59 BookStack tools.

The server is a thin BookStack CRUD facade plus semantic-search enrichment, OAuth, audit, and the reconciliation worker. Personal-memory primitives (journals, identities, reminders) and the v0.8.0/v0.9.0 briefing surface were removed in v0.10.0; v0.11.0 added the optional cross-encoder reranker on the embedder side; v0.13.0 (current) refactors that reranker from a third semantic_search mode into a flag on both semantic_search and search_content (breaking — see the v0.12 → v0.13 migration below). See the migration notes below.

Setup

Prerequisites

  • A BookStack instance with API access enabled
  • A BookStack API token (created in your BookStack user profile under "API Tokens")
  • Docker and Docker Compose (for container deployment)

Quick Start (PostgreSQL — recommended)

cp .env.example .env
# Edit .env with your BookStack URL, encryption key, and database password

docker compose -f docker/docker-compose.yml up -d

This starts four containers:

  • bsmcp-postgres — PostgreSQL 17 with pgvector extension
  • bsmcp-server — MCP server (port 8080)
  • bsmcp-embedder — Background embedding service (--role=embedder, default); also serves /rerank when a reranker is configured
  • bsmcp-worker — Reconciliation worker (same image as the embedder, started with --role=worker): initial walk on cold start, webhook + cron job consumption, periodic delta walk

Quick Start (SQLite — simple)

cp .env.example .env
# Edit .env with your BookStack URL and encryption key

docker compose -f docker/docker-compose.sqlite.yml up -d

This starts three containers (server + embedder + worker) sharing a SQLite database file.

Run from source

The project distributes as multi-arch (linux/amd64 + linux/arm64) container images on GHCR — ghcr.io/bees-roadhouse/bsmcp-server and ghcr.io/bees-roadhouse/bsmcp-embedder. Native binaries for bsmcp-server only are attached to each GitHub Release for linux-x86_64, linux-aarch64, darwin-x86_64, darwin-aarch64, and windows-x86_64. The embedder is not distributed as a bare binary — it depends on ONNX Runtime (a per-platform C++ shared library), so running it outside Docker is awkward. Either run the published embedder container, or build from source:

# Server
cargo run --release -p bsmcp-server

# Embedder (separate terminal)
cargo run --release -p bsmcp-embedder

The server is pure Rust + bundled SQLite and builds cleanly on any target the Rust toolchain supports. The embedder depends on fastembed, which links ONNX Runtime; the crate downloads a matching prebuilt at build time for common targets, but cross-compiling or running on uncommon platforms may require installing ONNX Runtime separately. For most users, running the embedder from the published container avoids that complexity entirely.

Configuration

Server Variables

| Variable | Required | Default | Description | |----------|----------|---------|-------------| | BSMCP_BOOKSTACK_URL | Yes | - | Your BookStack instance URL | | BSMCP_ENCRYPTION_KEY | Yes | - | 32+ char key for AES-256-GCM token encryption | | BSMCP_DB_BACKEND | No | sqlite | Database backend: sqlite or postgres | | BSMCP_DATABASE_URL | If postgres | - | PostgreSQL connection string | | BSMCP_DB_PATH | No | /data/bookstack-mcp.db | SQLite database path | | BSMCP_PUBLIC_DOMAIN | No | - | Public domain for OAuth redirects (e.g. mcp.example.com) | | BSMCP_INTERNAL_DOMAIN | No | - | Internal/Docker-network domain | | BSMCP_HOST | No | 0.0.0.0 | Bind address | | BSMCP_PORT | No | 8080 | Bind port | | BSMCP_INSTANCE_NAME | No | - | Instance name shown to AI | | BSMCP_INSTANCE_DESC | No | - | Instance description shown to AI | | BSMCP_SEMANTIC_SEARCH | No | false | Enable semantic search tools | | BSMCP_EMBEDDER_URL | No | http://bsmcp-embedder:8081 | Embedder HTTP endpoint | | BSMCP_WEBHOOK_SECRET | If semantic | - | BookStack webhook secret | | BSMCP_ACCESS_TOKEN_TTL | No | 86400 | Access token TTL in seconds (24h) | | BSMCP_REFRESH_TOKEN_TTL | No | 7776000 | Refresh token TTL in seconds (90d) | | BSMCP_BACKUP_INTERVAL | No | - | Hours between backups (0 = disabled) | | BSMCP_BACKUP_PATH | No | /data/backups | Backup directory | | BSMCP_BOOKSTACK_RATE_LIMIT_PER_MIN | No | 180 | Per-process BookStack API request cap. Lower if multiple processes share a token and you see 429s. |

Embedder Variables

| Variable | Required | Default | Description | |----------|----------|---------|-------------| | BSMCP_EMBED_TOKEN_ID | Yes | - | BookStack API token ID for crawling | | BSMCP_EMBED_TOKEN_SECRET | Yes | - | BookStack API token secret | | BSMCP_EMBED_PROVIDER | No | local | Embedding backend: local (fastembed ONNX), ollama, openai (or OpenAI-compatible), voyage. See Embedding Providers for per-provider config. | | BSMCP_EMBED_MODEL | No | (per provider) | Model name (see Embedding Providers) | | BSMCP_EMBED_API_KEY | If openai | - | API key for OpenAI embedding provider | | BSMCP_EMBED_API_URL | No | (per provider) | Base URL for Ollama or OpenAI-compatible endpoint | | BSMCP_EMBED_DIMS | No | (auto) | Embedding dimensions (auto-detected for Ollama) | | BSMCP_MODEL_PATH | No | /data/models | ONNX model cache directory (local provider only) | | BSMCP_EMBED_CPUS | No | 0 (unlimited) | Docker CPU limit for embedder | | BSMCP_EMBED_JOB_TIMEOUT | No | 14400 | Seconds before stuck jobs reset | | BSMCP_EMBED_BATCH_SIZE | No | 32 | Chunks per embedding batch | | BSMCP_EMBED_DELAY_MS | No | 50 | Delay between pages (API throttle) | | `BSMCP_EM

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars10
CategoryAI
Updated1d ago
Forks1

Languages

Rust

Security Score

85/100

Audited on Sep 20, 2026

1 medium1 info