Skip to main content

Best-in-class MCP server for Things 3 — token-efficient, full CRUD, AppleScript + URL scheme

Project description

Things 3 MCP Server

Best-in-class MCP server for Things 3 — token-efficient, full CRUD, AppleScript + URL scheme.

Built to be the most capable and efficient Things integration for Claude Desktop, Claude Code, and any MCP-compatible client.

Features

  • Token-efficient output — concise one-line-per-item by default, detailed on demand
  • 30+ tools — full coverage of every Things 3 view and operation
  • Smart Someday filtering — correctly handles inherited Someday status (matches Things UI exactly)
  • Random samplingget_random_inbox(5) for manageable LLM context instead of dumping hundreds of items
  • Summary mode — full GTD overview (get_summary) in ~20 lines
  • AppleScript + URL scheme — reliable writes with UUID feedback; automatic fallback
  • Bulk JSON import/export — Things URL scheme JSON format
  • HTTP transport — optional remote access with API key authentication
  • SKILL.md — self-teaching instructions so Claude uses tools optimally

Requirements

  • macOS (Things 3 is macOS/iOS only)
  • Things 3 installed and running
  • Python 3.12+
  • uv (recommended) or pip

Quick Start

Install and run

# Clone and install
git clone https://github.com/Groupthink-dev/things3-blade-mcp.git
cd things3-blade-mcp
uv sync

# Run (stdio transport — for Claude Desktop)
uv run things3-mcp

Claude Desktop configuration

Add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "things3": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/things3-blade-mcp", "things3-mcp"]
    }
  }
}

Claude Code

# Add as MCP server
claude mcp add things3 -- uv run --directory /path/to/things3-blade-mcp things3-mcp

Token-Saving Tips

The server is designed to minimize LLM context consumption:

  1. Start with get_summary() — 20-line GTD overview, not hundreds of tasks
  2. Use random samplingget_random_inbox(5) before get_inbox(limit=100)
  3. Defaults are efficientconcise=True, limit=10 on all tools
  4. One-line format: □ Buy groceries [3F8A2B1C] | today | deadline:2026-03-01 | #errands
  5. Null fields omitted — no "Notes: None" or "Tags: []" clutter
  6. Batch lookups — no N+1 queries; project/area names resolved in bulk

All Tools (30)

List Views (9)

Tool Description
get_inbox Unprocessed tasks
get_today Today's schedule (Someday-filtered)
get_upcoming Future scheduled tasks
get_anytime Available tasks
get_someday Deferred tasks (includes inherited)
get_logbook Completed tasks (configurable period)
get_trash Trashed tasks
get_deadlines All tasks with deadlines, sorted
get_summary Full GTD overview in ~20 lines

Random Sampling (4) — recommended entry points

Tool Description
get_random_inbox Random sample from inbox
get_random_today Random sample from today
get_random_anytime Random sample from anytime
get_random_todos Random sample, optional project filter

Entity Views (5)

Tool Description
get_todos All open todos (optional project filter)
get_projects Projects with open/done counts
get_areas High-level categories
get_tags All tags
get_tagged_items Todos with a specific tag

Search & Detail (4)

Tool Description
search_todos Search by title/notes
search_advanced Multi-filter search (status, date, tag, area)
get_recent Recently created items
show_item Single item by UUID with full details

Write (4) — AppleScript primary, URL scheme fallback

Tool Description
add_todo Create a todo (returns UUID)
add_project Create a project with optional todos
update_todo Update any todo field
update_project Update any project field

Bulk & Navigation (4)

Tool Description
json_import Bulk create via Things JSON format
json_export Export todos as compact JSON
show_in_things Reveal item in Things app
search_in_things Open Things search UI

HTTP Transport

For remote access (e.g., from a different machine or mobile):

# Set environment variables
export THINGS_MCP_TRANSPORT=http
export THINGS_MCP_HOST=127.0.0.1
export THINGS_MCP_PORT=8765
export THINGS_MCP_API_KEY=your-secret-key-here  # auto-generated if empty

# Run
uv run things3-mcp

Bearer Token Authentication

When exposing the server through a tunnel or reverse proxy, set THINGS_MCP_API_TOKEN to require a bearer token on every request:

export THINGS_MCP_API_TOKEN=your-secret-token-here

All HTTP requests must then include the header:

Authorization: Bearer your-secret-token-here

Requests without a valid token receive 401 Unauthorized. If the env var is unset or empty, bearer auth is disabled and the server behaves as before (suitable for localhost-only access).

Security Warning

Never expose the HTTP port directly to the internet. Use a reverse proxy with TLS:

  • Cloudflare Tunnel (recommended — free, zero-config TLS)
  • Caddy (automatic HTTPS)
  • Nginx with Let's Encrypt

Cloudflare Tunnel example

# Install cloudflared
brew install cloudflare/cloudflare/cloudflared

# Create tunnel
cloudflared tunnel create things-mcp
cloudflared tunnel route dns things-mcp things-mcp.yourdomain.com

# Run tunnel
cloudflared tunnel --url http://localhost:8765 run things-mcp

Testing the HTTP endpoint

# Health check
curl http://localhost:8765/

# Call a tool (via MCP protocol)
curl -X POST http://localhost:8765/mcp \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-secret-key-here" \
  -d '{"method": "tools/call", "params": {"name": "get_summary", "arguments": {}}}'

Environment Variables

Variable Default Description
THINGS_MCP_TRANSPORT stdio stdio or http
THINGS_MCP_HOST 127.0.0.1 HTTP bind address
THINGS_MCP_PORT 8765 HTTP port
THINGS_MCP_API_TOKEN (none) Bearer token for HTTP auth — if set, requires Authorization: Bearer <token>
THINGS_MCP_API_KEY (auto) API key for HTTP auth (X-API-Key header)
THINGS_AUTH_TOKEN (auto) Things URL scheme auth token

Architecture

src/things3_mcp/
├── server.py       # FastMCP instance + all 30 @mcp.tool definitions
├── formatters.py   # Two-tier output: concise (1-line) + detailed
├── someday.py      # Someday filtering (matches Things UI behavior)
├── applescript.py   # AppleScript bridge for writes (temp-file approach)
├── url_scheme.py   # URL scheme builder (fallback writes + checklist items)
├── sampling.py     # Random sampling helpers
├── auth.py         # API key auth for HTTP transport
└── models.py       # Shared constants

Design principles:

  • Reads via things.py (direct SQLite — fast, no app needed)
  • Writes via AppleScript (reliable, returns UUIDs, no auth token needed)
  • Fallback writes via URL scheme (for checklist items or when AppleScript fails)
  • Batch lookups eliminate N+1 queries in formatters
  • Someday filtering handles the Things 3 project-inheritance edge case

Development

# Install with dev/test dependencies
uv sync --all-extras

# Run tests
uv run pytest tests/ -v

# Lint
uv run ruff check src/ tests/

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

things3_blade_mcp-0.1.1.tar.gz (105.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

things3_blade_mcp-0.1.1-py3-none-any.whl (24.7 kB view details)

Uploaded Python 3

File details

Details for the file things3_blade_mcp-0.1.1.tar.gz.

File metadata

  • Download URL: things3_blade_mcp-0.1.1.tar.gz
  • Upload date:
  • Size: 105.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for things3_blade_mcp-0.1.1.tar.gz
Algorithm Hash digest
SHA256 d270aabbb3a51fbc54d6d2068d97b2734626f403bccf8880ddd2eee65ecce8b9
MD5 bcd7d036590a04953a473ebc659906dc
BLAKE2b-256 37fdb6cbe9ea2963a6f972ed6776538ece0e0bda8385c737f2ab2ac511c4cfcd

See more details on using hashes here.

Provenance

The following attestation bundles were made for things3_blade_mcp-0.1.1.tar.gz:

Publisher: publish.yml on Groupthink-dev/things3-blade-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file things3_blade_mcp-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for things3_blade_mcp-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0272bf999d7fc7b4acae4e1a8877ce5991fef65383e9446aa773e4dc72c418b8
MD5 6a803657a6ed6b3dde69f83c4652ef42
BLAKE2b-256 46f73abcec02bb285e8fcf1114a1279f47a40979d3aa8fa55ff570433f8a9332

See more details on using hashes here.

Provenance

The following attestation bundles were made for things3_blade_mcp-0.1.1-py3-none-any.whl:

Publisher: publish.yml on Groupthink-dev/things3-blade-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page