@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/README.md
CHANGED
|
@@ -3,23 +3,35 @@
|
|
|
3
3
|
[](https://archestra.ai/mcp-catalog/rashidazarang__airtable-mcp)
|
|
4
4
|
[](https://smithery.ai/server/@rashidazarang/airtable-mcp)
|
|
5
5
|

|
|
6
|
-
[](https://github.com/rashidazarang/airtable-mcp)
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
8
8
|
[](https://github.com/rashidazarang/airtable-mcp)
|
|
9
9
|
[](https://github.com/rashidazarang/airtable-mcp)
|
|
10
10
|
[](https://modelcontextprotocol.io/)
|
|
11
11
|
|
|
12
|
-
🤖 **Revolutionary AI Agent v3.
|
|
12
|
+
🤖 **Revolutionary AI Agent v3.2.5** - Advanced AI-powered Airtable MCP server with **fixed TypeScript architecture**, world-class project organization, comprehensive intelligence capabilities, predictive analytics, and enterprise automation features.
|
|
13
13
|
|
|
14
|
-
## 🚀 Latest:
|
|
14
|
+
## 🚀 Latest: v3.2.5 - Optional Base ID & Enhanced Multi-Base Support
|
|
15
15
|
|
|
16
|
-
**
|
|
16
|
+
**Major Improvements** with full backward compatibility:
|
|
17
|
+
- 🔓 **Optional Base ID** - Start without specifying a base, discover them using `list_bases` tool
|
|
18
|
+
- 🔍 **Enhanced Base Discovery** - New `list_bases` tool fully implemented in TypeScript
|
|
19
|
+
- 🎯 **Dynamic Base Selection** - Specify base IDs per tool call, no startup requirement
|
|
20
|
+
- ✅ **Fixed Issue #9** - Resolved "base required at startup" limitation
|
|
21
|
+
- 🔧 **Improved Governance** - Smart base allowlist handling for multi-base workflows
|
|
22
|
+
- 📦 **Full STDIO Support** - Confirmed compatibility with Claude Desktop/Code
|
|
23
|
+
|
|
24
|
+
## 📋 Previous: v3.2.4 - XSS Security Fix & Complete Protection
|
|
25
|
+
|
|
26
|
+
**Major Improvements** with full backward compatibility:
|
|
27
|
+
- 🔧 **TypeScript Architecture Fixed** - Resolved compilation issues, proper separation of types and runtime code
|
|
28
|
+
- 📁 **World-Class Organization** - Restructured project with src/typescript, src/javascript, src/python
|
|
29
|
+
- 🔒 **Security Fix Complete** - Fully resolved command injection vulnerability with comprehensive validation
|
|
17
30
|
- 🔷 **TypeScript Implementation** - Complete type-safe server with strict validation
|
|
18
31
|
- 📘 **Comprehensive Type Definitions** - All 33 tools and 10 AI prompts fully typed
|
|
19
32
|
- 🛡️ **Compile-Time Safety** - Catch errors before runtime with advanced type checking
|
|
20
33
|
- 🎯 **Developer Experience** - IntelliSense, auto-completion, and refactoring support
|
|
21
34
|
- 🔄 **Dual Distribution** - Use with JavaScript or TypeScript, your choice
|
|
22
|
-
- 📖 **Type Documentation** - Self-documenting APIs through comprehensive type definitions
|
|
23
35
|
|
|
24
36
|
## 🤖 AI Intelligence Suite
|
|
25
37
|
|
|
@@ -109,9 +121,14 @@ Create a `.env` file in your project directory:
|
|
|
109
121
|
|
|
110
122
|
```env
|
|
111
123
|
AIRTABLE_TOKEN=your_personal_access_token_here
|
|
112
|
-
AIRTABLE_BASE_ID=your_base_id_here
|
|
124
|
+
AIRTABLE_BASE_ID=your_base_id_here # OPTIONAL - can be discovered using list_bases tool
|
|
113
125
|
```
|
|
114
126
|
|
|
127
|
+
**New in v3.2.5**: The `AIRTABLE_BASE_ID` is now **optional**! You can:
|
|
128
|
+
- Start without a base ID and use the `list_bases` tool to discover your accessible bases
|
|
129
|
+
- Specify base IDs dynamically in each tool call
|
|
130
|
+
- Set a default base for convenience (recommended)
|
|
131
|
+
|
|
115
132
|
**Security Note**: Never commit `.env` files to version control!
|
|
116
133
|
|
|
117
134
|
### Step 4: Configure Your MCP Client
|
|
@@ -128,14 +145,10 @@ Add to your Claude Desktop configuration file with TypeScript binary:
|
|
|
128
145
|
"mcpServers": {
|
|
129
146
|
"airtable-typescript": {
|
|
130
147
|
"command": "npx",
|
|
131
|
-
"args": [
|
|
132
|
-
"@rashidazarang/airtable-mcp",
|
|
133
|
-
"--token",
|
|
134
|
-
"YOUR_AIRTABLE_TOKEN",
|
|
135
|
-
"--base",
|
|
136
|
-
"YOUR_BASE_ID"
|
|
137
|
-
],
|
|
148
|
+
"args": ["@rashidazarang/airtable-mcp"],
|
|
138
149
|
"env": {
|
|
150
|
+
"AIRTABLE_TOKEN": "YOUR_AIRTABLE_TOKEN",
|
|
151
|
+
"AIRTABLE_BASE_ID": "YOUR_BASE_ID",
|
|
139
152
|
"NODE_ENV": "production",
|
|
140
153
|
"LOG_LEVEL": "INFO"
|
|
141
154
|
}
|
|
@@ -144,6 +157,8 @@ Add to your Claude Desktop configuration file with TypeScript binary:
|
|
|
144
157
|
}
|
|
145
158
|
```
|
|
146
159
|
|
|
160
|
+
**Note**: `AIRTABLE_BASE_ID` is optional. Omit it to discover bases using `list_bases` tool.
|
|
161
|
+
|
|
147
162
|
#### 📦 JavaScript Configuration (Standard)
|
|
148
163
|
|
|
149
164
|
Add to your Claude Desktop configuration file:
|
|
@@ -156,19 +171,21 @@ Add to your Claude Desktop configuration file:
|
|
|
156
171
|
"mcpServers": {
|
|
157
172
|
"airtable": {
|
|
158
173
|
"command": "npx",
|
|
159
|
-
"args": [
|
|
160
|
-
|
|
161
|
-
"
|
|
162
|
-
"
|
|
163
|
-
|
|
164
|
-
"YOUR_BASE_ID"
|
|
165
|
-
]
|
|
174
|
+
"args": ["@rashidazarang/airtable-mcp"],
|
|
175
|
+
"env": {
|
|
176
|
+
"AIRTABLE_TOKEN": "YOUR_AIRTABLE_TOKEN",
|
|
177
|
+
"AIRTABLE_BASE_ID": "YOUR_BASE_ID"
|
|
178
|
+
}
|
|
166
179
|
}
|
|
167
180
|
}
|
|
168
181
|
}
|
|
169
182
|
```
|
|
170
183
|
|
|
171
|
-
|
|
184
|
+
**Note**: `AIRTABLE_BASE_ID` is optional. Omit it to discover bases using `list_bases` tool.
|
|
185
|
+
|
|
186
|
+
#### Configuration Without Base ID (New!)
|
|
187
|
+
|
|
188
|
+
Start without specifying a base and discover them dynamically:
|
|
172
189
|
|
|
173
190
|
```json
|
|
174
191
|
{
|
|
@@ -177,14 +194,15 @@ Add to your Claude Desktop configuration file:
|
|
|
177
194
|
"command": "npx",
|
|
178
195
|
"args": ["@rashidazarang/airtable-mcp"],
|
|
179
196
|
"env": {
|
|
180
|
-
"AIRTABLE_TOKEN": "YOUR_AIRTABLE_TOKEN"
|
|
181
|
-
"AIRTABLE_BASE_ID": "YOUR_BASE_ID"
|
|
197
|
+
"AIRTABLE_TOKEN": "YOUR_AIRTABLE_TOKEN"
|
|
182
198
|
}
|
|
183
199
|
}
|
|
184
200
|
}
|
|
185
201
|
}
|
|
186
202
|
```
|
|
187
203
|
|
|
204
|
+
Then use the `list_bases` tool to discover your accessible bases!
|
|
205
|
+
|
|
188
206
|
### Step 5: Restart Your MCP Client
|
|
189
207
|
|
|
190
208
|
After configuration, restart Claude Desktop or your MCP client to load the Airtable server.
|
|
@@ -227,6 +245,7 @@ const insights = await server.handlePromptGet('analyze_data', analysis);
|
|
|
227
245
|
|
|
228
246
|
**Basic Operations**
|
|
229
247
|
```
|
|
248
|
+
"List all my accessible Airtable bases"
|
|
230
249
|
"Show me all records in the Projects table"
|
|
231
250
|
"Create a new task with priority 'High' and due date tomorrow"
|
|
232
251
|
"Update the status of task ID rec123 to 'Completed'"
|
|
@@ -334,7 +353,7 @@ const insights = await server.handlePromptGet('analyze_data', analysis);
|
|
|
334
353
|
| `list_collaborators` | View base collaborators and their permission levels |
|
|
335
354
|
| `list_shares` | List shared views and their public configurations |
|
|
336
355
|
|
|
337
|
-
### 🤖 AI Intelligence Suite (10 prompts) - **
|
|
356
|
+
### 🤖 AI Intelligence Suite (10 prompts) - **New in v3.0.0**
|
|
338
357
|
| Prompt | Description | Enterprise Features |
|
|
339
358
|
|--------|-------------|-------------------|
|
|
340
359
|
| `analyze_data` | Advanced statistical analysis with ML insights | Confidence intervals, anomaly detection |
|
|
@@ -503,6 +522,24 @@ lsof -ti:8010 | xargs kill -9
|
|
|
503
522
|
- **v1.2.3** (2025-08-11) - Bug fixes and error handling
|
|
504
523
|
- **v1.2.2** (2025-08-10) - Initial stable release
|
|
505
524
|
|
|
525
|
+
## 📂 Project Structure
|
|
526
|
+
|
|
527
|
+
```
|
|
528
|
+
airtable-mcp/
|
|
529
|
+
├── src/ # Source code
|
|
530
|
+
│ ├── index.js # Main entry point
|
|
531
|
+
│ ├── typescript/ # TypeScript implementation
|
|
532
|
+
│ ├── javascript/ # JavaScript implementation
|
|
533
|
+
│ └── python/ # Python implementation
|
|
534
|
+
├── dist/ # Compiled TypeScript output
|
|
535
|
+
├── docs/ # Documentation
|
|
536
|
+
│ ├── guides/ # User guides
|
|
537
|
+
│ └── releases/ # Release notes
|
|
538
|
+
├── tests/ # Test files
|
|
539
|
+
├── examples/ # Usage examples
|
|
540
|
+
└── types/ # TypeScript type definitions
|
|
541
|
+
```
|
|
542
|
+
|
|
506
543
|
## 🤝 Contributing
|
|
507
544
|
|
|
508
545
|
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
@@ -524,4 +561,4 @@ MIT License - see [LICENSE](./LICENSE) file for details
|
|
|
524
561
|
|
|
525
562
|
---
|
|
526
563
|
|
|
527
|
-
**Version**: 3.
|
|
564
|
+
**Version**: 3.2.4 | **Status**: 🔷 TypeScript Fixed + 🤖 AI Agent | **MCP Protocol**: 2024-11-05 Complete | **Type Safety**: Enterprise-Grade | **Intelligence**: 10 AI Prompts | **Security**: Fully Patched (XSS Fixed) | **Last Updated**: September 9, 2025
|
package/bin/airtable-mcp.js
CHANGED
|
@@ -2,43 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
const { spawn } = require('child_process');
|
|
4
4
|
const path = require('path');
|
|
5
|
+
const fs = require('fs');
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
const getPythonPath = () => {
|
|
8
|
-
try {
|
|
9
|
-
const whichPython = require('child_process').execSync('which python3.10').toString().trim();
|
|
10
|
-
return whichPython;
|
|
11
|
-
} catch (e) {
|
|
12
|
-
try {
|
|
13
|
-
const whichPython = require('child_process').execSync('which python3').toString().trim();
|
|
14
|
-
return whichPython;
|
|
15
|
-
} catch (e) {
|
|
16
|
-
return 'python';
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
};
|
|
7
|
+
const distServer = path.join(__dirname, '..', 'dist', 'typescript', 'airtable-mcp-server.js');
|
|
20
8
|
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
if (!fs.existsSync(distServer)) {
|
|
10
|
+
console.error('Airtable MCP: compiled server not found.');
|
|
11
|
+
console.error('Run `npm install && npm run build` and try again.');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
23
14
|
|
|
24
|
-
// Get the arguments
|
|
25
15
|
const args = process.argv.slice(2);
|
|
26
|
-
|
|
27
|
-
// Construct the full command
|
|
28
|
-
const serverProcess = spawn(pythonPath, [serverScript, ...args], {
|
|
16
|
+
const child = spawn(process.execPath, [distServer, ...args], {
|
|
29
17
|
stdio: 'inherit',
|
|
18
|
+
env: process.env,
|
|
30
19
|
});
|
|
31
20
|
|
|
32
|
-
|
|
33
|
-
serverProcess.on('close', (code) => {
|
|
34
|
-
process.exit(code);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// Handle signals
|
|
38
|
-
process.on('SIGINT', () => {
|
|
39
|
-
serverProcess.kill('SIGINT');
|
|
40
|
-
});
|
|
21
|
+
child.on('close', (code) => process.exit(code));
|
|
41
22
|
|
|
42
|
-
process.on('
|
|
43
|
-
|
|
44
|
-
});
|
|
23
|
+
process.on('SIGINT', () => child.kill('SIGINT'));
|
|
24
|
+
process.on('SIGTERM', () => child.kill('SIGTERM'));
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.start = start;
|
|
5
|
+
// Import via require to avoid TS type resolution issues with deep subpath exports
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
7
|
+
const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp');
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
9
|
+
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio');
|
|
10
|
+
const config_1 = require("./app/config");
|
|
11
|
+
const logger_1 = require("./app/logger");
|
|
12
|
+
const rateLimiter_1 = require("./app/rateLimiter");
|
|
13
|
+
const airtable_client_1 = require("./app/airtable-client");
|
|
14
|
+
const governance_1 = require("./app/governance");
|
|
15
|
+
const exceptions_1 = require("./app/exceptions");
|
|
16
|
+
const tools_1 = require("./app/tools");
|
|
17
|
+
const PROTOCOL_VERSION = '2024-11-05';
|
|
18
|
+
function buildContext(config, rootLogger) {
|
|
19
|
+
const baseLimiter = new rateLimiter_1.RateLimiter({ maxRequestsPerSecond: 5 });
|
|
20
|
+
const patLimiter = new rateLimiter_1.RateLimiter({ maxRequestsPerSecond: 50 });
|
|
21
|
+
const airtable = new airtable_client_1.AirtableClient(config.auth.personalAccessToken, {
|
|
22
|
+
baseLimiter,
|
|
23
|
+
patLimiter,
|
|
24
|
+
logger: rootLogger.child({ component: 'airtable_client' }),
|
|
25
|
+
userAgent: `airtable-brain-mcp/${config.version}`,
|
|
26
|
+
patHash: config.auth.patHash
|
|
27
|
+
});
|
|
28
|
+
const governance = new governance_1.GovernanceService(config.governance);
|
|
29
|
+
const exceptions = new exceptions_1.ExceptionStore(config.exceptionQueueSize, rootLogger);
|
|
30
|
+
return {
|
|
31
|
+
config,
|
|
32
|
+
logger: rootLogger,
|
|
33
|
+
airtable,
|
|
34
|
+
governance,
|
|
35
|
+
exceptions
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function start() {
|
|
39
|
+
const config = (0, config_1.loadConfig)();
|
|
40
|
+
const logger = new logger_1.Logger(config.logLevel, { component: 'server' });
|
|
41
|
+
const context = buildContext(config, logger);
|
|
42
|
+
const server = new McpServer({
|
|
43
|
+
name: 'airtable-brain',
|
|
44
|
+
version: config.version,
|
|
45
|
+
protocolVersion: PROTOCOL_VERSION
|
|
46
|
+
}, {
|
|
47
|
+
capabilities: {
|
|
48
|
+
tools: {},
|
|
49
|
+
prompts: {},
|
|
50
|
+
resources: {}
|
|
51
|
+
},
|
|
52
|
+
instructions: 'Use describe and query tools for read flows. All mutations require diff review and idempotency keys.'
|
|
53
|
+
});
|
|
54
|
+
(0, tools_1.registerAllTools)(server, context);
|
|
55
|
+
const transport = new StdioServerTransport();
|
|
56
|
+
await server.connect(transport);
|
|
57
|
+
logger.info('Airtable Brain MCP server ready', {
|
|
58
|
+
version: config.version,
|
|
59
|
+
protocolVersion: PROTOCOL_VERSION
|
|
60
|
+
});
|
|
61
|
+
const shutdown = async (signal) => {
|
|
62
|
+
logger.info('Shutting down due to signal', { signal });
|
|
63
|
+
await server.close();
|
|
64
|
+
await transport.close();
|
|
65
|
+
process.exit(0);
|
|
66
|
+
};
|
|
67
|
+
process.on('SIGINT', () => void shutdown('SIGINT'));
|
|
68
|
+
process.on('SIGTERM', () => void shutdown('SIGTERM'));
|
|
69
|
+
}
|
|
70
|
+
if (typeof require !== 'undefined' && require.main === module) {
|
|
71
|
+
start().catch((error) => {
|
|
72
|
+
// eslint-disable-next-line no-console
|
|
73
|
+
console.error('Failed to start Airtable Brain MCP server:', error);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=airtable-mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"airtable-mcp-server.js","sourceRoot":"","sources":["../../src/typescript/airtable-mcp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AirtableClient = void 0;
|
|
7
|
+
const node_https_1 = __importDefault(require("node:https"));
|
|
8
|
+
const node_url_1 = require("node:url");
|
|
9
|
+
const promises_1 = require("node:timers/promises");
|
|
10
|
+
const errors_1 = require("../errors");
|
|
11
|
+
function toQueryString(query) {
|
|
12
|
+
if (!query) {
|
|
13
|
+
return '';
|
|
14
|
+
}
|
|
15
|
+
const params = new URLSearchParams();
|
|
16
|
+
for (const [key, value] of Object.entries(query)) {
|
|
17
|
+
if (value === undefined)
|
|
18
|
+
continue;
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
value.forEach((item) => params.append(`${key}[]`, String(item)));
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
params.append(key, String(value));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const queryString = params.toString();
|
|
27
|
+
return queryString.length > 0 ? `?${queryString}` : '';
|
|
28
|
+
}
|
|
29
|
+
function parseRetryAfter(headers) {
|
|
30
|
+
const retryAfter = headers['retry-after'];
|
|
31
|
+
if (!retryAfter)
|
|
32
|
+
return undefined;
|
|
33
|
+
const parsedSeconds = Number(retryAfter);
|
|
34
|
+
if (!Number.isNaN(parsedSeconds)) {
|
|
35
|
+
return parsedSeconds * 1000;
|
|
36
|
+
}
|
|
37
|
+
const retryDate = new Date(retryAfter);
|
|
38
|
+
if (!Number.isNaN(retryDate.getTime())) {
|
|
39
|
+
return Math.max(retryDate.getTime() - Date.now(), 0);
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
class AirtableClient {
|
|
44
|
+
constructor(personalAccessToken, options) {
|
|
45
|
+
this.pat = personalAccessToken;
|
|
46
|
+
this.baseLimiter = options.baseLimiter;
|
|
47
|
+
this.patLimiter = options.patLimiter;
|
|
48
|
+
this.logger = options.logger;
|
|
49
|
+
this.userAgent = options.userAgent;
|
|
50
|
+
this.patHash = options.patHash;
|
|
51
|
+
this.maxRetries = options.maxRetries ?? 3;
|
|
52
|
+
}
|
|
53
|
+
async listBases() {
|
|
54
|
+
return this.request({
|
|
55
|
+
method: 'GET',
|
|
56
|
+
path: '/v0/meta/bases'
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async getBase(baseId) {
|
|
60
|
+
return this.request({
|
|
61
|
+
method: 'GET',
|
|
62
|
+
path: `/v0/meta/bases/${encodeURIComponent(baseId)}`,
|
|
63
|
+
baseId
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async listTables(baseId) {
|
|
67
|
+
return this.request({
|
|
68
|
+
method: 'GET',
|
|
69
|
+
path: `/v0/meta/bases/${encodeURIComponent(baseId)}/tables`,
|
|
70
|
+
baseId
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async queryRecords(baseId, table, query) {
|
|
74
|
+
const requestOptions = {
|
|
75
|
+
method: 'GET',
|
|
76
|
+
path: `/v0/${encodeURIComponent(baseId)}/${encodeURIComponent(table)}`,
|
|
77
|
+
baseId
|
|
78
|
+
};
|
|
79
|
+
if (query && Object.keys(query).length > 0) {
|
|
80
|
+
requestOptions.query = query;
|
|
81
|
+
}
|
|
82
|
+
return this.request(requestOptions);
|
|
83
|
+
}
|
|
84
|
+
async createRecords(baseId, table, payload, idempotencyKey) {
|
|
85
|
+
const requestOptions = {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
path: `/v0/${encodeURIComponent(baseId)}/${encodeURIComponent(table)}`,
|
|
88
|
+
baseId,
|
|
89
|
+
body: payload
|
|
90
|
+
};
|
|
91
|
+
if (idempotencyKey) {
|
|
92
|
+
requestOptions.idempotencyKey = idempotencyKey;
|
|
93
|
+
}
|
|
94
|
+
return this.request(requestOptions);
|
|
95
|
+
}
|
|
96
|
+
async updateRecords(baseId, table, payload, idempotencyKey) {
|
|
97
|
+
const requestOptions = {
|
|
98
|
+
method: 'PATCH',
|
|
99
|
+
path: `/v0/${encodeURIComponent(baseId)}/${encodeURIComponent(table)}`,
|
|
100
|
+
baseId,
|
|
101
|
+
body: payload
|
|
102
|
+
};
|
|
103
|
+
if (idempotencyKey) {
|
|
104
|
+
requestOptions.idempotencyKey = idempotencyKey;
|
|
105
|
+
}
|
|
106
|
+
return this.request(requestOptions);
|
|
107
|
+
}
|
|
108
|
+
async upsertRecords(baseId, table, payload, idempotencyKey) {
|
|
109
|
+
const requestOptions = {
|
|
110
|
+
method: 'PATCH',
|
|
111
|
+
path: `/v0/${encodeURIComponent(baseId)}/${encodeURIComponent(table)}`,
|
|
112
|
+
baseId,
|
|
113
|
+
body: payload
|
|
114
|
+
};
|
|
115
|
+
if (idempotencyKey) {
|
|
116
|
+
requestOptions.idempotencyKey = idempotencyKey;
|
|
117
|
+
}
|
|
118
|
+
return this.request(requestOptions);
|
|
119
|
+
}
|
|
120
|
+
async request(options) {
|
|
121
|
+
const { baseId } = options;
|
|
122
|
+
if (baseId) {
|
|
123
|
+
await this.baseLimiter.schedule(baseId);
|
|
124
|
+
}
|
|
125
|
+
await this.patLimiter.schedule(this.patHash);
|
|
126
|
+
return this.withRetry(() => this.performRequest(options));
|
|
127
|
+
}
|
|
128
|
+
async withRetry(fn) {
|
|
129
|
+
let attempt = 0;
|
|
130
|
+
let lastError;
|
|
131
|
+
while (attempt < this.maxRetries) {
|
|
132
|
+
try {
|
|
133
|
+
return await fn();
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
lastError = error;
|
|
137
|
+
attempt += 1;
|
|
138
|
+
if (error instanceof errors_1.RateLimitError) {
|
|
139
|
+
const delayMs = error.retryAfterMs ?? this.backoffWithJitter(attempt);
|
|
140
|
+
this.logger.warn('Rate limited, backing off', {
|
|
141
|
+
attempt,
|
|
142
|
+
delayMs
|
|
143
|
+
});
|
|
144
|
+
await (0, promises_1.setTimeout)(delayMs);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
if (error instanceof errors_1.InternalServerError && attempt < this.maxRetries) {
|
|
148
|
+
const delayMs = this.backoffWithJitter(attempt);
|
|
149
|
+
this.logger.warn('Upstream error, retrying', {
|
|
150
|
+
attempt,
|
|
151
|
+
delayMs
|
|
152
|
+
});
|
|
153
|
+
await (0, promises_1.setTimeout)(delayMs);
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (lastError instanceof errors_1.AirtableBrainError) {
|
|
160
|
+
throw lastError.withContext({ attempt: this.maxRetries, totalAttempts: this.maxRetries });
|
|
161
|
+
}
|
|
162
|
+
throw lastError;
|
|
163
|
+
}
|
|
164
|
+
backoffWithJitter(attempt) {
|
|
165
|
+
const baseDelay = Math.min(1000 * 2 ** (attempt - 1), 8000);
|
|
166
|
+
const jitter = Math.random() * 250;
|
|
167
|
+
return baseDelay + jitter;
|
|
168
|
+
}
|
|
169
|
+
performRequest(options) {
|
|
170
|
+
const { method = 'GET', path, query, body, idempotencyKey } = options;
|
|
171
|
+
const logger = this.logger.child({
|
|
172
|
+
op: 'airtable_request',
|
|
173
|
+
method,
|
|
174
|
+
path,
|
|
175
|
+
baseId: options.baseId,
|
|
176
|
+
patHash: this.patHash
|
|
177
|
+
});
|
|
178
|
+
const queryString = toQueryString(query);
|
|
179
|
+
const url = new node_url_1.URL(`https://api.airtable.com${path}${queryString}`);
|
|
180
|
+
const payload = body === undefined ? undefined : JSON.stringify(body);
|
|
181
|
+
return new Promise((resolve, reject) => {
|
|
182
|
+
const request = node_https_1.default.request({
|
|
183
|
+
method,
|
|
184
|
+
hostname: url.hostname,
|
|
185
|
+
path: url.pathname + url.search,
|
|
186
|
+
headers: {
|
|
187
|
+
Authorization: `Bearer ${this.pat}`,
|
|
188
|
+
'Content-Type': 'application/json',
|
|
189
|
+
'User-Agent': this.userAgent,
|
|
190
|
+
...(payload ? { 'Content-Length': Buffer.byteLength(payload) } : {}),
|
|
191
|
+
...(idempotencyKey ? { 'Idempotency-Key': idempotencyKey } : {})
|
|
192
|
+
}
|
|
193
|
+
}, (response) => {
|
|
194
|
+
const chunks = [];
|
|
195
|
+
response.on('data', (chunk) => {
|
|
196
|
+
chunks.push(chunk);
|
|
197
|
+
});
|
|
198
|
+
response.on('end', () => {
|
|
199
|
+
const rawBody = Buffer.concat(chunks).toString('utf8');
|
|
200
|
+
let parsedBody;
|
|
201
|
+
if (rawBody.length > 0) {
|
|
202
|
+
try {
|
|
203
|
+
parsedBody = JSON.parse(rawBody);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
reject(new errors_1.InternalServerError('Failed to parse Airtable response', {
|
|
207
|
+
cause: error,
|
|
208
|
+
status: response.statusCode ?? 0
|
|
209
|
+
}));
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const result = {
|
|
214
|
+
status: response.statusCode ?? 0,
|
|
215
|
+
body: parsedBody,
|
|
216
|
+
headers: response.headers
|
|
217
|
+
};
|
|
218
|
+
try {
|
|
219
|
+
if (result.status >= 200 && result.status < 300) {
|
|
220
|
+
resolve(parsedBody);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
reject(this.toDomainError(result, options));
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
reject(error);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
request.on('error', (error) => {
|
|
231
|
+
logger.error('Network error calling Airtable', {
|
|
232
|
+
error: error instanceof Error ? error.message : String(error)
|
|
233
|
+
});
|
|
234
|
+
reject(new errors_1.InternalServerError('Network error communicating with Airtable', {
|
|
235
|
+
cause: error
|
|
236
|
+
}));
|
|
237
|
+
});
|
|
238
|
+
request.setTimeout(30000, () => {
|
|
239
|
+
request.destroy();
|
|
240
|
+
reject(new errors_1.InternalServerError('Airtable request timed out', {
|
|
241
|
+
status: 504
|
|
242
|
+
}));
|
|
243
|
+
});
|
|
244
|
+
if (payload) {
|
|
245
|
+
request.write(payload);
|
|
246
|
+
}
|
|
247
|
+
request.end();
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
toDomainError(response, request) {
|
|
251
|
+
const { status, body, headers } = response;
|
|
252
|
+
const baseContext = {
|
|
253
|
+
endpoint: request.path
|
|
254
|
+
};
|
|
255
|
+
if (request.baseId) {
|
|
256
|
+
baseContext.baseId = request.baseId;
|
|
257
|
+
}
|
|
258
|
+
if (status === 401 || status === 403) {
|
|
259
|
+
return new errors_1.AuthError('Authentication failed with Airtable', {
|
|
260
|
+
status,
|
|
261
|
+
context: baseContext
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
if (status === 404) {
|
|
265
|
+
return new errors_1.NotFoundError('Requested resource was not found in Airtable', {
|
|
266
|
+
status,
|
|
267
|
+
context: baseContext
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
if (status === 409) {
|
|
271
|
+
return new errors_1.ConflictError('Airtable reported a conflict', {
|
|
272
|
+
status,
|
|
273
|
+
context: baseContext
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
if (status === 400 || status === 422) {
|
|
277
|
+
const validationContext = { ...baseContext };
|
|
278
|
+
const upstreamErrorType = this.safeExtractErrorType(body);
|
|
279
|
+
if (upstreamErrorType) {
|
|
280
|
+
validationContext.upstreamErrorType = upstreamErrorType;
|
|
281
|
+
}
|
|
282
|
+
return new errors_1.AirtableValidationError('Airtable validation error', {
|
|
283
|
+
status,
|
|
284
|
+
context: validationContext
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
if (status === 429) {
|
|
288
|
+
const retryAfterMs = parseRetryAfter(headers);
|
|
289
|
+
return new errors_1.RateLimitError('Airtable rate limit exceeded', {
|
|
290
|
+
status,
|
|
291
|
+
...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
|
|
292
|
+
context: baseContext
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
if (status >= 500) {
|
|
296
|
+
const internalContext = { ...baseContext };
|
|
297
|
+
const upstreamErrorType = this.safeExtractErrorType(body);
|
|
298
|
+
if (upstreamErrorType) {
|
|
299
|
+
internalContext.upstreamErrorType = upstreamErrorType;
|
|
300
|
+
}
|
|
301
|
+
return new errors_1.InternalServerError('Airtable returned an internal error', {
|
|
302
|
+
status,
|
|
303
|
+
context: internalContext
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
return new errors_1.InternalServerError('Unexpected Airtable response', {
|
|
307
|
+
status,
|
|
308
|
+
context: baseContext
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
safeExtractErrorType(body) {
|
|
312
|
+
if (body && typeof body === 'object' && 'error' in body) {
|
|
313
|
+
const error = body.error;
|
|
314
|
+
if (error && typeof error === 'object' && 'type' in error) {
|
|
315
|
+
const type = error.type;
|
|
316
|
+
if (typeof type === 'string') {
|
|
317
|
+
return type;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
exports.AirtableClient = AirtableClient;
|
|
325
|
+
//# sourceMappingURL=airtable-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"airtable-client.js","sourceRoot":"","sources":["../../../src/typescript/app/airtable-client.ts"],"names":[],"mappings":"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"}
|