Skip to main content
Glama
timetree-mcp
by ap311036

TimeTree MCP

TimeTree MCP is an unofficial Model Context Protocol server that accesses TimeTree calendars over HTTPS. It uses the Python direct client by default and does not launch a browser; the browser transport is kept only as a compatibility fallback. Session cookies and CSRF tokens exist only in the MCP process memory.

Important: TimeTree's official Connect App/API has been discontinued. This project uses TimeTree Web's non-public endpoint, which may stop working when the service changes. Please assess the risks yourself and comply with TimeTree's terms and policies.

Features

  • Read calendars, events, memos, comments, labels, and members.

  • Create, update, and delete events and memos.

  • Add, update, and delete event comments.

  • Update calendar labels using merge mode.

  • Monitor calendar changes in the background and send MCP notifications.

  • All write operations require explicitly passing confirm: true.

  • Credentials are not placed in MCP tool arguments; the authenticated session is kept only in memory.

Related MCP server: Apple Calendar MCP

Requirements

  • Python 3.10 or later.

  • A TimeTree account.

  • macOS is required to use the Keychain helper; other platforms can use environment variables or a password file.

Installation

git clone <repository-url>
cd timetree-mcp
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --editable .

The runtime uses only the Python standard library. After installation, the timetree-mcp and timetree-credentials commands are available.

Using the NPM wrapper

The NPM wrapper requires Node.js 18+ and Python 3.10+; it launches the Python MCP server bundled with the package and forwards MCP's stdin/stdout:

npx --yes timetree-mcp

It can also be installed globally:

npm install --global timetree-mcp
timetree-mcp

Setting up credentials

Using the Keychain on macOS is recommended. When setting it up, the password is only entered hidden in the terminal; it does not enter shell history, MCP arguments, or source code:

./scripts/setup_timetree_keychain.sh
timetree-credentials status

MCP automatically reads the email/password in the Keychain. status only reports whether they exist and does not return values; clear both Keychain items:

timetree-credentials clear

If you are not using the Keychain, you can also use environment variables:

export TIMETREE_EMAIL='your-email@example.com'
export TIMETREE_PASSWORD='your-password'

An even better option is to use a password file with permissions of 600:

chmod 600 /absolute/path/to/timetree-password
export TIMETREE_EMAIL='your-email@example.com'
export TIMETREE_PASSWORD_FILE='/absolute/path/to/timetree-password'

Registering with Codex

Replace /absolute/path/to/timetree-mcp with your checkout location. If a timetree server with the same name already exists, remove it and then add it again:

codex mcp remove timetree
codex mcp add timetree \
  --env TIMETREE_EMAIL=your-email@example.com \
  --env TIMETREE_PASSWORD_FILE=/absolute/path/to/timetree-password \
  -- python3 /absolute/path/to/timetree-mcp/src/timetree_mcp/server.py

Do not put the actual password in shell history, MCP tool arguments, the README, or source code.

When registering with the NPM wrapper, change the server command to:

codex mcp add timetree \
  --env TIMETREE_EMAIL=your-email@example.com \
  --env TIMETREE_PASSWORD_FILE=/absolute/path/to/timetree-password \
  -- npx --yes timetree-mcp

MCP tools

Login and read

  • timetree_login, timetree_logout, timetree_status

  • timetree_keychain_status

  • timetree_list_calendars, timetree_list_events, timetree_list_memos

  • timetree_list_event_comments

  • timetree_get_calendar_labels, timetree_get_calendar_members, timetree_get_calendar_virtual_members

Writes

  • timetree_create_event, timetree_update_event, timetree_delete_event

  • timetree_create_memo, timetree_update_memo, timetree_delete_memo

  • timetree_add_event_comment, timetree_update_event_comment, timetree_delete_event_comment

  • timetree_update_calendar_labels

Time can be passed as an ISO-8601 string or Unix milliseconds; all write tools must explicitly pass confirm: true. Member invitation/removal endpoints are not yet verified, so they are intentionally not included.

If some older calendars' TimeTree sync endpoint returns -425, event queries skip that calendar and report it in the skipped_calendars field, without causing the whole batch of other readable calendars to fail.

Background monitoring

  • timetree_start_monitor: Starts background polling, with an interval of 30–3600 seconds.

  • timetree_monitor_status: Views monitoring status, last poll, errors, and notification count.

  • timetree_stop_monitor: Stops monitoring.

The first poll only establishes a baseline; afterward, when additions, modifications, or removals are detected, the server sends MCP notifications/message. The monitor is tied to the MCP process and also stops when the client exits.

Project structure

src/timetree_mcp/          Python package 與 MCP server
bin/                       NPM wrapper launcher
scripts/                   本機設定輔助腳本
tests/                     standard-library unittest 測試
test/                      NPM wrapper 測試
.github/workflows/ci.yml   Continuous integration

Testing

python3 -m unittest discover -s tests -v
npm test

The legacy ego-browser transport is kept at src/timetree_mcp/browser.py as a compatibility fallback, but the server does not load it by default.

License

This project is licensed under the MIT License.

Available Tools

29 tools
timetree_add_event_commentA

Add a comment to a TimeTree event. Requires confirm=true. Passes TimeTree's silent flag, whose notification effects are unverified; it does not guarantee notification suppression.

Inputs: confirm (required), content (required), event_uuid (required), calendar_id (required), +1 more.

timetree_create_eventB

Create a TimeTree event. Requires confirm=true and writes to the real calendar. The silent argument is unsupported; upstream notifications may occur.

Inputs: title (required), end_at (required), confirm (required), start_at (required), +15 more.

timetree_create_memoC

Create a TimeTree memo. Requires confirm=true.

Inputs: title (required), confirm (required), calendar_id (required), url, +6 more.

timetree_delete_eventA
DestructiveIdempotent

Delete a TimeTree event. This cannot be undone and requires confirm=true.

Inputs: confirm (required), event_uuid (required), calendar_id (required).

timetree_delete_event_commentC
DestructiveIdempotent

Delete a TimeTree event comment. Requires confirm=true.

Inputs: confirm (required), comment_id (required), event_uuid (required), calendar_id (required).

timetree_delete_memoB
DestructiveIdempotent

Delete a TimeTree memo. This cannot be undone and requires confirm=true.

Inputs: confirm (required), memo_uuid (required), calendar_id (required).

timetree_get_calendar_labelsC
Read-onlyIdempotent

Read all labels for a TimeTree calendar.

Inputs: calendar_id (required).

timetree_get_calendar_membersB
Read-onlyIdempotent

Read active members of a TimeTree calendar, optionally including deactivated members.

Inputs: calendar_id (required), include_deactivated.

timetree_get_calendar_virtual_membersB
Read-onlyIdempotent

Read virtual members of a TimeTree calendar, optionally including deactivated members.

Inputs: calendar_id (required), include_deactivated.

timetree_get_occurrence_for_editA
Read-onlyIdempotent

Read and validate one timed DAILY/WEEKLY occurrence in Asia/Taipei, Asia/Tokyo, Asia/Kolkata, America/New_York or Europe/London. Start/end timezones must match. Returns a calendar revision and timezone; unsafe DST/metadata is rejected and unverified parent links mark it uneditable. No calendar writes.

Inputs: event_uuid (required), calendar_id (required), occurrence_start_at (required).

timetree_keychain_statusA
Read-onlyIdempotent

Report whether the macOS Keychain contains TimeTree email/password items; never returns their values.

Inputs: no named parameters.

timetree_list_calendarsA
Read-onlyIdempotent

Read the calendars available in the authenticated TimeTree account.

Inputs: no named parameters.

timetree_list_event_commentsC
Read-onlyIdempotent

Read comments attached to a TimeTree event.

Inputs: event_uuid (required), calendar_id (required).

timetree_list_eventsC
Read-onlyIdempotent

Read TimeTree events overlapping a date range. This tool is read-only.

Inputs: limit, query, end_date, start_date, +1 more.

timetree_list_memosC
Read-onlyIdempotent

Read category-2 TimeTree memos from a calendar.

Inputs: calendar_id (required), limit, updated_after.

timetree_list_occurrencesA
Read-onlyIdempotent

Read dated occurrences overlapping an explicit window of at most 93 days, including a narrow DAILY/WEEKLY/MONTHLY/YEARLY rule subset. Requires a complete selected-calendar snapshot; unsupported rules, unsafe DST, or truncation mark complete=false. Does not establish edit eligibility or prove a time is free.

Inputs: end_at (required), start_at (required), calendar_id (required), limit, +1 more.

timetree_loginA

Login to TimeTree over direct HTTPS using one complete configured credential source: explicit integration settings, environment/password file, or macOS Keychain. Partial explicit settings fail without mixing sources. Do not pass credentials as tool arguments; browser sessions are not imported.

Inputs: no named parameters.

timetree_logoutA
DestructiveIdempotent

Clear the in-memory TimeTree session cookie and CSRF token.

Inputs: no named parameters.

timetree_monitor_statusA
Read-onlyIdempotent

Read monitor activity, last successful baseline, incomplete-check errors, and pending notification states. Unknown delivery blocks automatic sending; notifications_sent counts completed transport writes, not client receipts. State is memory-only.

Inputs: no named parameters.

timetree_move_occurrenceA
Destructive

Move ONLY one preflighted occurrence, preserving duration/metadata. Requires confirm=true, revision and operation_id. TWO NON-ATOMIC writes: create child then exclude original. Partial/uncertain operations remain durably blocked; never retry with a new ID or delete/rollback automatically.

Inputs: confirm (required), event_uuid (required), calendar_id (required), new_start_at (required), +3 more.

timetree_occurrence_operation_statusA
Read-onlyIdempotent

Read the local occurrence journal by operation_id, including the last dispatch phase and known child UUID. Does not query TimeTree, resume, retry, or unlock an uncertain operation.

Inputs: operation_id (required).

timetree_start_monitorB
Idempotent

Start process-local polling of complete calendar snapshots. Changes use MCP notifications/message; transport writes do not prove client receipt. Uncertain notifications remain pending without automatic retry. Baselines and pending state are memory-only.

Inputs: calendar_id, interval_seconds.

timetree_statusA
Read-onlyIdempotent

Read the current direct HTTPS TimeTree authentication status.

Inputs: no named parameters.

timetree_stop_monitorA
DestructiveIdempotent

Request stopping the monitor without clearing baselines or pending notifications. Inspect stopping and poll_in_flight: an in-progress read may still be finishing, and restart is refused until it stops.

Inputs: no named parameters.

timetree_timezone_statusA
Read-onlyIdempotent

Diagnose installed IANA timezone data locally without credentials, calendar reads, or writes. Checks the five supported occurrence zones by default, or one requested IANA zone. Availability does not imply that occurrence tools support the requested zone.

Inputs: timezone.

timetree_update_calendar_labelsA
Destructive

Merge-update TimeTree label names/colors. Requires confirm=true; omitted labels are preserved.

Inputs: labels (required), confirm (required), calendar_id (required).

timetree_update_eventC
Destructive

Update selected fields of a TimeTree event. Requires confirm=true. The silent argument is unsupported; upstream notifications may occur.

Inputs: confirm (required), event_uuid (required), calendar_id (required), url, +16 more.

timetree_update_event_commentB
Destructive

Update a TimeTree event comment. Requires confirm=true.

Inputs: confirm (required), content (required), comment_id (required), event_uuid (required), +1 more.

timetree_update_memoC
Destructive

Update a TimeTree memo. Requires confirm=true.

Inputs: confirm (required), memo_uuid (required), calendar_id (required), url, +6 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.1/5.0

    Scored across 29 tools

    Disambiguation3/5

    Most families are distinct (events, comments, memos, labels, members, monitors, auth), but the event/occurrence split is ambiguous: timetree_list_events, timetree_list_occurrences, and timetree_get_occurrence_for_edit all read event data over a date window and an agent could easily misselect. The cluster of status tools (status, keychain_status, timezone_status, monitor_status, occurrence_operation_status) is differentiated only by long descriptions, which helps but does not fully disambiguate.

    Naming Consistency4/5

    Nearly all tools use a timetree_ prefix plus snake_case verb_noun form (list_calendars, create_event, update_memo, delete_event_comment), which is predictable. The deviation is the noun-only status tools (timetree_status, timetree_keychain_status, timetree_timezone_status, timetree_occurrence_operation_status) that drop the verb, but the pattern remains readable.

    Tool Count3/5

    At 29 tools the surface is heavy and sits at the upper end of the rubric, though the breadth is largely earned by a wide domain (events, occurrences, comments, memos, labels, members, monitoring, auth). Some thinning is possible—several status/diagnostic tools could be consolidated—but nothing is obviously redundant padding.

    Completeness3/5

    Core lifecycle coverage is strong: full CRUD for events, comments, and memos, plus labels update, member reads, occurrence moves, and operation recovery. However, calendar-level create/delete is absent and members are read-only (no invite/remove), leaving notable gaps in calendar administration.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers