# BookStack MCP Server — 69 tools via DADL

The BookStack DADL turns BookStack's API into an MCP server that Claude, GPT or any MCP-compatible agent can consume directly. One YAML file declares all 69 tools — book, chapter, image, page, role, attachment, and more — and ToolMesh serves them at runtime. No Python boilerplate, no per-endpoint code, no separate MCP server process.

Below: the endpoint coverage matrix, a two-block ToolMesh setup, the full tool reference grouped by BookStack feature area, required credential scopes.

**Source:** [BookStack REST API](https://demo.bookstackapp.com/api/docs)

**Updated:** 2026-06-12

**Tags:** wiki, crud, user-management, file-management, notifications, logging, version-control, documentation, auth:apikey

## Which BookStack endpoints are covered?

**98%** (69 of ~77 endpoints).

**Focus:** BookStack full API: books (CRUD, exports), pages (CRUD, HTML, markdown, exports), chapters (CRUD, exports), shelves (CRUD, book assignment), attachments (links, uploads), images (gallery, drawio, file data), comments (threads, replies, archiving), search (cross-entity), users (CRUD, invites), roles (permissions, MFA), recycle-bin (restore, purge), content-permissions (role overrides, fallback), audit-log, tags, ZIP imports.

**Missing:** Cover-image upload on book/shelf create/update and file replacement on attachment/image update (multipart facets of covered endpoints); the _method=PUT form workaround. All 77 documented endpoints are otherwise reachable -- the 15 export endpoints are collapsed into 6 parameterized tools.

*Last reviewed: 2026-06-12*

## How do you configure the BookStack DADL?

1. Log in to your BookStack instance as the user the API should act as (its roles define what the API can see and do)
2. Ensure one of the user's roles grants the 'Access System API' permission: Settings > Roles > (role) > System Permissions
3. Open the user's profile (avatar top-right > 'Edit Profile') and scroll to the 'API Tokens' section
4. Click 'Create Token', enter a name and expiry date, then Save -- the Token ID and Token Secret are shown
5. Join both values with a colon to form the credential: '<token_id>:<token_secret>' -- store this single string as bookstack_token

**Environment variable:** `CREDENTIAL_BOOKSTACK_TOKEN`

[Authentication docs](https://demo.bookstackapp.com/api/docs)

*The backends.yaml url MUST include the /api suffix. The header sent is "Authorization: Token <token_id>:<token_secret>" -- the credential value is the colon-joined pair, ToolMesh prepends the "Token " prefix. Content visibility mirrors the token user's roles exactly; for read-mostly agents prefer a dedicated low-privilege user. Default rate limit is 180 requests/min per user (env API_REQUESTS_PER_MIN).
*

## How do you install the BookStack MCP server with ToolMesh?

Add to your `backends.yaml`:

```yaml
- name: bookstack
  transport: rest
  dadl: bookstack.dadl
  url: "https://wiki.example.com/api"

```

Set the credential:

```
CREDENTIAL_BOOKSTACK_TOKEN=your-token-here
```

## What 69 tools does the BookStack DADL expose?

- **GET** `search_content` — Search across all content types (shelves, books, chapters, pages) using the same query syntax as the BookStack UI search bar. Returns {data, total}; each result has a 'type' property (bookshelf, book, chapter, page), tags, parent references (book/chapter), and a 'preview_html' object with highlighted name/content snippets. Uses its own page/count paging -- sort and filter params are NOT supported here.

- **GET** `list_shelves` — List all shelves visible to the API user. Returns id, name, slug, description, created_at, updated_at, created_by, updated_by, owned_by per shelf in {data, total}.

- **GET** `get_shelf` — Get a single shelf with tags, cover image info, description_html and the visible books on it (id, name, slug each).

- **POST** `create_shelf` — Create a new shelf. Optionally assign books by ID -- they appear on the shelf in the order given. Provide description (plain text) or description_html, not both.

- **PUT** `update_shelf` — Update a shelf. Providing 'books' REPLACES the entire book assignment with the given list -- fetch current books via get_shelf first when only adding/removing one.

- **DELETE** `delete_shelf` — Delete a shelf (sent to the recycle bin; books on it are NOT deleted). Returns 204.
- **GET** `list_books` — List all books visible to the API user. Returns id, name, slug, description, created_at, updated_at, created_by, updated_by, owned_by plus cover image info per book in {data, total}.

- **GET** `get_book` — Get a single book with tags, cover, description_html, shelves it is on, and a 'contents' tree listing its direct chapters and pages in display order -- each entry has a 'type' (chapter/page); chapters nest their pages. Use this to navigate a book's structure before reading pages.

- **POST** `create_book` — Create a new book. Provide description (plain text) or description_html. Cover-image upload requires multipart and is not supported here.

- **PUT** `update_book` — Update a book's details. Same writable fields as create_book.
- **DELETE** `delete_book` — Delete a book including its chapters and pages (sent to the recycle bin). Returns 204.
- **GET** `export_book` — Export a whole book (all chapters and pages compiled) as text. The result is the raw exported content -- HTML document, Markdown, or plain text. For PDF/ZIP use export_book_file.

- **GET** `export_book_file` — Export a whole book as a binary file -- 'pdf' or 'zip' (portable BookStack ZIP). Returns a download URL via the ToolMesh file broker.

- **GET** `list_chapters` — List all chapters visible to the API user. Returns id, book_id, name, slug, description, priority, created_at, updated_at, created_by, updated_by, owned_by per chapter in {data, total}.

- **GET** `get_chapter` — Get a single chapter with tags, description_html, book_slug and its visible pages (listing-level fields each).

- **POST** `create_chapter` — Create a new chapter inside a book.
- **PUT** `update_chapter` — Update a chapter. Passing a different book_id MOVES the chapter (and its pages) into that book -- requires delete permission on the chapter.

- **DELETE** `delete_chapter` — Delete a chapter including its pages (sent to the recycle bin). Returns 204.
- **GET** `export_chapter` — Export a chapter (all its pages compiled) as text -- HTML document, Markdown, or plain text. For PDF/ZIP use export_chapter_file.

- **GET** `export_chapter_file` — Export a chapter as a binary file -- 'pdf' or 'zip' (portable BookStack ZIP). Returns a download URL via the ToolMesh file broker.

- **GET** `list_pages` — List all pages visible to the API user. Returns id, book_id, chapter_id (0 when directly in a book), name, slug, priority, draft, template, created_at, updated_at, created_by, updated_by, owned_by per page in {data, total}. Content is NOT included -- call get_page for that.

- **GET** `get_page` — Get a single page with full content: 'html' (rendered output, includes resolved), 'raw_html' (stored source -- use as editing basis), 'markdown' (only if last saved with the Markdown editor), tags, and a 'comments' object with 'active' and 'archived' comment trees.

- **POST** `create_page` — Create a new page. Exactly ONE of book_id (page directly in book) or chapter_id (page inside chapter) is required, and exactly ONE of html or markdown content. Keep HTML to a single-block depth of plain elements for editor compatibility; base64 data-URI images are extracted into the image gallery automatically.

- **PUT** `update_page` — Update a page's details or content. Passing book_id or chapter_id MOVES the page to that parent (requires delete permission on the page). When updating content, base your edit on 'raw_html' from get_page and send it via 'html' -- the rendered 'html' field has include-tags resolved and round-trips badly.

- **DELETE** `delete_page` — Delete a page (sent to the recycle bin). Returns 204.
- **GET** `export_page` — Export a single page as text -- HTML document, Markdown, or plain text. For PDF/ZIP use export_page_file. Note: get_page already returns html/markdown content; exports add standalone document wrapping.

- **GET** `export_page_file` — Export a single page as a binary file -- 'pdf' or 'zip' (portable BookStack ZIP). Returns a download URL via the ToolMesh file broker.

- **GET** `list_attachments` — List attachments visible to the API user. Returns id, name, extension, uploaded_to (page ID), external (true = link attachment, false = file upload), order, created_at, updated_at, created_by, updated_by in {data, total}.

- **GET** `get_attachment` — Get details and content of an attachment. 'content' holds the link URL for external attachments, or the FULL base64-encoded file data for uploads -- which can be very large; strip it with a jq override when you only need metadata. 'links' provides ready-made HTML and Markdown embed snippets.

- **POST** `create_attachment` — Attach an external LINK to a page. For uploading a file as attachment use upload_attachment instead.

- **POST** `upload_attachment` — Upload a FILE as attachment to a page (multipart request). The file is fetched from the given URL by ToolMesh and uploaded to BookStack.

- **PUT** `update_attachment` — Update an attachment's name, target link, or move it to another page. Replacing an uploaded FILE requires a multipart PUT which is not modeled -- delete and re-create via upload_attachment instead.

- **DELETE** `delete_attachment` — Permanently delete an attachment (no recycle bin). Returns 204.
- **GET** `list_images` — List images in the system (page gallery images and drawio diagrams). Returns id, name, url, path, type (gallery|drawio), uploaded_to (page ID), created_by, updated_by, created_at, updated_at in {data, total}. Visibility requires access to the page each image was uploaded to.

- **GET** `get_image` — Get details of a single image: url, 'thumbs' (scaled variants) and 'content' with ready-made HTML/Markdown embed snippets as BookStack would insert them. Image file data is NOT included -- use get_image_data or the 'url' property.

- **POST** `create_image` — Upload a new image to the gallery of a page (multipart request). Use type 'gallery' for normal page images; 'drawio' ONLY for PNG files with embedded diagrams.net data. If name is omitted the filename is used.

- **PUT** `update_image` — Update an image's name. Replacing the image FILE requires a multipart PUT which is not modeled -- upload a new image instead.

- **DELETE** `delete_image` — Permanently delete an image and its thumbnails (no recycle bin). Usage is NOT checked -- pages referencing the image will show broken references. Returns 204.

- **GET** `get_image_data` — Download the raw image file data for an image ID. Returns a download URL via the ToolMesh file broker instead of JSON.

- **GET** `get_image_data_by_url` — Download raw image file data identified by its public BookStack image URL (as found in page content src attributes) instead of an ID. Returns a download URL via the ToolMesh file broker.

- **GET** `list_comments` — List comments visible to the API user. Returns id, commentable_id (page ID), commentable_type, parent_id, local_id, content_ref, created_by, updated_by, created_at, updated_at in {data, total}. Comment HTML is NOT included -- use get_comment. For a page's full comment tree prefer get_page (comments property).

- **GET** `get_comment` — Get a single comment (with safe HTML content) plus its direct replies. Note: 'local_id' is page-scoped; 'parent_id' of replies refers to the parent's local_id, not the global id.

- **POST** `create_comment` — Create a comment on a page. To reply to an existing comment set reply_to to the parent comment's LOCAL_ID (page-scoped), not its global id.

- **PUT** `update_comment` — Update a comment's content and/or archive state. Only provide 'archived' when actively changing it; only top-level comments (non-replies) can be archived/unarchived.

- **DELETE** `delete_comment` — Permanently delete a comment (no recycle bin). Returns 204.
- **GET** `list_users` — List all users. Requires 'Manage users' permission. Returns id, name, slug, email, external_auth_id, created_at, updated_at, last_activity_at plus profile/avatar URLs in {data, total}.

- **GET** `get_user` — Get a single user including their assigned roles (id + display_name). Requires 'Manage users' permission.
- **POST** `create_user` — Create a new user. Requires 'Manage users' permission. Either set a password or send_invite=true so the user sets their own via email.

- **PUT** `update_user` — Update a user. Requires 'Manage users' permission. 'roles' replaces the full role assignment.
- **DELETE** `delete_user` — Permanently delete a user. Requires 'Manage users' permission. Pass migrate_ownership_id to transfer ownership of their content to another user first. Returns 204.

- **GET** `list_roles` — List all roles. Requires 'Manage roles' permission. Returns display_name, description, mfa_enforced, external_auth_id, timestamps plus permissions_count and users_count in {data, total}.

- **GET** `get_role` — Get a single role including its granted permission name strings and a high-level list of assigned users. Requires 'Manage roles' permission.

- **POST** `create_role` — Create a new role. Permissions are given as an array of permission name strings (e.g. 'access-api', 'page-create-all', 'book-view-own') -- inspect an existing role via get_role for the full vocabulary.

- **PUT** `update_role` — Update a role. CAUTION: 'permissions' replaces ALL granted permissions and an empty array clears them -- fetch current permissions via get_role and send the modified full set.

- **DELETE** `delete_role` — Permanently delete a role (users keep their other roles). Requires 'Manage roles' permission. Returns 204.
- **GET** `list_recycle_bin` — List items in the recycle bin. Requires permission to manage both system settings and permissions. Each entry has a deletion id (use for restore/purge), deleted_by, deletable_type (page/chapter/book/ bookshelf), deletable_id and a 'deletable' object with child counts (books/chapters) or parent info (chapters/pages).

- **PUT** `restore_recycle_bin_item` — Restore a deletion from the recycle bin, including all child content. Takes the DELETION id from list_recycle_bin, not the content's own ID. Returns {restore_count}.

- **DELETE** `purge_recycle_bin_item` — PERMANENTLY destroy a deletion from the recycle bin including all child content -- this cannot be undone. Takes the DELETION id from list_recycle_bin. Returns {delete_count}.

- **GET** `get_content_permissions` — Read the content-level permission OVERRIDES for one item: owner, role_permissions (per-role view/create/update/delete flags) and fallback_permissions ('inheriting': true means no override; its flag values are null then). Shows only overrides on this item -- not evaluated/inherited permissions.

- **PUT** `update_content_permissions` — Update content-level permission overrides for one item. OMIT owner_id / role_permissions / fallback_permissions entirely to leave that category unchanged. CAUTION: an empty role_permissions array CLEARS all configured role overrides -- read existing permissions first and send the merged result.

- **GET** `list_audit_log` — List audit log events. Requires permission to manage both users and system settings. Returns id, type (e.g. page_create, auth_login, permissions_update), detail, user_id (plus user object), loggable_id, loggable_type, ip, created_at in {data, total}.

- **GET** `list_tag_names` — List distinct tag NAMES used across visible content, with usage totals: name, values (count of distinct values), usages, page_count, chapter_count, book_count, shelf_count. Only 'name' is filterable. Requires BookStack >= v26.05 -- older instances return a 404 HTML page.

- **GET** `list_tag_values` — List the distinct VALUES set for one tag name across visible content, with usage totals per value. Only 'value' is filterable. Requires BookStack >= v26.05 -- older instances return a 404 HTML page.

- **GET** `list_imports` — List pending ZIP imports visible to the user. Requires 'Import content' permission. Returns id, name, size, type (book/chapter/page), created_by, created_at, updated_at in {data, total}.

- **POST** `create_import` — Upload and validate a BookStack portable ZIP file (from export_*_file zip exports) as a pending import. Does NOT import yet -- call run_import afterwards. Requires 'Import content' permission.

- **GET** `get_import` — Read a pending ZIP import including a 'details' property with metadata about the ZIP content (structure varies by import type).

- **POST** `run_import` — Execute a pending ZIP import. parent_type + parent_id are REQUIRED when the import's type is 'chapter' or 'page' (check via get_import); book imports need no parent. Returns the imported item on success.

- **DELETE** `delete_import` — Delete a pending ZIP import (the staged upload, not imported content). Returns 204.
- **GET** `get_system_info` — Read instance details: version, instance_id, app_name, app_logo (may be null), base_url. Useful for verifying connectivity and version-gated features.


## Which DADLs are related to BookStack?

- [NetBox](https://www.dadl.ai/d/netbox/) — NetBox DCIM/IPAM API -- full v4 coverage: sites, racks, devices, modules, interfaces, cables, power, IPAM (prefixes, IPs, VLANs, VRFs, route-targets, VLAN translation), virtualization, circuits (including virtual circuits), tenants, contacts, VPN (IKE/IPSec/L2VPN), wireless, extras (webhooks, event-rules, scripts, config-templates, bookmarks, notifications), users/permissions/tokens, and core data sources & jobs
- [Alertmanager](https://www.dadl.ai/d/alertmanager/) — Prometheus Alertmanager API v2 -- alerts, silences, receivers, alert groups, status, and operational health
- [DokuWiki](https://www.dadl.ai/d/dokuwiki/) — DokuWiki JSON-RPC API — wiki pages, media files, search, ACL management, and user administration
- [Hacker News](https://www.dadl.ai/d/hackernews/) — Hacker News API — read-only access to stories, comments, polls, jobs, users, and live feeds from news.ycombinator.com
- [Mempool](https://www.dadl.ai/d/mempool/) — mempool.space — Bitcoin block explorer, mempool visualizer, fee estimator, Lightning Network explorer, and transaction accelerator
- [Mikrotik](https://www.dadl.ai/d/mikrotik/) — MikroTik RouterOS REST API -- manage interfaces, IP addresses, routing, firewall, DHCP, DNS, PPP, queues, wireless, system configuration, users, certificates, files, logs, and diagnostics on RouterOS v7.1+ devices

---

**Canonical URL:** https://www.dadl.ai/d/bookstack/
**Raw DADL:** https://github.com/DunkelCloud/dadl-registry/blob/main/bookstack.dadl
