---
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.

This note is flagged `update_note: experience-driven` — when a session follows these steps and finds a discrepancy (API changes, UI shifts, scope updates), update the steps rather than relying on a review date. The frontmatter contract in `vault-conventions.md` documents this pattern.

## 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

**Customization Point**: Adapt the file path and structure below to match your project's conventions. This step captures project-specific Airtable configuration that may differ from project to project.

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
