Let your AI agent
use Things 3.
Things Orchestrator is a small MCP server you run yourself. It lets Claude Code, Codex, Cursor, or Hermes manage your to-dos, even while your Mac is asleep.
Three to read, four to write, and one to check receipts.
The server writes to Things Cloud. Your Mac picks up the changes the next time it syncs.
Your Things password is stored only on the server you run.
Open source. It only updates when you install a new release.
Ask in plain language.
Changes sync to all your devices like any other edit in Things.
You have four to-dos today. Renew passport is due in three days.
Done. It's scheduled for Monday.
Done. I checked it off in Admin.
How it works
Things Cloud has no public API, so the server uses the same sync protocol as the Things apps and checks every change before reporting back.
-
Your agent
Gets a URL and a key, never your password.
-
Your server
Runs on a machine you choose and holds your login.
-
Things Cloud
Where your to-dos live.
-
Your Mac
Can stay asleep. Syncs when it wakes.
Where the server runs
Your Mac
Easiest to try. Works only while the Mac is awake.
Private server Recommended
On your Tailscale network. Nothing on the public internet.
Public server
Your own domain over HTTPS, for hosted agents.
Eight tools, and none of them delete.
Every write is confirmed in Things Cloud before your agent gets a receipt. Trashed items can be restored.
Read
things_viewReads a list, like Today or Inbox.things_findSearches to-dos and projects.things_getReads items by ID.Write
things_captureAdds to-dos and projects.things_updateEdits dates, notes, tags, and more.things_completeChecks items off.things_trashMoves items to the Trash.Check
things_receiptShows what a write changed.Set up the server,
then connect your agent.
# 1 Install a pinned release
$ uv tool install \
"git+https://github.com/matsvarn/things3-orchestrator.git@v0.12.0"
# 2 Sign in. Your password stays on this Mac.
$ things-orchestrator login
# 3 Run it as a launchd service on loopback
$ things-orchestrator service install
# 4 Check that it works
$ things-orchestrator doctor --wait
mcp: ok (http://127.0.0.1:8787/mcp; 8 tools; commit 96e163ee9698)
service: current
# 1 Install a pinned release
$ uv tool install \
"git+https://github.com/matsvarn/things3-orchestrator.git@v0.12.0"
# 2 Sign in. Your password stays on this machine.
$ things-orchestrator login --url https://MACHINE.TAILNET.ts.net \
--timezone Europe/Berlin
# 3 Run it as a service, reachable only on your tailnet
$ things-orchestrator service install
$ sudo tailscale serve --bg 8787
# 4 Check that it works
$ things-orchestrator doctor --wait --url https://MACHINE.TAILNET.ts.net
mcp: ok (http://127.0.0.1:8787/mcp; 8 tools; commit 96e163ee9698)
mcp: ok (https://MACHINE.TAILNET.ts.net/mcp; 8 tools; commit 96e163ee9698)
service: current
# 1 Install a pinned release
$ uv tool install \
"git+https://github.com/matsvarn/things3-orchestrator.git@v0.12.0"
# 2 Sign in. Your password stays on this machine.
$ things-orchestrator login --url https://mcp.example.com \
--timezone Europe/Berlin
# 3 Run it as a service behind Caddy. Keep port 8787 closed.
$ things-orchestrator service install
$ sudo apt install caddy
$ things-orchestrator print-config --client caddy \
| sudo tee /etc/caddy/Caddyfile >/dev/null
$ sudo systemctl reload caddy
# 4 Check that it works
$ things-orchestrator doctor --wait --url https://mcp.example.com
mcp: ok (http://127.0.0.1:8787/mcp; 8 tools; commit 96e163ee9698)
mcp: ok (https://mcp.example.com/mcp; 8 tools; commit 96e163ee9698)
service: current
# 5 On the host, print your client's config
$ things-orchestrator print-config \
--client claude-code --show-secrets
# Then run the printed command where Claude Code runs
claude mcp add --transport http things \
https://MACHINE.TAILNET.ts.net/mcp \
--header 'Authorization: Bearer <mcp_token>'
# 5 On the host, print your client's config
$ things-orchestrator print-config \
--client codex --show-secrets
# Then merge what it prints into ~/.codex/config.toml
[mcp_servers.things]
url = "https://MACHINE.TAILNET.ts.net/mcp"
http_headers = { Authorization = "Bearer <mcp_token>" }
# 5 On the host, print your client's config
$ things-orchestrator print-config \
--client cursor --show-secrets
# Then merge the things entry into ~/.cursor/mcp.json
{ "mcpServers": { "things": {
"url": "https://MACHINE.TAILNET.ts.net/mcp",
"headers": { "Authorization": "Bearer <mcp_token>" }
} } }
# 5 On the host, print your client's config
$ things-orchestrator print-config \
--client hermes --show-secrets
# Then run both printed commands where Hermes runs.
# Paste the bearer only at Hermes's private prompt.
hermes mcp add things --url https://MACHINE.TAILNET.ts.net/mcp --auth header
hermes skills install https://raw.githubusercontent.com/matsvarn/things3-orchestrator/v0.12.0/plugin/skills/things-orchestrator/SKILL.md --yes
# 5 Every MCP client needs the same two values.
# This prints them in the common mcpServers JSON shape.
$ things-orchestrator print-config \
--client cursor --show-secrets
# Then carry the URL and bearer into your client's config
{ "mcpServers": { "things": {
"url": "https://MACHINE.TAILNET.ts.net/mcp",
"headers": { "Authorization": "Bearer <mcp_token>" }
} } }
This is an unofficial integration.
It uses a reverse-engineered protocol that Cultured Code hasn't approved. It could stop working at any time.
Read the trust notes →- Password stays on your server
- Trash only, no permanent deletes
- Every write confirmed