Skip to main content
Glama

ticktick-md-mcp

A Python tool for importing and exporting TickTick notes and tasks to Markdown and JSON formats.

Three ways to use:

  1. 🖥️ Terminal CLI - Interactive command-line interface

  2. 🐍 Python Library - Import and use in your own code

  3. 🤖 MCP Server - AI integration with Claude (via Model Context Protocol)

Features

  • OAuth 2.0 authentication with TickTick

  • Import tasks from Markdown files with tags and project assignment

  • Export tasks filtered by tag or entire projects

  • Multiple export formats (Markdown, JSON)

  • Automatic date extraction from task titles

  • Extensible exporter architecture

  • 🆕 MCP Server - Expose functionality to Claude AI via Model Context Protocol

Installation

Prerequisites

  • Python 3.11 or higher

  • TickTick account

  • TickTick OAuth app credentials (Setup Guide)

Install Dependencies

# Using pip pip install -r requirements.txt # Or using uv (recommended) uv pip install -r requirements.txt

Quick Start

1. Set Up Environment Variables

Create a .env file in the project root:

cp .env.example .env

Edit .env and add your TickTick OAuth credentials:

TICKTICK_CLIENT_ID=your_client_id_here TICKTICK_CLIENT_SECRET=your_client_secret_here TICKTICK_REDIRECT_URI=http://localhost:8000/auth/ticktick/callback TICKTICK_ACCESS_TOKEN=your_access_token_here

2. Get Access Token

Run the token helper to authenticate:

python -m src.utils.get_token

Follow the prompts to:

  1. Visit the authorization URL

  2. Authorize the app

  3. Copy the authorization code from the redirect URL

  4. The script will save your access token to .env

3. Run the CLI

python ticktick_cli.py

The interactive menu provides all functionality:

  1. Import tasks from Markdown - Create tasks from markdown files with tags

  2. Export notes by tag - Filter and export tasks by tag

  3. Export entire projects - Export all tasks from a project

  4. List tags in a project - See available tags

  5. Exit

Choose your output format (Markdown or JSON) when exporting.

Usage

The CLI provides a unified interface for all operations:

Importing Tasks from Markdown

Run the CLI and select option 1:

python ticktick_cli.py # Then select: 1. Import tasks from Markdown

You'll be prompted to:

  1. Enter the markdown file path

  2. Choose a default project (or leave empty for Inbox)

  3. Preview (dry run) or import directly

Markdown Format

Tasks should be formatted as bullet lists with checkboxes:

- [ ] Review pull request Tags: code-review, urgent Project: Work Tasks Check for performance issues and security - [ ] Buy groceries Tags: shopping, personal Milk, bread, eggs - [x] Completed task Tags: done

Metadata Fields:

  • Tags: Comma-separated list of tags (e.g., Tags: work, urgent)

  • Project: TickTick project/list name (e.g., Project: Work Tasks)

  • Description: Multi-line task description (any non-metadata text after the title)

Task States:

  • - [ ] - Unchecked task (will be imported)

  • - [x] - Completed task (skipped during import)

Exporting Tasks

Run the CLI and select option 2 or 3:

python ticktick_cli.py # Then select: # 2. Export notes by tag # 3. Export entire project

Export options:

  • Choose between Markdown or JSON format

  • Specify output filename

Programmatic Usage

If you need to use the functionality in your own Python scripts:

from src.exporters.notes_exporter import NotesManager, MarkdownExporter, JSONExporter from src.importers.task_importer import TaskImporter # Initialize manager = NotesManager() # Export by tag (Markdown) manager.export_by_tag( tag_name="journal", output_file="journal.md", project_name="On My Mind" ) # Export by tag (JSON) manager.export_by_tag( tag_name="work", output_file="work_notes.json", project_name="Work Tasks", exporter=JSONExporter() ) # Export entire project manager.export_project( project_name="Personal", output_file="personal_notes.md" ) # List all projects manager.list_projects() # List tags in a project manager.list_tags(project_name="On My Mind")

API Usage

Use the TickTick API wrapper directly:

from src.api.ticktick_api import TickTickAPI, TickTickOAuth import os # Initialize API api = TickTickAPI(os.getenv('TICKTICK_ACCESS_TOKEN')) # Get user info user = api.get_user_info() # Get all projects projects = api.get_projects() # Get project data with tasks project_data = api.get_projects_data(project_id) # Create a task task = api.create_task( title="New Task", content="Task description", project_id="project_id_here", tags=["work", "urgent"] )

MCP Server - AI Integration

The MCP (Model Context Protocol) server allows Claude AI to directly interact with your TickTick account for importing and exporting tasks.

What is MCP?

MCP is a protocol that lets AI assistants like Claude access external tools and data sources. With the TickTick MCP server, you can ask Claude to:

  • "Export my work tasks to markdown"

  • "Import these tasks to my Home project"

  • "List all my TickTick projects"

  • "Create a task in my Work project"

Quick Start

  1. Install MCP dependency:

    pip install mcp>=1.0.0
  2. The in the project root - no setup needed!

  3. Set your access token:

    export TICKTICK_ACCESS_TOKEN=your_token_here
  4. Use with Claude Code:

    • Open this project in Claude Code

    • The MCP server will be automatically detected

    • Ask Claude to interact with TickTick!

Available MCP Tools

The server exposes these tools to Claude:

list-projects

List all your TickTick projects/lists.

Example: "Show me all my TickTick projects"

list-tags

List all tags in a specific project.

Parameters: - project_name: Name of the project Example: "What tags are in my Work Tasks project?"

export-by-tag

Export tasks filtered by a specific tag.

Parameters: - tag_name: Tag to filter by - project_name: Project to export from - format: 'markdown' or 'json' (default: markdown) Example: "Export all tasks tagged 'urgent' from Work Tasks"

export-project

Export all tasks from an entire project.

Parameters: - project_name: Project to export - format: 'markdown' or 'json' (default: markdown) Example: "Export my Personal project as markdown"

import-from-markdown

Import tasks from markdown content into TickTick.

Parameters: - markdown_content: Markdown formatted task list - project_name: Target project (defaults to Inbox) - dry_run: Preview without creating (default: true) Example: "Import these tasks to my Work project: - [ ] Review documentation Tags: work, urgent - [ ] Schedule meeting Tags: work"

create-task

Create a single task in TickTick.

Parameters: - title: Task title - project_name: Project to add to (optional) - content: Task description (optional) - tags: List of tags (optional) Example: "Create a task 'Buy groceries' with tags shopping and personal"

Example Claude Conversations

Export tasks:

You: "Export all my work tasks tagged 'urgent' as markdown" Claude: *uses export-by-tag tool* Claude: "Here are your urgent work tasks: [markdown content]"

Import tasks:

You: "Here's a list of tasks, import them to my Home project: - [ ] Fix leaky faucet Tags: home, maintenance - [ ] Plant garden Tags: home, weekend" Claude: *uses import-from-markdown tool with dry_run=false* Claude: "I've imported 2 tasks to your Home project"

List and organize:

You: "What projects do I have in TickTick?" Claude: *uses list-projects tool* Claude: "You have 5 projects: Work Tasks, Personal, Home Tasks, Shopping, Ideas"

MCP Configuration

The .mcp.json file in the project root is pre-configured:

{ "mcpServers": { "ticktick": { "command": "python3", "args": ["ticktick_mcp_server.py"] } } }

Make sure TICKTICK_ACCESS_TOKEN is set in your environment or .env file.

For Claude Desktop (if you use it), add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{ "mcpServers": { "ticktick": { "command": "python3", "args": ["/absolute/path/to/pyTickTick/ticktick_mcp_server.py"], "env": { "TICKTICK_ACCESS_TOKEN": "your_token_here" } } } }

Architecture

The MCP server reuses all existing code:

  • Same API wrapper (src/api/ticktick_api.py)

  • Same import logic (src/importers/)

  • Same export logic (src/exporters/)

No duplication - the MCP server is a thin wrapper that exposes existing functionality to Claude via the Model Context Protocol.

Troubleshooting MCP

"Server not detected":

  • Ensure .mcp.json exists in project root

  • Check that TICKTICK_ACCESS_TOKEN is set in environment

  • Restart Claude Code

"Authentication failed":

  • Run python -m src.utils.get_token to get a fresh token

  • Update .env file with new token

  • Set environment variable: export TICKTICK_ACCESS_TOKEN=token

"Import not working":

  • Set dry_run=False in the import command

  • Default is dry_run=True for safety (preview mode)

Export Formats

Markdown

Exports tasks as a formatted Markdown document:

# Journal Notes Exported on January 03, 2026 at 07:31 PM Total notes: 7 --- ## 2025-12-31 My Note Title **Date:** December 31, 2025 Note content here... ---

Features:

  • Tasks sorted by date (most recent first)

  • Dates extracted from task titles (format: YYYY-MM-DD)

  • Fallback to API dates if available

  • Metadata header with export info

JSON

Exports tasks as structured JSON:

{ "metadata": { "exported_at": "2026-01-03T19:31:00.123456", "total_tasks": 7, "tag_name": "journal", "project_name": "On My Mind" }, "tasks": [ { "id": "...", "title": "2025-12-31 My Note", "content": "Note content...", "tags": ["journal"], ... } ] }

Date Handling

The exporter intelligently handles dates:

  1. From Title - Extracts dates from titles like 2025-12-31 Task Name

    • Supports optional leading whitespace

    • Format: YYYY-MM-DD at the start of the title

    • Displays as: "December 31, 2025"

  2. From API - Falls back to modifiedTime or createdTime if available

    • Note: TickTick's Open API may not return these fields for notes

  3. No Date - Shows "No date" if neither source is available

Utilities

Get Token Helper

Quickly get a new OAuth access token:

python -m src.utils.get_token

Debug Tags

Inspect task structure and find tags:

python -m src.utils.debug_tags

Shows:

  • All projects in your account

  • Sample task structures

  • Tasks containing specific keywords

  • Available tags

Project Structure

pyTickTick/ ├── 🚀 ticktick_cli.py # Main CLI - Interactive terminal interface ├── 🤖 ticktick_mcp_server.py # MCP Server - AI integration with Claude │ ├── src/ # Source code (organized by function) │ ├── api/ │ │ └── ticktick_api.py # TickTick API wrapper (OAuth + API client) │ │ │ ├── exporters/ │ │ └── notes_exporter.py # Export tasks to Markdown/JSON │ │ │ ├── importers/ │ │ ├── task_importer.py # Import tasks from Markdown │ │ └── markdown_parser.py# Parse markdown task format │ │ │ └── utils/ │ ├── get_token.py # OAuth token helper │ └── debug_tags.py # Task structure debugger │ ├── tests/ # Comprehensive test suite │ ├── conftest.py # Pytest fixtures and configuration │ ├── test_markdown_parser.py │ ├── test_task_importer.py │ ├── test_notes_exporter.py │ └── test_ticktick_api.py │ ├── 📝 Config: │ ├── .env.example # Template for credentials (copy to .env) │ ├── .mcp.json # MCP server configuration for Claude │ ├── requirements.txt # Python dependencies │ ├── pyproject.toml # Project metadata │ └── pytest.ini # Pytest configuration │ ├── LICENSE # MIT License └── README.md # This file

Three Ways to Use:

  1. Terminal CLI: Run python ticktick_cli.py for interactive interface

  2. Python Library: Import and use src/ modules in your own code

  3. MCP with Claude: Open project in Claude Code - MCP auto-detected!

Getting Started:

  1. Run python -m src.utils.get_token once to authenticate

  2. CLI: Run python ticktick_cli.py for all import/export operations

  3. MCP: Open project in Claude Code and ask Claude to interact with TickTick!

  4. (Optional) Run python -m src.utils.debug_tags to inspect task structures

TickTick OAuth Setup

1. Create a TickTick Developer App

  1. Go to TickTick Developer Portal

  2. Sign in with your TickTick account

  3. Create a new app

  4. Set the Redirect URI to: http://localhost:8000/auth/ticktick/callback

  5. Copy your Client ID and Client Secret

2. Configure Environment

Add your credentials to .env:

TICKTICK_CLIENT_ID=your_client_id_from_developer_portal TICKTICK_CLIENT_SECRET=your_client_secret_from_developer_portal TICKTICK_REDIRECT_URI=http://localhost:8000/auth/ticktick/callback

3. Get Access Token

Run python -m src.utils.get_token and follow the prompts.

Troubleshooting

"No access token found"

Run python -m src.utils.get_token to authenticate and get a new token.

"Failed to fetch projects"

  • Verify your access token is valid

  • Check that your OAuth app has the correct scopes: tasks:read tasks:write

  • Try getting a new token with python -m src.utils.get_token

"No date" showing for all tasks

  • The TickTick Open API doesn't return createdTime/modifiedTime for notes

  • Add dates to your task titles in format YYYY-MM-DD Task Name

  • The exporter will automatically extract and format these dates

Import errors

Make sure all dependencies are installed:

pip install -r requirements.txt

Development

Testing

The project includes a comprehensive test suite using pytest.

Running Tests

# Install test dependencies pip install -r requirements.txt # Run all tests pytest # Run with coverage report pytest --cov=src --cov-report=html # Run specific test file pytest tests/test_markdown_parser.py # Run tests with specific marker pytest -m unit # Run only unit tests pytest -m integration # Run only integration tests pytest -m api # Run only API tests # Run with verbose output pytest -v

Test Structure

  • tests/conftest.py - Shared fixtures and test configuration

  • tests/test_markdown_parser.py - Tests for markdown parsing (40+ tests)

  • tests/test_task_importer.py - Tests for task import functionality

  • tests/test_notes_exporter.py - Tests for export functionality

  • tests/test_ticktick_api.py - Tests for API wrapper

Test Coverage

The test suite covers:

  • Markdown parsing with various formats

  • Task import with dry-run and actual creation

  • Export to Markdown and JSON formats

  • API wrapper with mocked responses

  • Edge cases and error handling

  • Project and tag filtering

Writing New Tests

# tests/test_example.py import pytest @pytest.mark.unit def test_example(sample_markdown_content): """Test description""" # Your test code here assert True

Available fixtures:

  • sample_markdown_content - Sample markdown for testing

  • mock_ticktick_api - Mocked API instance

  • mock_env_token - Mocked environment token

  • sample_tasks - Sample task data

File Responsibilities

  • src/api/ticktick_api.py - Pure API wrapper, no business logic

  • src/exporters/notes_exporter.py - Export logic and functionality

  • src/importers/task_importer.py - Import logic and functionality

  • src/utils/get_token.py - Simple OAuth flow helper

  • src/utils/debug_tags.py - Debugging and inspection utility

  • ticktick_cli.py - Main unified CLI interface

Adding New Export Formats

Extend the BaseExporter class:

from src.exporters.notes_exporter import BaseExporter class CSVExporter(BaseExporter): def export(self, tasks, output_file, metadata): # Your CSV export logic here pass

Then use it:

manager.export_by_tag( tag_name="notes", output_file="notes.csv", exporter=CSVExporter() )

Requirements

  • python-dotenv >= 1.1.1

  • requests >= 2.26.0

See requirements.txt for complete list.

License

MIT License - see LICENSE for details.

Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

Roadmap

Future ideas under consideration:

  • Full CLI interface with Click

  • Additional export formats (CSV, HTML, PDF)

  • Task management features (update, delete, complete)

  • Configuration system

  • Package distribution on PyPI

Support

For issues or questions:

  1. Check the Troubleshooting section

  2. Review the TickTick API Documentation

  3. Open an issue (once repository is public)

-
security - not tested
A
license - permissive license
-
quality - not tested

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sidlendhe/ticktick-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server