Skip to main content

dida365

PyPI version Python versions License: MIT

滴答清单 / dida365(TickTick)官方 MCP 服务 的 Python SDK。把 32 个 MCP 工具包装成同名方法,同时提供同步与异步接口、完整类型标注、自动重试与凭据隔离。

A Python SDK for the official dida365 / TickTick MCP server. Wraps all 32 MCP tools as Python methods with sync + async clients, full type stubs, automatic retries, and safe credential handling.


中文文档

安装

pip install dida365-sdk            # 仅同步客户端
pip install "dida365-sdk[async]"   # 同时安装 httpx,启用 AsyncClient

安装名是 dida365-sdk,导入名仍是 import dida365。

获取 Token

打开 滴答清单网页版,进入 头像 → 设置 → 账户与安全 → API 口令,新建并复制 token。

设置环境变量(推荐):

export DIDA365_TOKEN=dp_xxxxxxxxxxxxxxxxxxxxxxxxxx

或者在项目目录创建 .env 文件:

DIDA365_TOKEN=dp_xxxxxxxxxxxxxxxxxxxxxxxxxx

快速开始

import dida365

with dida365.Client() as client:
    # 1. 列出所有清单
    projects = client.list_projects()

    # 2. 创建任务
    task = client.create_task(task={
        "projectId": projects[0]["id"],
        "title": "明天提交周报",
        "priority": 5,                    # 0=无 1=低 3=中 5=高
        "startDate": "2026-05-09T09:00:00+08:00",
        "isAllDay": False,
        "timeZone": "Asia/Shanghai",
        "tags": ["work"],
    })

    # 3. 查询今日待办
    today = client.list_undone_tasks_by_time_query(query_command="today")

    # 4. 完成任务
    client.complete_task(project_id=task["projectId"], task_id=task["id"])

异步用法

import asyncio
import dida365

async def main() -> None:
    async with dida365.AsyncClient() as client:
        projects, today = await asyncio.gather(
            client.list_projects(),
            client.list_undone_tasks_by_time_query(query_command="today"),
        )
        print(f"{len(projects)} projects, {len(today)} tasks today")

asyncio.run(main())

错误处理

import dida365

try:
    client = dida365.Client(token="bad-token")
except dida365.AuthenticationError as e:
    print(f"token 失效: {e.code}")          # 401 / 403
except dida365.MCPProtocolError as e:
    print(f"网络/协议错误: {e}")
except dida365.ToolError as e:
    print(f"工具调用失败: {e.tool} -> {e}")

全部 32 个工具

类别 工具
清单 list_projects get_project_by_id get_project_with_undone_tasks create_project update_project
任务 create_task update_task get_task_in_project get_task_by_id complete_task complete_tasks_in_project move_task batch_add_tasks batch_update_tasks
查询 search search_task fetch filter_tasks list_undone_tasks_by_date list_undone_tasks_by_time_query list_completed_tasks_by_date
习惯 list_habits list_habit_sections get_habit create_habit update_habit upsert_habit_checkins get_habit_checkins
专注 get_focus get_focuses_by_time delete_focus
偏好 get_user_preference

每个工具的参数与返回类型已经在 dida365/client.pyi 中声明,IDE / mypy / pyright 都能直接获取补全。

高级配置

client = dida365.Client(
    token="dp_xxx",                  # 显式 token(默认从 env 读取)
    url="https://mcp.dida365.com",   # MCP 服务地址
    timeout=(5.0, 30.0),             # (connect, read)
    max_retries=3,                   # 5xx / 429 / 网络错误的重试次数
)

Client 与 AsyncClient 都自动遵循 Retry-After 头部、自动透传 Mcp-Session-Id 与 MCP-Protocol-Version 头部。

安全约定

  • repr(client) 不会泄露 token;只显示 Client(url=...)。
  • 进程环境变量只接受 DIDA365_TOKEN,避免与其他工具的 TOKEN 冲突。
  • .env 中可使用 DIDA365_TOKEN 或 TOKEN(仅在 cwd/.env 中生效)。

开发

本仓库使用 uv 管理 Python 环境与依赖。

git clone https://github.com/shawn-bluce/dida365-sdk.git
cd dida365-sdk
uv sync --all-extras           # 创建 .venv 并安装 dev + async 依赖

# 单元测试(不联网)
uv run pytest

# 实测脚本(会创建并关闭一个沙箱清单)
DIDA365_TOKEN=dp_xxx uv run python tests/integration/test_smoke_live.py

# 重新生成类型存根
uv run python scripts/generate_stubs.py --refresh

# 打包与发布
uv build                       # 生成 dist/*.whl 与 dist/*.tar.gz
uv publish                     # 上传到 PyPI(需配置 token)

English Documentation

Install

pip install dida365-sdk            # sync client only
pip install "dida365-sdk[async]"   # also installs httpx for AsyncClient

The distribution name is dida365-sdk; the import name remains import dida365.

Get a token

In the dida365 web app, open Profile → Settings → Account & Security → API Token, create and copy a new token. Then either:

export DIDA365_TOKEN=dp_xxxxxxxxxxxxxxxxxxxxxxxxxx

…or drop a .env file at the project root with DIDA365_TOKEN=....

Quickstart

import dida365

with dida365.Client() as client:
    projects = client.list_projects()

    task = client.create_task(task={
        "projectId": projects[0]["id"],
        "title": "Submit weekly report",
        "priority": 5,
        "startDate": "2026-05-09T09:00:00+08:00",
        "isAllDay": False,
        "timeZone": "Asia/Shanghai",
        "tags": ["work"],
    })

    today = client.list_undone_tasks_by_time_query(query_command="today")
    client.complete_task(project_id=task["projectId"], task_id=task["id"])

Async usage

import asyncio
import dida365

async def main() -> None:
    async with dida365.AsyncClient() as client:
        projects, today = await asyncio.gather(
            client.list_projects(),
            client.list_undone_tasks_by_time_query(query_command="today"),
        )
        print(f"{len(projects)} projects, {len(today)} tasks today")

asyncio.run(main())

Error handling

import dida365

try:
    client = dida365.Client(token="bad-token")
except dida365.AuthenticationError as e:
    ...                                  # HTTP 401 / 403
except dida365.MCPProtocolError as e:
    ...                                  # network / HTTP / JSON-RPC error
except dida365.ToolError as e:
    ...                                  # tool reported isError=true

Tool catalogue

All 32 server-advertised tools are dispatched dynamically by name and statically typed via client.pyi / async_client.pyi. Categories: projects (5), tasks (9), querying (7), habits (7), focus (3), preferences (1).

Advanced configuration

client = dida365.Client(
    token="dp_xxx",                   # explicit token (defaults to env)
    url="https://mcp.dida365.com",    # MCP endpoint
    timeout=(5.0, 30.0),              # (connect, read)
    max_retries=3,                    # 5xx / 429 / network retries
)

Both Client and AsyncClient honor Retry-After, round-trip Mcp-Session-Id, and send MCP-Protocol-Version on every non-initialize request.

Security defaults

  • repr(client) masks the bearer token.
  • Only DIDA365_TOKEN is read from process env (avoids collisions with TOKEN set by other tools).
  • .env in the current working directory accepts DIDA365_TOKEN or TOKEN.

Development

This repo uses uv to manage the Python environment and dependencies.

git clone https://github.com/shawn-bluce/dida365-sdk.git
cd dida365-sdk
uv sync --all-extras           # creates .venv and installs dev + async extras

# Unit tests (offline)
uv run pytest

# Live integration smoke test (creates a sandbox project, closes it after)
DIDA365_TOKEN=dp_xxx uv run python tests/integration/test_smoke_live.py

# Regenerate type stubs from the live MCP catalogue
uv run python scripts/generate_stubs.py --refresh

# Build & publish
uv build                       # produces dist/*.whl and dist/*.tar.gz
uv publish                     # uploads to PyPI (requires token)

License

MIT © 2026 Hao Zhang

Metadata

Release files for dida365-sdk 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dida365-sdk 0.1.0
File Size Uploaded
dida365_sdk-0.1.0.tar.gz 37.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dida365-sdk 0.1.0
File Interpreter ABI Platform
dida365_sdk-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 62.1 kB

Release files / dida365_sdk-0.1.0.tar.gz

Download URL dida365_sdk-0.1.0.tar.gz
Size 37.7 kB
Tags Source
SHA-256 checksum
How to use checksums
9a554b62d71777408a99ce16f6fbad67808766a6a42150487bd86ff74ad0a409
BLAKE2b-256 checksum
How to use checksums
63855b5aa8f55e3691bb350c76d0f3a088e5f3640c1c7cbc7208da16af822a73
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 8, 2026.

Transparency log

Release files / dida365_sdk-0.1.0-py3-none-any.whl

Download URL dida365_sdk-0.1.0-py3-none-any.whl
Size 24.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dc3dce1451735220eb10da9650e1fc2d13b0f079e0fba216af107a7c8e512263
BLAKE2b-256 checksum
How to use checksums
dcf7b7832f6449ca3ae9f631618685f1436e3916737e55b8f49371d7689d187b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page