mcpField
T
Ticktick Mcp

Ticktick Mcp

本地服务
github.com/dev-mirzabicer开发工具14540 周前更新

关于 Ticktick Mcp

ticktick-sdk 是一个面向 TickTick(及滴答清单)的异步 Python SDK,并内置 MCP 服务,可让 AI 助手管理任务、项目、标签和习惯。适合需要以编程方式或通过 AI 助手操作 TickTick 的用户。

主要功能

  1. 01异步 Python SDK,基于 httpx 构建
  2. 02通过 MCP 服务暴露 43 个工具
  3. 03批量创建、更新、完成与删除任务
  4. 04管理看板列、标签与文件夹
  5. 05完整的习惯追踪与打卡功能
  6. 06基于 Pydantic v2 的类型校验

适用场景

  1. 01让 AI 助手查询今日到期任务并创建新任务
  2. 02通过 AI 助手为习惯打卡并查看连续记录
  3. 03在 Python 应用中批量管理 TickTick 任务

MCP 相关

该项目提供 MCP 服务,向 MCP 客户端暴露任务、项目、看板列、标签、习惯、用户统计与专注数据等工具,并支持按模块或工具名过滤。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

ticktick-sdk:TickTick MCP 服务与完整 Python SDK

PyPI - Version Python 3.11+ License: MIT PyPI Downloads

一款功能全面的异步 Python SDK,适用于 TickTick,并支持 MCP(Model Context Protocol)服务。

也完整支持 Dida365(滴答清单)。

通过 Python 以编程方式使用 TickTick,或让 AI 助手管理你的任务。

目录


功能

MCP 服务
  • 43 个工具:精简覆盖 TickTick 的各项功能
  • 批量操作:所有修改操作均接受列表(1–100 项)以进行批量处理
  • 适用于 AI:可与 Claude、GPT 及其他兼容 MCP 的助手配合使用
  • 双重输出:面向用户的 Markdown,面向机器的 JSON
Python 库
  • 全面支持异步:基于 httpx 构建,支持高性能异步操作
  • 批量操作:单次调用最多可创建、更新、删除或完成 100 个任务
  • 完整的任务管理:创建、读取、更新、删除、完成、移动和置顶任务
  • 看板:全面的列管理(创建、更新、删除列,以及在列之间移动任务)
  • 项目组织:项目、文件夹、看板
  • 标签系统:支持颜色的分层标签
  • 习惯追踪:完整支持习惯的增删改查,以及批量签到、连续记录和目标
  • 专注/Pomodoro:访问专注时段数据和统计信息
  • 用户分析:效率评分、等级、完成率
开发者体验
  • 类型安全:使用 Pydantic v2 进行全面验证,并提供完善的类型提示
  • 经过充分测试:包含 300 多项测试,覆盖模拟和实时 API 交互
  • 文档齐全:提供详尽的文档字符串和示例

为什么选择这个库?

两套 API 难题

TickTick 有两套不同的 API:

API类型用途
V1 (OAuth2)官方,提供文档获取包含所有任务的项目、执行基本操作
V2 (Session)非官方,通过逆向工程得出标签、文件夹、习惯、专注、子任务等

官方 V1 API 的功能有限。TickTick 的大多数高级功能(标签、习惯、专注追踪)只能通过未公开文档的 V2 Web API 使用。本库结合了两套 API,会自动将每项操作路由到合适的 API。

与其他库的比较

根据对现有 TickTick Python 库实际源代码的分析:

功能ticktick-sdkpyticktickticktick-pytickthonticktick-python
I/O 模型异步异步同步同步同步
类型系统Pydantic V2Pydantic V2字典attrsaddict
MCP 服务是否否否否
习惯完整 CRUD否基础基础否
专注/Pomo是是是是否
统一 V1+V2智能路由分离两者仅 V2仅 V2
子任务高级批量是基础基础
标签完整(合并/重命名)是是是否

主要区别:

  • MCP 服务:只有 ticktick-sdk 提供基于 Model Context Protocol 的 AI 助手集成
  • 统一 API 路由:根据功能需求,自动将操作路由到 V1 或 V2
  • 完整的习惯 CRUD:完整的习惯管理,包括打卡、连续记录、归档/取消归档
  • 异步优先:基于 httpx 构建,支持高性能异步操作

安装

pip install ticktick-sdk

要求:

  • Python 3.11+
  • TickTick 账户(免费版或 Pro)

MCP 服务设置与使用

通过 Model Context Protocol,使用 Claude 等 AI 助手操作 TickTick。

第 1 步:注册应用
  1. 前往 TickTick Developer Portal
  2. 点击 "Create App"
  3. 填写:
    • App Name:例如,"My TickTick MCP"
    • Redirect URI:http://127.0.0.1:8080/callback
  4. 保存你的 Client ID 和 Client Secret
第 2 步:获取 OAuth2 访问令牌

使用你的凭据运行身份验证命令:

TICKTICK_CLIENT_ID=your_client_id \
TICKTICK_CLIENT_SECRET=your_client_secret \
ticktick-sdk auth

此操作将:

  1. 打开浏览器,前往 TickTick 授权页面
  2. 授权应用——点击 "Authorize" 以授予访问权限
  3. 返回终端——授权后,你将看到类似以下内容的输出:
============================================================
  SUCCESS! Here is your access token:
============================================================

a]234abc-5678-90de-f012-34567890abcd

============================================================

NEXT STEPS:

For Claude Code users:
  Run (replace YOUR_* placeholders):
    claude mcp add ticktick \
      -e TICKTICK_CLIENT_ID=YOUR_CLIENT_ID \
      ...
  1. 复制此令牌——下一步需要用到它

注意:有时浏览器会显示“凭据无效”错误页面。只需刷新页面即可正常使用。

SSH/无头模式用户:添加 --manual 标志,使用无需浏览器的文本流程。

第 3 步:配置 AI 助手
Claude Code(推荐)
claude mcp add ticktick \
  -e TICKTICK_CLIENT_ID=your_client_id \
  -e TICKTICK_CLIENT_SECRET=your_client_secret \
  -e TICKTICK_ACCESS_TOKEN=your_access_token \
  -e TICKTICK_USERNAME=your_email \
  -e TICKTICK_PASSWORD=your_password \
  -- ticktick-sdk

注意:对于 TICKTICK_ACCESS_TOKEN,粘贴从第 2 步复制的令牌。

验证是否正常工作:

claude mcp list        # See all configured servers
/mcp                   # Within Claude Code, check server status
Claude Desktop

将以下内容添加到 Claude Desktop 配置中:

macOS:~/Library/Application Support/Claude/claude_desktop_config.json Windows:%APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "ticktick": {
      "command": "ticktick-sdk",
      "env": {
        "TICKTICK_CLIENT_ID": "your_client_id",
        "TICKTICK_CLIENT_SECRET": "your_client_secret",
        "TICKTICK_ACCESS_TOKEN": "your_access_token",
        "TICKTICK_USERNAME": "your_email",
        "TICKTICK_PASSWORD": "your_password"
      }
    }
  }
}
其他兼容 MCP 的工具

此服务适用于任何支持 Model Context Protocol 的工具,包括大多数现代 AI 助手和 IDE。配置方式类似——只需提供命令(ticktick-sdk)和上文所示的环境变量。

CLI 参考

ticktick-sdk 命令提供多个子命令:

命令描述
ticktick-sdk启动 MCP 服务(默认)
ticktick-sdk server启动 MCP 服务(显式指定)
ticktick-sdk server --host HOST使用指定的 API 主机(ticktick.com 或 dida365.com)
ticktick-sdk server --enabledModules MODULES仅启用指定的工具模块(逗号分隔)
ticktick-sdk server --enabledTools TOOLS仅启用指定的工具(逗号分隔)
ticktick-sdk auth获取 OAuth2 访问令牌(打开浏览器)
ticktick-sdk auth --manual获取 OAuth2 访问令牌(适用于 SSH)
ticktick-sdk --version显示版本信息
ticktick-sdk --help显示帮助信息

工具筛选(减少 AI 助手的上下文窗口用量):

# Enable only task and project tools
ticktick-sdk server --enabledModules tasks,projects

# Enable specific tools only
ticktick-sdk server --enabledTools ticktick_create_tasks,ticktick_list_tasks

# Available modules: tasks, projects, folders, columns, tags, habits, user, focus
示例对话

配置完成后,你可以向 Claude 提出以下问题或请求:

  • “我今天有哪些到期任务?”
  • “创建一个任务,明天下午 2 点给 John 打电话”
  • “显示我的高优先级任务”
  • “将购物任务标记为已完成”
  • “我目前的「锻炼」习惯连续打卡了多少天?”
  • “为我今天的冥想习惯打卡”
  • “创建一个新习惯:每天喝 8 杯水”
可用的 MCP 工具(共 43 个)

所有变更类工具都支持以列表形式批量操作(1-100 项)。

任务工具(支持批量操作)
工具描述
ticktick_create_tasks创建 1-50 个任务,并设置标题、日期、标签等
ticktick_get_task按 ID 获取任务详情
ticktick_list_tasks列出任务(可通过状态筛选器查看进行中/已完成/已放弃/已删除的任务)
ticktick_update_tasks更新 1-100 个任务(包括列分配)
ticktick_complete_tasks完成 1-100 个任务
ticktick_delete_tasks删除 1-100 个任务(移至回收站)
ticktick_move_tasks在项目之间移动 1-50 个任务
ticktick_set_task_parents为 1-50 个任务设置父子关系
ticktick_unparent_tasks移除 1-50 个任务的父级关系
ticktick_search_tasks按文本搜索任务
ticktick_pin_tasks置顶或取消置顶 1-100 个任务
项目工具
工具描述
ticktick_list_projects列出所有项目
ticktick_get_project获取项目详情及其任务
ticktick_create_project创建新项目
ticktick_update_project更新项目属性
ticktick_delete_project删除项目
文件夹工具
工具描述
ticktick_list_folders列出所有文件夹
ticktick_create_folder创建文件夹
ticktick_rename_folder重命名文件夹
ticktick_delete_folder删除文件夹
看板列工具
工具描述
ticktick_list_columns列出看板项目的列
ticktick_create_column创建看板列
ticktick_update_column更新列名称或顺序
ticktick_delete_column删除看板列
标签工具
工具描述
ticktick_list_tags列出所有标签
ticktick_create_tag创建带颜色的标签
ticktick_update_tag更新标签属性(包括通过标签名称重命名)
ticktick_delete_tag删除标签
ticktick_merge_tags合并两个标签
习惯工具(支持批量操作)
工具描述
ticktick_habits列出所有习惯
ticktick_habit获取习惯详情
ticktick_habit_sections列出时段(早晨/下午/夜间)
ticktick_create_habit创建新习惯
ticktick_update_habit更新习惯属性(包括归档/取消归档)
ticktick_delete_habit删除习惯
ticktick_checkin_habits为 1-50 个习惯打卡(支持补打卡)
ticktick_habit_checkins获取打卡历史记录
用户与分析工具
工具描述
ticktick_get_profile获取用户个人资料
ticktick_get_status获取账户状态
ticktick_get_statistics获取效率统计数据
ticktick_get_preferences获取用户偏好设置
ticktick_focus_heatmap获取专注热力图数据
ticktick_focus_by_tag按标签获取专注时间

Python 库的设置与使用

在 Python 应用中以编程方式使用 TickTick。

设置
步骤 1:注册应用

与 MCP 设置相同,前往 TickTick 开发者门户 并创建应用。

步骤 2:创建 .env 文件

在项目目录中创建一个 .env 文件:

# V1 API (OAuth2)
TICKTICK_CLIENT_ID=your_client_id_here
TICKTICK_CLIENT_SECRET=your_client_secret_here
TICKTICK_REDIRECT_URI=http://127.0.0.1:8080/callback
TICKTICK_ACCESS_TOKEN=  # Will be filled in Step 3

# V2 API (Session)
[email protected]
TICKTICK_PASSWORD=your_ticktick_password

# Optional
TICKTICK_TIMEOUT=30
步骤 3:获取 OAuth2 访问令牌
# Source your .env file first, or export the variables
ticktick-sdk auth

将访问令牌复制到 .env 文件中。

步骤 4:验证设置
import asyncio
from ticktick_sdk import TickTickClient

async def test():
    async with TickTickClient.from_settings() as client:
        profile = await client.get_profile()
        print(f'Connected as: {profile.display_name}')

asyncio.run(test())
快速开始
import asyncio
from ticktick_sdk import TickTickClient

async def main():
    async with TickTickClient.from_settings() as client:
        # Create a task
        task = await client.create_task(
            title="Learn ticktick-sdk",
            tags=["python", "productivity"],
        )
        print(f"Created: {task.title} (ID: {task.id})")

        # List all tasks
        tasks = await client.get_all_tasks()
        print(f"You have {len(tasks)} active tasks")

        # Complete the task
        await client.complete_task(task.id, task.project_id)
        print("Task completed!")

asyncio.run(main())
任务
创建任务
from datetime import datetime, timedelta
from ticktick_sdk import TickTickClient

async with TickTickClient.from_settings() as client:
    # Simple task
    task = await client.create_task(title="Buy groceries")

    # Task with due date and priority
    task = await client.create_task(
        title="Submit report",
        due_date=datetime.now() + timedelta(days=1),
        priority="high",  # none, low, medium, high
    )

    # Task with tags and content
    task = await client.create_task(
        title="Review PR #123",
        content="Check for:\n- Code style\n- Tests\n- Documentation",
        tags=["work", "code-review"],
    )

    # Recurring task (MUST include start_date!)
    task = await client.create_task(
        title="Daily standup",
        start_date=datetime(2025, 1, 20, 9, 0),
        recurrence="RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR",
    )

    # Task with reminder
    task = await client.create_task(
        title="Meeting with team",
        due_date=datetime(2025, 1, 20, 14, 0),
        reminders=["TRIGGER:-PT15M"],  # 15 minutes before
    )

    # All-day task
    task = await client.create_task(
        title="Project deadline",
        due_date=datetime(2025, 1, 31),
        all_day=True,
    )
管理任务
async with TickTickClient.from_settings() as client:
    # Get a specific task
    task = await client.get_task(task_id="...")

    # Update a task
    task.title = "Updated title"
    task.priority = 5  # high priority
    await client.update_task(task)

    # Complete a task
    await client.complete_task(task_id="...", project_id="...")

    # Delete a task (moves to trash)
    await client.delete_task(task_id="...", project_id="...")

    # Move task to another project
    await client.move_task(
        task_id="...",
        from_project_id="...",
        to_project_id="...",
    )
子任务
async with TickTickClient.from_settings() as client:
    # Create parent task
    parent = await client.create_task(title="Main task")

    # Create child task
    child = await client.create_task(title="Subtask")

    # Make it a subtask (parent_id in create is ignored by API)
    await client.make_subtask(
        task_id=child.id,
        parent_id=parent.id,
        project_id=child.project_id,
    )

    # Remove parent relationship
    await client.unparent_subtask(
        task_id=child.id,
        project_id=child.project_id,
    )
查询任务
async with TickTickClient.from_settings() as client:
    # All active tasks
    all_tasks = await client.get_all_tasks()

    # Tasks due today
    today = await client.get_today_tasks()

    # Overdue tasks
    overdue = await client.get_overdue_tasks()

    # Tasks by tag
    work_tasks = await client.get_tasks_by_tag("work")

    # Tasks by priority
    urgent = await client.get_tasks_by_priority("high")

    # Search tasks
    results = await client.search_tasks("meeting")

    # Recently completed
    completed = await client.get_completed_tasks(days=7, limit=50)

    # Abandoned tasks ("won't do")
    abandoned = await client.get_abandoned_tasks(days=30)

    # Deleted tasks (in trash)
    deleted = await client.get_deleted_tasks(limit=50)
项目与文件夹
项目
async with TickTickClient.from_settings() as client:
    # List all projects
    projects = await client.get_all_projects()
    for project in projects:
        print(f"{project.name} ({project.id})")

    # Get project with all its tasks
    project_data = await client.get_project_tasks(project_id="...")
    print(f"Project: {project_data.project.name}")
    print(f"Tasks: {len(project_data.tasks)}")

    # Create a project
    project = await client.create_project(
        name="Q1 Goals",
        color="#4A90D9",
        view_mode="kanban",  # list, kanban, timeline
    )

    # Update a project
    await client.update_project(
        project_id=project.id,
        name="Q1 Goals 2025",
        color="#FF5500",
    )

    # Delete a project
    await client.delete_project(project_id="...")
文件夹(项目组)
async with TickTickClient.from_settings() as client:
    # List all folders
    folders = await client.get_all_folders()

    # Create a folder
    folder = await client.create_folder(name="Work Projects")

    # Create project in folder
    project = await client.create_project(
        name="Client A",
        folder_id=folder.id,
    )

    # Rename a folder
    await client.rename_folder(folder_id=folder.id, name="Work")

    # Delete a folder
    await client.delete_folder(folder_id="...")
标签

TickTick 标签支持层级关系(父子关系)和自定义颜色。

async with TickTickClient.from_settings() as client:
    # List all tags
    tags = await client.get_all_tags()
    for tag in tags:
        print(f"{tag.label} ({tag.name}) - {tag.color}")

    # Create a tag
    tag = await client.create_tag(
        name="urgent",
        color="#FF0000",
    )

    # Create nested tag
    child_tag = await client.create_tag(
        name="critical",
        parent="urgent",  # Parent tag name
    )

    # Rename a tag
    await client.rename_tag(old_name="urgent", new_name="priority")

    # Update tag color or parent
    await client.update_tag(
        name="priority",
        color="#FF5500",
    )

    # Merge tags (move all tasks from source to target)
    await client.merge_tags(source="old-tag", target="new-tag")

    # Delete a tag
    await client.delete_tag(name="obsolete")
习惯

TickTick 习惯是你想要每天追踪的重复活动。

习惯类型
类型描述示例
Boolean简单的“是”或“否”“你今天锻炼了吗?”
Real数值计数器“你读了多少页?”
创建和管理习惯
async with TickTickClient.from_settings() as client:
    # List all habits
    habits = await client.get_all_habits()

    # Boolean habit (yes/no)
    exercise = await client.create_habit(
        name="Exercise",
        color="#4A90D9",
        reminders=["07:00", "19:00"],
        target_days=30,
        encouragement="Stay strong!",
    )

    # Numeric habit
    reading = await client.create_habit(
        name="Read",
        habit_type="Real",
        goal=30,           # 30 pages per day
        step=5,            # +5 button increment
        unit="Pages",
    )

    # Check in a habit (today)
    habit = await client.checkin_habit("habit_id")
    print(f"Streak: {habit.current_streak} days!")

    # Check in for a past date (backdate)
    from datetime import date
    habit = await client.checkin_habit("habit_id", checkin_date=date(2025, 12, 15))

    # Archive/unarchive
    await client.archive_habit("habit_id")
    await client.unarchive_habit("habit_id")
习惯重复规则(RRULE 格式)
日程RRULE
每天(每天)RRULE:FREQ=WEEKLY;BYDAY=SU,MO,TU,WE,TH,FR,SA
仅工作日RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR
仅周末RRULE:FREQ=WEEKLY;BYDAY=SA,SU
每周 X 次RRULE:FREQ=WEEKLY;TT_TIMES=5
指定日期RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR
专注/番茄钟
from datetime import date, timedelta

async with TickTickClient.from_settings() as client:
    # Focus heatmap (like GitHub contribution graph)
    heatmap = await client.get_focus_heatmap(
        start_date=date.today() - timedelta(days=90),
        end_date=date.today(),
    )

    # Focus time by tag
    by_tag = await client.get_focus_by_tag(days=30)
    for tag, seconds in sorted(by_tag.items(), key=lambda x: -x[1]):
        hours = seconds / 3600
        print(f"  {tag}: {hours:.1f} hours")
用户与统计信息
async with TickTickClient.from_settings() as client:
    # User profile
    profile = await client.get_profile()
    print(f"Username: {profile.username}")

    # Account status
    status = await client.get_status()
    print(f"Pro User: {status.is_pro}")
    print(f"Inbox ID: {status.inbox_id}")

    # Productivity statistics
    stats = await client.get_statistics()
    print(f"Level: {stats.level}")
    print(f"Score: {stats.score}")
    print(f"Tasks completed today: {stats.today_completed}")
错误处理
from ticktick_sdk import (
    TickTickClient,
    TickTickError,
    TickTickNotFoundError,
    TickTickAuthenticationError,
    TickTickRateLimitError,
    TickTickValidationError,
)

async with TickTickClient.from_settings() as client:
    try:
        task = await client.get_task("nonexistent-id")
    except TickTickNotFoundError as e:
        print(f"Task not found: {e}")
    except TickTickAuthenticationError:
        print("Authentication failed - check credentials")
    except TickTickRateLimitError:
        print("Rate limited - wait and retry")
    except TickTickValidationError as e:
        print(f"Invalid input: {e}")
    except TickTickError as e:
        print(f"TickTick error: {e}")

架构

┌─────────────────────────────────────────────────────────────┐
│                    Your Application                         │
│              (or MCP Server for AI Assistants)              │
└─────────────────────────┬───────────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────────┐
│                    TickTickClient                           │
│            High-level, user-friendly async API              │
│   (tasks, projects, tags, habits, focus, user methods)      │
└─────────────────────────┬───────────────────────────────────┘
                          │
┌─────────────────────────▼───────────────────────────────────┐
│                  UnifiedTickTickAPI                         │
│        Routes calls to V1 or V2, converts responses         │
│              to unified Pydantic models                     │
└─────────────────────────┬───────────────────────────────────┘
                          │
           ┌──────────────┴──────────────┐
           ▼                             ▼
┌──────────────────────┐      ┌──────────────────────┐
│      V1 API          │      │      V2 API          │
│     (OAuth2)         │      │     (Session)        │
│                      │      │                      │
│ • Official API       │      │ • Unofficial API     │
│ • Project with tasks │      │ • Tags, folders      │
│ • Limited features   │      │ • Habits, focus      │
│                      │      │ • Full subtasks      │
└──────────────────────┘      └──────────────────────┘
关键设计决策
  1. V2 优先:大多数操作使用 V2 API(功能更多),仅在必要时回退到 V1
  2. 统一模型:无论数据由哪个 API 提供,都使用同一套 Pydantic 模型
  3. 全程异步:所有 I/O 操作均为异步,以提升性能
  4. 类型安全:提供完整的类型提示和 Pydantic 验证

API 参考

模型
模型描述
Task包含标题、日期、优先级、标签、子任务、重复规则等的任务
Project用于容纳任务的项目/列表
ProjectGroup用于整理项目的文件夹
ProjectData包含其任务的项目(来自 get_project_tasks)
Column看板中用于整理任务的列
Tag包含名称、标签、颜色和可选父级的标签
Habit包含类型、目标、连续记录和签到的重复习惯
HabitSection按一天中的时段分组(上午/下午/晚上)
HabitCheckin单条习惯签到记录
HabitPreferences用户习惯设置
User用户个人资料信息
UserStatus账户状态(Pro、收件箱 ID 等)
UserStatistics生产力统计信息(等级、分数、计数)
ChecklistItem任务中的子任务/清单项目
枚举
枚举值
TaskStatusABANDONED (-1)、ACTIVE (0)、COMPLETED (2)
TaskPriorityNONE (0)、LOW (1)、MEDIUM (3)、HIGH (5)
TaskKindTEXT、NOTE、CHECKLIST
ProjectKindTASK、NOTE
ViewModeLIST、KANBAN、TIMELINE
异常
异常描述
TickTickError所有错误的基类异常
TickTickAuthenticationError身份验证失败
TickTickNotFoundError未找到资源
TickTickValidationError输入数据无效
TickTickRateLimitError超出速率限制
TickTickConfigurationError缺少配置
TickTickForbiddenError访问被拒绝
TickTickServerError服务端错误

重要:TickTick API 的特殊行为

TickTick 的 API 有一些你需要了解的独特行为:

1. 重复任务需要 start_date

如果创建重复任务时未设置 start_date,TickTick 会悄无声息地忽略重复规则。

# WRONG - recurrence will be ignored!
task = await client.create_task(
    title="Daily standup",
    recurrence="RRULE:FREQ=DAILY",
)

# CORRECT
task = await client.create_task(
    title="Daily standup",
    start_date=datetime(2025, 1, 20, 9, 0),
    recurrence="RRULE:FREQ=DAILY",
)
2. 子任务需要单独调用

在创建任务时设置 parent_id 会被 API 忽略:

# Create the child task first
child = await client.create_task(title="Subtask")

# Then make it a subtask
await client.make_subtask(
    task_id=child.id,
    parent_id="parent_task_id",
    project_id=child.project_id,
)
3. 软删除

删除任务会将其移至垃圾箱(deleted=1),而非永久删除。

4. 清除日期

要清除任务的 due_date,还必须清除 start_date:

task.due_date = None
task.start_date = None
await client.update_task(task)
5. 标签顺序不会保留

API 不会保留标签顺序——返回的标签顺序可能不同。

6. 收件箱是特殊项目

收件箱是一个特殊项目,无法删除。通过 await client.get_status() 获取其 ID。


环境变量

变量必填描述
TICKTICK_CLIENT_ID是开发者门户中的 OAuth2 客户端 ID
TICKTICK_CLIENT_SECRET是OAuth2 客户端密钥
TICKTICK_ACCESS_TOKEN是OAuth2 访问令牌(来自 auth 命令)
TICKTICK_USERNAME是你的 TickTick 邮箱
TICKTICK_PASSWORD是你的 TickTick 密码
TICKTICK_REDIRECT_URI否OAuth2 重定向 URI(默认值:http://127.0.0.1:8080/callback)
TICKTICK_HOST否API 主机:ticktick.com(默认值)或 dida365.com(中文)
TICKTICK_TIMEOUT否请求超时时间(秒,默认值:30)
TICKTICK_DEVICE_ID否V2 API 的设备 ID(自动生成)

运行测试

# Install dev dependencies
pip install -e ".[dev]"

# All tests (mock mode - no API calls)
pytest

# With verbose output
pytest -v

# Live tests (requires credentials)
pytest --live

# With coverage
pytest --cov=ticktick_sdk --cov-report=term-missing
测试标记
标记描述
unit单元测试(快速、隔离)
tasks与任务相关的测试
projects与项目相关的测试
tags与标签相关的测试
habits与习惯相关的测试
focus专注/Pomodoro 测试
pinning任务置顶测试
columnsKanban 列测试
mock_only仅适用于模拟对象的测试
live_only仅在使用 --live 时运行的测试

故障排除

“Token exchange failed”
  • 确认 Client ID 和 Client Secret 正确无误
  • 确保 Redirect URI 完全一致(包括末尾的斜杠)
  • 检查你使用的是正确的 TickTick 开发者门户
“Authentication failed”
  • 检查你的 TickTick 用户名(邮箱)和密码
  • 尝试登录 ticktick.com 以验证凭据
“V2 initialization failed”
  • 你的密码可能包含特殊字符,请尝试更改密码
  • 检查是否启用了 2FA/MFA(目前不支持)
“Rate limit exceeded”
  • 等待 30-60 秒后重试
  • 降低 API 调用频率

贡献

欢迎贡献!请按以下步骤操作:

  1. Fork 此仓库
  2. 创建功能分支(git checkout -b feature/amazing-feature)
  3. 为新功能编写测试
  4. 确保所有测试均通过(pytest)
  5. 运行类型检查(mypy src/)
  6. 提交 pull request
开发环境设置
git clone https://github.com/dev-mirzabicer/ticktick-sdk.git
cd ticktick-sdk
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

许可证

MIT License - 详见 LICENSE。


致谢

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。