@rashidazarang/airtable-mcp 3.1.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.
- package/README.md +62 -25
- package/bin/airtable-mcp.js +12 -32
- package/dist/typescript/airtable-mcp-server.js +77 -0
- package/dist/typescript/airtable-mcp-server.js.map +1 -0
- package/dist/typescript/app/airtable-client.js +325 -0
- package/dist/typescript/app/airtable-client.js.map +1 -0
- package/dist/typescript/app/config.js +141 -0
- package/dist/typescript/app/config.js.map +1 -0
- package/dist/typescript/app/context.js +3 -0
- package/dist/typescript/app/context.js.map +1 -0
- package/dist/typescript/app/exceptions.js +85 -0
- package/dist/typescript/app/exceptions.js.map +1 -0
- package/dist/typescript/app/governance.js +58 -0
- package/dist/typescript/app/governance.js.map +1 -0
- package/dist/typescript/app/logger.js +47 -0
- package/dist/typescript/app/logger.js.map +1 -0
- package/dist/typescript/app/rateLimiter.js +37 -0
- package/dist/typescript/app/rateLimiter.js.map +1 -0
- package/dist/typescript/app/tools/create.js +54 -0
- package/dist/typescript/app/tools/create.js.map +1 -0
- package/dist/typescript/app/tools/describe.js +146 -0
- package/dist/typescript/app/tools/describe.js.map +1 -0
- package/dist/typescript/app/tools/handleError.js +54 -0
- package/dist/typescript/app/tools/handleError.js.map +1 -0
- package/dist/typescript/app/tools/index.js +24 -0
- package/dist/typescript/app/tools/index.js.map +1 -0
- package/dist/typescript/app/tools/listBases.js +52 -0
- package/dist/typescript/app/tools/listBases.js.map +1 -0
- package/dist/typescript/app/tools/listExceptions.js +18 -0
- package/dist/typescript/app/tools/listExceptions.js.map +1 -0
- package/dist/typescript/app/tools/listGovernance.js +17 -0
- package/dist/typescript/app/tools/listGovernance.js.map +1 -0
- package/dist/typescript/app/tools/query.js +126 -0
- package/dist/typescript/app/tools/query.js.map +1 -0
- package/dist/typescript/app/tools/update.js +56 -0
- package/dist/typescript/app/tools/update.js.map +1 -0
- package/dist/typescript/app/tools/upsert.js +65 -0
- package/dist/typescript/app/tools/upsert.js.map +1 -0
- package/dist/typescript/app/tools/webhooks.js +44 -0
- package/dist/typescript/app/tools/webhooks.js.map +1 -0
- package/dist/typescript/app/types.js +282 -0
- package/dist/typescript/app/types.js.map +1 -0
- package/dist/typescript/apps-sdk/mappers.js +70 -0
- package/dist/typescript/apps-sdk/mappers.js.map +1 -0
- package/dist/typescript/errors.js +75 -0
- package/dist/typescript/errors.js.map +1 -0
- package/dist/typescript/index.js +27 -0
- package/dist/typescript/index.js.map +1 -0
- package/package.json +49 -30
- package/tsconfig.json +10 -4
- package/types/typescript/airtable-mcp-server.d.ts +2 -0
- package/types/typescript/app/airtable-client.d.ts +49 -0
- package/types/typescript/app/config.d.ts +16 -0
- package/types/typescript/app/context.d.ts +12 -0
- package/types/typescript/app/exceptions.d.ts +12 -0
- package/types/typescript/app/governance.d.ts +18 -0
- package/types/typescript/app/logger.d.ts +13 -0
- package/types/typescript/app/rateLimiter.d.ts +13 -0
- package/types/typescript/app/tools/create.d.ts +3 -0
- package/types/typescript/app/tools/describe.d.ts +3 -0
- package/types/typescript/app/tools/handleError.d.ts +8 -0
- package/types/typescript/app/tools/index.d.ts +3 -0
- package/types/typescript/app/tools/listBases.d.ts +33 -0
- package/types/typescript/app/tools/listExceptions.d.ts +3 -0
- package/types/typescript/app/tools/listGovernance.d.ts +3 -0
- package/types/typescript/app/tools/query.d.ts +3 -0
- package/types/typescript/app/tools/update.d.ts +3 -0
- package/types/typescript/app/tools/upsert.d.ts +3 -0
- package/types/typescript/app/tools/webhooks.d.ts +3 -0
- package/types/typescript/app/types.d.ts +830 -0
- package/types/typescript/apps-sdk/mappers.d.ts +53 -0
- package/types/typescript/errors.d.ts +55 -0
- package/types/typescript/index.d.ts +10 -0
- package/types/typescript/prompt-templates.d.ts +5 -0
- package/types/typescript/tools-schemas.d.ts +5 -0
- package/airtable_simple.js +0 -1561
- package/airtable_simple_production.js +0 -1564
- package/dist/airtable-mcp-server.js +0 -660
- package/dist/airtable-mcp-server.js.map +0 -1
- package/dist/test-suite.js +0 -421
- package/dist/test-suite.js.map +0 -1
- package/examples/airtable-crud-example.js +0 -203
- package/examples/building-mcp.md +0 -6666
- package/examples/claude_config.json +0 -4
- package/examples/claude_simple_config.json +0 -7
- package/examples/env-demo.js +0 -172
- package/examples/example-tasks-update.json +0 -23
- package/examples/example-tasks.json +0 -26
- package/examples/example_usage.md +0 -124
- package/examples/python_debug_patch.txt +0 -27
- package/examples/sample-transform.js +0 -76
- package/examples/typescript/advanced-ai-prompts.ts +0 -447
- package/examples/typescript/basic-usage.ts +0 -174
- package/examples/typescript/claude-desktop-config.json +0 -29
- package/examples/windsurf_mcp_config.json +0 -17
- package/types/ai-prompts.d.ts +0 -321
- package/types/airtable-mcp-server.d.ts +0 -52
- package/types/index.d.ts +0 -357
- package/types/tools.d.ts +0 -514
- /package/types/{test-suite.d.ts → typescript/test-suite.d.ts} +0 -0
package/examples/env-demo.js
DELETED
|
@@ -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
|
-
};
|