mcpField
N
notion-sdk

notion-sdk

github.com/terrylica生産性1132 回インストール今日更新
リポジトリ

notion-sdk について

notion-sdkは、公式Python notion-client SDKを通じてNotionを自動化するスキルです。ページ作成、コンテンツブロック追加、データベース検索のスクリプトを備え、トークン検証とリトライ処理にも対応します。

主な機能

  1. 01ページとデータベース項目の作成
  2. 02書式付きコンテンツブロックの追加
  3. 03データベースの検索、絞り込み、並べ替え
  4. 04インテグレーショントークンの検証
  5. 05レート制限やサーバーエラー時の再試行

活用シーン

  1. 01PythonワークフローでのNotionページ作成
  2. 02ページへの構造化コンテンツの追加
  3. 03絞り込んだデータベースレコードの取得
  4. 04一時的なAPIエラーへの対処

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/terrylica/cc-skills --skill notion-sdk

インストール後、Claude Code で/notion-sdkを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
block-types.md
evolution-log.md
pagination.md
property-types.md
rich-text.md
scripts/
add_blocks.py
create_page.py
notion_wrapper.py
query_database.py
tests/
test_block_builders.py
test_client.py
test_filter_builders.py
test_integration.py
test_property_builders.py

詳細

Notion SDK スキル

公式の notion-client Python SDK を使用して、Notion をプログラムから操作します。最新バージョンは PyPI をご覧ください。

自己進化型スキル:このスキルは使用することで改善されます。手順に誤りがある場合、パラメーターに変更があった場合、または回避策が必要だった場合は、後回しにせず、すぐにこのファイルを修正してください。実際に再現できる問題がある場合にのみ更新してください。

このスキルを使用する場面

次のような場合にこのスキルを使用します。

  • API 経由で Notion にページやデータベースを作成する
  • Notion のデータベースをプログラムからクエリする
  • Notion のページにブロック(テキスト、コード、見出し)を追加する
  • Python で Notion のワークフローを自動化する
  • 外部データソースを Notion と連携する

事前準備:トークンの取得

Notion API を操作する前に、インテグレーショントークンを取得します。

AskUserQuestion(questions=[{
    "question": "Please provide your Notion Integration Token (starts with ntn_ or secret_)",
    "header": "Notion Token",
    "options": [
        {"label": "I have a token ready", "description": "Token from notion.so/my-integrations"},
        {"label": "Need to create one", "description": "Go to notion.so/my-integrations → New integration"}
    ],
    "multiSelect": false
}])

ユーザーからトークンを受け取った後:

  1. 形式を検証します(ntn_ または secret_ で始まる必要があります)
  2. scripts/notion_wrapper.py の validate_token() でテストします
  3. ユーザーに注意を促します:各ページ/データベースをインテグレーションと共有する必要があります

クイックスタート

1. データベースにページを作成する
from notion_client import Client
from scripts.create_page import (
    create_database_page,
    title_property,
    status_property,
    date_property,
)

client = Client(auth="ntn_...")
page = create_database_page(
    client,
    data_source_id="abc123...",  # Database ID
    properties={
        "Name": title_property("My New Task"),
        "Status": status_property("In Progress"),
        "Due Date": date_property("2025-12-31"),
    }
)
print(f"Created: {page['url']}")
2. コンテンツブロックを追加する
from scripts.add_blocks import (
    append_blocks,
    heading,
    paragraph,
    bullet,
    code_block,
    callout,
)

blocks = [
    heading("Overview", level=2),
    paragraph("This page was created via the Notion API."),
    callout("Remember to share the page with your integration!", emoji="⚠️"),
    heading("Tasks", level=3),
    bullet("First task"),
    bullet("Second task"),
    code_block("print('Hello, Notion!')", language="python"),
]
append_blocks(client, page["id"], blocks)
3. データベースをクエリする
from scripts.query_database import (
    query_data_source,
    checkbox_filter,
    status_filter,
    and_filter,
    sort_by_property,
)

# Find incomplete high-priority items
results = query_data_source(
    client,
    data_source_id="abc123...",
    filter_obj=and_filter(
        checkbox_filter("Done", False),
        status_filter("Priority", "High")
    ),
    sorts=[sort_by_property("Due Date", "ascending")]
)
for page in results:
    title = page["properties"]["Name"]["title"][0]["plain_text"]
    print(f"- {title}")

利用可能なスクリプト

スクリプト用途
notion_wrapper.pyクライアントのセットアップ、トークンの検証、再試行ラッパー
create_page.pyページの作成、プロパティビルダー
add_blocks.pyブロックの追加、ブロックタイプビルダー
query_database.pyクエリ、フィルター、並べ替え、検索

リファレンス

重要な制約

レート制限
  • 平均 毎秒 3 リクエスト(短時間のバーストは許容されます)
  • レート制限を自動的に処理するには、api_call_with_retry() を使用します
  • 429 レスポンスには Retry-After ヘッダーが含まれます
認証モデル
  • ページ単位での共有が必要です(ワークスペース全体での共有ではありません)
  • ユーザーは各ページ/データベースにインテグレーションを明示的に追加する必要があります:
    • ページ → ... メニュー → コネクション → コネクションを追加 → インテグレーションを選択
API バージョン(v2.6.0+)
  • 複数ソースのデータベースでは、database_id の代わりに data_source_id を使用します
  • シンプルなデータベースでは、従来の database_id も引き続き使用できます
  • スクリプトは両方の形式を自動的に処理します
サポートされていない操作
  • ワークスペース設定の変更
  • ユーザー権限の管理
  • テンプレートの作成/管理
  • 請求/サブスクリプションへのアクセス

API の動作パターン

インテグレーションテストを通じて確認された知見です(検証用のテスト引用を記載)。

レート制限と再試行ロジック

api_call_with_retry() は一時的な障害を自動的に処理します。

エラーの種類動作待機方法
429 レート制限再試行しますRetry-After ヘッダーに従います(デフォルト 1 秒)
500 サーバーエラー再試行します指数バックオフ:1 秒、2 秒、4 秒
認証/検証直ちに失敗します再試行しません

引用:test_client.py::TestRetryLogic(146~193 行目)

書き込み後の読み取り整合性

新しく作成したブロックは、すぐにクエリできない場合があります。最低 0.5 秒の遅延を設けてください。

append_blocks(client, page_id, blocks)
time.sleep(0.5)  # Eventual consistency delay
children = client.blocks.children.list(page_id)

引用:test_integration.py::TestBlockAppend::test_retrieve_appended_blocks(298 行目)

v2.6.0 API の移行
旧パターン新パターン(v2.6.0+)
client.databases.query()client.data_sources.query()
filter: {"value": "database"}filter: {"value": "data_source"}

引用:test_integration.py::TestDatabaseQuery(110 行目)

アーカイブのみ可能な削除

ページは API 経由で完全に削除することはできず、アーカイブ(ゴミ箱に移動)のみ可能です。

client.pages.update(page_id, archived=True)  # Trash, not delete

引用:test_integration.py のクリーンアップ用フィクスチャ(72~76 行目)

エッジケースと検証

プロパティビルダーのエッジケース
入力動作有効?
空文字列 ""空のコンテンツを作成はい
空配列 []マルチセレクト/リレーションをクリアはい
数値に対する Noneプロパティ値をクリアはい
ゼロ 0有効な数値(falsy ではありません)はい
負数 -42有効な数値はい
Unicode/絵文字完全に保持されますはい

引用:test_property_builders.py::TestPropertyBuildersEdgeCases(302~341 行目)

入力検証の責任

ビルダーは意図的に寛容で、検証は API レベルで行われます。

プロパティビルダーが受け付ける値API による検証
日付任意の文字列ISO 8601 のみ
URL任意の文字列有効な URL 形式
チェックボックス真偽値として評価される値ブール値が必要

ベストプラクティス:プロパティを作成する前に、アプリケーション内で検証してください。

引用:test_property_builders.py::TestPropertyBuildersInvalidInputs(347~376 行目)

トークンの検証
  • 大文字と小文字を区別します。有効なのは小文字の ntn_ と secret_ のみです。
  • API 呼び出し前に形式を確認します(不要なリクエストを節約できます)。
  • 空または空白のみのトークンは即座に拒否されます。

引用:test_client.py::TestClientEdgeCases(196~224 行目)

クエリとフィルターのパターン

複合フィルターの構成
# Empty compound (matches all)
and_filter()  # {"and": []}

# Deep nesting supported
and_filter(
    or_filter(filter_a, filter_b),
    and_filter(filter_c, filter_d)
)

引用:test_filter_builders.py::TestFilterEdgeCases(323~360 行目)

フィルターの制限

フィルターでは NULL プロパティは除外されないため、Python で確認してください。

if row["properties"]["Rating"]["number"] is not None:
    # Process non-null values

引用:test_integration.py::TestDatabaseQuery::test_query_database_with_filter(120~135 行目)

ページネーションの不変条件
条件has_morenext_cursor
結果がさらに存在するTrue存在し、None ではない
これ以上結果がないFalse存在しない場合/None の場合があります

next_cursor を使用する前に、必ず has_more を確認してください。

引用:test_integration.py::TestDatabaseQuery::test_query_database_with_pagination(137~151 行目)

エラー処理

from notion_client import APIResponseError, APIErrorCode

try:
    result = client.pages.create(...)
except APIResponseError as e:
    if e.code == APIErrorCode.ObjectNotFound:
        print("Page/database not found or not shared with integration")
    elif e.code == APIErrorCode.Unauthorized:
        print("Token invalid or expired")
    elif e.code == APIErrorCode.RateLimited:
        print(f"Rate limited. Retry after {e.additional_data.get('retry_after')}s")
    else:
        raise

インストール

uv pip install notion-client  # v2.6+ required for data_source support

または、PEP 723 のインライン依存関係を使用してください(スクリプトに含めることができます)。


トラブルシューティング

問題原因解決策
オブジェクトが見つからないページがインテグレーションと共有されていないページを共有します:... メニュー → 接続 → インテグレーションを追加
認証されていないトークンが無効または期限切れnotion.so/my-integrations で新しいトークンを生成します
レート制限(429)リクエストが多すぎる自動処理には api_call_with_retry() を使用します
クエリの結果が空フィルターに一致するものがないフィルター構文とプロパティ名を確認します
作成後にブロックが見つからない結果整合性の遅延書き込み後、読み取り前に 0.5s の遅延を追加します
無効なプロパティ型誤ったビルダーを使用しているデータベーススキーマでプロパティ型を確認します
トークン形式が拒否された接頭辞が正しくない(大文字と小文字を区別)トークンは ntn_ または secret_(小文字)で始まる必要があります
データソース ID が機能しない古い API バージョンnotion-client を最新バージョンにアップグレードします

実行後の振り返り

このスキルの実行後、終了する前に確認してください:

  1. コマンドは成功しましたか? — 失敗した場合は、失敗の原因となった指示またはエラーテーブルを修正します。
  2. パラメーターや出力に変更はありましたか? — 基盤となるツールのインターフェースに変更があった場合は、使用例とパラメーターテーブルを更新して一致させます。
  3. 回避策が必要でしたか? — 別のフラグや追加手順などで即興の対応が必要だった場合は、次回同じ回避策が不要になるよう、この SKILL.md を更新します。

問題が実際に発生し、再現可能な場合にのみ更新してください。推測で更新しないでください。

コメント