@rashidazarang/airtable-mcp 3.0.0 → 3.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +210 -43
  2. package/bin/airtable-mcp.js +12 -32
  3. package/dist/typescript/airtable-mcp-server.js +77 -0
  4. package/dist/typescript/airtable-mcp-server.js.map +1 -0
  5. package/dist/typescript/app/airtable-client.js +325 -0
  6. package/dist/typescript/app/airtable-client.js.map +1 -0
  7. package/dist/typescript/app/config.js +141 -0
  8. package/dist/typescript/app/config.js.map +1 -0
  9. package/dist/typescript/app/context.js +3 -0
  10. package/dist/typescript/app/context.js.map +1 -0
  11. package/dist/typescript/app/exceptions.js +85 -0
  12. package/dist/typescript/app/exceptions.js.map +1 -0
  13. package/dist/typescript/app/governance.js +58 -0
  14. package/dist/typescript/app/governance.js.map +1 -0
  15. package/dist/typescript/app/logger.js +47 -0
  16. package/dist/typescript/app/logger.js.map +1 -0
  17. package/dist/typescript/app/rateLimiter.js +37 -0
  18. package/dist/typescript/app/rateLimiter.js.map +1 -0
  19. package/dist/typescript/app/tools/create.js +54 -0
  20. package/dist/typescript/app/tools/create.js.map +1 -0
  21. package/dist/typescript/app/tools/describe.js +146 -0
  22. package/dist/typescript/app/tools/describe.js.map +1 -0
  23. package/dist/typescript/app/tools/handleError.js +54 -0
  24. package/dist/typescript/app/tools/handleError.js.map +1 -0
  25. package/dist/typescript/app/tools/index.js +24 -0
  26. package/dist/typescript/app/tools/index.js.map +1 -0
  27. package/dist/typescript/app/tools/listBases.js +52 -0
  28. package/dist/typescript/app/tools/listBases.js.map +1 -0
  29. package/dist/typescript/app/tools/listExceptions.js +18 -0
  30. package/dist/typescript/app/tools/listExceptions.js.map +1 -0
  31. package/dist/typescript/app/tools/listGovernance.js +17 -0
  32. package/dist/typescript/app/tools/listGovernance.js.map +1 -0
  33. package/dist/typescript/app/tools/query.js +126 -0
  34. package/dist/typescript/app/tools/query.js.map +1 -0
  35. package/dist/typescript/app/tools/update.js +56 -0
  36. package/dist/typescript/app/tools/update.js.map +1 -0
  37. package/dist/typescript/app/tools/upsert.js +65 -0
  38. package/dist/typescript/app/tools/upsert.js.map +1 -0
  39. package/dist/typescript/app/tools/webhooks.js +44 -0
  40. package/dist/typescript/app/tools/webhooks.js.map +1 -0
  41. package/dist/typescript/app/types.js +282 -0
  42. package/dist/typescript/app/types.js.map +1 -0
  43. package/dist/typescript/apps-sdk/mappers.js +70 -0
  44. package/dist/typescript/apps-sdk/mappers.js.map +1 -0
  45. package/dist/typescript/errors.js +75 -0
  46. package/dist/typescript/errors.js.map +1 -0
  47. package/dist/typescript/index.js +27 -0
  48. package/dist/typescript/index.js.map +1 -0
  49. package/package.json +63 -17
  50. package/tsconfig.json +44 -0
  51. package/types/typescript/airtable-mcp-server.d.ts +2 -0
  52. package/types/typescript/app/airtable-client.d.ts +49 -0
  53. package/types/typescript/app/config.d.ts +16 -0
  54. package/types/typescript/app/context.d.ts +12 -0
  55. package/types/typescript/app/exceptions.d.ts +12 -0
  56. package/types/typescript/app/governance.d.ts +18 -0
  57. package/types/typescript/app/logger.d.ts +13 -0
  58. package/types/typescript/app/rateLimiter.d.ts +13 -0
  59. package/types/typescript/app/tools/create.d.ts +3 -0
  60. package/types/typescript/app/tools/describe.d.ts +3 -0
  61. package/types/typescript/app/tools/handleError.d.ts +8 -0
  62. package/types/typescript/app/tools/index.d.ts +3 -0
  63. package/types/typescript/app/tools/listBases.d.ts +33 -0
  64. package/types/typescript/app/tools/listExceptions.d.ts +3 -0
  65. package/types/typescript/app/tools/listGovernance.d.ts +3 -0
  66. package/types/typescript/app/tools/query.d.ts +3 -0
  67. package/types/typescript/app/tools/update.d.ts +3 -0
  68. package/types/typescript/app/tools/upsert.d.ts +3 -0
  69. package/types/typescript/app/tools/webhooks.d.ts +3 -0
  70. package/types/typescript/app/types.d.ts +830 -0
  71. package/types/typescript/apps-sdk/mappers.d.ts +53 -0
  72. package/types/typescript/errors.d.ts +55 -0
  73. package/types/typescript/index.d.ts +10 -0
  74. package/types/typescript/prompt-templates.d.ts +5 -0
  75. package/types/typescript/test-suite.d.ts +33 -0
  76. package/types/typescript/tools-schemas.d.ts +5 -0
  77. package/airtable_simple.js +0 -1561
  78. package/airtable_simple_production.js +0 -1564
  79. package/examples/airtable-crud-example.js +0 -203
  80. package/examples/building-mcp.md +0 -6666
  81. package/examples/claude_config.json +0 -4
  82. package/examples/claude_simple_config.json +0 -7
  83. package/examples/env-demo.js +0 -172
  84. package/examples/example-tasks-update.json +0 -23
  85. package/examples/example-tasks.json +0 -26
  86. package/examples/example_usage.md +0 -124
  87. package/examples/python_debug_patch.txt +0 -27
  88. package/examples/sample-transform.js +0 -76
  89. package/examples/windsurf_mcp_config.json +0 -17
@@ -1,4 +0,0 @@
1
- {
2
- "airtable_token": "YOUR_AIRTABLE_TOKEN",
3
- "base_id": "YOUR_BASE_ID"
4
- }
@@ -1,7 +0,0 @@
1
- {
2
- "mcpServers": {
3
- "airtable": {
4
- "url": "http://localhost:8010/mcp"
5
- }
6
- }
7
- }
@@ -1,172 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Demo script that uses the AIRTABLE_BASE_ID from the .env file
5
- * Demonstrates various operations with the Airtable API
6
- */
7
-
8
- require('dotenv').config();
9
- const baseUtils = require('../tools/airtable-base');
10
- const crudUtils = require('../tools/airtable-crud');
11
- const schemaUtils = require('../tools/airtable-schema');
12
-
13
- // Constants
14
- const DEMO_TABLE_NAME = 'ENV Demo Table';
15
- const SAMPLE_RECORDS = [
16
- { Name: 'Record from ENV Demo', Description: 'Created using AIRTABLE_BASE_ID from .env file', Status: 'Active' },
17
- { Name: 'Another ENV Record', Description: 'Second record from the environment demo', Status: 'Pending' }
18
- ];
19
-
20
- async function runDemo() {
21
- console.log('=================================');
22
- console.log(' AIRTABLE ENV DEMO SCRIPT ');
23
- console.log('=================================');
24
-
25
- // Check environment variables
26
- if (!process.env.AIRTABLE_PERSONAL_ACCESS_TOKEN) {
27
- console.error('❌ Error: AIRTABLE_PERSONAL_ACCESS_TOKEN is not set in .env file');
28
- process.exit(1);
29
- }
30
-
31
- if (!process.env.AIRTABLE_BASE_ID) {
32
- console.error('❌ Error: AIRTABLE_BASE_ID is not set in .env file');
33
- process.exit(1);
34
- }
35
-
36
- const baseId = process.env.AIRTABLE_BASE_ID;
37
- console.log(`✅ Using AIRTABLE_BASE_ID: ${baseId}`);
38
-
39
- try {
40
- // Step 1: Verify base access
41
- console.log('\nStep 1: Verifying access to the base...');
42
- const baseAccess = await baseUtils.checkBaseAccess(baseId);
43
-
44
- if (!baseAccess.accessible) {
45
- console.error(`❌ Error: Cannot access base with ID ${baseId}`);
46
- console.error(` Reason: ${baseAccess.error}`);
47
- process.exit(1);
48
- }
49
-
50
- console.log(`✅ Access confirmed to base: ${baseAccess.name}`);
51
-
52
- // Step 2: List existing tables
53
- console.log('\nStep 2: Listing existing tables...');
54
- const tables = await baseUtils.listTables(baseId);
55
- console.log(`✅ Found ${tables.length} tables in the base`);
56
-
57
- // Step 3: Check if our demo table exists
58
- console.log('\nStep 3: Checking if demo table exists...');
59
- const demoTableExists = await crudUtils.tableExists(baseId, DEMO_TABLE_NAME);
60
-
61
- if (demoTableExists) {
62
- console.log(`✅ Demo table "${DEMO_TABLE_NAME}" already exists`);
63
- } else {
64
- console.log(`ℹ️ Demo table "${DEMO_TABLE_NAME}" does not exist, creating it...`);
65
-
66
- // Step 4: Create the demo table
67
- console.log('\nStep 4: Creating the demo table...');
68
- const tableConfig = {
69
- name: DEMO_TABLE_NAME,
70
- description: 'Table created from the Environment Demo script',
71
- fields: [
72
- {
73
- name: 'Name',
74
- type: 'singleLineText',
75
- description: 'Record name'
76
- },
77
- {
78
- name: 'Description',
79
- type: 'multilineText',
80
- description: 'Record description'
81
- },
82
- {
83
- name: 'Status',
84
- type: 'singleSelect',
85
- options: {
86
- choices: [
87
- { name: 'Active' },
88
- { name: 'Pending' },
89
- { name: 'Completed' }
90
- ]
91
- },
92
- description: 'Current status'
93
- },
94
- {
95
- name: 'Created',
96
- type: 'date',
97
- options: {
98
- dateFormat: {
99
- name: 'local'
100
- }
101
- },
102
- description: 'Creation date'
103
- }
104
- ]
105
- };
106
-
107
- await schemaUtils.createTable(baseId, tableConfig);
108
- console.log(`✅ Created demo table: ${DEMO_TABLE_NAME}`);
109
- }
110
-
111
- // Step 5: Create sample records
112
- console.log('\nStep 5: Creating sample records...');
113
- // Add today's date to all records
114
- const recordsWithDate = SAMPLE_RECORDS.map(record => ({
115
- ...record,
116
- Created: new Date().toISOString().split('T')[0] // Format as YYYY-MM-DD
117
- }));
118
-
119
- const createdRecords = await crudUtils.createRecords(baseId, DEMO_TABLE_NAME, recordsWithDate);
120
- console.log(`✅ Created ${createdRecords.length} sample records`);
121
-
122
- // Step 6: Read records back
123
- console.log('\nStep 6: Reading records from the table...');
124
- const records = await crudUtils.readRecords(baseId, DEMO_TABLE_NAME, 100);
125
- console.log(`✅ Read ${records.length} records from the table`);
126
-
127
- console.log('\nSample record:');
128
- console.log(JSON.stringify(records[0], null, 2));
129
-
130
- // Step 7: Update a record
131
- console.log('\nStep 7: Updating the first record...');
132
- const recordToUpdate = {
133
- id: createdRecords[0].id,
134
- fields: {
135
- Description: createdRecords[0].Description + ' (UPDATED)',
136
- Status: 'Completed'
137
- }
138
- };
139
-
140
- const updatedRecords = await crudUtils.updateRecords(baseId, DEMO_TABLE_NAME, [recordToUpdate]);
141
- console.log(`✅ Updated ${updatedRecords.length} record`);
142
-
143
- // Step 8: Get the updated record
144
- console.log('\nStep 8: Getting the updated record...');
145
- const updatedRecord = await crudUtils.getRecord(baseId, DEMO_TABLE_NAME, createdRecords[0].id);
146
- console.log('Updated record:');
147
- console.log(JSON.stringify(updatedRecord, null, 2));
148
-
149
- // Step 9: Demonstrate filtering records
150
- console.log('\nStep 9: Filtering records by status...');
151
- const completedRecords = await crudUtils.readRecords(baseId, DEMO_TABLE_NAME, 100, 'Status="Completed"');
152
- console.log(`✅ Found ${completedRecords.length} records with Status="Completed"`);
153
-
154
- console.log('\n=================================');
155
- console.log(' ENV DEMO COMPLETED ');
156
- console.log('=================================');
157
- console.log('\nThis script demonstrated:');
158
- console.log('1. Loading environment variables from .env file');
159
- console.log('2. Accessing an Airtable base using AIRTABLE_BASE_ID');
160
- console.log('3. Creating a table (if it doesn\'t exist)');
161
- console.log('4. Creating, reading, and updating records');
162
- console.log('5. Filtering records using Airtable formulas');
163
- console.log('\nAll operations used the AIRTABLE_BASE_ID environment variable');
164
-
165
- } catch (error) {
166
- console.error(`❌ Error: ${error.message}`);
167
- process.exit(1);
168
- }
169
- }
170
-
171
- // Run the demo
172
- runDemo();
@@ -1,23 +0,0 @@
1
- [
2
- {
3
- "id": "rec1qeTzIUy1p8DF5",
4
- "fields": {
5
- "Status": "Completed",
6
- "Description": "Implement the new feature requested by the client (UPDATED)"
7
- }
8
- },
9
- {
10
- "id": "recA443jGkhk4fe8B",
11
- "fields": {
12
- "Status": "Completed",
13
- "Priority": "High"
14
- }
15
- },
16
- {
17
- "id": "recvMTGZYKi8Dcds4",
18
- "fields": {
19
- "Status": "In Progress",
20
- "Description": "Write comprehensive documentation for the project (IN PROGRESS)"
21
- }
22
- }
23
- ]
@@ -1,26 +0,0 @@
1
- [
2
- {
3
- "id": "rec1qeTzIUy1p8DF5",
4
- "Name": "Add new feature",
5
- "Description": "Implement the new feature requested by the client",
6
- "Status": "In Progress",
7
- "Priority": "Medium",
8
- "DueDate": "2024-01-15"
9
- },
10
- {
11
- "id": "recA443jGkhk4fe8B",
12
- "Name": "Fix login bug",
13
- "Description": "Users are experiencing issues with the login process",
14
- "Status": "In Progress",
15
- "Priority": "Critical",
16
- "DueDate": "2023-11-15"
17
- },
18
- {
19
- "id": "recvMTGZYKi8Dcds4",
20
- "Name": "Complete project documentation",
21
- "Description": "Write comprehensive documentation for the project",
22
- "Status": "In Progress",
23
- "Priority": "High",
24
- "DueDate": "2023-12-31"
25
- }
26
- ]
@@ -1,124 +0,0 @@
1
- # Airtable MCP Example Usage
2
-
3
- This document provides examples of how to use the Airtable MCP tools within a compatible MCP client like Cursor.
4
-
5
- ## Base Management
6
-
7
- ### List all available bases
8
-
9
- ```
10
- Using the Airtable MCP, please list all the bases I have access to.
11
- ```
12
-
13
- ### Set the active base
14
-
15
- ```
16
- Set the active Airtable base to "Project Management" (or use the base ID directly).
17
- ```
18
-
19
- ## Table Operations
20
-
21
- ### List all tables in the current base
22
-
23
- ```
24
- Show me all the tables in my current Airtable base.
25
- ```
26
-
27
- ### View table structure
28
-
29
- ```
30
- Show me the structure of the "Tasks" table, including all fields and their types.
31
- ```
32
-
33
- ## Record Operations
34
-
35
- ### List records
36
-
37
- ```
38
- Show me the first 10 records from the "Clients" table.
39
- ```
40
-
41
- ### Filter records
42
-
43
- ```
44
- Find all "Tasks" with a status of "In Progress" and due date before today.
45
- ```
46
-
47
- ### Get a specific record
48
-
49
- ```
50
- Get the record with ID "rec123456" from the "Projects" table.
51
- ```
52
-
53
- ### Create a new record
54
-
55
- ```
56
- Create a new record in the "Tasks" table with the following information:
57
- - Title: "Complete project documentation"
58
- - Status: "Not Started"
59
- - Due Date: "2024-12-31"
60
- - Assigned To: "John Smith"
61
- ```
62
-
63
- ### Update an existing record
64
-
65
- ```
66
- Update the task with ID "rec123456" in the "Tasks" table:
67
- - Change status to "In Progress"
68
- - Update due date to "2024-11-30"
69
- ```
70
-
71
- ### Delete a record
72
-
73
- ```
74
- Delete the record with ID "rec123456" from the "Tasks" table.
75
- ```
76
-
77
- ## Schema Management
78
-
79
- ### Export the schema
80
-
81
- ```
82
- Export the schema of my current Airtable base in JSON format.
83
- ```
84
-
85
- ### Compare schemas
86
-
87
- ```
88
- Compare this schema with my current base schema to identify any differences.
89
- ```
90
-
91
- ## Data Migration
92
-
93
- ### Generate field mapping
94
-
95
- ```
96
- Generate a field mapping between the "Clients" and "Customers" tables.
97
- ```
98
-
99
- ### Migrate data
100
-
101
- ```
102
- Migrate data from the "Clients" table to the "Customers" table using the generated mapping.
103
- ```
104
-
105
- ## Tips for Better Results
106
-
107
- 1. **Be specific** when referencing table and field names
108
- 2. **Use record IDs** when updating or deleting specific records
109
- 3. **Use natural language** to describe the operations you want to perform
110
- 4. **Check your base ID** is correctly set if you get unexpected results
111
- 5. **Format JSON data** properly when creating or updating records
112
-
113
- ## Combining Operations
114
-
115
- You can combine multiple operations in a single request:
116
-
117
- ```
118
- Please help me organize my project data:
119
- 1. First, show me all the tables in my base
120
- 2. Then, list the overdue tasks (status is not "Complete" and due date is before today)
121
- 3. Finally, update those tasks to have a status of "Urgent"
122
- ```
123
-
124
- The Airtable MCP can help with complex workflows by understanding your intentions and executing the appropriate sequence of operations.
@@ -1,27 +0,0 @@
1
- # Add proper error handling
2
- import traceback
3
- import sys
4
-
5
- # Override the default error handlers to format errors as proper JSON
6
- def handle_exceptions(func):
7
- async def wrapper(*args, **kwargs):
8
- try:
9
- return await func(*args, **kwargs)
10
- except Exception as e:
11
- error_trace = traceback.format_exc()
12
- sys.stderr.write(f"Error in MCP handler: {str(e)}\n{error_trace}\n")
13
- # Return a properly formatted JSON error
14
- return {"error": {"code": -32000, "message": str(e)}}
15
- return wrapper
16
-
17
- # Apply the decorator to all RPC methods
18
- original_rpc_method = app.rpc_method
19
- def patched_rpc_method(*args, **kwargs):
20
- def decorator(func):
21
- wrapped_func = handle_exceptions(func)
22
- return original_rpc_method(*args, **kwargs)(wrapped_func)
23
- return decorator
24
-
25
- # Then add this line right before creating the FastMCP instance:
26
- # Replace app.rpc_method with our patched version
27
- app.rpc_method = patched_rpc_method
@@ -1,76 +0,0 @@
1
- /**
2
- * Sample transform function for syncing data between tables
3
- *
4
- * This module demonstrates how to transform records when syncing
5
- * between two tables with different schemas.
6
- *
7
- * To use with the airtable-crud.js sync command:
8
- * node airtable-crud.js sync "Source Table" "Target Table" sample-transform.js
9
- */
10
-
11
- /**
12
- * Transform function that converts records from source table format to target table format
13
- * @param {Object} sourceRecord - Record from the source table
14
- * @returns {Object} - Transformed record for the target table
15
- */
16
- function transform(sourceRecord) {
17
- // Example: Converting a customer record to a simplified format
18
-
19
- // Extract the needed fields
20
- const { id, Name, Email, Phone, "Company Name": Company, "Date Added": DateAdded, Status } = sourceRecord;
21
-
22
- // Create the transformed record
23
- const transformedRecord = {
24
- // You can optionally include the source record ID
25
- // This is useful for updating existing records in sync operations
26
- // "Source Record ID": id,
27
-
28
- // Map fields from source to target
29
- CustomerName: Name,
30
- CustomerEmail: Email,
31
- CustomerPhone: Phone || '',
32
- Organization: Company || 'Individual',
33
-
34
- // Transform dates
35
- JoinDate: DateAdded,
36
-
37
- // Add calculated fields
38
- CustomerCategory: Company ? 'Business' : 'Individual',
39
-
40
- // Transform status to a different format
41
- IsActive: Status === 'Active',
42
-
43
- // Add constant values
44
- DataSource: 'Customer Table Sync',
45
- LastSyncedAt: new Date().toISOString()
46
- };
47
-
48
- return transformedRecord;
49
- }
50
-
51
- // You can define other utility functions here
52
-
53
- /**
54
- * Helper function to clean and format phone numbers
55
- * @param {string} phone - Raw phone number
56
- * @returns {string} - Formatted phone number
57
- */
58
- function formatPhoneNumber(phone) {
59
- if (!phone) return '';
60
-
61
- // Remove non-numeric characters
62
- const cleaned = ('' + phone).replace(/\D/g, '');
63
-
64
- // Format as (XXX) XXX-XXXX
65
- const match = cleaned.match(/^(\d{3})(\d{3})(\d{4})$/);
66
- if (match) {
67
- return '(' + match[1] + ') ' + match[2] + '-' + match[3];
68
- }
69
-
70
- return phone;
71
- }
72
-
73
- // Export the transform function
74
- module.exports = {
75
- transform
76
- };
@@ -1,17 +0,0 @@
1
- {
2
- "mcpServers": {
3
- "AIRTABLE": {
4
- "command": "npx",
5
- "args": [
6
- "-y",
7
- "@smithery/cli@latest",
8
- "run",
9
- "@rashidazarang/airtable-mcp",
10
- "--token",
11
- "YOUR_AIRTABLE_TOKEN",
12
- "--base",
13
- "YOUR_BASE_ID"
14
- ]
15
- }
16
- }
17
- }