This file tracks the agent's thoughts, ideas, and work flow for the mcp_things repository.
- Append a new entry under
## Logfor each change made. - Briefly describe the reasoning behind significant decisions.
- Run
ruff check .andpytestafter modifications.
- Problem: Tasks created via the write path (capture-task / bulk-capture / schedule-task → Things URL scheme) were not reliably visible to the read path (search-tasks, get-tasks, fuzzy task_title lookup → direct SQLite via the reader, CDI-711). Things 3 does not flush URL-scheme writes to the on-disk store immediately, so reads saw a stale snapshot → confident false "No task found".
- Decision: The write path uses the Things URL/JSON scheme, which returns no UUID — so the ticket's option #1 (AppleScript read-back by id) is not cleanly possible. Implemented option #2 (in-process write overlay, title-keyed, TTL 90s) + option #4 (staleness-aware "not found" signalling), with a touch of #3 (DB-file mtime comparison) to make the staleness signal accurate.
- Changes:
- New
write_overlay.py: thread-safe TTL store of just-written items keyed by syntheticoverlay:id; de-dupes by title against persisted rows; exposesis_index_stale()(compares DB mtime captured at write vs. now). reader.py:inbox()/todos()/search()now fold matching overlay rows in (narrow project/area/tag/deadline filters are skipped to avoid false matches). Addedindex_stale()passthrough.capture-task,bulk-capture,schedule-taskrecord into the overlay after a successful write (best-effort, never fails the write).search-tasks,complete-task,modify-task(_resolve_task_by_title) distinguish "not found" from "index may be stale" (text +meta.index_stale).- Inbox-as-area fix:
search-tasksandget-tasksnow reject a built-in list name (Inbox/Today/Anytime/…) passed asarea=with a clear redirect toget-tasks(view=…), instead of silently returning empty. The documented correct usage: Inbox is a LIST →get-tasks(view="inbox");areais for areas of responsibility only.
- New
- Tests:
tests/test_write_overlay.py(overlay unit) +tests/test_read_after_write.py(tool-level Inbox guard, staleness signalling, reader merge). Full suite: 502 passed, 14 skipped, 36 deselected (real).ruff check+ruff formatclean. Could NOT exercise the live Things app here (macOS app + real SQLite); overlay/staleness logic verified via mocks.
- Implemented OpenSpec change
add-mcp-crud-tests- Comprehensive test suite for MCP operations- Created
tests/directory with full test infrastructure - Added
tests/conftest.pywith fixtures for both mocked unit tests and real Things 3 integration tests - Implemented unit tests (mocked) for all CRUD operations: todos, projects, read operations, integration workflows, error handling
- Implemented real integration tests with automatic cleanup using
test_data_trackerfixture - Added test commands to
pyproject.toml:test(unit only, CI/CD safe),test:dev(all tests),test:unit,test:integration - Updated
pytest.inito exclude real integration tests by default (-m "not real") - Added
pytest-asynciodependency for async test support - Created comprehensive
TESTING.mddocumentation - Updated README.md with testing section
- All tests use pytest markers:
unit(default),integration,real(dev only),slow - Real integration tests gracefully skip if Things 3 is not available
- Test coverage target: >80% on handler functions
- Created
- Implemented OpenSpec change
modernize-osascript-fastmcp- Background execution for AppleScript operations- Modified
run_applescript()inapplescript_bridge.pyto automatically wrap Things3 commands withwithout activatingclause - Added
THINGS_MCP_DISABLE_BACKGROUND_OSASCRIPTenvironment variable to allow disabling background execution for debugging - Updated
tag_handler.pyto userun_applescript()instead of direct subprocess calls for consistency - Updated
utils.pyto userun_applescript()for Things3 operations (version detection, app state checks) - Reviewed FastMCP integration - confirmed it already uses modern best practices (introspection for backward compatibility, metadata usage, proper annotations)
- Updated README.md to document new environment variable in Configuration section
- All AppleScript operations now run in background by default, preventing Things from appearing in foreground and interrupting user workflow
- Modified
- Completed and archived OpenSpec change
remove-legacy-mcp- Consolidated to FastMCP-only implementation (v2.0.0)- Deleted 5 legacy files: things_server.py, simple_server.py, simple_url_scheme.py, mcp_tools.py, and src/things_mcp/things_server.py
- Updated pyproject.toml, smithery.yaml, and init.py to version 2.0.0
- Updated README.md: removed Migration & Deprecation section, added concise Version 2.0 Changes section
- Created comprehensive CHANGELOG.md entry for 2.0.0 with breaking changes and migration guide
- Maintained all 19 MCP tool APIs - full backward compatibility at tool level
- Removed ~714 lines of duplicate code, simplified maintenance
- Archived to openspec/changes/archive/2025-10-16-remove-legacy-mcp/
- Created OpenSpec change proposal
remove-legacy-mcpfor consolidating to FastMCP-only implementation- Comprehensive proposal.md documenting why (dual-implementation burden), what (remove 5 legacy files), and impact (breaking change → v2.0.0)
- Detailed tasks.md with 8 implementation phases: pre-flight checks, code removal, import cleanup, config updates, documentation, testing, versioning, validation
- Design.md with technical decisions, migration plan, risks/mitigations, rollback strategy
- No spec deltas needed (implementation consolidation maintains all 19 tool APIs)
- Created comprehensive openspec/project.md with full project context (purpose, tech stack, conventions, domain knowledge, constraints, dependencies)
- Cleaned up and improved README.md based on openspec structure:
- Enhanced overview and key benefits section
- Added prerequisites section upfront
- Better organized features by category (Things 3 Integration, Reliability, MCP)
- Complete inventory of all 19 MCP tools with descriptions
- Added architecture diagram and data flow
- New sections: Usage with AI Assistants, Code Quality, Troubleshooting, Migration & Deprecation
- Fixed all 44 markdown linting errors
- Removed redundant documentation files:
- Deleted RELEASE_NOTES.md (redundant with CHANGELOG.md)
- Deleted IMPLEMENTATION_SUMMARY.md (covered by openspec/project.md, README.md, and AGENTS.md)
- Updated smithery.yaml to align with improved documentation:
- Refreshed descriptions to match new README
- Added all 19 tools (was only 10)
- Added THINGS_MCP_HOST and THINGS_MCP_PORT config options
- Updated tags for better discoverability
- Added shared MCP error helper returning
CallToolResultand updated tool handlers to use it for failure cases.
- Added MCP tool annotations across registration and Fast/Simple server implementations to align with MCP metadata expectations.
- Added CLI flags and env var validation to the run script so operators can easily bind to alternate hosts and ports without manual exports.
- Extended FastMCP server binding logic and README guidance to document the new port override support.
- Added FastMCP constructor introspection for icon support and guarded icon metadata so older runtimes still launch cleanly.
- Added compatibility helper so FastMCP icon metadata works whether or not
mcp.types.Iconis available in the runtime. - Guarded FastMCP server construction so
website_urlmetadata is only passed when supported by the installed MCP version.
- Implemented logging redaction across handlers and the AppleScript bridge so user task content stays out of logs.
- Removed duplicate binding announcements from the CLI entrypoint so runtime logging only happens once and cached the binding helper for reuse.
- Clarified binding logs and helper exports so launchers surface localhost default without double logging.
- Switched FastMCP server default bind address to localhost with env override and documented exposure steps.
- Added FastMCP metadata (instructions, website, icon) constants and wired them into the server instantiation.
- Documented the surfaced assistant guidance in the README to mirror the MCP experience.
- Converted MCP icon metadata to use
mcp.types.Iconobjects to satisfy FastMCP validation.
- Added
run_things_fastmcp.shhelper script and integrated Rich logging. - Documented macOS limitations preventing Docker usage for opening scripts.
- Introduced this AGENTS.md to record ongoing work.
- Updated run script to bootstrap a uv-managed virtual environment or fall back to system Python.
- Clarified Quick Start docs about the helper script's environment handling.
- Added standalone privacy and terms documents so operators understand local data handling and policy expectations.
- Updated README to link to the new policies and prompt users to review them before setup, keeping onboarding aligned with compliance guidance.