Bookstack MCP

An MCP server for interacting with Bookstack, built with the mcp-framework for Node.js.

BookStack MCP Server

This repository hosts a Python FastMCP-based server that exposes consolidated tools for managing a BookStack instance. The flagship capabilities are the image gallery management workflows that power authoring experiences in downstream MCP clients.

⚠️ DEPRECATION NOTICE: The TypeScript/mcp-framework server (src/ directory) is deprecated and no longer maintained. All development has moved to the Python FastMCP server (fastmcp_server/ directory). Please migrate to the Python server for the latest features and bug fixes.

Quick start

# Install Python dependencies for the FastMCP server
pip install -r fastmcp_server/requirements.txt

Launch the FastMCP server after exporting your BookStack credentials (see below):

cd fastmcp_server
python3 -m fastmcp_server

Required environment

Copy .env.example to .env and populate these variables before invoking any BookStack tools:

BS_URL=https://your-bookstack.example.com
BS_TOKEN_ID=...
BS_TOKEN_SECRET=...

The API token must belong to a user that can view and manage the image gallery. Local helper scripts use set -a && source .env so the values apply to ad-hoc Python snippets as well.

BookStack tools

The Python FastMCP server provides comprehensive BookStack management through consolidated tools:

Content Management

  • bookstack_content_crud — unified CRUD operations for books, bookshelves, chapters, and pages (Letta-compatible)
  • bookstack_list_content — list and filter content entities with pagination
  • bookstack_search — full-text search across BookStack content
  • bookstack_batch_operations — bulk create, update, and delete operations

Image Gallery Management

  • bookstack_manage_images — unified create/read/update/delete/list interface for images
  • bookstack_search_images — advanced discovery with extension, date, size, and usage filters

All tools are registered by fastmcp_server/bookstack/tools.py and surfaced automatically when the FastMCP server starts.

📘 Letta Compatibility: If you're using Letta as your MCP client, please read docs/LETTA_COMPATIBILITY.md for important compatibility requirements and best practices.

Image uploads from URLs

bookstack_manage_images accepts three input shapes for the image/new_image fields during create and update operations:

  1. Plain base64 strings
  2. Data URLs (data:image/png;base64,...)
  3. HTTP or HTTPS URLs

When a URL is supplied the tool:

  • Streams the remote image with a 30 second timeout and a 50 MB limit
  • Restricts schemes to HTTP/HTTPS to avoid SSRF
  • Validates the MIME type against BookStack's accepted formats (jpeg, png, gif, webp, bmp, tiff, svg+xml)
  • Infers a filename from the URL path when one is not supplied

Required BookStack parameters

BookStack's POST /api/image-gallery endpoint enforces two additional fields beyond the binary payload:

  • type — must be gallery for standard content images (use drawio only when uploading diagrams.net PNGs)
  • uploaded_to — the numeric page ID to attach the image to. BookStack rejects uploads without a real page context.

The tool surfaces these as optional inputs named image_type and uploaded_to. Default values of gallery and 0 preserve backward compatibility while allowing callers to target specific pages when required.

Manual verification against a live instance

After exporting your environment variables you can confirm an end-to-end URL upload with the following snippet (replace PAGE_ID with an existing page id):

cd /opt/stacks/bookstack-mcp/Bookstack-MCP
set -a && source .env && set +a
python3 - <<'PY'
import asyncio, json, time
from fastmcp import FastMCP
from fastmcp_server.bookstack.tools import register_bookstack_tools

TEST_IMAGE_URL = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"
PAGE_ID = 39  # replace with a page id from your BookStack instance

async def main():
    mcp = FastMCP("manual-test")
    register_bookstack_tools(mcp)
    tool = await mcp.get_tool("bookstack_manage_images")
    result = await tool.run({
        "operation": "create",
        "name": f"URL Upload Test {int(time.time())}",
        "image": TEST_IMAGE_URL,
        "uploaded_to": PAGE_ID,
    })
    print(json.dumps(json.loads(result.content[0].text), indent=2))

asyncio.run(main())
PY

You should receive a JSON payload describing the uploaded image, including thumbnails and the uploaded_to identifier. A 422 error means BookStack rejected the request (common causes: missing uploaded_to, disallowed MIME type, image exceeding the 50 MB limit). A 404 response typically indicates the API token lacks gallery permissions.

Testing

Run the Python unit tests for the BookStack tools:

cd fastmcp_server
python3 -m pytest tests/test_manage_images.py -v

The suite covers URL handling, timeout and size enforcement, invalid scheme rejection, and the forwarding of type/uploaded_to metadata.

Additional references

Related Servers