orgwarrior-mcp
Your org agenda for Claude. It's an MCP server on top of orgwarrior. Ask "what's on today?", "push the dentist to Friday" or "what did I get done this week?", and your running Emacs does the org work, the same as it would from the agenda.
- Your agenda, the way org builds it. Your views, TODO keywords, tags,
custom agenda commands, refile targets, logging and repeaters all work
as they do in Emacs. Claude reads what
orgwarriorprints, IDs included. - Change anything about a task. States (with a note where org asks for one), dates, tags, priority, effort, properties, notes and history, its text and checklists. Claude can also rename, move, refile and archive tasks, and add tasks and events. Adds go in as separate fields, so nothing in a title gets mistaken for a date or a tag.
- Look back. Ask what you finished in any span, how much time you clocked, or search everything you've ever archived.
- Safe by design. Deleting asks you every time, and a task's text is never treated as instructions.
- Works where Claude has no shell: claude.ai on the web, the desktop app and your phone, through your own server. Any client that speaks MCP works too.
Which one do you need?
If Claude can run commands on the machine with your Emacs (Claude
Code there, or over SSH), use the
orgwarrior command and its
skill (orgwarrior help --skill, see
With Claude).
It has every command, and there's no server to run or expose to the
network.
orgwarrior-mcp is for when it can't: claude.ai in a browser, the desktop and phone apps, or an MCP client on another machine. They reach your Emacs through this server and nothing else.
How it fits
Org is the task manager. orgwarrior-mcp is a friendlier way in, alongside orgwarrior's command line and orgwarrior-web's page:
orgwarrior orgwarrior-web orgwarrior-mcp
(a terminal) (a browser) (Claude, any MCP client)
\ | /
orgwarrior.el, loaded into your running Emacs
|
Org mode ──▶ your .org files
Claude calls a tool, the server passes it to Emacs, and Emacs does the work. The server never reads or writes your org files itself.
Tools
| tool | what it does |
|---|---|
agenda |
shows any view orgwarrior can: today, week, fri, all, next +@phone, a search, your own [views], a file's whole outline, clocked week. With archive, it includes archived tasks. |
views |
lists your named views (your page's tabs and your [views]), so "my inbox tab" means what it means to you |
done |
lists what you finished in a span (week, lastweek, month, a date, a range), day by day, archived tasks included |
show |
shows a task in full: where it is, its dates, text, notes and the headings under it |
details, edit_details |
reads a task's text as it is in the file, and changes it by replacing a part or adding to the end. A change is refused if the text changed in the meantime. |
check |
ticks or unticks a checkbox and updates its [1/3] |
add_task, add_event |
adds where your [add] says, or wherever you ask. A task added as already done (an import) keeps its done date. |
places, files |
lists where an add can go (your [add] place first), and your agenda files |
set_state, schedule, deadline, set_when (an event's date), tag, set_priority, set_effort, set_property, add_note, rename |
each changes one field, the way org does |
history, edit_note, remove_note |
lists a task's log (notes and state changes) by number, and changes or deletes an entry. remove_note is marked destructive. |
move, reorder |
moves a task up, down, in or out with its subtree, like org's M-arrows, or puts a heading's children in a new order |
clock, clock_in, clock_out |
shows what's running, and clocks in or out now or at a time you forgot |
log_time |
logs time already spent ("an hour on it yesterday at 2") without touching a running clock |
clocks, edit_clock, remove_clock |
lists a task's clocks, and fixes or deletes one. remove_clock is marked destructive. |
refile_targets, refile |
lists your org-refile-targets, and refiles to one, or into a new heading made there (for a new project) |
archive, kill |
both marked destructive. kill first lists what would be deleted, and only deletes on a second, confirmed call. |
The server's instructions include orgwarrior's own help for views and
dates, so Claude knows the syntax from the start. They also say where your
config puts new tasks (an inbox heading, a file's top level, or wherever
[add] points). Before adding more than a few tasks at once, Claude asks
where they should go.
Install
Install it on the machine with your Emacs. You'll need Emacs 29 or later
running as a daemon (emacs --daemon, or your system's Emacs service), and
Python 3.11 or later. One install gives you all three commands:
orgwarrior-mcp, orgwarrior, and orgwarrior-web (its token command
signs Claude in).
uv tool install orgwarrior-mcp # or: pipx install orgwarrior-mcp
orgwarrior --check then checks that Emacs, your agenda files and your
config are ready, and says what to fix.
To update, run uv tool upgrade orgwarrior-mcp (or pipx upgrade orgwarrior-mcp), which updates the other two as well. If you installed
orgwarrior or orgwarrior-web on its own first with pipx or uv, uninstall
it before installing this, since this one brings its own copy. It also
works alongside the Homebrew or AUR packages, but Emacs then reloads
orgwarrior's code whenever you switch between them.
Quick start: claude.ai
claude.ai, its desktop app and the phone apps connect to your server from
Anthropic's cloud. That means your server needs an address the internet
can reach, over HTTPS, so you'll need a reverse proxy with a real
certificate in front of orgwarrior-mcp. The server itself stays on
127.0.0.1.
-
Run it (to keep it running, see below):
orgwarrior-mcp # http://127.0.0.1:22548/mcp
-
Point your web server's
/mcpat it. With Caddy, which gets the certificate for you:agenda.example.org { reverse_proxy /mcp* 127.0.0.1:22548 }With Apache, put this in the site's
<VirtualHost *:443>, before anyProxyPass /(the first match wins):ProxyPass /mcp http://127.0.0.1:22548/mcp ProxyPassReverse /mcp http://127.0.0.1:22548/mcp
-
Make a token for Claude:
orgwarrior-web token add claude --mcp --url https://agenda.example.org
It prints the URL and the header to give your client. The token is shown only this once, and
token revoke claudecuts it off. Tokens live in orgwarrior-web's tokens file, sotoken listshows Claude's next to your devices'. An--mcptoken only opens this server, not the web page. -
Add the connector. In claude.ai, go to Settings → Connectors → Add custom connector. The URL is
https://agenda.example.org/mcp. For authentication choose No sign-in and leave the OAuth settings alone, then add a header namedAuthorizationwith the valueBearer TOKEN. It works in every conversation from then on, on the web, the desktop app and the phone.
Then, in the connector's tool settings, keep kill on needs
approval, never "always allow". Your tap is the check that nothing in a
task's text talked Claude into deleting it.
If you also use Claude Code: a claude.ai connector shows up in Claude
Code too, when it's signed in to the same account, next to the
orgwarrior command if you use that. To keep Claude Code on the command
line, deny the connector in ~/.claude/settings.json. Use the name you
gave the connector, with spaces as underscores:
{"permissions": {"deny": ["mcp__claude_ai_orgwarrior"]}}
Other clients
Anything that speaks MCP can connect in one of two ways:
-
On the machine with Emacs, without a shell (a desktop app's chat, for example): the client runs
orgwarrior-mcp --stdioitself and talks to it over a pipe. Nothing goes over the network and no token is needed. Desktop apps usually start it with a bare environment, so give the command's full path, and see Troubleshooting if it can't find Emacs. For example, in Claude Desktop'sclaude_desktop_config.json:{"mcpServers": {"orgwarrior": { "command": "/home/you/.local/bin/orgwarrior-mcp", "args": ["--stdio"]}}}
-
Over the network: Streamable HTTP at
https://agenda.example.org/mcpwith the headerAuthorization: Bearer TOKEN. A client that only takes a URL can carry the token in it:…/mcp?key=TOKEN. Keep that URL out of your web server's log. In Apache, log%Uinstead of%r. Caddy logs nothing unless you turn logging on.
Claude Code can use either, if you'd rather it used MCP than the command:
claude mcp add --scope user orgwarrior -- orgwarrior-mcp --stdio # on the machine with Emacs
claude mcp add --transport http orgwarrior https://agenda.example.org/mcp \
--header "Authorization: Bearer TOKEN" # from another machine
Security
- A token is the whole sign-in. Make one per client, so you can revoke
each one separately. Only a hash of it is stored. Requests are logged
with the token's name and the tool (
claude add_task), never the token or what was sent. - It won't listen on anything but 127.0.0.1 without a token. On 127.0.0.1 it's open until you create the first token, so you can try it out. While it's open, it only answers requests addressed to this machine by name, so a web page elsewhere can't reach it by pointing a domain at 127.0.0.1.
- Deleting needs you.
killfirst lists what would be deleted, children included, and only deletes on a second call. Your client asks you before each call. For a task you won't do, a done state keeps it, andarchiveputs it away where you can still find it (agendawitharchive). - Text in your tasks is content, not instructions. Anyone who can add to your list (with an orgwarrior-web add token) can write anything in a task's text. Claude is told to treat it as content, and deleting needs your approval no matter what the text says.
- Archived tasks are read only. Their ID marks them as archived, and every tool that changes things refuses them.
Running it as a service
orgwarrior-mcp service prints a service that runs orgwarrior-mcp with the
options you give it: a systemd user unit on Linux, or a launch agent on a
Mac. It fills in the command's full path and a PATH that finds
emacsclient, with comments at the top saying where to save it and how to
start it. On Linux:
mkdir -p ~/.config/systemd/user
orgwarrior-mcp service > ~/.config/systemd/user/orgwarrior-mcp.service
systemctl --user daemon-reload && systemctl --user enable --now orgwarrior-mcp
loginctl enable-linger "$USER" # keeps it (and Emacs) running when you're logged out
journalctl --user -u orgwarrior-mcp # who called which tool, and when
After an upgrade, run systemctl --user restart orgwarrior-mcp. Tokens
and connectors stay as they are, and a client sees new tools in its next
conversation or session.
| option | what it does |
|---|---|
--stdio |
speaks MCP on stdin and stdout, for a client that starts the command itself |
--host |
the address to listen on (default 127.0.0.1) |
--port |
the port (default 22548) |
-s, --socket |
Emacs's server socket, as a name or a full path. Otherwise it uses orgwarrior's config.toml, or the default. |
service [OPTION…] |
prints a service that runs it with these options (see above) |
It reads orgwarrior's config.toml (in ~/.config/orgwarrior/) the same
way the command does, for where add_task writes, your [views], and
the socket.
Troubleshooting
orgwarrior --check, run as the same user as the server, checks Emacs,
your init file, your agenda files and your config, and prints the socket's
full path.
- "no Emacs daemon is running", while
orgwarriorworks in a terminal: the client startedorgwarrior-mcpwith a bare environment, missingXDG_RUNTIME_DIR, which is where emacsclient looks for the socket. Give it the socket's full path, likeorgwarrior-mcp --stdio -s /run/user/1000/emacs/server. Emacs can tell you its own withM-: (expand-file-name server-name server-socket-dir). On macOS, also give the client aPATHthat includes Homebrew'semacsclient(/opt/homebrew/bin). - 401 from your server: the token is missing, wrong, or revoked.
curl -i https://agenda.example.org/mcpshould answer 401. If you get a 404 or the wrong page, the proxy isn't sending/mcphere. Put its rule before the one for/. - "no token yet, and … isn't loopback": create a token first
(
orgwarrior-web token add claude --mcp), or listen on 127.0.0.1 behind the proxy. - claude.ai can't connect: it has to reach the URL from the internet, with a certificate browsers trust. A certificate from your own CA isn't enough.
- New tools don't show up: start a new conversation (claude.ai) or
session (Claude Code, or run
/mcpto reconnect). - Anything org refuses, like an unknown ID, a date it can't read, a file with unsaved changes in Emacs, or a read-only file such as an exported calendar, goes back to Claude as orgwarrior's own error message, so it can correct itself.
Contributing
I read every issue and fix what I can, bugs first. Pull requests are
welcome. For anything big, open an issue first so we can talk it through.
uv run pytest runs every test (Development).
Development
git clone https://github.com/aleksozolins/orgwarrior
git clone https://github.com/aleksozolins/orgwarrior-web
git clone https://github.com/aleksozolins/orgwarrior-mcp
cd orgwarrior-mcp
uv tool install --editable . # orgwarrior-mcp runs this checkout, the other two run theirs
uv run pytest # every tool against a throwaway Emacs, over stdio and HTTP
Keep the three checkouts side by side. For development, orgwarrior-mcp
uses orgwarrior and orgwarrior-web from ../ ([tool.uv.sources]).
Installed, it uses the releases from PyPI. The tests run each tool against
a throwaway emacs -Q daemon on orgwarrior's test files, so your own
Emacs, config and org files are never touched.
Claude (Anthropic's AI) was used in developing orgwarrior-mcp. I review all the code, and every behavior is covered by tests.
License
GPL-3.0-or-later, the same as Emacs and Org.
Metadata
Release files for orgwarrior-mcp 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| orgwarrior_mcp-0.3.0.tar.gz | 89.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| orgwarrior_mcp-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 121.4 kB
Release files / orgwarrior_mcp-0.3.0.tar.gz
| Download URL | orgwarrior_mcp-0.3.0.tar.gz |
|---|---|
| Size | 89.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
36c153d5e8d0766a18f4d352164c740e705349f6dde0a77255a56f6fb2cce7a7
|
|
BLAKE2b-256 checksum How to use checksums |
e5ca58bd2019b39423eb981ca9434ff70e35d449c8821d47444258a67654141d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logRelease files / orgwarrior_mcp-0.3.0-py3-none-any.whl
| Download URL | orgwarrior_mcp-0.3.0-py3-none-any.whl |
|---|---|
| Size | 32.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a39f34bb2d210551c24d5194bbc41572faf7836313d037ab4d84d7b969ef7bab
|
|
BLAKE2b-256 checksum How to use checksums |
532f2870884fc972855ae261a8efafc50e9ed9c95751c419351fe15d5644ca3e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logSecurity for orgwarrior-mcp 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for orgwarrior_mcp-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.