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-blade-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-blade-mcp"]
    }
  }
}

Claude Code

# Add as MCP server
claude mcp add things3 -- uv run --directory /path/to/things3-blade-mcp things3-blade-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-blade-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_blade_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.2.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.2-py3-none-any.whl (24.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: things3_blade_mcp-0.1.2.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.2.tar.gz
Algorithm Hash digest
SHA256 6264e193cc78ba00234ab25978687f75bf4d5e331e8c991ff21b4f85fae4dad7
MD5 f975a21dab84bb40d7547fb458805484
BLAKE2b-256 7b765a413aa350785fc3575327295c3d27c911dcc920e6bb5f6f73f1f297c676

See more details on using hashes here.

Provenance

The following attestation bundles were made for things3_blade_mcp-0.1.2.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.2-py3-none-any.whl.

File metadata

File hashes

Hashes for things3_blade_mcp-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 976956748c7885c9c72761b3a7513da54effef4313d78355e308a28900a87760
MD5 0388a6abed1342dad90350dcfa06c058
BLAKE2b-256 e4d0df28fe796513c229e76a4454d2ba116bc8a07f74135b01401b2f0f20d4ec

See more details on using hashes here.

Provenance

The following attestation bundles were made for things3_blade_mcp-0.1.2-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