mcpField
A
airtable

airtable

github.com/nousresearchデータ・データベース258.1k376 回インストール今日更新
リポジトリ

airtable について

Hermes ユーザー向けに、terminal ツールから curl で Airtable REST API を操作する方法を案内するスキルです。トークン権限、レコード操作、ページネーション、一括処理、安全な変更の注意点を扱います。

主な機能

  1. 01curl による Airtable REST API 呼び出し
  2. 02ベースとテーブルスキーマの確認
  3. 03レコードの検索、絞り込み、並べ替え
  4. 04レコードの作成、更新、削除、アップサート
  5. 05ページネーション、レート制限、権限の管理

活用シーン

  1. 01変更前にテーブルスキーマを確認
  2. 02数式でレコードを絞り込んで更新
  3. 03レコードの一括作成や冪等な同期

インストール

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

$npx skills add https://github.com/nousresearch/hermes-agent --skill airtable

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

詳細

Airtable — ベース、テーブル、レコード

terminal ツールを使って、curl から Airtable の REST API を直接利用します。MCP サーバーも OAuth フローも Python SDK も不要です。必要なのは curl と個人用アクセストークンだけです。

前提条件

  1. https://airtable.com/create/tokens で 個人用アクセストークン(PAT) を作成します(トークンは pat... で始まります)。
  2. 次のスコープを付与します(最小限):
    • data.records:read — 行の読み取り
    • data.records:write — 行の作成/更新/削除
    • schema.bases:read — ベースとテーブルの一覧表示
  3. 重要: 同じトークンの UI で、アクセスする各ベースをトークンの Access リストに追加します。PAT のアクセス範囲はベースごとです。対象と異なるベースに対して有効なトークンを使うと、403 が返されます。
  4. トークンを ${HERMES_HOME:-~/.hermes}/.env に保存します(または hermes setup を実行します):
    AIRTABLE_API_KEY=pat_your_token_here
    

注:従来の key... API キーは 2024 年 2 月に非推奨になりました。現在は PAT と OAuth トークンのみ使用できます。

API の基本

  • エンドポイント: https://api.airtable.com/v0
  • 認証ヘッダー: Authorization: Bearer $AIRTABLE_API_KEY
  • すべてのリクエストで JSON を使用します(POST/PATCH/PUT の本文には Content-Type: application/json を指定します)。
  • オブジェクト ID: ベースは app...、テーブルは tbl...、レコードは rec...、フィールドは fld... です。ID は変わりませんが、名前は変わる可能性があります。自動化では ID を優先してください。
  • レート制限: ベースごとに毎秒 5 リクエストです。429 が返されたら、リクエストの間隔を空けてください。単一のベースに対するリクエストが集中すると、スロットリングされます。

ベースへの curl の基本パターン:

curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?maxRecords=5" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool

-s は curl の進行状況バーを抑制します。Hermes のツール出力をきれいに保つため、すべての呼び出しで設定してください。読みやすい JSON にするには、python -m json.tool(常に利用可能)または jq(インストール済みの場合)にパイプします。

フィールドの種類(リクエスト本文の形式)

フィールドの種類書き込み形式
単一行テキスト"Name": "hello"
長文テキスト"Notes": "multi\nline"
数値"Score": 42
チェックボックス"Done": true
単一選択"Status": "Todo"(typecast: true を指定しない限り、名前がすでに存在している必要があります)
複数選択"Tags": ["urgent", "bug"]
日付"Due": "2026-04-01"
日時(UTC)"At": "2026-04-01T14:30:00.000Z"
URL/メールアドレス/電話番号"Link": "https://…"
添付ファイル"Files": [{"url": "https://…"}](Airtable が取得して再ホストします)
リンクされたレコード"Owner": ["recXXXXXXXXXXXXXX"](レコード ID の配列)
ユーザー"AssignedTo": {"id": "usrXXXXXXXXXXXXXX"}

作成/更新の本文の最上位に "typecast": true を指定すると、Airtable が値を自動変換します(例:新しい選択肢をその場で作成する、"42" を 42 に変換する)。

よく使うクエリ

トークンから参照できるベースの一覧
curl -s "https://api.airtable.com/v0/meta/bases" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
ベースのテーブルとスキーマを一覧表示
curl -s "https://api.airtable.com/v0/meta/bases/$BASE_ID/tables" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool

変更を加える前に必ず実行してください。正確なフィールド名と ID を確認でき、選択フィールドの options.choices や主フィールド名も表示されます。

レコード一覧(最初の 10 件)
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?maxRecords=10" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
単一レコードを取得
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
レコードを絞り込む(filterByFormula)

Airtable の数式は URL エンコードする必要があります。Python 標準ライブラリを使い、手動でエンコードしないでください:

FORMULA="{Status}='Todo'"
ENC=$(python -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$FORMULA")
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?filterByFormula=$ENC&maxRecords=20" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool

便利な数式のパターン:

  • 完全一致:{Email}='[email protected]'
  • 含む:FIND('bug', LOWER({Title}))
  • 複数条件:AND({Status}='Todo', {Priority}='High')
  • または:OR({Owner}='alice', {Owner}='bob')
  • 空でない:NOT({Assignee}='')
  • 日付の比較:IS_AFTER({Due}, TODAY())
並べ替えと特定フィールドの選択
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?sort%5B0%5D%5Bfield%5D=Priority&sort%5B0%5D%5Bdirection%5D=asc&fields%5B%5D=Name&fields%5B%5D=Status" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool

クエリパラメーター内の角括弧は必ず URL エンコードしてください(%5B/%5D)。

名前付きビューを使用
curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?view=Grid%20view&maxRecords=50" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool

ビューに保存されたフィルターと並べ替えが、サーバー側で適用されます。

よく使う変更操作

レコードを作成
curl -s -X POST "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fields":{"Name":"New task","Status":"Todo","Priority":"High"}}' | python -m json.tool
1 回の呼び出しで最大 10 件のレコードを作成
curl -s -X POST "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "typecast": true,
    "records": [
      {"fields": {"Name": "Task A", "Status": "Todo"}},
      {"fields": {"Name": "Task B", "Status": "In progress"}}
    ]
  }' | python -m json.tool

バッチエンドポイントで処理できるのは、1 リクエストあたり 10 件までです。さらに多くのレコードを挿入する場合は、ベースごとに毎秒 5 リクエストの制限を守るため、10 件ずつ短いスリープを挟んで繰り返します。

レコードを更新(PATCH — マージし、変更のないフィールドを保持)
curl -s -X PATCH "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fields":{"Status":"Done"}}' | python -m json.tool
マージフィールドでアップサート(ID 不要)
curl -s -X PATCH "https://api.airtable.com/v0/$BASE_ID/$TABLE" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "performUpsert": {"fieldsToMergeOn": ["Email"]},
    "records": [
      {"fields": {"Email": "[email protected]", "Status": "Active"}}
    ]
  }' | python -m json.tool

performUpsert は、マージフィールドの値が新しいレコードを作成し、その値がすでに存在するレコードを PATCH します。冪等な同期に最適です。

レコードを削除
curl -s -X DELETE "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool
1 回の呼び出しで最大 10 件のレコードを削除
curl -s -X DELETE "https://api.airtable.com/v0/$BASE_ID/$TABLE?records%5B%5D=rec1&records%5B%5D=rec2" \
  -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool

ページネーション

一覧エンドポイントは、1ページあたり最大 100 件のレコードを返します。レスポンスに "offset": "..." が含まれている場合は、次の呼び出しでその値を渡してください。このフィールドがなくなるまで繰り返します。

OFFSET=""
while :; do
  URL="https://api.airtable.com/v0/$BASE_ID/$TABLE?pageSize=100"
  [ -n "$OFFSET" ] && URL="$URL&offset=$OFFSET"
  RESP=$(curl -s "$URL" -H "Authorization: Bearer $AIRTABLE_API_KEY")
  echo "$RESP" | python -c 'import json,sys; d=json.load(sys.stdin); [print(r["id"], r["fields"].get("Name","")) for r in d["records"]]'
  OFFSET=$(echo "$RESP" | python -c 'import json,sys; d=json.load(sys.stdin); print(d.get("offset",""))')
  [ -z "$OFFSET" ] && break
done

Hermes の一般的なワークフロー

  1. 認証を確認します。 curl -s -o /dev/null -w "%{http_code}\n" https://api.airtable.com/v0/meta/bases -H "Authorization: Bearer $AIRTABLE_API_KEY" — 200 が返ることを確認します。
  2. ベースを見つけます。 ベースの一覧を取得する(上記の手順)か、トークンに schema.bases:read がない場合は、ユーザーに app... ID を直接尋ねます。
  3. スキーマを確認します。 GET /v0/meta/bases/$BASE_ID/tables — 変更を加える前に、正確なフィールド名とプライマリフィールド名をセッション内にキャッシュします。
  4. 書き込む前に読み取ります。 「Y に該当する X を更新する」場合は、まず filterByFormula で rec... ID を特定し、その後 PATCH /v0/$BASE_ID/$TABLE/$RECORD_ID を実行します。レコード ID を推測してはいけません。
  5. 書き込みをまとめます。 関連する作成処理を 10 レコードの POST 1 回にまとめ、5 リクエスト/秒の上限を超えないようにします。
  6. 破壊的な操作。 API 経由で削除を取り消すことはできません。ユーザーが「X をすべて削除して」と指示した場合は、実行前にフィルターとレコード件数を伝え、確認を取ります。

注意点

  • filterByFormula は必ず URL エンコードしてください。 スペースや非 ASCII 文字を含むフィールド名もエンコードが必要です({My Field} → %7BMy%20Field%7D)。上記のパターンのように Python 標準ライブラリを使用し、手作業でエスケープしてはいけません。
  • 空のフィールドはレスポンスから省略されます。 "Assignee" キーがないからといって、そのフィールドが存在しないとは限りません。このレコードの値が空であることを意味します。フィールドが存在しないと判断する前に、スキーマ(手順 3)を確認してください。
  • PATCH と PUT。 PATCH は指定したフィールドをレコードにマージします。PUT はレコード全体を置き換え、含めなかったフィールドをすべてクリアします。デフォルトでは PATCH を使用してください。
  • 単一選択のオプションは存在している必要があります。 フィールドのオプション一覧に Shipping がない状態で "Status": "Shipping" を書き込むと、"typecast": true を渡さない限り INVALID_MULTIPLE_CHOICE_OPTIONS エラーになります(typecast を指定すると、オプションが自動作成されます)。
  • トークンのアクセス範囲はベースごとに設定されます。 あるベースでは 403 が返り、別のベースでは正常に動作する場合、トークンの Access リストにそのベースが含まれていないことを意味します。スコープや認証の問題ではありません。ユーザーに https://airtable.com/create/tokens でアクセス権を付与してもらってください。
  • レート制限はトークン単位ではなく、ベース単位です。 baseA で 5 リクエスト/秒、baseB で 5 リクエスト/秒なら問題ありませんが、baseA だけで 6 リクエスト/秒を実行すると制限されます。429 の Retry-After ヘッダーを確認してください。

Hermes に関する重要な注意事項

  • 必ず curl と terminal ツールを使用してください。 web_extract(認証ヘッダーを送信できません)や browser_exec(UI での認証が必要で、時間もかかります)は使用しないでください。
  • AIRTABLE_API_KEY は、このスキルが読み込まれると ${HERMES_HOME:-~/.hermes}/.env からサブプロセスに自動的に渡されます。 curl を呼び出すたびに再エクスポートする必要はありません。
  • 数式内の波括弧は慎重に扱ってください。 ヒアドキュメントの本文では {Status} はそのままの文字列です。シェル引数では、波括弧展開のコンテキスト外であれば {Status} は安全です。ただし、動的な文字列を URL に埋め込む前に、python urllib.parse.quote を通してください。
  • 整形には jq(オプション)ではなく、常に利用できる python -m json.tool を使用してください。 フィルタリングや射影が必要な場合に限り、jq を使用してください。
  • ページネーションは全体ではなく、ページごとに行います。 Airtable の 100 レコード上限は固定で、引き上げる方法はありません。offset フィールドがなくなるまでループしてください。
  • 2xx 以外のレスポンスでは errors 配列を確認してください。 Airtable は AUTHENTICATION_REQUIRED、INVALID_PERMISSIONS、MODEL_ID_NOT_FOUND、INVALID_MULTIPLE_CHOICE_OPTIONS などの構造化されたエラーコードを返すため、問題を正確に把握できます。

コメント