A full-coverage CLI and MCP server for the Airtable API — built for AI agents and humans alike.
- 21 commands across bases, tables, fields, records, views, and webhooks
- MCP server — plug directly into Claude, Cursor, VS Code, or any MCP-compatible AI client
- Dual interface — every command works as both a CLI tool and an MCP tool from the same codebase
- Agent-native — rich descriptions, upsert, formula filtering, batch ops, and pagination built in
npm install -g airtable-agent-cliOr use without installing:
npx airtable-agent-cli --helpGet a Personal Access Token at airtable.com/create/tokens.
Required scopes:
schema.bases:read— list bases, tables, fieldsschema.bases:write— create/update tables and fieldsdata.records:read— read recordsdata.records:write— create, update, delete, upsert recordswebhook:manage— manage webhooks
airtable login
# or non-interactively:
airtable login --token pat_XXXXXXXXXXexport AIRTABLE_TOKEN=pat_XXXXXXXXXXairtable records list --base appXXX --table tblXXX --token pat_XXXXXXXXXXairtable bases list # List all accessible bases
airtable bases schema --base appXXX # Full schema: tables + fields + viewsairtable tables list --base appXXX
airtable tables create --base appXXX --name "Contacts" \
--fields '[{"name":"Name","type":"singleLineText"}]'
airtable tables update --base appXXX --table tblXXX --name "New Name"airtable fields list --base appXXX --table tblXXX
airtable fields create --base appXXX --table tblXXX --name "Email" --type email
airtable fields create --base appXXX --table tblXXX --name "Status" --type singleSelect \
--options '{"choices":[{"name":"Active"},{"name":"Inactive"}]}'
airtable fields update --base appXXX --table tblXXX --field fldXXX --name "New Name"# List with filtering, sorting, pagination
airtable records list --base appXXX --table tblXXX
airtable records list --base appXXX --table tblXXX --formula "AND({Status}='Active')"
airtable records list --base appXXX --table tblXXX --select "Name,Email,Status"
airtable records list --base appXXX --table tblXXX --sort "Name:asc,CreatedTime:desc"
airtable records list --base appXXX --table tblXXX --view "Grid view" --max-records 50
airtable records list --base appXXX --table tblXXX --offset "itrXXXXXXXXXXXXXX"
# Get single record
airtable records get --base appXXX --table tblXXX --record recXXX
# Create (single or batch, max 10)
airtable records create --base appXXX --table tblXXX \
--fields '{"Name":"Alice","Email":"[email protected]"}'
airtable records create --base appXXX --table tblXXX \
--records '[{"fields":{"Name":"Alice"}},{"fields":{"Name":"Bob"}}]'
# Partial update / PATCH (only provided fields change)
airtable records update --base appXXX --table tblXXX \
--record recXXX --fields '{"Status":"Done"}'
airtable records update --base appXXX --table tblXXX \
--records '[{"id":"recAAA","fields":{"Status":"Done"}},{"id":"recBBB","fields":{"Status":"Active"}}]'
# Full replace / PUT (unincluded fields are cleared)
airtable records replace --base appXXX --table tblXXX \
--record recXXX --fields '{"Name":"Alice","Status":"Active"}'
# Delete (single or comma-separated batch, max 10)
airtable records delete --base appXXX --table tblXXX --record recXXX
airtable records delete --base appXXX --table tblXXX --records "recAAA,recBBB,recCCC"
# Upsert — update if exists, create if not
airtable records upsert --base appXXX --table tblXXX \
--merge-on "Email" \
--fields '{"Name":"Alice","Email":"[email protected]","Status":"Active"}'
airtable records upsert --base appXXX --table tblXXX \
--merge-on "Email,ExternalId" \
--records '[{"fields":{"Email":"[email protected]","Name":"Alice"}},{"fields":{"Email":"[email protected]","Name":"Bob"}}]'airtable views list --base appXXX # Enterprise onlyairtable webhooks list --base appXXX
airtable webhooks create --base appXXX \
--notify-url "https://example.com/hook" \
--data-types "tableData"
airtable webhooks create --base appXXX \
--notify-url "https://example.com/hook" \
--data-types "tableData,tableFields,tableMetadata" \
--record-scope tblXXX
airtable webhooks refresh --base appXXX --webhook achXXX
airtable webhooks payloads --base appXXX --webhook achXXX
airtable webhooks delete --base appXXX --webhook achXXX# Compact JSON (default — pipe-friendly)
airtable records list --base appXXX --table tblXXX
# Pretty-printed JSON
airtable records list --base appXXX --table tblXXX --pretty
# Select specific output fields
airtable records list --base appXXX --table tblXXX --fields id,fields
# Quiet — exit codes only (0 = success, 1 = error)
airtable records delete --base appXXX --table tblXXX --record recXXX --quietRun as an MCP server so AI assistants can call Airtable directly:
airtable mcpAdd to your MCP config (~/.claude/config.json, .cursor/mcp.json, etc.):
{
"mcpServers": {
"airtable": {
"command": "npx",
"args": ["airtable-agent-cli", "mcp"],
"env": {
"AIRTABLE_TOKEN": "pat_XXXXXXXXXX"
}
}
}
}If installed globally:
{
"mcpServers": {
"airtable": {
"command": "airtable",
"args": ["mcp"],
"env": {
"AIRTABLE_TOKEN": "pat_XXXXXXXXXX"
}
}
}
}All 21 CLI commands are exposed as MCP tools with the same names:
| Tool | Description |
|---|---|
bases_list |
List all accessible bases |
bases_schema |
Get full base schema (tables, fields, views) |
tables_list |
List tables in a base |
tables_create |
Create a new table |
tables_update |
Update table name/description |
fields_list |
List fields in a table |
fields_create |
Create a new field |
fields_update |
Update field name/description |
records_list |
List records with filtering, sorting, pagination |
records_get |
Get a single record by ID |
records_create |
Create one or more records |
records_update |
Partially update records (PATCH) |
records_replace |
Fully replace records (PUT) |
records_delete |
Delete one or more records |
records_upsert |
Upsert records by merge fields |
views_list |
List views in a base |
webhooks_list |
List webhooks |
webhooks_create |
Create a webhook |
webhooks_delete |
Delete a webhook |
webhooks_refresh |
Refresh webhook expiration |
webhooks_payloads |
Fetch webhook payloads |
# Get all active contacts
airtable records list --base appXXX --table tblXXX \
--formula "{Status}='Active'" | jq '.records[].fields'
# Export record IDs
airtable records list --base appXXX --table tblXXX \
--fields id | jq -r '.[].id'
# Pipe bases list into jq
airtable bases list | jq '.bases[] | {id, name}'This tool follows a dual CLI/MCP pattern:
- A single
CommandDefinition[]array powers both the Commander.js CLI and the MCP server - Zod schemas are the source of truth for validation, help text, and MCP input schemas
- Every command works identically whether called from the terminal or by an AI agent
CommandDefinition {
name → MCP tool name ("records_list")
group → CLI group ("records")
subcommand → CLI subcommand ("list")
inputSchema → Zod schema → CLI validation + MCP input schema
handler → Async function called by both CLI and MCP
}
MIT