A native LM Studio plugin for reading and managing local Microsoft OneNote. It talks to
the OneNote desktop app directly through the OneNote COM API.
Credits
This plugin is a native reimplementation based on the excellent
local-onenote-mcp by
Peteroooooooo. All of the OneNote COM techniques —
the PowerShell COM bridge, the hierarchy/XML handling, and the content pipeline — come
from that project. Full credit and thanks to Peteroooooooo for the original work.
Additional functionality exists beyond what was available originally in
local-onenote-mcp.
This LM Studio plugin was created by Morxeton in collaboration with Qwen 3.6
via the LM Studio Code
Visual Studio Code extension.
How it works
Every tool drives OneNote through a small, fixed PowerShell program that uses the
OneNote.Application COM object. User data is passed only via JSON temp files (no string
interpolation), and the COM object is released after each call. The only external
requirement beyond OneNote is Windows PowerShell (always present on Windows).
Reads that can be large (page text, raw XML, hierarchies, search results, binary content)
are paginated: text/XML use offset + ; lists use + . Each
response returns / , and full documents are cached so paging does
not re-hit OneNote.
Requirements
Windows 10 / 11 with the Microsoft OneNote desktop app (the traditional Office
app, not the Store/UWP "OneNote for Windows 10").
LM Studio with the lms CLI available ( once if it isn't on PATH).
If you'd like to work on the development of this plugin for yourself or to contribute, execute these commands in the folder where you saved the source files (onenote-manager):
Run non-elevated. Launch LM Studio (and lms dev, if you use it) without
administrator rights, at the same privilege level as OneNote. A privilege mismatch makes
the OneNote COM object fail to start (0x80080005).
Then, in a chat, enable the onenote-manager plugin and ask it to work with OneNote.
Tools
All tools list alphabetically in LM Studio. Reads marked (paged) accept
offset/max_chars (text/XML) or offset/limit (lists).
Tool
Purpose
add_buffer_between_page_outlines
Adjust outline positions so they are separated by a given buffer amount (pixels; configurable adjustment mode)
add_content_to_page_outline
Add content (plain/html/markdown) to an existing outline
add_image_to_page
Add a local image to a page (native size inferred)
add_outline_to_page
Add a new outline block to a page (plain/html/markdown)
add_todo_items_to_page_outline
Add one or more To Do items to an outline (plain/html/markdown text, auto TagDef, per-item indentation)
clone_table_schema
Clone column headers or row labels from a source table into a target table (works across pages)
close_notebook
Close a notebook
create_notebook
Create and open a local notebook
create_page
Create a page (plain / html / markdown)
create_section
Create a section
create_section_group
Create a section group
delete_hierarchy
Delete a notebook / group / section / page (destructive)
delete_page_content
Delete one content object by id (destructive)
Write, structural, and app-control tools can create, modify, delete, and export your
OneNote content. Enable the plugin only in chats where you want the model to have that access.
Highlighted commands
Tables
Every table tool identifies a table the same way: by its objectID (from
get_page_objects or the page XML — either the table's own objectID or the objectID of the
outline element that contains it) or by its 1-based position on the page ("1" =
first table).
Row and column numbers are 1-based (row 1 is the first/top row, which is often a header).
Outlines
OneNote lays out content in floating Outline boxes positioned by x/y. Identify an
outline by its objectID or 1-based index ("1" = first outline).
Cleans up pages where outlines have drifted, overlapped, or are too close together by ensuring
they are separated by a minimum buffer amount. Buffer is specified in pixels.
Example: ensure all outlines on a page have at least 20 pixels of spacing between them:
Sets all outlines on a page to the same target width while preserving their relative vertical spacing. Outlines that vertically overlap with neighbors are shifted horizontally so they don't collide after resizing. If an outline contains tables, each table's column widths are also adjusted so the table fills the new outline width.
target_width_pixels: Desired width for all outlines in pixels (e.g. 400–800 is typical).
target_table_index(default: last column): Which column within each embedded table to adjust when resizing tables inside outlines. Specify a 1-based column index; if the value exceeds a table's actual column count, that table's last column is used instead. Set to 0 to disable automatic table width adjustments entirely.
Example: set all outlines on a page to 600 pixels wide and adjust each embedded table's last column:
These generate XML only (they don't modify a page); insert the result with another
command.
Hyperlinks on existing text — set_hyperlink_on_object
Turns existing plain text into clickable hyperlinks without replacing the text itself.
Finds all occurrences of search_text on a page (or within an optional container object)
and wraps each with <a href="hyperlink_url">...</a>.
Preserves existing inline formatting (bold/italic/etc.) around matched text.
Works inside tables, outlines, cells — anywhere OneNote stores text in <one:T> elements.
Optional container_object_id scopes the search to a specific object (table, cell, outline)
from get_page_objects.
Example: add glossary links to terms on character sheets:
add_todo_items_to_page_outline — hyperlinks in To Do items
Each item's text is interpreted per content_format, so you can embed hyperlinks directly.
For example, use the inline_html from generate_onenote_hyperlinks_xml:
duplicate_page
Copies a page (for example a template) into a new page. By default the copy lands in the
source page's own section; you may pass target_section_identifier and/or new_title.
OneNote assigns fresh object IDs to the copy.
save_page_xml_to_file writes one page's raw XML; the file is named after the page title
(.xml) unless you pass .
save_all_notebook_pages_xml_to_file reads every page via GetPageContent, which loads
them into OneNote. For very large notebooks this can make OneNote sluggish — restart
OneNote afterward if needed.
Configuration
Setting
Default
Meaning
OneNote operation timeout (s)
90
Max time for one COM operation
Markdown conversion timeout (s)
30
Only used when writing Markdown
Default page size (characters)
15000
Text/XML chars per read when max_chars omitted
Default item page size
100
List items per read when limit omitted
Default export directory
(empty)
Where save_*_to_file writes when output_dir omitted
Troubleshooting
Project layout
License
MIT (this plugin). See local-onenote-mcp
for the original project's license and terms.
max_chars
offset
limit
next_offset
has_more
lms bootstrap
OneMore add-in for OneNote(optional) — only required if you write content with
content_format: "markdown". Set ONENOTE_MANAGER_MARKDIG_DLL if OneMore is installed in
a non-standard location.
delete_row_from_table
Delete a table row by index or by first-column text
duplicate_page
Duplicate a page (template → new page); optional target section + title
duplicate_page_outline
Duplicate an Outline (by id/index) to the far bottom or right
find_meta
Find objects by OneNote meta name (paged)
find_references_to_hyperlink
Scan pages for all references to a given hyperlink URL (returns path + object IDs)
generate_onenote_hyperlinks_xml
Generate hyperlink XML(s) to one or more pages (for later insertion)
generate_todo_tag_xml
Generate OneNote "To Do" checkbox tag XML (for later insertion)
get_binary_content
Read binary content (base64) by callback id (paged)
get_hyperlink
Client or web link for an object
get_page
Page text (+ title/objects on first slice) (paged)
Get one Outline's XML by objectID or 1-based index
get_page_table_xml
Get one table's XML by objectID or 1-based index
get_page_text
Page plain text (paged)
get_page_xml
Raw OneNote page XML (paged)
get_parent
Parent object id
get_special_locations
Backup / unfiled / default notebook folder
health_check
Verify the OneNote connection + counts
insert_page_outline_xml
Insert an Outline into a page at the far bottom or right
insert_page_outline_xml_from_file
Read an Outline XML from a file and insert it into a page
insert_row_into_table
Insert a table row (text per column); preserves formatting
list_hierarchy
List hierarchy from a start point (paged)
list_notebooks
List notebooks (paged)
list_pages
List pages in a section (paged)
list_sections
List sections (optionally in one notebook) (paged)
merge_sections
Merge one section into another (destructive)
navigate_to
Focus an object in the OneNote UI
navigate_to_url
Open a onenote: URL
open_hierarchy
Open or create a notebook / group / section by path
publish_object
Export to PDF / Word / XPS / HTML / .one, etc.
replace_entire_page_body
Replace a page's entire body content (destructive)
replace_page_table_xml
Replace one table's XML by objectID or 1-based index
replace_page_text
Find and replace all occurrences of text on a page (preserves formatting by default)
replace_table_cell_text
Replace one table cell's text by row/column
resolve_identifier
Resolve GUID / path / name to one object
save_all_notebook_pages_xml_to_file
Save a whole notebook's page XML to <notebook>.xml
save_page_outline_xml_to_file
Save one Outline's XML to a file
save_page_xml_to_file
Save one page's XML to a file
search_pages
Indexed text search with snippets (paged)
set_filing_location
Filing location for email / clips / printouts
set_all_outlines_width_on_page
Set all outlines on a page to the same width, shifting adjacent outlines' positions to maintain relative spacing (also adjusts embedded tables)
set_hyperlink_on_object
Find all occurrences of text on a page and wrap each with a hyperlink anchor (preserves formatting; optional container scope)
sync_hierarchy
Sync a notebook hierarchy object
update_hierarchy_xml
Advanced: submit raw hierarchy XML
update_page_title
Rename a page
update_page_xml
Advanced: submit raw page XML
get_page_table_xml / replace_page_table_xml — read a table's raw
<one:Table>…</one:Table>, or replace it wholesale. To hand-edit, fetch, modify the
returned XML, and pass it back.
insert_row_into_table — add a row with values (text per column). Existing
formatting is preserved by cloning an existing row's cell styles (choose which with
template_row_index, default = last row). index sets the 1-based position (default:
append).
replace_table_cell_text — replace one cell's text by 1-based row/column; the cell's
formatting is kept.
delete_row_from_table — remove a row by 1-based row_index, or by matching
first_column_text (case-insensitive; wins if both are given).
clone_table_schema — clone column headers (horizontal mode) or row labels
(vertical mode) from a source table into a target table, reordering and adding/deleting
as needed while preserving existing data cells. Works across pages. Useful for keeping
character sheets aligned to a master schema.
get_page_outline_xml — read one outline's raw <one:Outline> XML.
insert_page_outline_xml — insert a <one:Outline> (or loose one:OE content, which
is auto-wrapped) into a page, positioned automatically after all existing outlines at the
far bottom (default) or far right. Fresh object IDs are assigned.
duplicate_page_outline — clone an existing outline and place the copy at the far
bottom or right.
save_page_outline_xml_to_file — extract one outline's raw <one:Outline> XML and write it to a file. The file is named after the page title with _outline_<index>.xml unless you pass file_name. Optional output_dir, overwrite. Defaults its directory to the plugin's Default export directory setting.
insert_page_outline_xml_from_file — read an Outline XML from a local .xml file and insert it into a page, positioned automatically at the far bottom (default) or far right. Fresh object IDs are assigned.
add_outline_to_page — create a new floating outline on the page from content
(plain / html / markdown). (This is the command formerly named append_to_page.)
add_content_to_page_outline — add content (plain / html / markdown) to an outline
identified by objectID or 1-based index. If outline_id is omitted the first outline is
used, and if the page has no outline, one is created automatically.
add_todo_items_to_page_outline — add one or more To Do (checkbox) items to an
outline in a single call. It creates the page's To Do TagDef if the page has none (and
reuses it otherwise). If outline_id is omitted the first outline is used, and if the
page has no outline, one is created. Each item's text is interpreted per
content_format (plain, html, or markdown), so items can carry hyperlinks or inline
formatting — e.g. a onenote: link from generate_onenote_hyperlinks_xml, or markdown
[text](url) (block structure collapses to line breaks). Each entry in items has its own
text, optional completed, and optional indent_level (0 = top level, 1 = indented
under the previous item, …; an item can go at most one level deeper than the one before it,
and deeper values are clamped). By default the batch is appended (continuing the list); pass
position (1-based) to insert the batch between existing items at the first item's
indent level.
Identifies all outlines on the page and adjusts their positions based on adjustment_mode.
buffer_pixels: Minimum spacing between outlines (e.g. 10–50 is typical).
adjustment_mode(default: "only_overlapped"):
"only_overlapped" — least intrusive; only moves outlines that actually overlap with another. When an outline overlaps on both axes, it moves along whichever axis has the smaller overlap (the "easier" direction to separate them). If overlaps are equal, horizontal movement is prioritized.
"all_directions" — ensures all outlines that are close to each other (within buffer distance) are separated by at least the buffer gap, preserving multi-column layouts and relative positions. Only adjusts outlines that would otherwise touch or overlap; does not rearrange the entire page into a single column/row.
"top_to_bottom" — adds vertical spacing between outlines that share horizontal space (same column), pushing lower ones down. Preserves separate columns.
"left_to_right" — adds horizontal spacing between outlines that share vertical space (same row), pushing rightward ones over. Preserves separate rows.
generate_onenote_hyperlinks_xml resolves one or more target pages' links and returns
an array of results, each with inline_html (for add_outline_to_page /
add_content_to_page_outline with content_format: "html") plus one_t_xml /
one_oe_xml for raw insertion (e.g. inside insert_page_outline_xml). Supports
bold/italic/underline/strikethrough per item and web (https link vs onenote: link).
generate_todo_tag_xml returns a To Do checkbox tag: tag_def_xml (a page-level
one:TagDef — add once via update_page_xml if the page has none), tag_xml (the
one:Tag that goes first inside a one:OE), and, if you pass text, a ready one_oe_xml.
file_name
save_all_notebook_pages_xml_to_file reads an entire notebook by name and writes one XML
file (named <notebook>.xml) that mirrors the section-group / section / page structure,
with each page's raw OneNote XML embedded inline. Optional output_dir, page_info,
overwrite.
Both default their directory to the plugin's Default export directory setting, or the
plugin working directory if unset. Files are written on the machine running OneNote.
0x80080005 / focus flips to OneNote then times out — a privilege-level mismatch.
Run LM Studio non-elevated, at the same level as OneNote. Make sure OneNote isn't running
elevated either.
First call is slow / times out — OneNote is starting up. Raise OneNote operation
timeout and retry.
Reads look cut off — lower Default page size (characters); the model pages the
rest via next_offset.
Markdown content fails — install the OneMore add-in, or set
ONENOTE_MANAGER_MARKDIG_DLL to its Markdig.Signed.dll. Plain and HTML content need no
add-in.
OneNote gets sluggish after many reads — reads are cached and page GUIDs skip a
full-store scan, but reading many distinct pages still loads them into OneNote; restart
OneNote periodically for long sessions.
npm install # installs dependencies and creates package-lock.json (required by LM Studio)lms dev # loads the plugin into LM Studio and hot-reloads on changes
set_all_outlines_width_on_page( page_identifier="My Section/My Page", target_width_pixels=600, target_table_index=9999 // uses the last column of each table)
set_hyperlink_on_object( page_identifier="Characters/My Character Sheet", search_text="Dragon", hyperlink_url="onenote:...glossary-dragon-page...", container_object_id="{table-cell-object-id}" // optional: limit to one cell/table)