Joplin for ChatGPT and MCP
joplin-md-sync gives AI assistants controlled access to your own
Joplin knowledge base. Search, read, create, update,
move, tag, and trash notes from a private Custom GPT or any Streamable HTTP MCP
client without moving your notes into another hosted note service.
Run it beside Joplin Desktop, or deploy a complete headless Joplin Terminal and agent API stack on your own Linux host. A separate Markdown sync workflow is available when a coding agent needs reviewable files, three-way diffs, and Git history.
Website · Connect ChatGPT · MCP tools · Deploy headless
What you get
- Joplin inside ChatGPT. A generated OpenAPI contract exposes authenticated Actions for current notes, notebooks, tags, and search to a private Custom GPT.
- Typed MCP tools. One Streamable HTTP endpoint gives compatible clients structured note operations plus attachment upload, download, replacement, and relationship traversal.
- A headless Joplin service. The rootless Linux installer deploys Joplin Terminal, recurrent sync, and the combined MCP/Actions adapter as coordinated systemd user services. Joplin Desktop does not need to remain running.
- Your storage and encryption choices. Use filesystem, Nextcloud, WebDAV, Dropbox, OneDrive, S3, Joplin Server, or Joplin Cloud, with existing Joplin end-to-end encryption where the selected topology supports it.
- Reviewable Markdown when you need it. Pull notebooks to ordinary files, let an agent work with repository context, inspect a three-way diff and dry-run, then push the verified result back to Joplin.
Joplin remains the source of truth. The adapter uses its documented local Data API and never edits the Joplin database, profile, or sync target directly.
Fast path: headless Joplin for ChatGPT
This topology keeps Joplin and the adapter on your own Linux host. Only the authenticated Actions routes need to reach ChatGPT over HTTPS; the Joplin Data API stays on loopback.
1. Install Joplin and the agent service
The host needs Linux with systemd user services, Python 3.13.5 or newer, and Node.js/npm. This interactive example connects the new headless profile to an existing Nextcloud Joplin sync target:
set -o pipefail
curl --proto '=https' --tlsv1.2 --fail --silent --show-error --location \
'https://raw.githubusercontent.com/kogeler/joplin-md-sync/main/scripts/joplin_terminal_service/install_joplin_terminal.py' \
| python3 - \
--sync-target nextcloud \
--sync-location 'https://cloud.example.com/remote.php/dav/files/user/Joplin' \
--sync-username 'user'
The installer asks for secrets through hidden prompts, handles existing Joplin E2EE keys, verifies release checksums, and creates:
joplin-terminal.service Joplin profile, Data API, and recurrent sync
joplin-md-sync.service MCP and ChatGPT Actions on one guarded adapter
It also generates separate protected credentials for Joplin, MCP, and Actions. The full guide covers every sync target, a reviewed-download flow, dry-run, upgrade, rollback, and removal: Joplin API Service.
2. Publish the narrow HTTPS route
Route /api/gpt/v1/* from a trusted HTTPS hostname to the adapter on
127.0.0.1:8765. Do not expose the upstream Joplin Data API. Keep /mcp
private unless a remote MCP client needs it; public MCP requires its own bearer
token and TLS.
The supported boundaries and deployment choices are documented in Self-hosted deployment.
3. Connect a private Custom GPT
From a checkout matching the deployed release, run the setup assistant:
git clone --depth 1 --branch v1.5.6 \
https://github.com/kogeler/joplin-md-sync.git
cd joplin-md-sync
python3 scripts/prepare_chatgpt_action.py
Enter the public hostname and the generated Actions token when prompted. The assistant validates TLS, authentication, and live read operations, then writes the OpenAPI file for the Custom GPT editor. Continue with the exact GPT instructions and acceptance test in ChatGPT Actions setup.
Use Joplin from an MCP client
For a local Joplin Desktop instance, enable Tools > Options > Web Clipper, install the adapter, and start the MCP listener:
pipx install "joplin-md-sync==1.5.6"
export JOPLIN_TOKEN=...
joplin-md-sync mcp serve
Then configure a Streamable HTTP MCP connection:
{
"type": "streamable-http",
"url": "http://127.0.0.1:8765/mcp"
}
The service can start while Joplin is offline and recovers on later calls. Create operations reject an existing notebook, note, tag, or resource identity instead of creating accidental duplicates. Remote MCP deployment requires a separate protected bearer token and TLS. See the complete MCP API reference.
Use Joplin notes as reviewable files
Choose the Markdown workflow when an agent needs repository context, broad transformations, an exact diff before writes, or selected notebooks in Git:
export JOPLIN_TOKEN=...
joplin-md-sync init --root ./notes --mode remote-first
joplin-md-sync pull --root ./notes --json
# Let an agent edit the managed Markdown files, then review the result.
joplin-md-sync diff --root ./notes --three-way --unified
joplin-md-sync push --root ./notes --dry-run --json
joplin-md-sync push --root ./notes --json
Managed note files carry a one-line Joplin identity header. Base snapshots,
conflicts, journals, backups, and downloaded resources stay under the ignored
.joplin-sync/ directory. Start with the copyable
agent notes repository template
or the
Markdown quick start.
Control and failure behavior
- The Joplin Data API remains private on loopback in the headless topology.
- Joplin, MCP, and Actions credentials are distinct and read from protected files or the environment, never accepted as raw token arguments.
- Direct API writes are sent once. An ambiguous timeout is reported instead of being replayed and possibly duplicated.
- Creating an occupied notebook, note, tag, or resource identity returns an
explicit
*_ALREADY_EXISTSerror with the existing ID and recommended update tool. - Note and notebook deletion uses Joplin trash. Resource and tag deletion is explicitly marked destructive because Joplin has no trash endpoint for them.
- Divergent file edits produce a conflict bundle instead of a silent overwrite.
- File deletion propagation is off by default; interrupted mutations are
journaled and recoverable;
diffnever mutates state.
The exact test-backed guarantees live in the contract catalog. Agents operating a Markdown workspace should also follow AGENTS.md.
Installation options
Python installations require CPython 3.13 or 3.14 on Windows or Linux:
python -m pip install "joplin-md-sync==1.5.6"
# or: pipx install "joplin-md-sync==1.5.6"
GitHub Releases also provide a standalone zipapp and native executables that include Python:
| Platform | Asset |
|---|---|
| Linux AMD64 | joplin-md-sync-linux-amd64 |
| Linux ARM64 | joplin-md-sync-linux-arm64 |
| Windows AMD64 | joplin-md-sync-windows-amd64.exe |
| Python zipapp | joplin-md-sync.pyz |
Download them with SHA256SUMS.txt from the
latest release.
Interface guide
| Goal | Interface |
|---|---|
| Work with current Joplin notes in ChatGPT | Authenticated ChatGPT Actions |
| Give an editor or assistant typed note tools | MCP |
| Run without a desktop session | Headless Joplin Terminal plus MCP/Actions |
| Review every broad agent edit before applying it | Markdown workspace |
| Keep selected notebooks in Git | Markdown workspace |
Compare consistency models and deployment choices in Choose an agent interface.
Development
make venv
make venv-dev
make check
make ci
make test-live
make package
make docs-audit
make docs-screenshots
make help
Runtime dependencies are empty by design. Development, test, package, and docs tools use purpose-specific hash-verified locks. See Development and Dependency maintenance.
Releases and license
Git tags use vX.Y.Z. Release assets include wheel, sdist, zipapp, native
executables, and checksums; the same wheel and sdist are published to PyPI
through Trusted Publishing. See the
changelog.
MIT licensed. This is an independent project and is not affiliated with or endorsed by the Joplin project.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file joplin_md_sync-1.5.6.tar.gz.
File metadata
- Download URL: joplin_md_sync-1.5.6.tar.gz
- Upload date:
- Size: 202.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1a195cab87f955a814fab6e26da05cd072948e26827c8f7d8bbd864711bdcdf0
|
|
| MD5 |
64556b90f9405b702a8bdbf2c3272043
|
|
| BLAKE2b-256 |
0e8b193d047d058cd1620aaac3c4abf20039660463e7ebd0eb624ff2a65daeed
|
Provenance
The following attestation bundles were made for joplin_md_sync-1.5.6.tar.gz:
Publisher:
release.yml on kogeler/joplin-md-sync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
joplin_md_sync-1.5.6.tar.gz -
Subject digest:
1a195cab87f955a814fab6e26da05cd072948e26827c8f7d8bbd864711bdcdf0 - Sigstore transparency entry: 2553233472
- Sigstore integration time:
-
Permalink:
kogeler/joplin-md-sync@bbdd656a6070a6bf8b54c2eb3c82ae85167dec60 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/kogeler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bbdd656a6070a6bf8b54c2eb3c82ae85167dec60 -
Trigger Event:
push
-
Statement type:
File details
Details for the file joplin_md_sync-1.5.6-py3-none-any.whl.
File metadata
- Download URL: joplin_md_sync-1.5.6-py3-none-any.whl
- Upload date:
- Size: 99.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8a4696bcfd6d8ea2088ce0c52bd1ba76d87b221461d1ef2309d9806f2d777e8
|
|
| MD5 |
c44e84a106f9a9d0d67c88a6990ef70d
|
|
| BLAKE2b-256 |
8c900e31e2f962f95fa698b4d587930a7e9a634fad2491e4028ddd3a1d18be44
|
Provenance
The following attestation bundles were made for joplin_md_sync-1.5.6-py3-none-any.whl:
Publisher:
release.yml on kogeler/joplin-md-sync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
joplin_md_sync-1.5.6-py3-none-any.whl -
Subject digest:
c8a4696bcfd6d8ea2088ce0c52bd1ba76d87b221461d1ef2309d9806f2d777e8 - Sigstore transparency entry: 2553233499
- Sigstore integration time:
-
Permalink:
kogeler/joplin-md-sync@bbdd656a6070a6bf8b54c2eb3c82ae85167dec60 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/kogeler
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bbdd656a6070a6bf8b54c2eb3c82ae85167dec60 -
Trigger Event:
push
-
Statement type: