scribus-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@scribus-mcpCreate a new A4 document with 3 pages and add a title text frame on the first page"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
scribus-mcp
An MCP (Model Context Protocol) server that lets Claude drive Scribus — the open-source desktop publishing app — through its Python Scripter API.
TL;DR — wire it to Claude Code (Linux, fully auto)
One command, both auto-downloads stacked: uvx fetches the MCP server from PyPI on demand, and SCRIBUS_MCP_AUTO_APPIMAGE=1 makes the launcher pull the official Scribus 1.7.x AppImage to ~/Applications/ on the first interactive tool call. SCRIBUS_MCP_IGNORE_HOST_SCRIBUS=1 skips every host-binary lookup so the AppImage is used even when the distro ships an older Scribus 1.6. No system-wide install of either piece needed.
claude mcp add scribus -s user \
-e SCRIBUS_MCP_AUTO_APPIMAGE=1 \
-e SCRIBUS_MCP_IGNORE_HOST_SCRIBUS=1 \
-- uvx scribus-mcpOne-time prerequisites on Debian/Ubuntu (the AppImage needs FUSE, the QR-code tool needs Ghostscript):
sudo apt install fuse libfuse2t64 ghostscriptRestart Claude Code so it picks up the new server. Ask Claude to make any document — both downloads kick off in sequence (~5 sec for uvx, ~30–60 sec for the AppImage on first call), then everything's cached for subsequent sessions.
First-run papercut on Linux: Scribus's "New Document" wizard blocks
-pyexecution until dismissed. Launch the AppImage once (~/Applications/Scribus-1.7.3-x86_64.AppImage), dismiss the welcome, quit, then run./scripts/disable-startup-dialog-linux.sh --force(clone the repo first) so the prefs file persistsShowStartupDialog="0". After that, every session is hands-off.
Updating after a new release: uvx caches package metadata for ~15 minutes, so a freshly-published version may not be picked up immediately. Force a refresh with:
uvx --refresh scribus-mcp --help
# or wipe just this package's cache:
uv cache clean scribus-mcpThen restart Claude Code (or /mcp reconnect inside it) so the spawned server reloads.
For Windows / macOS / non-uvx paths, see Install.
What's in it
Two backends behind one tool surface:
Headless — fires a fresh
scribus -g -py …per call. Best for batch jobs (CI manual generation, data merges).Interactive — talks over TCP loopback to a small
.spybridge running inside an open Scribus window. Best for assisting on a document you already have open.
mode="auto" (the default for every tool) prefers the interactive bridge when one is reachable, otherwise falls back to headless.
Status
Validated end-to-end on:
Platform | Scribus | Qt binding | Phase 1 (interactive) | Phase 2 (headless) |
Windows 11 | 1.7.3 | PyQt6 6.10.2 | 125/125 PASS | 8/8 PASS |
Debian 13 | 1.6.3 | PySide2 | 132/134 PASS, 2 skip | 11/11 PASS |
On Linux + 1.6.3, one skip is the 1.7-gated create_qr_code_block (see Scribus version requirements per feature) and one is a first-test bridge-startup race; both go to PASS on a 1.7.x build (run scribus-mcp --fetch-appimage to grab one — see Auto-fetch the Scribus AppImage). Re-run anytime with pytest tests/ and SCRIBUS_MCP_LIVE=1. See:
doc/BEST_PRACTICES.md — house style for driving the MCP (also exposed as the
best_practicesprompt so an LLM session can pull it directly).doc/COOKBOOK.md — end-to-end recipes for one-pagers, manuals, dashboards, comparison reports, code walkthroughs, PDF forms.
doc/SUPPORT.md — per-Scripter-function support matrix (~140 functions tabulated).
doc/threading-and-scribus.md — architectural rationale behind the bridge.
What's in the box
~125 MCP tools spanning:
Primitives: document lifecycle, pages, text/image/shape frames, text content + flow + formatting, paragraph & character styles, colors, layers, search/replace.
Object styling: fill / stroke / shade / transparency / line caps & joins / corner radius / 2-stop gradients.
Typography:
list_fonts,list_fonts_detailed,list_monospace_fonts,font_is_available, plus pre-launch custom font staging viainstall_custom_font(copies to a managed dir + patches Scribus's prefsExtraFontDirs).Export:
export_pdf,render_page_to_image(inlines a base64 PNG straight into the model's context),preflight_check.PDF interactivity (forms package): 6 form fields (text, checkbox, radio, combo, list, push button), 4 annotation types (link, URI, file, sticky-note), JS action setter/getter for all 10 field events.
High-level patterns (one call → composed multi-element output):
create_radar_chart,create_bar_chart,create_pie_chart,create_timeline,create_callout_box,create_kpi_tile,create_comparison_table,create_qr_code_block,create_dot_label,create_numbered_badge,create_code_sample(Pygments-tokenized syntax-highlighted code blocks).Region-shaped layouts:
create_two_column_text,create_text_with_image,create_section_header,create_hero_band,create_numbered_steps,create_image_caption,create_table_of_contents,create_sidebar_layout,create_kpi_row,create_equal_columns,create_card_grid.Markdown bridge:
import_markdownturns a Markdown document into a stack of styled Scribus frames in one call.
4 MCP resources exposing read-only document state (
scribus://document/info,…/colors,…/fonts,…/missing-resources).3 MCP prompts:
best_practices(rules + patterns an LLM should follow when driving the MCP — pull this at session start),manual_from_markdown,data_merge_csv.A gated
run_scriptescape hatch for arbitrary Scripter Python (off by default).Both stdio and Streamable HTTP transports.
A Python helper for caller-side scripts:
from scribus_mcp.layout import PageCursor. Tracks the running y for a column so multi-band scripts (the demos inscripts/, custom batch generators) declare a sequence of bands instead of hand-coding y. See src/scribus_mcp/layout.py for the API.
Requirements
Python 3.11+ for the MCP server.
Scribus 1.7.x for the full tool surface. Scribus 1.6.x is supported with a small handful of features gated off — see Scribus version requirements per feature below. On Linux Scribus links against system Python — see the distro caveat below.
For the interactive backend: a running Scribus window with the bridge
.spyfile loaded.For headless on Linux servers without a display:
xvfb(virtual framebuffer).
Scribus version requirements per feature
The MCP works on both Scribus 1.6 and 1.7. A small number of tools wrap Scripter functions that were added in 1.7+, so calling them on a 1.6 host returns a structured error to the MCP client instead of letting Scribus's AttributeError leak through:
{
"ok": false,
"error": "create_qr_code_block (scribus.createBarcode) requires Scribus 1.7.0+ (this Scribus reports 1.6.3). Install / point SCRIBUS_BIN at a 1.7.x build — see README 'Scribus version requirements per feature'.",
"required_version": "1.7.0",
"actual_version": "1.6.3"
}The version probe runs once per backend instance (cached via scribus.scribus_version_info), so the floor check costs effectively nothing on subsequent calls. An LLM client driving the MCP can match on required_version to surface a clean "upgrade Scribus" suggestion to the user.
Tool | Scripter call | Min Scribus | Notes |
|
| 1.7.0 | Also needs Ghostscript on the host. |
Everything else in the tool surface (~140 functions) works on both 1.6 and 1.7. If you hit a Scripter AttributeError from a tool not in this table, it's likely a missing gate — please file an issue.
Linux: Python version caveat
Because Scribus on Linux uses system Python, the .spy bridge runs on whatever your distro ships. The bridge requires Python 3.11+, which means:
Distro | System Python | Status |
Debian 12 / Ubuntu 23.04+ / Fedora 37+ / Arch | 3.11+ | OK |
Ubuntu 22.04 LTS / Debian 11 / RHEL 9 | 3.10 or older | Use the Scribus AppImage (bundles its own Python) |
Headless mode has the same constraint, since it also runs Scribus's Python.
Install
Step 1 — install Scribus
Platform | How |
Linux (Debian 12 / Ubuntu 23.04+ / Fedora 37+) |
|
Linux (older — Ubuntu 22.04 LTS, etc., or distros that only ship 1.6) |
|
Windows | Installer from scribus.net — default path |
macOS |
|
Auto-fetch the Scribus AppImage
If your distro only ships Scribus 1.6 (Debian 13, Ubuntu 24.04, etc.) — or you'd rather not install Scribus system-wide — the MCP can pull the official 1.7.x AppImage for you. Two entry points:
# (A) Explicit one-shot install — prints the installed path on stdout
scribus-mcp --fetch-appimage
# → /home/<user>/Applications/Scribus-1.7.3-x86_64.AppImage
# (B) Lazy fetch — set the env var; the MCP fetches on first call when no Scribus is found
SCRIBUS_MCP_AUTO_APPIMAGE=1 scribus-mcpEither way, the AppImage lands at ~/Applications/Scribus-X.Y.Z-x86_64.AppImage, which scribus-mcp already probes by default — no SCRIBUS_BIN tweak needed afterwards. Subsequent runs are idempotent (the file isn't redownloaded).
Already have an older Scribus on the host? Set SCRIBUS_MCP_IGNORE_HOST_SCRIBUS=1 alongside SCRIBUS_MCP_AUTO_APPIMAGE=1 to skip every host-binary lookup (SCRIBUS_BIN, $PATH, the well-known install paths, the AppImage glob in ~/Applications/) and go straight to the AppImage. Useful when the distro ships Scribus 1.6 but you want the 1.7.x AppImage for the full feature set (create_qr_code_block, etc.).
claude mcp add scribus -s user \
-e SCRIBUS_MCP_AUTO_APPIMAGE=1 \
-e SCRIBUS_MCP_IGNORE_HOST_SCRIBUS=1 \
-- uvx scribus-mcpCaveats (Linux only; the AppImage doesn't apply to macOS / Windows):
Pulls ~140 MB from SourceForge over HTTPS. Off by default.
Upstream doesn't ship a SHA256 file alongside the AppImage. The default path verifies via TLS + a 50 MB sanity floor (truncated downloads / HTML error pages get rejected). To pin a hash you computed yourself, use
--appimage-sha256 <hex>orSCRIBUS_MCP_APPIMAGE_SHA256=<hex>.AppImages need FUSE to mount —
sudo apt install fuseon Debian/Ubuntu if Scribus fails to launch withdlopen()errors.
Override knobs (CLI flag → env var fallback):
Flag | Env var | Default |
|
| SourceForge URL for the pinned default version |
|
|
|
|
| (no pin — TLS only) |
|
|
|
Step 2 — install the MCP server
Recommended path uses uv (one-line installer in uv's docs). uvx runs Python apps in cached isolated envs — no manual venv, no global install.
# Once published to PyPI (canonical form):
uvx scribus-mcp --help
# Pre-PyPI (today): run straight from GitHub
uvx --from git+https://github.com/caewa/scribus-mcp scribus-mcp --helpThat's all you need if the only consumer is the MCP server — Claude spawns it on demand (see Connect Claude). Auto-launch handles starting Scribus + bridge for you on the first interactive call.
If you want scribus-mcp on PATH directly (e.g. to run scribus-mcp --print-bridge-path from a shell), use uv tool install scribus-mcp (or pipx install scribus-mcp) once it's on PyPI; pre-PyPI, swap in git+https://github.com/caewa/scribus-mcp.
Dev mode (editable install from source)
For contributors / anyone hacking on the MCP itself: clone the repo and install editable. Edits to src/scribus_mcp/** take effect immediately, no reinstall.
git clone https://github.com/caewa/scribus-mcp
cd scribus-mcp
# Option A — uv (recommended)
uv sync # creates .venv with all deps
uv pip install -e ".[dev]" # editable install + dev extras (pytest, ruff)
# Option B — plain pip
python3.11 -m venv .venv
.venv/bin/activate # or .venv\Scripts\activate on Windows
pip install -e ".[dev]"
# Verify
scribus-mcp --help # the editable install puts this on PATH
pytest # 52 unit tests (no Scribus needed)
SCRIBUS_MCP_LIVE=1 pytest # full Phase 1/2 suite (needs Scribus + bridge)In dev mode, your MCP client config uses the bare command — your editable install is already on PATH:
{
"mcpServers": {
"scribus": {
"command": "scribus-mcp",
"env": { "SCRIBUS_BIN": "C:\\Program Files\\Scribus 1.7.3\\scribus.exe" }
}
}
}Auto-launch is wired in: any tool call with mode="interactive" will spawn Scribus + load the bridge for you if no bridge is already running. No need to manually run the launch command at the start of every session.
Wire Claude Code at a local checkout (no editable install)
If you just want to test a local branch against Claude Code without installing into a venv or touching PATH, point uvx directly at the checkout. Each spawn rebuilds from your working tree, so further edits are picked up the next time the server starts:
claude mcp remove scribus -s user 2>/dev/null
claude mcp add scribus -s user -e SCRIBUS_MCP_AUTO_APPIMAGE=1 -- uvx --from /absolute/path/to/scribus-mcp scribus-mcpVerify with claude mcp list — the line should end with ✓ Connected. Restart Claude Code (or /mcp reconnect) so it re-spawns the server. To switch back to the published release, drop the --from /absolute/path/to/scribus-mcp so uvx resolves the package from PyPI again — leave the trailing scribus-mcp in place.
Windows: Scribus path
If Scribus isn't at the default path, point the server at it:
$env:SCRIBUS_BIN = "C:\path\to\scribus.exe"(Or set it per-MCP-client in the env block — see below.)
Connect Claude to it
Claude Code (stdio)
Add to your Claude Code settings (~/.claude/settings.json or via claude mcp add):
{
"mcpServers": {
"scribus": {
"command": "uvx",
"args": ["scribus-mcp"],
"env": {
"SCRIBUS_BIN": "/usr/bin/scribus"
}
}
}
}uvx fetches the package on first use, caches it, then runs the binary. No manual pip install step.
Pre-PyPI note: until
scribus-mcpis published to PyPI, swap theargsfor the git form:"args": ["--from", "git+https://github.com/caewa/scribus-mcp", "scribus-mcp"]
On Windows replace the env value with "C:\\Program Files\\Scribus 1.7.3\\scribus.exe". If you've done a persistent install (uv tool install / pipx install), or you're in dev mode, use "command": "scribus-mcp" directly with no args.
Streamable HTTP (CI, remote, with progress streaming)
uvx scribus-mcp --http :8765 # zero-install
# or, if installed:
scribus-mcp --http :8765Point your MCP client at http://localhost:8765/mcp. Use this transport for long-running headless jobs — it streams progress updates in real time, where stdio would block.
Enable the interactive backend
The interactive backend lets the MCP drive a Scribus window you already have open — fast IPC, persistent doc state, and you can watch (or take over) the work in real time. The server also works headless-only without it; this is opt-in.
The bridge runs inside Scribus and dispatches MCP calls onto Scribus's Qt main thread via a QTimer. It needs a Qt Python binding (PyQt6 / PyQt5 / PySide6 / PySide2 — whichever Scribus's Python can import) to keep Scribus's GUI responsive while serving requests. Without one, the bridge falls back to a main-thread blocking loop that freezes the GUI — usable only with -g (headless) Scribus.
Step 1 — Install a matching Qt binding
Platform | Command |
Linux (Debian/Ubuntu) |
|
Linux (Fedora) |
|
Windows | Run |
macOS |
|
Why a matching version? PyQt6's PyPI wheel bundles its own Qt6 DLLs. If those don't match Scribus's bundled Qt6 minor version,
import PyQt6.QtCorefails withImportError: DLL load failed. The install script readsQt6Core.dll's FileVersion and pins PyQt6 to the same minor.
Step 2 — Locate the bridge file
scribus-mcp --print-bridge-path(Or directly: src/scribus_mcp/bridge/scribus_mcp_bridge.spy.)
Step 3 — Launch Scribus with the bridge
Tip: the MCP auto-launches Scribus + bridge whenever a tool call with
mode="interactive"finds no live bridge. You only need to run this manually if you want Scribus open before making the first call (e.g., to position windows or load a doc first).
The simplest path for a test session:
# Linux
scribus --console -py "$(scribus-mcp --print-bridge-path)"# Windows
& "C:\Program Files\Scribus 1.7.3\scribus.exe" --console -py "C:\Users\William\scribus-mcp\src\scribus_mcp\bridge\scribus_mcp_bridge.spy"Dismiss the welcome dialog (if any). Confirm the bridge picked up Qt by inspecting the log:
Linux/macOS:
cat $XDG_RUNTIME_DIR/scribus-mcp/bridge.logWindows:
Get-Content "$env:LOCALAPPDATA\scribus-mcp\bridge.log"
You should see a line like:
scribus_mcp_bridge: listening on 127.0.0.1:<port> qt=PyQt6 discovery=...If qt= says NONE-thread-fallback, the Qt binding isn't being detected — re-check Step 1.
Step 4 — The bridge writes a discovery file
The MCP server reads <runtime-dir>/scribus-mcp/scribus-mcp.json automatically (port + auth token). Once that file exists, every tool call with mode="auto" (or "interactive") is routed to your live Scribus instead of spawning a new one.
Step 5 — Skip the "New Document" startup dialog
By default Scribus shows a New Document wizard at every launch, which blocks -py script execution until dismissed. Disable it once with:
# Windows — close Scribus first, then:
& .\scripts\disable-startup-dialog-windows.ps1# Linux — close Scribus first, then:
./scripts/disable-startup-dialog-linux.shBoth set ShowStartupDialog="0" in your user prefs (%APPDATA%\Scribus\scribusXYZ.rc on Windows, ~/.config/scribus/scribusXYZ.rc on Linux), where XYZ is the Scribus minor version (172, 163, …). Persistent across launches; reversible with -Enable / --enable; use -Force / --force for non-interactive flows (CI, auto-spawn). You can also flip it manually via File → Preferences → General → uncheck "Always show 'New Document' dialog at startup".
First-run note: the prefs file is created by Scribus on its first save, so you need to launch Scribus once and exit (you can dismiss the welcome dialog inline) before either script can find a file to edit. macOS uses the same XML; the helper for it is TBD.
Optional: autoload at Scribus startup
If your Scribus build ships ScripterNG (note: not standard in Scribus 1.7.3 Windows), drop the .spy in:
Linux:
~/.scribus/scripterng/autoload/Windows:
%APPDATA%\Scribus\scripterng\autoload\macOS:
~/Library/Preferences/Scribus/scripterng/autoload/
Otherwise stick with the explicit -py launch (Step 3).
Run the dangerous escape hatch
run_script lets the model execute arbitrary Python inside Scribus's interpreter. It's disabled by default. To enable it:
scribus-mcp --enable-run-script # CLI flag
SCRIBUS_MCP_RUN_SCRIPT=1 scribus-mcp # or env varFor production / shared deployments: keep it off and add purpose-built tools instead. For experimenting locally: fine to enable.
Configuration
All env vars are optional:
Variable | Default | What it does |
| auto-detected | Path to Scribus executable |
|
| Set to |
|
| Set to |
|
| Python log level |
| (empty) |
|
|
| Set to |
|
| Set to |
| (SourceForge URL for the pinned default version) | Override the AppImage download URL. |
|
| Override the version tag used in the installed filename and the default URL. |
| (empty) | Pin a SHA256 to verify the downloaded AppImage against. Upstream doesn't publish one — you compute it yourself. |
|
| Override the AppImage install directory. |
Tool surface
A non-exhaustive selection (run scribus-mcp with MCP Inspector or check doc/SUPPORT.md for the full list):
Document:
create_document,open_document,save_document,save_document_as,close_document,get_document_info,set_document_metadataPages:
add_page,delete_page,goto_page,get_page_count,apply_master_page,list_master_pages,create_master_pageFrames:
create_text_frame,create_image_frame,create_rectangle,create_ellipse,create_line,create_polygon,create_polyline,create_bezier_line,create_path_text,delete_object,move_object,resize_object,list_page_objectsText:
set_text,append_text,get_text,get_visible_text,link_text_frames,is_text_overflowing,set_font,set_font_size,set_text_color,set_text_alignment,set_text_vertical_alignment,set_line_spacingFonts:
list_fonts,list_fonts_detailed,list_monospace_fonts,get_text_frame_font,font_is_available,install_custom_font,list_extra_font_dirsStyles:
list_paragraph_styles,apply_paragraph_style,apply_character_style,import_styles_from_fileObject styling:
set_fill_color,set_line_color,set_fill_shade,set_line_shade,set_fill_transparency,set_line_transparency,set_line_width,set_line_style,set_line_cap,set_line_join,set_corner_radius,apply_gradient,clear_gradient, plus matching gettersColors:
define_color_cmyk,define_color_rgb,list_colors,delete_colorImages:
load_image,set_image_scale,scale_image_to_frame,set_image_offsetLayers:
create_layer,delete_layer,list_layers,set_active_layer,send_to_layer,set_layer_visible,set_layer_printableSearch:
find_and_replace_text,find_objectsExport:
export_pdf,render_page_to_image(returns inline image to Claude),preflight_checkPDF forms:
create_pdf_text_field,create_pdf_checkbox,create_pdf_radio_button,create_pdf_combo_box,create_pdf_list_box,create_pdf_push_button,create_link_annotation,create_uri_annotation,create_file_annotation,create_text_annotation,set_js_action,get_js_action,is_annotatedPatterns (composed multi-element outputs):
create_radar_chart,create_bar_chart,create_pie_chart,create_timeline,create_callout_box,create_kpi_tile,create_comparison_table,create_qr_code_block,create_dot_label,create_numbered_badge,create_code_sampleLayouts (region-shaped):
create_two_column_text,create_text_with_image,create_section_header,create_hero_band,create_numbered_steps,create_image_caption,create_table_of_contents,create_sidebar_layout,create_kpi_row,create_equal_columns,create_card_gridHigh-level:
import_markdown(Markdown → frames)Escape:
run_script(gated)
Architecture
┌─────────────────────────────────────────────────────┐
│ Claude Code │ Anthropic API │ Other MCP clients│
└─────────────────────┬───────────────────────────────┘
│ stdio OR Streamable HTTP
▼
┌──────────────────────────────────┐
│ scribus-mcp (Python 3.11+) │
│ Tools / Resources / Prompts │
│ │ │
│ ┌─────────┴──────────┐ │
│ │ Headless │ │
│ │ ↳ scribus -g -py │ │
│ │ Interactive │ │
│ │ ↳ TCP loopback │ │
│ └────────┬───────────┘ │
└───────────┼──────────────────────┘
▼
┌──────────────────────────────────┐
│ Scribus 1.6.x or 1.7.x │
│ (one-shot OR persistent + .spy) │
└──────────────────────────────────┘License
MIT
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/caewa/scribus-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server