Skip to main content
Glama

RTM MCP Server

A production-quality Model Context Protocol (MCP) server for Remember The Milk task management.

Enables Claude to manage your tasks through natural language conversation.

Features

  • Full RTM API Coverage: 30+ tools covering tasks, lists, tags, notes, and more

  • Smart Add Syntax: Natural language task creation ("Call mom ^tomorrow !1 #family")

  • Undo Support: All write operations return transaction IDs for undo

  • Async Performance: Built on httpx with connection pooling

  • Type Safety: Full Pydantic models and type hints

Related MCP server: Todoist MCP Server

Installation

uvx rtm-mcp

Using pip

pip install rtm-mcp

From Source

git clone https://github.com/ljadach/rtm-mcp.git
cd rtm-mcp
uv sync

Setup

1. Get RTM API Credentials

RTM API keys are issued through a separate developer portal (not your account settings):

  1. Go to RTM API Key Registration — you may need to log in first

  2. Click "Apply for an API Key"

  3. Fill in the form — app name (e.g. "Claude MCP"), description, anything works

  4. After submitting, you'll see your API Key and Shared Secret — save both

2. Run Setup

rtm-setup

This will:

  • Prompt for your API credentials

  • Open your browser for authorization

  • Save the auth token to ~/.config/rtm-mcp/config.json

3. Configure Claude Desktop

Add to ~/.config/claude/claude_desktop_config.json:

{
  "mcpServers": {
    "rtm": {
      "command": "uvx",
      "args": ["rtm-mcp"]
    }
  }
}

Usage

Once configured, you can ask Claude to manage your tasks:

  • "Show my tasks due today"

  • "Add a task to buy groceries tomorrow, high priority"

  • "Complete the grocery task"

  • "What high priority tasks do I have?"

  • "Move the meeting prep task to my Work list"

  • "Add a note to the project task"

Smart Add Syntax

When adding tasks, use RTM's Smart Add syntax:

Symbol

Meaning

Example

^

Due date

^tomorrow, ^next friday

!

Priority

!1 (high), !2 (medium), !3 (low)

#

Tag

#work, #urgent

@

Location

@home, @office

=

Estimate

=30min, =2h

*

Repeat

*daily, *every monday

Example: "Review report ^friday !1 #work =1h *weekly"

Available Tools

Tasks

  • list_tasks - List tasks with filters

  • add_task - Create a new task

  • complete_task / uncomplete_task - Mark done or reopen

  • delete_task - Remove a task

  • postpone_task - Move due date by one day

  • move_task - Move to different list

  • set_task_name - Rename task

  • set_task_due_date - Change due date

  • set_task_priority - Set priority level

  • set_task_recurrence - Set repeat pattern

  • set_task_start_date - Set start date

  • set_task_estimate - Set time estimate

  • set_task_url - Attach URL

  • add_task_tags / remove_task_tags - Manage tags

Notes

  • add_note - Add note to task

  • edit_note - Edit existing note

  • delete_note - Remove note

  • get_task_notes - View all notes

Lists

  • get_lists - List all lists

  • add_list - Create new list

  • rename_list - Rename list

  • delete_list - Delete list

  • archive_list / unarchive_list - Archive management

  • set_default_list - Set default list

Utilities

  • test_connection - Test API connectivity

  • check_auth - Verify authentication

  • get_tags - List all tags

  • get_locations - List saved locations

  • get_settings - View user settings

  • get_contacts / get_groups - Contact management

  • parse_time - Parse natural language time

  • undo - Undo previous operation

Configuration

Environment Variables

RTM_API_KEY=your_api_key
RTM_SHARED_SECRET=your_shared_secret
RTM_AUTH_TOKEN=your_token

Config File

~/.config/rtm-mcp/config.json:

{
  "api_key": "your_api_key",
  "shared_secret": "your_shared_secret",
  "token": "your_token"
}

Development

# Install dev dependencies
make dev

# Run linting
make lint

# Run tests
make test

# Run with coverage
make test/coverage

# Format code
make format

Docker

docker build -t rtm-mcp .
docker run -it --rm \
  -e RTM_API_KEY \
  -e RTM_SHARED_SECRET \
  -e RTM_AUTH_TOKEN \
  rtm-mcp

Claude Desktop config for Docker:

{
  "mcpServers": {
    "rtm": {
      "command": "docker",
      "args": ["run", "-i", "--rm",
        "-e", "RTM_API_KEY",
        "-e", "RTM_SHARED_SECRET",
        "-e", "RTM_AUTH_TOKEN",
        "rtm-mcp"]
    }
  }
}

License

MIT License - see LICENSE for details.

Acknowledgments

Available Tools

36 tools
add_listC

Create a new list.

Args: name: Name for the new list filter: Optional RTM filter to make this a smart list

Returns: Created list details with transaction ID

Inputs: name (required), filter. Returns: object

add_noteA

Add a note to a task.

Args: note_text: The note content note_title: Optional title for the note task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Created note details with transaction ID

Inputs: note_text (required), note_title, task_name, task_id, +2 more. Returns: object

add_taskA

Add a new task.

Supports Smart Add syntax when parse=True: - ^date for due date (^tomorrow, ^next friday) - !priority (!1, !2, !3) - #tag for tags (#work, #urgent) - @location - =time estimate (=30min, =1h) - *repeat pattern (*daily, *weekly)

Args: name: Task name (with optional Smart Add syntax) list_name: List to add to (uses default list if not specified) parse: Parse Smart Add syntax (default: True)

Returns: Created task details with transaction ID for undo

Examples: - add_task("Buy groceries") - add_task("Call mom ^tomorrow !1 #family") - add_task("Weekly review *weekly ^monday", list_name="Work")

Inputs: name (required), list_name, parse. Returns: object

add_task_tagsB

Add tags to a task.

Args: tags: Comma-separated tags to add (e.g., "work,urgent") task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Updated task details

Inputs: tags (required), task_name, task_id, taskseries_id, +1 more. Returns: object

archive_listC

Archive a list.

Args: list_name: Name of the list to archive

Returns: Updated list details

Inputs: list_name (required). Returns: object

check_authA

Check if authentication token is valid.

Returns: Auth status and user info

Inputs: no named parameters. Returns: object

complete_taskB

Mark a task as complete.

Provide either task_name (for search) or all three IDs.

Args: task_name: Task name to search for (fuzzy match) task_id: Specific task ID taskseries_id: Task series ID (required with task_id) list_id: List ID (required with task_id)

Returns: Completed task details with transaction ID for undo

Inputs: task_name, task_id, taskseries_id, list_id. Returns: object

delete_listA

Delete a list.

Note: Lists with tasks cannot be deleted. Move or delete tasks first.

Args: list_name: Name of the list to delete

Returns: Deletion confirmation with transaction ID

Inputs: list_name (required). Returns: object

delete_noteB

Delete a note from a task.

Args: note_id: ID of the note to delete task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Deletion confirmation with transaction ID

Inputs: note_id (required), task_name, task_id, taskseries_id, +1 more. Returns: object

delete_taskA

Delete a task.

Args: task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Deletion confirmation with transaction ID for undo

Inputs: task_name, task_id, taskseries_id, list_id. Returns: object

edit_noteB

Edit an existing note.

Args: note_id: ID of the note to edit note_text: New note content note_title: New title (optional) task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Updated note details

Inputs: note_id (required), note_text (required), note_title, task_name, +3 more. Returns: object

get_contactsB

Get contacts for task sharing.

Returns: List of contacts

Inputs: no named parameters. Returns: object

get_groupsA

Get contact groups.

Returns: List of groups with member counts

Inputs: no named parameters. Returns: object

get_listsA

Get all RTM lists.

Args: include_archived: Include archived lists (default: false) include_smart: Include smart lists (default: true)

Returns: List of all lists with metadata

Inputs: include_archived, include_smart. Returns: object

get_locationsA

Get all saved locations.

Returns: List of locations

Inputs: no named parameters. Returns: object

get_settingsB

Get user settings.

Returns: User preferences and settings

Inputs: no named parameters. Returns: object

get_tagsA

Get all tags in use.

Returns: List of tags with usage counts

Inputs: no named parameters. Returns: object

get_task_notesB

Get all notes for a task.

Args: task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: List of notes for the task

Inputs: task_name, task_id, taskseries_id, list_id. Returns: object

list_tasksA

List tasks with optional filtering.

Args: filter: RTM filter string (e.g., "dueBefore:tomorrow", "tag:work", "priority:1") list_name: Filter to a specific list name include_completed: Include completed tasks (default: false)

Returns: List of tasks with metadata

Examples: - list_tasks() → all incomplete tasks - list_tasks(filter="dueBefore:tomorrow") → tasks due soon - list_tasks(filter="tag:work AND priority:1") → high priority work tasks - list_tasks(list_name="Personal") → tasks in Personal list

Inputs: filter, list_name, include_completed. Returns: object

move_taskC

Move a task to a different list.

Args: to_list_name: Destination list name task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: Current list ID (from_list_id)

Returns: Updated task details

Inputs: to_list_name (required), task_name, task_id, taskseries_id, +1 more. Returns: object

parse_timeA

Parse a natural language time string.

Args: text: Time to parse (e.g., "tomorrow", "next friday", "in 2 hours") timezone: Optional timezone (e.g., "America/New_York")

Returns: Parsed time in various formats

Inputs: text (required), timezone. Returns: object

postpone_taskA

Postpone a task (moves due date by one day).

Args: task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Updated task details with new due date

Inputs: task_name, task_id, taskseries_id, list_id. Returns: object

remove_task_tagsA

Remove tags from a task.

Args: tags: Comma-separated tags to remove task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Updated task details

Inputs: tags (required), task_name, task_id, taskseries_id, +1 more. Returns: object

rename_listA

Rename a list.

Args: list_name: Current name of the list new_name: New name for the list

Returns: Updated list details

Inputs: list_name (required), new_name (required). Returns: object

set_default_listB

Set the default list for new tasks.

Args: list_name: Name of the list to set as default

Returns: Confirmation message

Inputs: list_name (required). Returns: object

set_task_due_dateB

Set or change task due date.

Args: due: Due date (natural language: "tomorrow", "next friday", "2024-12-25") Use empty string to clear due date. task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Updated task details

Inputs: due (required), task_name, task_id, taskseries_id, +1 more. Returns: object

set_task_estimateA

Set task time estimate.

Args: estimate: Time estimate (e.g., "30 minutes", "1 hour", "2 hours 30 minutes"). Empty to clear. task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Updated task details

Inputs: estimate (required), task_name, task_id, taskseries_id, +1 more. Returns: object

set_task_nameB

Rename a task.

Args: new_name: New name for the task task_name: Current task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Updated task details

Inputs: new_name (required), task_name, task_id, taskseries_id, +1 more. Returns: object

set_task_priorityC

Set task priority.

Args: priority: Priority level (1/high, 2/medium, 3/low, 0/N/none) task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Updated task details

Inputs: priority (required), task_name, task_id, taskseries_id, +1 more. Returns: object

set_task_recurrenceB

Set task recurrence pattern.

Args: repeat: Recurrence pattern (e.g., "every week", "every 2 days", "every monday", "after 1 week"). Empty string to clear. task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Updated task details

Inputs: repeat (required), task_name, task_id, taskseries_id, +1 more. Returns: object

set_task_start_dateC

Set task start date.

Args: start: Start date (natural language). Empty to clear. task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Updated task details

Inputs: start (required), task_name, task_id, taskseries_id, +1 more. Returns: object

set_task_urlC

Set task URL.

Args: url: URL to attach to task. Empty to clear. task_name: Task name to search for task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Updated task details

Inputs: url (required), task_name, task_id, taskseries_id, +1 more. Returns: object

test_connectionA

Test connection to RTM API.

Returns: Connection status and response time

Inputs: no named parameters. Returns: object

unarchive_listB

Unarchive a list.

Args: list_name: Name of the list to unarchive

Returns: Updated list details

Inputs: list_name (required). Returns: object

uncomplete_taskC

Reopen a completed task.

Args: task_name: Task name to search for (searches completed tasks) task_id: Specific task ID taskseries_id: Task series ID list_id: List ID

Returns: Reopened task details

Inputs: task_name, task_id, taskseries_id, list_id. Returns: object

undoB

Undo a previous operation.

Use the transaction_id returned from write operations.

Args: transaction_id: Transaction ID from previous operation

Returns: Undo confirmation

Inputs: transaction_id (required). Returns: object

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A3.6/5.0

    Scored across 36 tools

    Disambiguation5/5

    Each tool has a unique, clearly defined purpose. For example, add_task, complete_task, delete_task, and set_task_due_date are distinct operations without overlap. Even property setters like set_task_estimate and set_task_priority are unambiguous.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun pattern using lowercase with underscores (e.g., add_task, list_tasks, set_task_due_date). No mixing of conventions, making the surface predictable.

    Tool Count4/5

    36 tools is higher than typical, but each serves a specific function in a comprehensive task management tool. The count is justified by the feature depth, though it could be streamlined slightly.

    Completeness5/5

    Covers full lifecycle for tasks (add, list, complete, uncomplete, delete, move, all property sets), lists (CRUD + archive), notes (add, edit, delete), tags (add, remove), plus utilities (undo, parse_time, check_auth). No obvious gaps for the domain.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers