Summary
Two gaps prevent the MCP from controlling content order within a book:
update_page doesn't expose priority — only name, html, markdown, book_id, chapter_id are passed through
- There is no
update_chapter tool — chapters can be created and deleted but not renamed, reordered, or moved
BookStack displays book contents in priority order (chapters and top-level pages interleaved), so without priority access the MCP can build a book but can't control or fix its table of contents.
BookStack API support (verified against development branch)
Both PUT endpoints accept priority as an optional integer:
PUT /api/pages/{id} — already used by update_page, just needs priority added to the passthrough:
'priority' => ['integer'],
PUT /api/chapters/{id} — not currently exposed as a tool:
'name' => ['string', 'min:1', 'max:255'],
'description' => ['string', 'max:1900'],
'description_html' => ['string', 'max:2000'],
'tags' => ['array'],
'priority' => ['integer'],
'book_id' => ['integer'], // moves chapter to another book
'default_template_id' => ['nullable', 'integer'],
There is no dedicated bulk "sort book" API endpoint — the UI's drag-and-drop uses an internal web route. Per-item priority via PUT is the supported API mechanism.
Proposed changes
1. update_page: add optional priority (integer, min 0)
Just add it to the input schema and pass it through — updatePage in the client already forwards the data object to axios unchanged.
2. New tool: update_chapter
Inputs:
id: number (required)
name: string (optional) — rename the chapter
description: string (optional) — max 1900 chars
priority: number (optional) — sort order within the book (lower = earlier)
book_id: number (optional) — move chapter to another book
tags: array (optional)
This also fixes the unrelated gap that chapters currently can't be renamed or have their description edited via MCP.
3. Client method: updateChapter(id, data)
Same pattern as updatePage:
async updateChapter(id, data) {
if (!this.enableWrite) throw new Error('Write operations are disabled...');
const response = await this.client.put(`/chapters/${id}`, data);
return await this.enhanceChapterResponse(response.data);
}
Use case
We had a book where the chapter/page order didn't match the source document. Without priority access, the only fix was manual drag-and-drop in the BookStack UI. With these changes, the model can reorder an entire book's table of contents in a few tool calls.
We've implemented this in our fork and it's working. Happy to PR if you'd like.
Summary
Two gaps prevent the MCP from controlling content order within a book:
update_pagedoesn't exposepriority— onlyname,html,markdown,book_id,chapter_idare passed throughupdate_chaptertool — chapters can be created and deleted but not renamed, reordered, or movedBookStack displays book contents in
priorityorder (chapters and top-level pages interleaved), so without priority access the MCP can build a book but can't control or fix its table of contents.BookStack API support (verified against
developmentbranch)Both PUT endpoints accept
priorityas an optional integer:PUT /api/pages/{id}— already used byupdate_page, just needspriorityadded to the passthrough:PUT /api/chapters/{id}— not currently exposed as a tool:There is no dedicated bulk "sort book" API endpoint — the UI's drag-and-drop uses an internal web route. Per-item
priorityvia PUT is the supported API mechanism.Proposed changes
1.
update_page: add optionalpriority(integer, min 0)Just add it to the input schema and pass it through —
updatePagein the client already forwards the data object to axios unchanged.2. New tool:
update_chapterThis also fixes the unrelated gap that chapters currently can't be renamed or have their description edited via MCP.
3. Client method:
updateChapter(id, data)Same pattern as
updatePage:Use case
We had a book where the chapter/page order didn't match the source document. Without priority access, the only fix was manual drag-and-drop in the BookStack UI. With these changes, the model can reorder an entire book's table of contents in a few tool calls.
We've implemented this in our fork and it's working. Happy to PR if you'd like.