Atlas / MCP servers / automations-project / Airtable Formula

Airtable FormulaBLOCK

mcp/automations-project/airtable-formula

VS Code extension and MCP server for Airtable, formula editor, schema tools, and 60+ automation utilities for bases, views, and fields.

Verdict
BLOCK
Grade
D
Trust score
61 /100
Exposed tools
100 44r · 47w · 9d
Transport
stdio · streamable-http
License
MIT
Stars
31
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

Formula, script & automation editor · MCP server (72 tools + `manage_tools`) · Language server · AI skills

VS Code Open VSX npm · MCP npm · LSP MCP Registry

Read from source at commit 7ca0d8237eaeOBSERVED · 2026-10-08
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code (npm)
claude mcp add airtable-user-mcp -- npx -y [email protected]
03

Exposed tools (100)

44 read · 47 write · 9 destructive. Blast radius: 9 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
actionread
airtable-build-tablewriteDesign and create a complete table structure from plain-language requirements
airtable-bulk-formula-editwriteDownload all formula fields from a base, edit them offline, then upload changes
airtable-create-formulawriteCreate an Airtable formula from a plain-language description
airtable-fix-formulareadDebug and fix an Airtable formula error or unexpected result
airtable-inspect-basereadExplore and summarise the schema of an Airtable base
airtable-manage-select-choicesdestructiveAdd, remove, or replace choices on a singleSelect or multipleSelects field
airtable-search-recordsreadSearch for records in an Airtable table by text, including lookup field values
airtable-setup-rollup-lookupwriteCreate or update a rollup or lookup field with guided field-ID resolution
airtable-setup-viewwriteConfigure an Airtable view — filters, sorts, groups, and column order
airtable-validate-formulareadValidate an Airtable formula and show its result type
appIdreadBase ID (appXXX) to validate against
apply_record_templatewriteApply (instantiate) a record template to create a new record pre-filled with the template\
apply_view_sortswriteApply sort conditions to a view. Default mode replaces all existing sorts — pass an empty array with operation=
choicesreadComma-separated choice names (e.g.
create_extensionwriteCreate a new extension (block) in an Airtable base. Returns the block ID needed for installation. Use this to register custom extensions before installing them.
create_extension_dashboardwriteCreate a new extension dashboard page in a base. Extensions are installed onto dashboard pages.
create_fieldwriteCreate a new field in an Airtable table. Supports all field types including computed fields (formula, rollup, lookup, count) that are not available via the official API. FIELD TYPES (fieldType parameter): Supported names:
create_formula_fieldwriteCreate a new formula field — shorthand for
create_record_templatewriteCreate a new record template for a table. Returns the generated templateId (rtp-prefixed). After creating, use set_record_template_cell to pre-fill field values.
create_recordswriteCreate one or more records in a table. Each item supplies cellValuesByColumnId (computed fields are read-only and must be omitted). Returns created record IDs. Per-row isolation: a failing row is reported, not fatal.
create_tablewriteCreate a new table in an Airtable base. Returns the generated table ID. The table starts with default fields (Name, Notes, Attachments, Status, etc.) — use list_fields after creation to inspect them.
create_viewwriteCreate a new view in an Airtable table. Optionally copy configuration from an existing view. View types:
create_view_sectionwriteCreate a new sidebar section in a table. Returns the new section ID (vsc-prefixed). Use
customreadUser-defined per-tool selection
delete_record_templatedestructive⚠️ DESTRUCTIVE — Permanently delete a record template. This cannot be undone.
delete_recordsdestructiveDelete one or more records from a table in a single batch call. The returned deleted count equals rowIds.length (optimistic) — already-deleted rows are silently skipped by the server.
delete_tabledestructiveDelete a table from an Airtable base. Requires both tableId AND the expected table name as a safety guard — refuses to delete if the name does not match. Airtable rejects deleting the last remaining table in a base.
delete_viewdestructiveDelete a view from a table. Cannot delete the last remaining view in a table.
delete_view_sectiondestructiveDelete a sidebar section. Views inside the section are NOT deleted — Airtable auto-promotes them to ungrouped at the table-level position the section used to occupy. Verified 2026-04-30.
descriptionreadWhat the formula should calculate or produce
download_base_formulasreadDownload ALL formula fields from a base to local .formula files, organized into per-table subfolders. Field refs are resolved to real field names ({Field Name}, Airtable\
download_formula_fieldreadDownload the formula text of a formula field to a local file. Field refs are resolved to real field names ({Field Name}, Airtable\
duplicate_extensionreadDuplicate an installed extension on a dashboard page.
duplicate_fieldreadDuplicate (clone) a field in a table. Optionally also duplicate the cell values.
duplicate_record_templatereadDuplicate a record template within the same or a different table. Returns the new template ID.
duplicate_recordsreadDuplicate one or more existing records within a table. Creates exact copies of the specified source records in the same table and view. Returns the new record IDs.
duplicate_viewreadDuplicate an existing view with all its configuration (filters, sorts, field visibility, etc).
errorreadError message or symptom (e.g. #ERROR, NaN)
fieldIdreadField ID (fldXXX)
fieldNamewriteName for the new field (or existing fieldId to update)
fieldTyperead
formulareadThe formula to fix
get_base_schemareadGet the full schema of an Airtable base — all tables, fields (with typeOptions), and views in one call. Use this when you need fields or views; use
get_table_schemareadGet the full schema for a single table — all fields (with typeOptions) and views. Use instead of
get_viewreadRead a view
goalreadWhat to roll up or look up (plain English)
install_extensionwriteInstall an extension onto a dashboard page. Requires a block ID (from create_extension) and a page ID (from create_extension_dashboard).
limitreadMax records to scan (1–1000, default 100)
list_fieldsreadList fields in a table — returns id, name, and type per field (lightweight by default). Use instead of
list_record_templatesreadList all record templates for a table. Templates are embedded in the base scaffolding data. If the templates array is empty, pass debug:true and inspect the raw response to locate the templates key — the API path may vary by base.
list_tablesreadList all tables in a base with their IDs and names — lightweight scaffolding call (no field data). Use this when you only need table IDs/names; use
list_view_sectionsreadList all sidebar sections for a table. Sections are user-organized groupings of views in the Airtable left sidebar (e.g.
list_viewsreadList all views in a specific table with their IDs, names, and types.
manage_daemonreadInspect and control the MCP daemon this server runs in. action=
manage_toolsreadControl which tools are available. Actions: list_profiles, switch_profile,
moderead
move_overall_columnswriteMove one or more columns to a new position in the *overall* index (visible + hidden). Sibling of
move_visible_columnswriteMove columns by visible-only index (index 0 = leftmost shown column, hidden columns not counted). Use when you want to position relative to what the user sees. Use
my-promptreadd
outputDirwriteLocal directory to write .formula files into
query_recordsreadRead records from an Airtable table view. Returns resolved field values including lookup fields. Supports optional client-side text search across all field values — unlike the REST API filterByFormula approach, this search works correctly on lookup fields. Fetch up to 1000 records per call.
remove_extensiondestructiveRemove an installed extension from a dashboard.
rename_extensionwriteRename an installed extension.
rename_fieldwriteRename a field (column) in an Airtable table. Pre-validates the field exists before mutating.
rename_record_templatewriteRename an existing record template.
rename_tablewriteRename a table in an Airtable base.
rename_viewwriteRename a view.
rename_view_sectionwriteRename a sidebar section.
reorder_view_fieldsreadReorder the fields (columns) displayed in a view. Accepts a partial map: pass only the field IDs you want to move, e.g.
requirementsreadWhat the view should show and how
searchreadText to search for (case-insensitive substring match)
set_calendar_date_columnswriteSet the date-column ranges shown on a Calendar view. Each entry is either { startColumnId } for single-point events or { startColumnId, endColumnId } for range events. The array form lets a single calendar overlay multiple date series at once (e.g.
set_form_metadatawriteUpdate one or more legacy-form-view metadata properties in a single call. Unset properties are not touched. Each property fans out to its own atomic Airtable endpoint. Supported properties: description — intro text shown above the form afterSubmitMessage —
set_form_submission_notificationwriteToggle email-on-submit notifications for a specific user on a form view. Per-user, not per-form (separate from set_form_metadata).
set_record_template_cellwritePre-fill a field value on a record template. CELL OBJECT TYPES (verified via API capture 2026-05-01): Static value (text, number, boolean, single-select choice ID): {
set_record_template_visible_columnswriteSet which columns are shown (pre-fillable) on a record template. Pass an empty array to show all columns. isPartialSelection:true means only listed columns are shown; false means all are shown.
set_view_cell_wrapdestructiveToggle whether long cell values wrap (multi-line) or truncate (single-line with ellipsis).
set_view_color_configwriteApply a color config to a view (Kanban / Gallery / Calendar). Currently supports
set_view_columnsdestructiveOne-shot view-column reset: hides every column then shows only
set_view_coverwriteSet the cover-image field and crop/fit mode for Kanban or Gallery views. Pass
show_or_hide_all_columnsreadShow or hide every column in a view in one call. Use when you want a clean all-visible or all-hidden baseline. Use
show_or_hide_view_columnsreadShow or hide specific columns in a view without affecting others. Pass field IDs + a visibility flag — every listed ID is set to that state, all other columns are untouched. Use
sync_basewriteBase-to-base schema + record sync. IMPORTANT: BOTH mode=
tableIdreadTable ID (tblXXX) for field context
tableNamereadName for the new table
update_extension_statewriteEnable or disable an extension installation.
update_field_configwriteUpdate the configuration of any field — computed OR non-computed. Works for formula, rollup, lookup, count, singleSelect, multipleSelects, number, date, text, and all other field types. COMMON typeOptions by fieldType: formula: { formulaText:
update_field_descriptionwriteUpdate the description text of a field.
update_formula_fieldwriteUpdate the formula body of an existing formula field — shorthand for
update_frozen_column_countwriteSet the frozen-column divider position for a grid view. The first N columns from the left are frozen and stay visible during horizontal scroll.
update_record_template_descriptionwriteSet or update the description text of a record template.
update_recordswriteUpdate primitive / single-select cells of existing records via cellValuesByColumnId. (Array cells — multi-select, links, attachments — are not set here.) Per-row isolation.
update_view_descriptionwriteUpdate the description text of a view.
update_view_filterswriteUpdate the filter configuration of a view. Supports AND/OR conjunctions, nested filter groups, and Airtable
update_view_group_levelswriteSet grouping on a view. Default mode replaces all existing group levels — pass an empty array with operation=
update_view_row_heightwriteChange the row height of a grid view.
upload_attachmentwriteUpload attachments into an attachment cell by URL. Airtable
validate_formulareadValidate a formula expression before creating or updating a formula field. Returns whether the formula is valid and what result type it produces (text, number, etc). Use this before create/update to catch errors early.
viewIdreadView ID (viwXXX) — determines which records are visible
04

Trust audit

BLOCKgrade D · trust 61/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (7 observation(s))
Network
declared (9 observation(s))
Shell
declared (4 observation(s))
Dependencies
not all pinned
Secrets in source
none-found

Findings (25)

HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
packages/mcp-server/src/process-tree.js:744
const { stdout } = await exec(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
packages/mcp-server/src/process-tree.js:841
const { stdout } = await exec(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
packages/extension/src/commands/formulaFile.ts:58
response = await fetch(`http://127.0.0.1:${port}/mcp`, {
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
packages/extension/src/mcp/auth-manager.ts:599
const resp = await fetch(`http://127.0.0.1:${status.port}/daemon/session-health`, {
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
packages/extension/src/mcp/auth-manager.ts:674
const res = await fetch(`http://127.0.0.1:${status.port}/daemon/release-browser`, {
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
packages/extension/src/mcp/daemon-manager.ts:117
const response = await fetch(`http://127.0.0.1:${port}/daemon/health`, {
MEDIUMObfuscation / stealth · obf.base64_blob · CWE-506, CWE-94
packages/mcp-server/src/icon.js:2
export const ICON_DATA_URI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAABtCAYAAABp5GmXAAAACXBIWXMAAAlyAAAJcgErz99GAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAADZJJREFUeJztnXuUVNWVh799
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
airtable-manage-select-choices, delete_record_template, delete_records, delete_table, delete_view, delete_view_section, remove_extension, set_view_cell_wrap, set_view_columns
Why it matters. 9 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.hidden_file · CWE-1104
packages/extension/.vscodeignore
.vscodeignore
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
packages/mcp-server/test/test-direct-login.test.js:425
const hash = crypto.createHash('sha1').update(`${salt}-${secret}`, 'ascii').digest('base64')
LOWFilesystem / path · fs.credential_store · CWE-22, CWE-59
scripts/safe-symlinks.test.mjs:78
writeFileSync(join(markerDir, 'id_rsa'), 'MARKER-CREDENTIAL-DO-NOT-COPY');
Why it matters. touches a credential store
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/extension/src/test/daemon-manager.test.ts:1167
'../../../shared/test-fixtures/process-attribution-cases.json',
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/extension/src/test/runTest.ts:9
const extensionDevelopmentPath = path.resolve(__dirname, '../../');
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/extension/src/test/suite/beautifier.test.ts:6
const vendorPath = path.resolve(__dirname, '../../../src/vendor');
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/extension/src/test/suite/beautifier.test.ts:103
const minifyCmdPath = path.resolve(__dirname, '../../../src/commands/minifyWithLevel.ts');
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/language-services/src/engines/automation/completions.ts:7
import type { LsCompletionItem, LsPosition } from '../../types.js';
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
CLAUDE.md:125
3. VS Code extension via `DaemonManager` — direct HTTP to `http://127.0.0.1:{port}/mcp` with bearer token
LOWObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
packages/mcp-server/test/test-demo.js:153
log('👁️🗨️', 'Hidden Priority Score & Days Open');
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
esbuild, rimraf
Why it matters. 2 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
packages/extension/package.json
@types/adm-zip, terser, @types/archiver, @types/node, @types/vscode, @vscode/test-electron, @vscode/vsce, adm-zip
Why it matters. 12 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
packages/language-services/package.json
tsup, typescript, vitest
Why it matters. 3 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
packages/lsp-server/package.json
vscode-languageserver, vscode-languageserver-textdocument, tsup, typescript, vitest
Why it matters. 5 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
packages/mcp-server/package.json
@modelcontextprotocol/sdk, cheerio, dotenv, fetch-cookie, node-fetch, tough-cookie, @ngrok/ngrok, impit
Why it matters. 11 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CLAUDE.md:54
The Airtable MCP server itself — ES modules Node app, **published to npm as `airtable-user-mcp`**. Provides **72 tools** across 16 categories (read, record-read, table-write, table-destructive, field-
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CLAUDE.md:273
- `mcp.authMode` — `browser` (default; headless Chrome mints the cookie, calls go direct-HTTP) / `byo` (cookie-only, no browser; cookie from `~/.airtable-user-mcp/credentials.json` or `AIRTABLE_COOKIE
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine

Gates applied: no_behavioural_pass.

Audited 2026-10-08 · audit v0.4.1 · source sha 7ca0d8237eaefull audit observations/trust-audit/mcp-server/automations-project__airtable-formula.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-087ca0d8237eaeBLOCKD61first audit
06

Questions

What is the Airtable Formula MCP server?

VS Code extension and MCP server for Airtable, formula editor, schema tools, and 60+ automation utilities for bases, views, and fields.

What tools does Airtable Formula expose?

100 in total: 44 read-only, 47 that write, and 9 that can delete or overwrite (airtable-manage-select-choices, delete_record_template, delete_records, delete_table, delete_view). Every one is listed on this page with its risk.

Is Airtable Formula safe to connect to an agent?

No — not without reading the findings first. The audit graded it D (61/100) and found 2 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 9 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does Airtable Formula need?

It reads AIRTABLE_AUTH_MODE, AIRTABLE_MAX_AUTH_QUEUE, AIRTABLE_OTP_SECRET, AIRTABLE_PASSWORD and AIRTABLE_TOTP_SECRET from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does Airtable Formula run?

It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as @airtable-formula/webview at 2.0.0.

How current is this page?

The grade is for one exact copy of the source (7ca0d8237eae), read on 2026-10-08. The repository is watched and re-audited when it changes.

Advertisement