--- type: howto title: "Airtable MCP Setup Guide" summary: Integrate the Airtable MCP server into a Claude Code project using project-local scope. Enables Claude Code to read and write Airtable data while keeping token overhead zero in unrelated projects. tags: - type/howto - tool/airtable - tool/claude-code - tool/mcp - domain/dev scope: global last_updated: 2026-06-27 update_note: experience-driven --- # Airtable MCP Setup Guide This guide sets up the Airtable MCP server in a Claude Code project using **project-local scope** — so MCP only loads when you're working in this project, not every session. Use it whenever you're starting a new project that reads or writes Airtable data via Claude Code. ## Prerequisites - [ ] Claude Code CLI installed and working (`claude --version`) - [ ] Airtable Personal Access Token (PAT) with `data.records:read` scope minimum; add write scopes if the project needs CRUD - [ ] PAT stored in an environment variable (e.g. `AIRTABLE_PAT` in `~/.zshrc`) — do not hardcode - [ ] `npx` available (ships with Node.js) ## Steps ### Step 1: Add Airtable MCP at project-local scope From the project root, register the MCP server with project-local scope: ```bash claude mcp add --scope local --transport stdio airtable \ --env AIRTABLE_API_KEY=${YOUR_PAT_ENV_VAR} \ -- npx -y airtable-mcp-server ``` Replace `YOUR_PAT_ENV_VAR` with the actual environment variable name holding your PAT. **Why project-local scope?** MCP servers consume Claude tokens whether or not they're being used. Global scope means Airtable MCP loads in every project session. Local scope (`--scope local`) keeps it isolated to this project directory and stores the config privately (outside version control). **Expected result:** Command exits cleanly. Verify: ```bash claude mcp list # airtable should appear in the list ``` ### Step 2: Configure permissions in .claude/settings.local.json Create or update `.claude/settings.local.json` to lock down which operations Claude Code can perform: ```json { "permissions": { "allow": [ "mcp__airtable__describe_table", "mcp__airtable__list_tables", "mcp__airtable__list_records", "mcp__airtable__get_record", "WebFetch(domain:airtable.com)", "WebFetch(domain:support.airtable.com)" ], "deny": [ "mcp__airtable__create_record(base_id:YOUR_PROD_BASE_ID:*)", "mcp__airtable__update_record(base_id:YOUR_PROD_BASE_ID:*)", "mcp__airtable__delete_record(base_id:YOUR_PROD_BASE_ID:*)" ] } } ``` Replace `YOUR_PROD_BASE_ID` with the actual production base ID (format: `appXXXXXXXXXXXXXX`). **Key points:** - `allow` — explicitly permit read operations and Airtable docs access - `deny` — block write/update/delete on the production base by base ID - Development/sandbox base: gets full CRUD by default (not in deny list) - `settings.local.json` is private and should be in `.gitignore` **Expected result:** File created. On next Claude Code session, write attempts to the production base will be blocked. ### Step 3: Add project-assets reference doc Create `docs/reference/project-assets.md` to track discovered table IDs and field conventions — Airtable table IDs change if tables are recreated, so document them as you find them: ```markdown # Project Assets Reference ## Airtable Configuration ### Bases - **Dev base ID**: `appXXXX` (full CRUD — safe to experiment) - **Prod base ID**: `appXXXX` (READ-ONLY — live data) ### Tables | Table Name | Table ID | Description | |------------|----------|-------------| | *TBD* | *TBD* | *TBD* | ### Common field patterns - `*_id` — record ID fields - `*_at` — timestamp fields - `*_status` — status/state fields ``` **Expected result:** Living reference doc that grows as you explore the base. ## Verification Run these checks at the end of setup: ```bash # 1. Confirm env var is set echo $YOUR_PAT_ENV_VAR # 2. Confirm MCP is registered claude mcp list # 3. In a Claude Code session: ask Claude to list all tables in the dev base # Expected: tables appear without a permission prompt # 4. In a Claude Code session: ask Claude to create a record in the prod base # Expected: blocked by permissions in settings.local.json ``` ## Gotchas **"Airtable MCP not available" in session** - Check env var is exported in shell profile, not just set: `export AIRTABLE_PAT=...` - Restart terminal after adding the variable; Claude Code inherits the shell environment at launch **"Permission denied" on dev base writes** - Double-check the deny rule: it should reference the prod base ID only - If you accidentally put the dev base ID in deny, remove it from `settings.local.json` **PAT scope errors** - PAT must have `data.records:read` for reads; add `data.records:write` for create/update/delete - Regenerate the PAT in Airtable → Account → Developer Hub if scopes need updating **npx slow on first run** - `npx -y airtable-mcp-server` downloads the package on first use; subsequent runs use the cache ## Related - [[vault-conventions]] — frontmatter and tag taxonomy for this vault