airtable-agent-cli
v0.1.0
Published
CLI and MCP server for the Airtable platform — full API coverage for AI agents
Maintainers
Readme
airtable-agent-cli
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
Installation
npm install -g airtable-agent-cliOr use without installing:
npx airtable-agent-cli --helpAuthentication
Get 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
Store credentials
airtable login
# or non-interactively:
airtable login --token pat_XXXXXXXXXXEnvironment variable
export AIRTABLE_TOKEN=pat_XXXXXXXXXXPer-command flag
airtable records list --base appXXX --table tblXXX --token pat_XXXXXXXXXXCommands
Bases
airtable bases list # List all accessible bases
airtable bases schema --base appXXX # Full schema: tables + fields + viewsTables
airtable 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"Fields
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"Records
# 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"}}]'Views
airtable views list --base appXXX # Enterprise onlyWebhooks
airtable 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 achXXXOutput Formats
# 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 --quietMCP Server (AI Agent Integration)
Run as an MCP server so AI assistants can call Airtable directly:
airtable mcpClaude Desktop / Cursor / VS Code
Add 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"
}
}
}
}Available MCP Tools
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 |
Scripting & Piping
# 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}'Architecture
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
}License
MIT
