Proxmox Notes MCP Server
Reads, creates and edits the Notes (description) field of Proxmox LXC containers and VMs over the Proxmox API, using a per-host API token with VM.Audit and VM.Config.Options. Supports listing guests and their facts (hostname, IP, MAC, DHCP, OS type), previewing a Note change before writing it, writing with a config digest check, and keeping snapshots of the previous Notes for history and rollback.
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., "@Proxmox Notes MCP Serveredit the notes for VM 200 to add its IP address"
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.
Proxmox Notes
A self-hosted service that creates, reads and edits the Notes (description) of Proxmox LXC containers and VMs. It has a web GUI, a REST API and an MCP server, and it replaces the browser-only Proxmox Notes Generator.
Status: 0.9.0, first release. The Notes format, the server (REST, MCP, Docker), reading and writing Notes in Proxmox, the web GUI with its settings page (English and Swedish) and the icon library work, and a ready-made image is published. Icon generation with AI is not built yet.
What it will do
Read the Notes of existing guests on one or more Proxmox hosts, edit them in the web GUI and save them back.
Create Notes for new guests, prefilled from Proxmox (hostname, IP, MAC, DHCP, OS).
Export and import a Note as a loose JSON file. Files saved by the old Notes Generator can be imported.
Embed icons in the Note itself, so no web server is needed for images. A URL to an icon set is still possible.
Make icons when one is missing: from ComfyUI (your own workflow), from a cloud image service (Nano Banana, OpenAI or Grok, to be tested), or from the open dashboard-icons set.
Give an AI assistant the same functions through MCP, with a preview before every write.
Related MCP server: mcp-server-example
Decisions
Decision | Choice | Why |
Where it runs | Its own Docker container, one independent instance per site | Anyone can run their own copy (home, work, other people). No dependency on another service. |
Publishing | Public GitHub repository (MIT licence), image on GitHub Container Registry | Others can use it, and the image lives next to the code. Nothing site-specific may be in the code or the repository; it goes in configuration. |
Icons | An icon library in the service; icons are always embedded as WebP ( | Proxmox shows embedded raster images (tested 2026-10-17), so no web server is needed. SVG cannot be embedded. See docs/NOTES_FORMAT.md. |
Language | Node.js 22+, plain ES modules, Vitest | Same stack as the original generator logic, so it ports directly. |
Layout | One full-width HTML table with the header inside; the old Markdown layout is still read and can be chosen | It fills the Proxmox Notes panel and gets the alternating row colours (tested in Proxmox 2026-10-17). |
Data model | One JSON document per Note | The web GUI, REST, MCP and JSON export all use the same model; Markdown is rendered from it. |
Writes | Preview first; the old Note is saved as a snapshot before every write | A write overwrites the old text in Proxmox. The snapshot makes it reversible. |
Login | None in the service; put it behind a reverse proxy with authentication (for example Authelia) | One less thing to build and maintain; the proxy already does it well. |
Connect a Proxmox host
Each Proxmox host gets its own user and API token. Run this on the Proxmox host as root. It creates a role, a user that cannot log in, and a token:
pveum role add ProxmoxNotesEditor -privs VM.Audit,VM.Config.Options
pveum user add proxmox-notes@pve -comment 'Proxmox Notes service'
pveum acl modify /vms -user proxmox-notes@pve -role ProxmoxNotesEditor
pveum user token add proxmox-notes@pve notes -privsep 1 -comment 'Proxmox Notes service'
pveum acl modify /vms -token 'proxmox-notes@pve!notes' -role ProxmoxNotesEditorpveum user token add shows the token secret once. Save it in a file, for example as a Docker secret. The token has privilege separation (-privsep 1), so it needs its own ACL as well as the user's.
Privilege | Needed for |
| List guests and read their config and Notes |
| Write the Notes ( |
VM.Config.Options is the narrowest privilege Proxmox has for the description, but it also covers other general options (name, onboot, OS type and similar). The service only ever sends description.
Writing
A write takes two steps. notes_prepare_write reads the guest's config and returns the current text, the new text and a single-use confirmation (valid 10 minutes); the web GUI shows both side by side. notes_write_confirmed then:
reads the config again and stops if it changed since the preview (Proxmox's config
digest);saves the current Notes as a snapshot in
/data/snapshots/<host>/<vmid>/;sends only
description, with the digest, so Proxmox itself refuses the write if the config changed in between;reads the Notes back and checks that Proxmox stored exactly what was sent.
Snapshots are never deleted automatically. History in the web GUI (or notes_snapshots and notes_snapshot) lists them; loading one puts it in the editor, and saving writes it back.
Then add the host under Settings → Proxmox hosts in the web GUI: address, token id and token secret. Read the certificate shows the host's certificate fingerprint; compare it with pvenode cert info on the host and pin it. Test connection shows the Proxmox version, how many guests the token sees, and whether it may write Notes. The secret is sent to the server once and never shown again.
The hosts are kept in /data/targets.json, which the settings page writes with mode 600. Secrets typed in the web GUI are stored in that file, so back the volume up as carefully as the tokens themselves. A host can also be written there by hand (see targets.example.json), with the secret in a separate file such as a Docker secret:
Field | Meaning |
| Short name used in tools and URLs, lower case |
|
|
|
|
| Path inside the container to the file with the secret (or |
| SHA-256 fingerprint of the host's certificate. The service then accepts only that certificate. Read it on the host with |
| Without a fingerprint: |
A pinned connection makes a full TLS handshake every time (no session reuse), because a resumed session carries no certificate to check.
The guests' facts come from their config: hostname, IP (static, or the DHCP address of a running LXC), MAC (written in lower case), DHCP and OS type. A VM's address is only known when it uses cloud-init; otherwise it needs the QEMU guest agent, which is not used yet.
The web GUI
Guest list: pick a Proxmox host; every guest shows whether its Notes are in the Notes format, other text, or empty.
Editor: heading icon and title, icon image, description, notes and the sections with their rows (add, move, remove). A guest with no Notes gets a new Note filled in from the template and from Proxmox. Notes that do not follow the format open as raw text, so nothing is lost.
Live preview, rendered by the same code as the server, cleaned the way current Proxmox versions clean Notes (inline styles removed, only safe tags, attributes and URLs) and styled with Proxmox's own Notes CSS in a panel of the same fixed width. A bar shows the size against the 8192-character limit, and a badge shows when the Note differs from what Proxmox has.
Layout: full-width table (default) or the old Markdown layout. A Note stored in the other layout is converted when it is saved, and the editor says so.
Icons: Choose icon opens the icon library as a searchable grid, with a second tab for dashboard-icons. An uploaded image is added to the library first. The icon is always embedded; if the Note has too little room left, it is encoded again at a lower quality.
Icon library (Settings → Icons): a grid of every icon with search, rename and remove; upload several files or drop them on the page; add icons from dashboard-icons by searching for them; import a whole web icon set once (for example the old Notes Generator's, from its
select.json), after which that web server is no longer needed. An uploaded file is named from its file name without the size (sonarr01-512x512.pngbecomes "Sonarr 01", taking the name from the icon-set list when the key is in it), and with Replace icons with the same name an upload updates an icon instead of adding a copy, so a whole folder can be uploaded again, for example in a larger size. Heading icons are chips, added from a searchable list of all 786 Font Awesome 4 icons.From Proxmox: one button updates IP, MAC, DHCP and OS from the guest's config. When the IP changes, service links that pointed at the old IP move along. An exact OS release in the Note ("Debian 13") is kept when Proxmox only knows the family ("Debian").
Import and export: export a Note as JSON; import JSON from this tool or from the old Notes Generator, or Markdown. Copy Markdown puts the text on the clipboard for the Proxmox Notes field.
Save to Proxmox: a dialog shows the Notes now in Proxmox and the Notes that will be written, side by side, before anything is written. History lists the snapshots kept before each save.
Settings: Proxmox hosts (add, edit, remove, read and pin the certificate, test the connection); Notes defaults (layout, heading icon, the template for a new Note with default values such as the owner, OS names); icons (icon-set address and size, image list, heading icons, import of the old
select.json); appearance (theme and language for this browser, and the defaults for every browser).Languages: English and Swedish. A missing Swedish text falls back to English; a test checks that both languages have every text the page uses.
Themes: dark (default), light, or follow the system.
The browser loads the Notes format modules from /format/, so the preview matches what the server renders. Font Awesome 4.7 is bundled (font: SIL OFL 1.1, CSS: MIT; see src/web/vendor/font-awesome/LICENSE.txt), because Proxmox uses that version for the icons in Notes.
Run it
The image is ghcr.io/snille/proxmox-notes-mcp, built for linux/amd64 and linux/arm64 by GitHub Actions for every release. Tags: latest, the version (0.9.0) and the minor version (0.9).
As a Portainer stack
Stacks → Add stack, name it for example
proxmox-notes.Web editor: paste compose.yaml. (Or Repository:
https://github.com/Snille/Proxmox-Notes-MCP, compose pathcompose.yaml.)Change the port,
ALLOWED_HOSTSandMCP_TOKENif you need to, then Deploy the stack.Open
http://<host>:8080/and add a Proxmox host under Settings → Proxmox hosts (see Connect a Proxmox host).
To update, open the stack, choose Update the stack and turn on Re-pull image. The data stays in the volume.
With Docker Compose
docker compose up -dThen open http://<host>:8080/.
The container keeps its data (options, hosts with their token secrets, snapshots and the icon library) in the volume mounted at /data. Back the volume up, and protect the backup as carefully as the tokens.
To build the image from the source instead, use compose.dev.yaml, which serves on port 8085. It mounts DEV_DATA_DIR (default private/dev-data) at /data and DEV_SECRETS_DIR (default private/secrets) read-only at /run/secrets/proxmox-notes:
docker compose -f compose.dev.yaml up -d --buildThe host it runs on must reach the Proxmox API (port 8006) of every Proxmox host it manages.
Settings
All settings are environment variables:
Variable | Default | Meaning |
|
| Port inside the container |
|
| Where options, targets, snapshots and icons are kept |
|
| The Proxmox hosts and their tokens |
| empty (any) | Comma-separated host names the service answers to, for example |
| empty (none) | When set, |
The service has no login of its own. Never expose it without a reverse proxy that has authentication. Requests from a web page on another site are refused (Origin check), so a logged-in browser cannot be used against it by another page.
Options
The choices in the forms (layout, heading icons, icon-set images, OS names, the template for a new Note, and the default theme and language) are kept in /data/options.json and edited on the settings page. On the first start, a select.json from the old Notes Generator in /data is converted automatically; the settings page can also import one. Read and save them with GET and PUT /api/options; a save is checked against a schema.
The host settings (/api/settings/...) are offered in the web GUI and REST only, not over MCP, so token secrets never pass through an assistant.
Interfaces
Path | What |
| Web GUI |
| The icon library: |
| Searches the names in dashboard-icons; |
| An icon from the configured web icon set, for the import. Only URLs built from that icon set are fetched. |
| REST: |
|
|
| MCP over Streamable HTTP |
| Health check |
MCP over stdio, for an assistant on the same machine: node src/stdio.mjs.
Tools: notes_status, notes_options, notes_icons, notes_hosts, notes_guests, notes_read, notes_prefill, notes_new, notes_render, notes_parse, notes_import_legacy, notes_prepare_write, notes_write_confirmed, notes_snapshots, notes_snapshot. Only notes_write_confirmed writes to Proxmox, and only with a confirmation from notes_prepare_write.
Development
npm install
npm run checknpm run check runs all tests. The tests include a round-trip check: every Note in reference/examples/ is parsed and rendered again, and the result must be identical. GitHub Actions runs them on every push and pull request.
To release a version:
Set the version in
package.json(the only place it is kept) and runnpm install --package-lock-only.Add a section
## <version> - <date>at the top of HISTORY.md.Commit, tag
v<version>and push withgit push --follow-tags.
The workflow checks that the tag matches package.json, runs the tests, builds and pushes the image, and creates the GitHub release with the text from HISTORY.md.
Layout
Path | Content |
| The Notes document model: |
| HTTP server, MCP server and the tools both use |
| Instance options ( |
| Targets ( |
| The icon library ( |
| The web GUI: |
| Vitest tests |
| Tests on every push; image and GitHub release on a version tag |
| Eleven real Notes with addresses and names replaced, used as golden test files |
| The old generator's options file (icons, image keys, OS names) |
| A Note with an embedded icon, used for the Proxmox display test |
| The format, the Proxmox display rules and the size budget |
| Local only, ignored by git: the original hand-over and the real Notes the fixtures were made from |
Plan
✅ Notes format: document model, render, parse, round-trip tests.
✅ Server: Docker image, configuration, REST API, MCP (HTTP and stdio).
✅ Proxmox: list guests on several hosts, read Notes, prefill from facts, write with preview, digest check and snapshot.
✅ Web GUI: guest list, editor with live preview, icons, JSON export and import, save to Proxmox, history.
✅ Settings page in the web GUI: Proxmox hosts, Notes defaults and template, icons, theme and language. The image generator settings come with icon generation.
✅ Icons: icon library, upload, dashboard-icons, import of a web icon set, icon picker in the editor.
✅ Release: MIT licence, image on GitHub Container Registry built by GitHub Actions, ready-made Portainer stack.
Icon generation: ComfyUI first, then the cloud services one at a time.
Open question: the project name (this could become the next major version of Snille/Proxmox-Notes).
History: HISTORY.md.
Licence
MIT, see LICENSE. The bundled Font Awesome 4.7 has its own licence (font: SIL OFL 1.1, CSS: MIT).
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP-native notes and memory for ChatGPT, Claude, and other AI tools.
- TaprootOAuthcom.taproothq
Persistent memory layer for AI tools. Save and recall notes across Claude and other MCP clients.
Shared Markdown notes for MCP-compatible AI tools.
Save notes in seconds. Your AI can then search, read, write and tag them over MCP.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to interact with a Markdown-based knowledge base with backlinks, tags, and full-text search, supporting note creation, reading, updating, renaming, and deletion through MCP tools.25 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to manage in-memory notes by listing, fetching, and creating notes through MCP tools over stdio.66 npmMIT
- AlicenseNot gradedqualityCmaintenanceEnables MCP-compatible clients to create, list, search, and delete notes, read all notes as markdown, and use prompts to summarize or clean up notes.MIT
- AlicenseNot gradedqualityBmaintenanceEnables managing plain-text notes on disk through MCP resources, tools, and prompts, so natural-language requests can create, read, search, delete, and summarize notes via an interactive client.MIT