mcp-origin-thesis
Provides tools for formatting OriginLab Origin projects into publication-ready figures, including per-layer grid layouts, unified fonts and sizes, measured axis-title placement, overlap resolution, panel labels, and 600-dpi export with corrected dpi metadata. Can format entire .opju projects, composite plates, individual graphs, export figures, and verify styles.
Click on "Deploy 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., "@mcp-origin-thesisformat my Origin project to thesis style, keep legend positions"
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.
dsh-origin-thesis
Format OriginLab Origin figures to a fixed house style from inside DeepSeek Harness.
One command turns a whole .opju project into publication-ready figures: per-layer
grid layout, unified fonts and sizes, render-measured axis-title placement,
overlap resolution, panel labels, and 600-dpi export with corrected dpi metadata.
Built for a PhD-thesis workflow where dozens of Origin graphs must end up looking identical, and rebuilt as a DSH bundle so the formatting runs from chat instead of a command line.
you: 把这份项目按论文格式重排,保留我手摆的图例
→ thesis_format_project(project="...\project.opju",
profile="thesis", keep_legend_pos=true)
→ 13 figures reformatted, <name>_thesis.opju + <name>_thesis_figures/*.pngRequirements
OS | Windows only. Origin's automation interface is Windows COM; there is no macOS/Linux path. |
Origin | A locally installed, licensed copy of Origin / OriginPro 2018 or newer. Tested on OriginPro 2026b and Origin 2021. Not bundled with this plugin — you must own an Origin licence. |
Python | An interpreter with |
DSH | DeepSeek Harness with the |
:: create the interpreter this plugin will drive Origin with
conda create -n origin python=3.9 -y
conda activate origin
pip install originpro numpy PillowThe plugin itself needs no
mcppackage:thesis_mcp_server.pyimplements the MCP stdio JSON-RPC loop directly, so it runs on Python 3.9 or 3.10 alike.
Why there is a .cmd launcher
cordis.patch.yml names start-thesis-mcp.cmd rather than
python.exe. That is deliberate, and it is what makes the package location-independent.
DSH evaluates the !!js expressions in its patch files in a sandbox where
__dirname, __filename and require do not exist — only process is reliably
available. Measured, not assumed:
mcp-origin-thesis (@deepseek-ai/dsh-mcp-client): ReferenceError: __dirname is not definedSo the patch cannot compute its own package directory in JavaScript, and any
!!js require('node:path').join(__dirname, …) construction fails at startup. A Windows
batch file, by contrast, gets its own directory from the built-in %~dp0 expansion with
no JavaScript involved. The launcher therefore:
locates
thesis_mcp_server.pynext to itself via%~dp0;picks an interpreter —
DSH_THESIS_PYTHON, else a conda env namedoriginin the usual places, elsepythononPATH;forwards all arguments (
-u -X utf8plus anything DSH passes) and runs the server.
The patch only has to name the launcher, so the package can live anywhere — the
default ~/dsh-vendor/dsh-origin-thesis is just a convention. If you install it
elsewhere, edit the two args/cwd values in cordis.patch.yml accordingly.
Related MCP server: OriginLab MCP Server
Install
1. Get the files
git clone https://github.com/xinchun2018/dsh-origin-thesis.git "%USERPROFILE%\dsh-vendor\dsh-origin-thesis"Everything needed at runtime — the server, the style profiles, and the plotting scripts — lives in that one directory.
2. Wire it into a DSH profile
Clone into the location DSH expects (or point the profile at wherever you put it), then link it into the profile the way any out-of-tree bundle is linked:
cd "%USERPROFILE%\.dsh\profiles\web"
pnpm add link:%USERPROFILE%\dsh-vendor\dsh-origin-thesisand make sure the bundle is listed in that profile's package.json:
"dsh": {
"profile": {
"bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app",
"dsh-origin-thesis"]
}
}The bundle's own cordis.patch.yml then registers the loader entry
(mcp-origin-thesis → @deepseek-ai/dsh-mcp-client, stdio) and resolves both the
server path and the interpreter automatically — no absolute paths to edit.
3. Restart DSH
The tools appear as mcp__origin_thesis__*. Check the wiring with:
thesis_batch_dir_info()It reports which interpreter was used, whether originpro imports, and which
copy of the plotting scripts is active.
Configuration
Everything is resolved at startup; nothing is hard-coded to a machine.
Environment variable | Default | Meaning |
| auto-detect | Interpreter that drives Origin. Detection order: this variable → |
| the package directory | Use your own |
|
| Use your own style profiles file. |
Style profiles
styles.json is the single source of truth for the look of the figures. Edit the
JSON to change the format — no Python changes needed. Three profiles ship:
Profile | For | Page | Tick / axis-title / legend | Line |
| Thesis figures, re-laid-out by layer count | 1 layer 9.8594×7.3999 cm (4:3); 2 layers 16×7.4; 3–4 16×13.2; 6 16×10.4; 8 16×8.6 | 9 / 10.5 bold / 9 pt | 1.0 pt |
| Hand-assembled multi-panel plates | 17.5 cm wide, height from the original aspect (or re-gridded) | 6.5 / 7.5 / 6.5 pt | 0.75 pt |
| Journal single figures (keeps the author's hand-placed legends) | same as | same as | same as |
manuscript is inherits: thesis + one override (move_legend: false), so editing
thesis also affects it. Change a value at runtime with thesis_style_set
(dry-run first, then dry_run=false; a .bak is written automatically).
Tools
Offline (no Origin needed, instant):
Tool | Purpose |
| List profiles and their key values |
| Show a full profile (with inheritance resolved) |
| Edit |
| Report resolved interpreter / scripts / styles (troubleshooting) |
Formatting and export:
Tool | Purpose |
| Format every graph in a project by layer count; saves |
| Format a hand-assembled multi-panel plate; |
| Point it at many projects / a directory; returns a per-project report |
| Export only, no restyling (multiple formats, unified width, margin cropping) |
| Read-only check of fonts / sizes / defects |
Atomic, for free composition:
Tool | Purpose |
| Format one named graph — the rest of the project is untouched |
| Apply style/layout only: no save, no export |
| Export from the already-open session (no file reopen) |
These three are what let you interleave with fine-grained editing. The plugin shares the Origin session with any other Origin tooling, so this works:
① thesis_apply_style_only(project=..., graph="Graph20", keep_open=true) # ~21 s
② origin_edit_plot / origin_edit_axis / origin_edit_legend ... # ms
③ thesis_export_open(graph="Graph20", out_path="D:\fig\Graph20.png") # ~0.3 sUse keep_open=true for chaining: op.exit() closes the project, and the next step
would then fail to find the graph.
The original files are never modified — formatting works on a copy in %TEMP%.
Why the exported figures are physically sized correctly
Origin writes 300 dpi into image headers no matter how many pixels you asked for,
so a 600-dpi figure dropped into Word is placed at twice its intended size. This
plugin patches the header after export (PNG pHYs, TIFF tags 282/283, JPEG JFIF,
BMP PelsPerMeter) without re-encoding, so the declared physical size equals the page
size set in Origin. Oversized output is also downscaled to the page width you meant
(2102 px for 8.9 cm at 600 dpi).
How the formatting works (and what it deliberately preserves)
The heavy lifting lives in the vendored scripts, unchanged:
Layout by structure — layers are classified (
main/inset/linked_inset/ overlay /linked_ext), then either gridded, stacked, or page-scaled. A vertical stack of spectra (XPS peak fits, MS comparisons) counts as one panel.Axis titles are measured, not guessed —
fit_axis_titleswrites a title, renders, measures the ink with Pillow, derives the anchor offset for that graph, and corrects over several rounds. Fixed offsets do not work: two graphs with the same frame and font size rendered their titles 0.28 cm apart.Overlaps are resolved vertically only —
clamp_textspulls annotations back inside the frame, thenseparate_textspushes them apart vertically. Horizontal nudging would move a label off the peak it points at.Inset layers only ever shrink — tick label sizes inside a millimetre-scale inset are left alone; enlarging them fuses
7.2and7.0into7.27.0.Never rewritten: legend strings (their own
|-separated syntax with per-entry escapes — wrapping the whole string bolds entry 1 and appends a stray)),\g()Symbol-font regions (stripping the inner\f:wrapper turnsCinto Chi), data values, axis ranges, curve colours, and inserted image content.
README-origin-batch-style.md is the original engineers' log — several hundred lines
of measured failure modes (LabTalk silently ignoring writes, linked-layer stale
frames, expgraph's undocumented argument traps). Read it before changing the scripts.
Limitations
Windows + a licensed Origin installation are hard requirements; without Origin the tools have nothing to drive.
One graph takes ~20–30 s. Each call starts the Origin COM session and runs the render-measure-correct loop. That step cannot be made fast; the payoff is that everything after it (
origin_edit_*,thesis_export_open) is sub-second.Origin is an exclusive resource. Formatting uses the single-instance COM server, so do not edit figures by hand in Origin while a batch is running.
Python ≤ 3.9 for the interpreter until OriginLab ships newer wheels.
PER_GRAPH_TWEAKSships empty. Per-figure exceptions are inherently project-specific (which label collided with which curve, how many millimetres a text box had to move), so the table is documented but not populated. Add your own entries in the shape shown next to it informat_thesis_figures.py— the outer key is the project file stem, becauseGraph8means different things in different projects. It is applied automatically when a project matches, andno_tweaks=trueskips it.
Relationship to the upstream origin-batch-style toolkit
The three vendored scripts come from a private, actively used plotting toolkit of the
same author (origin-batch-style/, driven from the command line). This repository ships
a curated variant of them:
upstream (private) | this repository | |
Per-figure exception table ( | populated for specific manuscripts | empty, scheme documented instead |
Comments / docstrings | name the real samples, figures and project files | genericized (technical insights kept verbatim) |
Usage examples | machine-specific interpreter paths |
|
Everything else — layout logic, anchor calibration, overlap resolution, export and dpi correction | identical | identical |
If you maintain your own copy, it will not automatically receive fixes made here, and vice versa. Two ways to keep them apart cleanly:
Keep your private toolkit as the source of truth for your figures and point
DSH_THESIS_BATCH_DIRat it. This repository's copy is then only the fallback for a fresh install — no sync problem, because you never use it.Or track this repository and re-apply your per-figure tweaks on top, using
sync_to_vendor.ps1to push the result into the DSH runtime directory.
The regression used when this variant was cut: reformat a 13-graph project (0 errors,
0 verify issues) and re-open the saved product to verify it read-only (clean: true).
Repository layout
thesis_mcp_server.py MCP server (stdlib only; no `mcp` package needed)
start-thesis-mcp.cmd launcher: self-locates via %~dp0, picks the interpreter
styles.json style profiles — the file you edit to change the look
cordis.patch.yml DSH loader entry (names the launcher; no toolchain paths)
index.js bundle entry artifact (no-op apply)
format_thesis_figures.py ┐
format_composite.py ├── vendored plotting scripts (replaceable via
export_figures.py ┘ DSH_THESIS_BATCH_DIR)
README-thesis.md internal reference: every tool, parameter and pitfall
README-origin-batch-style.md the original scripts' engineering log
sync_to_vendor.ps1 copy this repo to the DSH runtime directory
THIRD-PARTY-NOTICES.md Origin / originpro / dependency licensing and runtime needs
CONTRIBUTING.md how to run the smoke test, what needs discussion first
tests/smoke.py installation self-check (14 assertions, no DSH needed)Licence
MIT — see LICENSE. Origin itself is commercial software licensed separately;
originpro / OriginExt are BSD-licensed by OriginLab and installed by you, not
redistributed here. Full details, including the optional runtime dependencies of the
vendored scripts, are in THIRD-PARTY-NOTICES.md.
This server cannot be deployed
Maintenance
Related MCP Connectors
Persistent AI LaTeX workspace: edit and compile multi-file projects, export publication-ready PDFs.
Edit your Overleaf LaTeX projects from Claude and ChatGPT; every change is a real Git commit.
Use your own Word templates to convert Markdown → DOCX/PDF/HTML from any MCP-compatible AI.
Give your AI agents a design superpower. Generate, edit, and publish publication-grade decks, reports, landing pages, resumes, and marketing visuals directly within your agent workflow. Delivering frontier-level design quality at 3× the speed and 53× lower cost -from conversational prompt to live link or vector PDF in minutes.
Related MCP Servers
- AlicenseAqualityAmaintenanceEnables AI assistants to control Origin/OriginPro on Windows, including data import, worksheet editing, graphing, analysis, and figure export.25142 PyPI109MIT
- AlicenseNot gradedqualityCmaintenanceBridge between AI assistants and OriginLab, enabling data import, plotting, analysis, and export through natural language commands.80MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to control Origin 2025b for scientific plotting via natural language, with support for data import, 52+ chart types, curve fitting, statistics, and export.8MIT
- AlicenseAqualityDmaintenanceEnables AI assistants to control OriginLab Origin Pro via COM automation for data analysis, graphing, and styling, with real-time GUI updates.5693 PyPI41MIT