@rashidazarang/airtable-mcp 3.1.0 → 3.2.8
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 +209 -334
- 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 +327 -0
- package/dist/typescript/app/airtable-client.js.map +1 -0
- package/dist/typescript/app/config.js +151 -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/sanitize.js +95 -0
- package/dist/typescript/app/sanitize.js.map +1 -0
- package/dist/typescript/app/tools/create.js +55 -0
- package/dist/typescript/app/tools/create.js.map +1 -0
- package/dist/typescript/app/tools/describe.js +190 -0
- package/dist/typescript/app/tools/describe.js.map +1 -0
- package/dist/typescript/app/tools/handleError.js +205 -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 +47 -0
- package/dist/typescript/app/tools/listBases.js.map +1 -0
- package/dist/typescript/app/tools/listExceptions.js +16 -0
- package/dist/typescript/app/tools/listExceptions.js.map +1 -0
- package/dist/typescript/app/tools/listGovernance.js +15 -0
- package/dist/typescript/app/tools/listGovernance.js.map +1 -0
- package/dist/typescript/app/tools/query.js +133 -0
- package/dist/typescript/app/tools/query.js.map +1 -0
- package/dist/typescript/app/tools/response.js +21 -0
- package/dist/typescript/app/tools/response.js.map +1 -0
- package/dist/typescript/app/tools/update.js +57 -0
- package/dist/typescript/app/tools/update.js.map +1 -0
- package/dist/typescript/app/tools/upsert.js +66 -0
- package/dist/typescript/app/tools/upsert.js.map +1 -0
- package/dist/typescript/app/tools/webhooks.js +45 -0
- package/dist/typescript/app/tools/webhooks.js.map +1 -0
- package/dist/typescript/app/types.js +291 -0
- package/dist/typescript/app/types.js.map +1 -0
- package/dist/typescript/app/validateApiKey.js +75 -0
- package/dist/typescript/app/validateApiKey.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 -31
- package/tsconfig.json +10 -4
- package/types/typescript/airtable-mcp-server.d.ts +2 -0
- package/types/typescript/app/airtable-client.d.ts +50 -0
- package/types/typescript/app/config.d.ts +17 -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/sanitize.d.ts +50 -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 +13 -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/response.d.ts +20 -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 +318 -0
- package/types/typescript/app/validateApiKey.d.ts +25 -0
- package/types/typescript/errors.d.ts +57 -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
|
@@ -1,1564 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Airtable MCP Server - Production Ready
|
|
5
|
-
* Model Context Protocol server for Airtable integration
|
|
6
|
-
*
|
|
7
|
-
* Features:
|
|
8
|
-
* - Complete MCP 2024-11-05 protocol support
|
|
9
|
-
* - OAuth2 authentication with PKCE
|
|
10
|
-
* - Enterprise security features
|
|
11
|
-
* - Rate limiting and input validation
|
|
12
|
-
* - Production monitoring and health checks
|
|
13
|
-
*
|
|
14
|
-
* Author: Rashid Azarang
|
|
15
|
-
* License: MIT
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const http = require('http');
|
|
19
|
-
const https = require('https');
|
|
20
|
-
const fs = require('fs');
|
|
21
|
-
const path = require('path');
|
|
22
|
-
const crypto = require('crypto');
|
|
23
|
-
const url = require('url');
|
|
24
|
-
const querystring = require('querystring');
|
|
25
|
-
|
|
26
|
-
// Load environment variables
|
|
27
|
-
const envPath = path.join(__dirname, '.env');
|
|
28
|
-
if (fs.existsSync(envPath)) {
|
|
29
|
-
require('dotenv').config({ path: envPath });
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Parse command line arguments
|
|
33
|
-
const args = process.argv.slice(2);
|
|
34
|
-
let tokenIndex = args.indexOf('--token');
|
|
35
|
-
let baseIndex = args.indexOf('--base');
|
|
36
|
-
|
|
37
|
-
const token = tokenIndex !== -1 ? args[tokenIndex + 1] : process.env.AIRTABLE_TOKEN || process.env.AIRTABLE_API_TOKEN;
|
|
38
|
-
const baseId = baseIndex !== -1 ? args[baseIndex + 1] : process.env.AIRTABLE_BASE_ID || process.env.AIRTABLE_BASE;
|
|
39
|
-
|
|
40
|
-
if (!token || !baseId) {
|
|
41
|
-
console.error('Error: Missing Airtable credentials');
|
|
42
|
-
console.error('\nUsage options:');
|
|
43
|
-
console.error(' 1. Command line: node airtable_simple_production.js --token YOUR_TOKEN --base YOUR_BASE_ID');
|
|
44
|
-
console.error(' 2. Environment variables: AIRTABLE_TOKEN and AIRTABLE_BASE_ID');
|
|
45
|
-
console.error(' 3. .env file with AIRTABLE_TOKEN and AIRTABLE_BASE_ID');
|
|
46
|
-
process.exit(1);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Configuration
|
|
50
|
-
const CONFIG = {
|
|
51
|
-
PORT: process.env.PORT || 8010,
|
|
52
|
-
HOST: process.env.HOST || 'localhost',
|
|
53
|
-
MAX_REQUESTS_PER_MINUTE: parseInt(process.env.MAX_REQUESTS_PER_MINUTE) || 60,
|
|
54
|
-
LOG_LEVEL: process.env.LOG_LEVEL || 'INFO'
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Logging
|
|
58
|
-
const LOG_LEVELS = { ERROR: 0, WARN: 1, INFO: 2, DEBUG: 3, TRACE: 4 };
|
|
59
|
-
let currentLogLevel = LOG_LEVELS[CONFIG.LOG_LEVEL] || LOG_LEVELS.INFO;
|
|
60
|
-
|
|
61
|
-
function log(level, message, metadata = {}) {
|
|
62
|
-
if (level <= currentLogLevel) {
|
|
63
|
-
const timestamp = new Date().toISOString();
|
|
64
|
-
const levelName = Object.keys(LOG_LEVELS).find(key => LOG_LEVELS[key] === level);
|
|
65
|
-
// Sanitize message to prevent format string attacks
|
|
66
|
-
const safeMessage = String(message).replace(/%/g, '%%');
|
|
67
|
-
const output = `[${timestamp}] [${levelName}] ${safeMessage}`;
|
|
68
|
-
|
|
69
|
-
if (Object.keys(metadata).length > 0) {
|
|
70
|
-
// Use separate arguments to avoid format string injection
|
|
71
|
-
console.log('%s %s', output, JSON.stringify(metadata));
|
|
72
|
-
} else {
|
|
73
|
-
console.log('%s', output);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Rate limiting
|
|
79
|
-
const rateLimiter = new Map();
|
|
80
|
-
|
|
81
|
-
function checkRateLimit(clientId) {
|
|
82
|
-
const now = Date.now();
|
|
83
|
-
const windowStart = now - 60000; // 1 minute window
|
|
84
|
-
|
|
85
|
-
if (!rateLimiter.has(clientId)) {
|
|
86
|
-
rateLimiter.set(clientId, []);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const requests = rateLimiter.get(clientId);
|
|
90
|
-
const recentRequests = requests.filter(time => time > windowStart);
|
|
91
|
-
|
|
92
|
-
if (recentRequests.length >= CONFIG.MAX_REQUESTS_PER_MINUTE) {
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
recentRequests.push(now);
|
|
97
|
-
rateLimiter.set(clientId, recentRequests);
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Input validation and HTML escaping
|
|
102
|
-
function sanitizeInput(input) {
|
|
103
|
-
if (typeof input === 'string') {
|
|
104
|
-
return input.replace(/[<>]/g, '').trim().substring(0, 1000);
|
|
105
|
-
}
|
|
106
|
-
return input;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function escapeHtml(unsafe) {
|
|
110
|
-
if (typeof unsafe !== 'string') {
|
|
111
|
-
return String(unsafe);
|
|
112
|
-
}
|
|
113
|
-
return unsafe
|
|
114
|
-
.replace(/&/g, "&")
|
|
115
|
-
.replace(/</g, "<")
|
|
116
|
-
.replace(/>/g, ">")
|
|
117
|
-
.replace(/"/g, """)
|
|
118
|
-
.replace(/'/g, "'")
|
|
119
|
-
.replace(/\//g, "/");
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function validateUrl(url) {
|
|
123
|
-
try {
|
|
124
|
-
const parsed = new URL(url);
|
|
125
|
-
// Only allow http and https protocols
|
|
126
|
-
return ['http:', 'https:'].includes(parsed.protocol);
|
|
127
|
-
} catch {
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Airtable API integration
|
|
133
|
-
function callAirtableAPI(endpoint, method = 'GET', body = null, queryParams = {}) {
|
|
134
|
-
return new Promise((resolve, reject) => {
|
|
135
|
-
const isBaseEndpoint = !endpoint.startsWith('meta/');
|
|
136
|
-
const baseUrl = isBaseEndpoint ? `${baseId}/${endpoint}` : endpoint;
|
|
137
|
-
|
|
138
|
-
const queryString = Object.keys(queryParams).length > 0
|
|
139
|
-
? '?' + new URLSearchParams(queryParams).toString()
|
|
140
|
-
: '';
|
|
141
|
-
|
|
142
|
-
const apiUrl = `https://api.airtable.com/v0/${baseUrl}${queryString}`;
|
|
143
|
-
const urlObj = new URL(apiUrl);
|
|
144
|
-
|
|
145
|
-
log(LOG_LEVELS.DEBUG, 'API Request', { method, url: apiUrl });
|
|
146
|
-
|
|
147
|
-
const options = {
|
|
148
|
-
hostname: urlObj.hostname,
|
|
149
|
-
path: urlObj.pathname + urlObj.search,
|
|
150
|
-
method: method,
|
|
151
|
-
headers: {
|
|
152
|
-
'Authorization': `Bearer ${token}`,
|
|
153
|
-
'Content-Type': 'application/json',
|
|
154
|
-
'User-Agent': 'Airtable-MCP-Server/2.1.0'
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
const req = https.request(options, (response) => {
|
|
159
|
-
let data = '';
|
|
160
|
-
|
|
161
|
-
response.on('data', (chunk) => data += chunk);
|
|
162
|
-
response.on('end', () => {
|
|
163
|
-
try {
|
|
164
|
-
const parsed = data ? JSON.parse(data) : {};
|
|
165
|
-
|
|
166
|
-
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
167
|
-
resolve(parsed);
|
|
168
|
-
} else {
|
|
169
|
-
const error = parsed.error || {};
|
|
170
|
-
reject(new Error(`Airtable API error (${response.statusCode}): ${error.message || error.type || 'Unknown error'}`));
|
|
171
|
-
}
|
|
172
|
-
} catch (e) {
|
|
173
|
-
reject(new Error(`Failed to parse Airtable response: ${e.message}`));
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
req.on('error', reject);
|
|
179
|
-
|
|
180
|
-
if (body) {
|
|
181
|
-
req.write(JSON.stringify(body));
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
req.end();
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Tools schema
|
|
189
|
-
const TOOLS_SCHEMA = [
|
|
190
|
-
{
|
|
191
|
-
name: 'list_tables',
|
|
192
|
-
description: 'List all tables in the Airtable base',
|
|
193
|
-
inputSchema: {
|
|
194
|
-
type: 'object',
|
|
195
|
-
properties: {
|
|
196
|
-
include_schema: { type: 'boolean', description: 'Include field schema information', default: false }
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
name: 'list_records',
|
|
202
|
-
description: 'List records from a specific table',
|
|
203
|
-
inputSchema: {
|
|
204
|
-
type: 'object',
|
|
205
|
-
properties: {
|
|
206
|
-
table: { type: 'string', description: 'Table name or ID' },
|
|
207
|
-
maxRecords: { type: 'number', description: 'Maximum number of records to return' },
|
|
208
|
-
view: { type: 'string', description: 'View name or ID' },
|
|
209
|
-
filterByFormula: { type: 'string', description: 'Airtable formula to filter records' }
|
|
210
|
-
},
|
|
211
|
-
required: ['table']
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
name: 'get_record',
|
|
216
|
-
description: 'Get a single record by ID',
|
|
217
|
-
inputSchema: {
|
|
218
|
-
type: 'object',
|
|
219
|
-
properties: {
|
|
220
|
-
table: { type: 'string', description: 'Table name or ID' },
|
|
221
|
-
recordId: { type: 'string', description: 'Record ID' }
|
|
222
|
-
},
|
|
223
|
-
required: ['table', 'recordId']
|
|
224
|
-
}
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
name: 'create_record',
|
|
228
|
-
description: 'Create a new record in a table',
|
|
229
|
-
inputSchema: {
|
|
230
|
-
type: 'object',
|
|
231
|
-
properties: {
|
|
232
|
-
table: { type: 'string', description: 'Table name or ID' },
|
|
233
|
-
fields: { type: 'object', description: 'Field values for the new record' }
|
|
234
|
-
},
|
|
235
|
-
required: ['table', 'fields']
|
|
236
|
-
}
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
name: 'update_record',
|
|
240
|
-
description: 'Update an existing record',
|
|
241
|
-
inputSchema: {
|
|
242
|
-
type: 'object',
|
|
243
|
-
properties: {
|
|
244
|
-
table: { type: 'string', description: 'Table name or ID' },
|
|
245
|
-
recordId: { type: 'string', description: 'Record ID to update' },
|
|
246
|
-
fields: { type: 'object', description: 'Fields to update' }
|
|
247
|
-
},
|
|
248
|
-
required: ['table', 'recordId', 'fields']
|
|
249
|
-
}
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
name: 'delete_record',
|
|
253
|
-
description: 'Delete a record from a table',
|
|
254
|
-
inputSchema: {
|
|
255
|
-
type: 'object',
|
|
256
|
-
properties: {
|
|
257
|
-
table: { type: 'string', description: 'Table name or ID' },
|
|
258
|
-
recordId: { type: 'string', description: 'Record ID to delete' }
|
|
259
|
-
},
|
|
260
|
-
required: ['table', 'recordId']
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
];
|
|
264
|
-
|
|
265
|
-
// Enhanced AI-powered prompts for intelligent Airtable operations
|
|
266
|
-
const PROMPTS_SCHEMA = [
|
|
267
|
-
{
|
|
268
|
-
name: 'analyze_data',
|
|
269
|
-
description: 'Advanced AI data analysis with statistical insights, pattern recognition, and predictive modeling',
|
|
270
|
-
arguments: [
|
|
271
|
-
{
|
|
272
|
-
name: 'table',
|
|
273
|
-
description: 'Table name or ID to analyze',
|
|
274
|
-
required: true
|
|
275
|
-
},
|
|
276
|
-
{
|
|
277
|
-
name: 'analysis_type',
|
|
278
|
-
description: 'Type of analysis (trends, statistical, patterns, predictive, anomaly_detection, correlation_matrix)',
|
|
279
|
-
required: false
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
name: 'field_focus',
|
|
283
|
-
description: 'Specific fields to focus the analysis on',
|
|
284
|
-
required: false
|
|
285
|
-
},
|
|
286
|
-
{
|
|
287
|
-
name: 'time_dimension',
|
|
288
|
-
description: 'Time field for temporal analysis',
|
|
289
|
-
required: false
|
|
290
|
-
},
|
|
291
|
-
{
|
|
292
|
-
name: 'confidence_level',
|
|
293
|
-
description: 'Statistical confidence level (0.90, 0.95, 0.99)',
|
|
294
|
-
required: false
|
|
295
|
-
}
|
|
296
|
-
]
|
|
297
|
-
},
|
|
298
|
-
{
|
|
299
|
-
name: 'create_report',
|
|
300
|
-
description: 'Generate intelligent reports with AI-powered insights, visualizations, and actionable recommendations',
|
|
301
|
-
arguments: [
|
|
302
|
-
{
|
|
303
|
-
name: 'table',
|
|
304
|
-
description: 'Table name or ID for the report',
|
|
305
|
-
required: true
|
|
306
|
-
},
|
|
307
|
-
{
|
|
308
|
-
name: 'report_type',
|
|
309
|
-
description: 'Type of report (executive_summary, operational_dashboard, analytical_deep_dive, performance_metrics, predictive_forecast)',
|
|
310
|
-
required: false
|
|
311
|
-
},
|
|
312
|
-
{
|
|
313
|
-
name: 'time_period',
|
|
314
|
-
description: 'Time period for analysis (last_7_days, last_30_days, last_quarter, year_to_date, custom)',
|
|
315
|
-
required: false
|
|
316
|
-
},
|
|
317
|
-
{
|
|
318
|
-
name: 'stakeholder_level',
|
|
319
|
-
description: 'Target audience (executive, manager, analyst, operational)',
|
|
320
|
-
required: false
|
|
321
|
-
},
|
|
322
|
-
{
|
|
323
|
-
name: 'include_recommendations',
|
|
324
|
-
description: 'Include AI-generated actionable recommendations (true/false)',
|
|
325
|
-
required: false
|
|
326
|
-
}
|
|
327
|
-
]
|
|
328
|
-
},
|
|
329
|
-
{
|
|
330
|
-
name: 'data_insights',
|
|
331
|
-
description: 'Discover hidden patterns, correlations, and business insights using advanced AI algorithms',
|
|
332
|
-
arguments: [
|
|
333
|
-
{
|
|
334
|
-
name: 'tables',
|
|
335
|
-
description: 'Comma-separated list of table names to analyze',
|
|
336
|
-
required: true
|
|
337
|
-
},
|
|
338
|
-
{
|
|
339
|
-
name: 'insight_type',
|
|
340
|
-
description: 'Type of insights (correlations, outliers, trends, predictions, segmentation, attribution, churn_analysis)',
|
|
341
|
-
required: false
|
|
342
|
-
},
|
|
343
|
-
{
|
|
344
|
-
name: 'business_context',
|
|
345
|
-
description: 'Business domain context (sales, marketing, operations, finance, customer_success)',
|
|
346
|
-
required: false
|
|
347
|
-
},
|
|
348
|
-
{
|
|
349
|
-
name: 'insight_depth',
|
|
350
|
-
description: 'Analysis depth (surface, moderate, deep, comprehensive)',
|
|
351
|
-
required: false
|
|
352
|
-
}
|
|
353
|
-
]
|
|
354
|
-
},
|
|
355
|
-
{
|
|
356
|
-
name: 'optimize_workflow',
|
|
357
|
-
description: 'AI-powered workflow optimization with automation recommendations and efficiency improvements',
|
|
358
|
-
arguments: [
|
|
359
|
-
{
|
|
360
|
-
name: 'base_overview',
|
|
361
|
-
description: 'Overview of the base structure and current workflows',
|
|
362
|
-
required: false
|
|
363
|
-
},
|
|
364
|
-
{
|
|
365
|
-
name: 'optimization_focus',
|
|
366
|
-
description: 'Focus area (automation, data_quality, collaboration, performance, integration, user_experience)',
|
|
367
|
-
required: false
|
|
368
|
-
},
|
|
369
|
-
{
|
|
370
|
-
name: 'current_pain_points',
|
|
371
|
-
description: 'Known issues or bottlenecks in current workflow',
|
|
372
|
-
required: false
|
|
373
|
-
},
|
|
374
|
-
{
|
|
375
|
-
name: 'team_size',
|
|
376
|
-
description: 'Number of users working with this base',
|
|
377
|
-
required: false
|
|
378
|
-
}
|
|
379
|
-
]
|
|
380
|
-
},
|
|
381
|
-
{
|
|
382
|
-
name: 'smart_schema_design',
|
|
383
|
-
description: 'AI-assisted database schema optimization and field relationship analysis',
|
|
384
|
-
arguments: [
|
|
385
|
-
{
|
|
386
|
-
name: 'use_case',
|
|
387
|
-
description: 'Primary use case (crm, project_management, inventory, content_management, hr, finance)',
|
|
388
|
-
required: true
|
|
389
|
-
},
|
|
390
|
-
{
|
|
391
|
-
name: 'data_volume',
|
|
392
|
-
description: 'Expected data volume (small, medium, large, enterprise)',
|
|
393
|
-
required: false
|
|
394
|
-
},
|
|
395
|
-
{
|
|
396
|
-
name: 'integration_needs',
|
|
397
|
-
description: 'External systems to integrate with',
|
|
398
|
-
required: false
|
|
399
|
-
},
|
|
400
|
-
{
|
|
401
|
-
name: 'compliance_requirements',
|
|
402
|
-
description: 'Data compliance needs (gdpr, hipaa, sox, none)',
|
|
403
|
-
required: false
|
|
404
|
-
}
|
|
405
|
-
]
|
|
406
|
-
},
|
|
407
|
-
{
|
|
408
|
-
name: 'data_quality_audit',
|
|
409
|
-
description: 'Comprehensive AI-powered data quality assessment with cleansing recommendations',
|
|
410
|
-
arguments: [
|
|
411
|
-
{
|
|
412
|
-
name: 'tables',
|
|
413
|
-
description: 'Tables to audit (comma-separated or "all")',
|
|
414
|
-
required: true
|
|
415
|
-
},
|
|
416
|
-
{
|
|
417
|
-
name: 'quality_dimensions',
|
|
418
|
-
description: 'Quality aspects to check (completeness, accuracy, consistency, validity, uniqueness, timeliness)',
|
|
419
|
-
required: false
|
|
420
|
-
},
|
|
421
|
-
{
|
|
422
|
-
name: 'severity_threshold',
|
|
423
|
-
description: 'Minimum severity level to report (low, medium, high, critical)',
|
|
424
|
-
required: false
|
|
425
|
-
},
|
|
426
|
-
{
|
|
427
|
-
name: 'auto_fix_suggestions',
|
|
428
|
-
description: 'Include automated fix suggestions (true/false)',
|
|
429
|
-
required: false
|
|
430
|
-
}
|
|
431
|
-
]
|
|
432
|
-
},
|
|
433
|
-
{
|
|
434
|
-
name: 'predictive_analytics',
|
|
435
|
-
description: 'Advanced predictive modeling and forecasting using historical Airtable data',
|
|
436
|
-
arguments: [
|
|
437
|
-
{
|
|
438
|
-
name: 'table',
|
|
439
|
-
description: 'Table containing historical data',
|
|
440
|
-
required: true
|
|
441
|
-
},
|
|
442
|
-
{
|
|
443
|
-
name: 'target_field',
|
|
444
|
-
description: 'Field to predict or forecast',
|
|
445
|
-
required: true
|
|
446
|
-
},
|
|
447
|
-
{
|
|
448
|
-
name: 'prediction_horizon',
|
|
449
|
-
description: 'Forecast period (next_week, next_month, next_quarter, next_year)',
|
|
450
|
-
required: false
|
|
451
|
-
},
|
|
452
|
-
{
|
|
453
|
-
name: 'model_type',
|
|
454
|
-
description: 'Prediction model (trend_analysis, seasonal_forecast, regression, classification, time_series)',
|
|
455
|
-
required: false
|
|
456
|
-
},
|
|
457
|
-
{
|
|
458
|
-
name: 'feature_fields',
|
|
459
|
-
description: 'Fields to use as predictive features',
|
|
460
|
-
required: false
|
|
461
|
-
}
|
|
462
|
-
]
|
|
463
|
-
},
|
|
464
|
-
{
|
|
465
|
-
name: 'natural_language_query',
|
|
466
|
-
description: 'Process natural language questions about your data and provide intelligent answers',
|
|
467
|
-
arguments: [
|
|
468
|
-
{
|
|
469
|
-
name: 'question',
|
|
470
|
-
description: 'Natural language question about your data',
|
|
471
|
-
required: true
|
|
472
|
-
},
|
|
473
|
-
{
|
|
474
|
-
name: 'context_tables',
|
|
475
|
-
description: 'Tables that might contain relevant data',
|
|
476
|
-
required: false
|
|
477
|
-
},
|
|
478
|
-
{
|
|
479
|
-
name: 'response_format',
|
|
480
|
-
description: 'Desired response format (narrative, data_summary, visualization_suggestion, action_items)',
|
|
481
|
-
required: false
|
|
482
|
-
},
|
|
483
|
-
{
|
|
484
|
-
name: 'include_confidence',
|
|
485
|
-
description: 'Include confidence scores for answers (true/false)',
|
|
486
|
-
required: false
|
|
487
|
-
}
|
|
488
|
-
]
|
|
489
|
-
},
|
|
490
|
-
{
|
|
491
|
-
name: 'smart_data_transformation',
|
|
492
|
-
description: 'AI-assisted data transformation, cleaning, and enrichment with intelligent suggestions',
|
|
493
|
-
arguments: [
|
|
494
|
-
{
|
|
495
|
-
name: 'source_table',
|
|
496
|
-
description: 'Source table for transformation',
|
|
497
|
-
required: true
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
name: 'transformation_goal',
|
|
501
|
-
description: 'Goal (normalize, standardize, enrich, cleanse, aggregate, pivot)',
|
|
502
|
-
required: true
|
|
503
|
-
},
|
|
504
|
-
{
|
|
505
|
-
name: 'target_format',
|
|
506
|
-
description: 'Desired output format or structure',
|
|
507
|
-
required: false
|
|
508
|
-
},
|
|
509
|
-
{
|
|
510
|
-
name: 'quality_rules',
|
|
511
|
-
description: 'Data quality rules to apply during transformation',
|
|
512
|
-
required: false
|
|
513
|
-
},
|
|
514
|
-
{
|
|
515
|
-
name: 'preserve_history',
|
|
516
|
-
description: 'Maintain audit trail of changes (true/false)',
|
|
517
|
-
required: false
|
|
518
|
-
}
|
|
519
|
-
]
|
|
520
|
-
},
|
|
521
|
-
{
|
|
522
|
-
name: 'automation_recommendations',
|
|
523
|
-
description: 'Generate intelligent automation suggestions based on workflow patterns and data analysis',
|
|
524
|
-
arguments: [
|
|
525
|
-
{
|
|
526
|
-
name: 'workflow_description',
|
|
527
|
-
description: 'Description of current manual processes',
|
|
528
|
-
required: false
|
|
529
|
-
},
|
|
530
|
-
{
|
|
531
|
-
name: 'automation_scope',
|
|
532
|
-
description: 'Scope (single_table, multi_table, cross_base, external_integration)',
|
|
533
|
-
required: false
|
|
534
|
-
},
|
|
535
|
-
{
|
|
536
|
-
name: 'frequency_patterns',
|
|
537
|
-
description: 'How often tasks are performed',
|
|
538
|
-
required: false
|
|
539
|
-
},
|
|
540
|
-
{
|
|
541
|
-
name: 'complexity_tolerance',
|
|
542
|
-
description: 'Acceptable automation complexity (simple, moderate, advanced)',
|
|
543
|
-
required: false
|
|
544
|
-
},
|
|
545
|
-
{
|
|
546
|
-
name: 'integration_capabilities',
|
|
547
|
-
description: 'Available integration tools (zapier, make, custom_api, native_automations)',
|
|
548
|
-
required: false
|
|
549
|
-
}
|
|
550
|
-
]
|
|
551
|
-
}
|
|
552
|
-
];
|
|
553
|
-
|
|
554
|
-
// Roots configuration for filesystem access
|
|
555
|
-
const ROOTS_CONFIG = [
|
|
556
|
-
{
|
|
557
|
-
uri: 'file:///airtable-exports',
|
|
558
|
-
name: 'Airtable Exports'
|
|
559
|
-
},
|
|
560
|
-
{
|
|
561
|
-
uri: 'file:///airtable-attachments',
|
|
562
|
-
name: 'Airtable Attachments'
|
|
563
|
-
}
|
|
564
|
-
];
|
|
565
|
-
|
|
566
|
-
// Logging configuration (currentLogLevel is already declared above)
|
|
567
|
-
|
|
568
|
-
// HTTP server
|
|
569
|
-
const server = http.createServer(async (req, res) => {
|
|
570
|
-
// Security headers
|
|
571
|
-
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
572
|
-
res.setHeader('X-Frame-Options', 'DENY');
|
|
573
|
-
res.setHeader('X-XSS-Protection', '1; mode=block');
|
|
574
|
-
res.setHeader('Access-Control-Allow-Origin', process.env.ALLOWED_ORIGINS || '*');
|
|
575
|
-
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
|
|
576
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
577
|
-
|
|
578
|
-
// Handle preflight request
|
|
579
|
-
if (req.method === 'OPTIONS') {
|
|
580
|
-
res.writeHead(200);
|
|
581
|
-
res.end();
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
const parsedUrl = url.parse(req.url, true);
|
|
586
|
-
const pathname = parsedUrl.pathname;
|
|
587
|
-
|
|
588
|
-
// Health check endpoint
|
|
589
|
-
if (pathname === '/health' && req.method === 'GET') {
|
|
590
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
591
|
-
res.end(JSON.stringify({
|
|
592
|
-
status: 'healthy',
|
|
593
|
-
version: '3.0.0',
|
|
594
|
-
timestamp: new Date().toISOString(),
|
|
595
|
-
uptime: process.uptime()
|
|
596
|
-
}));
|
|
597
|
-
return;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
// OAuth2 authorization endpoint
|
|
601
|
-
if (pathname === '/oauth/authorize' && req.method === 'GET') {
|
|
602
|
-
const params = parsedUrl.query;
|
|
603
|
-
const clientId = params.client_id;
|
|
604
|
-
const redirectUri = params.redirect_uri;
|
|
605
|
-
const state = params.state;
|
|
606
|
-
const codeChallenge = params.code_challenge;
|
|
607
|
-
const codeChallengeMethod = params.code_challenge_method;
|
|
608
|
-
|
|
609
|
-
// Validate inputs to prevent XSS
|
|
610
|
-
if (!clientId || !redirectUri) {
|
|
611
|
-
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
612
|
-
res.end(JSON.stringify({ error: 'invalid_request', error_description: 'Missing required parameters' }));
|
|
613
|
-
return;
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
// Validate redirect URI
|
|
617
|
-
if (!validateUrl(redirectUri)) {
|
|
618
|
-
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
619
|
-
res.end(JSON.stringify({ error: 'invalid_request', error_description: 'Invalid redirect URI' }));
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
// Create safe copies of all variables for JavaScript use
|
|
624
|
-
const safeRedirectUri = redirectUri.slice(0, 2000); // Limit length
|
|
625
|
-
const safeState = (state || '').slice(0, 200); // Limit length
|
|
626
|
-
const safeClientId = clientId.slice(0, 200); // Limit length
|
|
627
|
-
|
|
628
|
-
// Sanitize for HTML display only
|
|
629
|
-
const displayClientId = escapeHtml(safeClientId);
|
|
630
|
-
const displayRedirectUri = escapeHtml(safeRedirectUri);
|
|
631
|
-
|
|
632
|
-
// Generate authorization code
|
|
633
|
-
const authCode = crypto.randomBytes(32).toString('hex');
|
|
634
|
-
|
|
635
|
-
// In a real implementation, store the auth code with expiration
|
|
636
|
-
// and associate it with the client and PKCE challenge
|
|
637
|
-
|
|
638
|
-
res.writeHead(200, {
|
|
639
|
-
'Content-Type': 'text/html',
|
|
640
|
-
'Content-Security-Policy': "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src 'none'; object-src 'none'; base-uri 'none'; form-action 'none';",
|
|
641
|
-
'X-Content-Type-Options': 'nosniff',
|
|
642
|
-
'X-Frame-Options': 'DENY',
|
|
643
|
-
'X-XSS-Protection': '1; mode=block',
|
|
644
|
-
'Referrer-Policy': 'no-referrer'
|
|
645
|
-
});
|
|
646
|
-
|
|
647
|
-
// Build HTML with proper escaping and separation of concerns
|
|
648
|
-
const htmlContent = `<!DOCTYPE html>
|
|
649
|
-
<html>
|
|
650
|
-
<head>
|
|
651
|
-
<meta charset="UTF-8">
|
|
652
|
-
<title>OAuth2 Authorization</title>
|
|
653
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
654
|
-
</head>
|
|
655
|
-
<body>
|
|
656
|
-
<h2>Airtable MCP Server - OAuth2 Authorization</h2>
|
|
657
|
-
<p>Client ID: ${displayClientId}</p>
|
|
658
|
-
<p>Redirect URI: ${displayRedirectUri}</p>
|
|
659
|
-
<div style="margin: 20px 0;">
|
|
660
|
-
<button onclick="authorize()" style="background: #18BFFF; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer;">
|
|
661
|
-
Authorize Application
|
|
662
|
-
</button>
|
|
663
|
-
<button onclick="deny()" style="background: #ff4444; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; margin-left: 10px;">
|
|
664
|
-
Deny Access
|
|
665
|
-
</button>
|
|
666
|
-
</div>
|
|
667
|
-
<script>
|
|
668
|
-
// All variables are safely JSON encoded to prevent XSS
|
|
669
|
-
(function() {
|
|
670
|
-
var config = ${JSON.stringify({
|
|
671
|
-
redirectUri: safeRedirectUri,
|
|
672
|
-
code: authCode,
|
|
673
|
-
state: safeState
|
|
674
|
-
})};
|
|
675
|
-
|
|
676
|
-
window.authorize = function() {
|
|
677
|
-
try {
|
|
678
|
-
var url = new URL(config.redirectUri);
|
|
679
|
-
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
680
|
-
throw new Error('Invalid protocol');
|
|
681
|
-
}
|
|
682
|
-
var finalUrl = config.redirectUri + '?code=' + encodeURIComponent(config.code) + '&state=' + encodeURIComponent(config.state);
|
|
683
|
-
window.location.href = finalUrl;
|
|
684
|
-
} catch (e) {
|
|
685
|
-
console.error('Authorization failed:', e);
|
|
686
|
-
alert('Invalid redirect URL');
|
|
687
|
-
}
|
|
688
|
-
};
|
|
689
|
-
|
|
690
|
-
window.deny = function() {
|
|
691
|
-
try {
|
|
692
|
-
var url = new URL(config.redirectUri);
|
|
693
|
-
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
694
|
-
throw new Error('Invalid protocol');
|
|
695
|
-
}
|
|
696
|
-
var finalUrl = config.redirectUri + '?error=access_denied&state=' + encodeURIComponent(config.state);
|
|
697
|
-
window.location.href = finalUrl;
|
|
698
|
-
} catch (e) {
|
|
699
|
-
console.error('Denial failed:', e);
|
|
700
|
-
alert('Invalid redirect URL');
|
|
701
|
-
}
|
|
702
|
-
};
|
|
703
|
-
})();
|
|
704
|
-
</script>
|
|
705
|
-
</body>
|
|
706
|
-
</html>`;
|
|
707
|
-
|
|
708
|
-
res.end(htmlContent);
|
|
709
|
-
return;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
// OAuth2 token endpoint
|
|
713
|
-
if (pathname === '/oauth/token' && req.method === 'POST') {
|
|
714
|
-
let body = '';
|
|
715
|
-
req.on('data', chunk => {
|
|
716
|
-
body += chunk.toString();
|
|
717
|
-
// Prevent DoS by limiting body size
|
|
718
|
-
if (body.length > 10000) {
|
|
719
|
-
res.writeHead(413, { 'Content-Type': 'application/json' });
|
|
720
|
-
res.end(JSON.stringify({ error: 'payload_too_large', error_description: 'Request body too large' }));
|
|
721
|
-
return;
|
|
722
|
-
}
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
req.on('end', () => {
|
|
726
|
-
try {
|
|
727
|
-
const params = querystring.parse(body);
|
|
728
|
-
const grantType = sanitizeInput(params.grant_type);
|
|
729
|
-
const code = sanitizeInput(params.code);
|
|
730
|
-
const codeVerifier = sanitizeInput(params.code_verifier);
|
|
731
|
-
const clientId = sanitizeInput(params.client_id);
|
|
732
|
-
|
|
733
|
-
// Validate required parameters
|
|
734
|
-
if (!grantType || !code || !clientId) {
|
|
735
|
-
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
736
|
-
res.end(JSON.stringify({
|
|
737
|
-
error: 'invalid_request',
|
|
738
|
-
error_description: 'Missing required parameters'
|
|
739
|
-
}));
|
|
740
|
-
return;
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
// In a real implementation, verify the authorization code and PKCE
|
|
744
|
-
if (grantType === 'authorization_code' && code) {
|
|
745
|
-
// Generate access token
|
|
746
|
-
const accessToken = crypto.randomBytes(32).toString('hex');
|
|
747
|
-
const refreshToken = crypto.randomBytes(32).toString('hex');
|
|
748
|
-
|
|
749
|
-
res.writeHead(200, {
|
|
750
|
-
'Content-Type': 'application/json',
|
|
751
|
-
'Cache-Control': 'no-store',
|
|
752
|
-
'Pragma': 'no-cache'
|
|
753
|
-
});
|
|
754
|
-
res.end(JSON.stringify({
|
|
755
|
-
access_token: accessToken,
|
|
756
|
-
token_type: 'Bearer',
|
|
757
|
-
expires_in: 3600,
|
|
758
|
-
refresh_token: refreshToken,
|
|
759
|
-
scope: 'data.records:read data.records:write schema.bases:read'
|
|
760
|
-
}));
|
|
761
|
-
} else {
|
|
762
|
-
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
763
|
-
res.end(JSON.stringify({
|
|
764
|
-
error: 'invalid_grant',
|
|
765
|
-
error_description: 'Invalid grant type or authorization code'
|
|
766
|
-
}));
|
|
767
|
-
}
|
|
768
|
-
} catch (error) {
|
|
769
|
-
log(LOG_LEVELS.WARN, 'OAuth token request parsing failed', { error: error.message });
|
|
770
|
-
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
771
|
-
res.end(JSON.stringify({
|
|
772
|
-
error: 'invalid_request',
|
|
773
|
-
error_description: 'Malformed request body'
|
|
774
|
-
}));
|
|
775
|
-
}
|
|
776
|
-
});
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
// MCP endpoint
|
|
781
|
-
if (pathname === '/mcp' && req.method === 'POST') {
|
|
782
|
-
// Rate limiting
|
|
783
|
-
const clientId = req.headers['x-client-id'] || req.connection.remoteAddress;
|
|
784
|
-
if (!checkRateLimit(clientId)) {
|
|
785
|
-
res.writeHead(429, { 'Content-Type': 'application/json' });
|
|
786
|
-
res.end(JSON.stringify({
|
|
787
|
-
jsonrpc: '2.0',
|
|
788
|
-
error: {
|
|
789
|
-
code: -32000,
|
|
790
|
-
message: 'Rate limit exceeded. Maximum 60 requests per minute.'
|
|
791
|
-
}
|
|
792
|
-
}));
|
|
793
|
-
return;
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
let body = '';
|
|
797
|
-
req.on('data', chunk => body += chunk.toString());
|
|
798
|
-
|
|
799
|
-
req.on('end', async () => {
|
|
800
|
-
try {
|
|
801
|
-
const request = JSON.parse(body);
|
|
802
|
-
|
|
803
|
-
// Sanitize inputs
|
|
804
|
-
if (request.params) {
|
|
805
|
-
Object.keys(request.params).forEach(key => {
|
|
806
|
-
request.params[key] = sanitizeInput(request.params[key]);
|
|
807
|
-
});
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
log(LOG_LEVELS.DEBUG, 'MCP request received', {
|
|
811
|
-
method: request.method,
|
|
812
|
-
id: request.id
|
|
813
|
-
});
|
|
814
|
-
|
|
815
|
-
let response;
|
|
816
|
-
|
|
817
|
-
switch (request.method) {
|
|
818
|
-
case 'initialize':
|
|
819
|
-
response = {
|
|
820
|
-
jsonrpc: '2.0',
|
|
821
|
-
id: request.id,
|
|
822
|
-
result: {
|
|
823
|
-
protocolVersion: '2024-11-05',
|
|
824
|
-
capabilities: {
|
|
825
|
-
tools: { listChanged: true },
|
|
826
|
-
resources: { subscribe: true, listChanged: true },
|
|
827
|
-
prompts: { listChanged: true },
|
|
828
|
-
sampling: {},
|
|
829
|
-
roots: { listChanged: true },
|
|
830
|
-
logging: {}
|
|
831
|
-
},
|
|
832
|
-
serverInfo: {
|
|
833
|
-
name: 'Airtable MCP Server - AI Agent Enhanced',
|
|
834
|
-
version: '3.0.0',
|
|
835
|
-
description: 'Advanced AI-powered MCP server with 10 intelligent prompt templates, predictive analytics, and enterprise automation capabilities'
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
};
|
|
839
|
-
log(LOG_LEVELS.INFO, 'Client initialized', { clientId: request.id });
|
|
840
|
-
break;
|
|
841
|
-
|
|
842
|
-
case 'tools/list':
|
|
843
|
-
response = {
|
|
844
|
-
jsonrpc: '2.0',
|
|
845
|
-
id: request.id,
|
|
846
|
-
result: {
|
|
847
|
-
tools: TOOLS_SCHEMA
|
|
848
|
-
}
|
|
849
|
-
};
|
|
850
|
-
break;
|
|
851
|
-
|
|
852
|
-
case 'tools/call':
|
|
853
|
-
response = await handleToolCall(request);
|
|
854
|
-
break;
|
|
855
|
-
|
|
856
|
-
case 'prompts/list':
|
|
857
|
-
response = {
|
|
858
|
-
jsonrpc: '2.0',
|
|
859
|
-
id: request.id,
|
|
860
|
-
result: {
|
|
861
|
-
prompts: PROMPTS_SCHEMA
|
|
862
|
-
}
|
|
863
|
-
};
|
|
864
|
-
break;
|
|
865
|
-
|
|
866
|
-
case 'prompts/get':
|
|
867
|
-
response = await handlePromptGet(request);
|
|
868
|
-
break;
|
|
869
|
-
|
|
870
|
-
case 'roots/list':
|
|
871
|
-
response = {
|
|
872
|
-
jsonrpc: '2.0',
|
|
873
|
-
id: request.id,
|
|
874
|
-
result: {
|
|
875
|
-
roots: ROOTS_CONFIG
|
|
876
|
-
}
|
|
877
|
-
};
|
|
878
|
-
break;
|
|
879
|
-
|
|
880
|
-
case 'logging/setLevel':
|
|
881
|
-
const level = request.params?.level;
|
|
882
|
-
if (level && LOG_LEVELS[level.toUpperCase()] !== undefined) {
|
|
883
|
-
currentLogLevel = LOG_LEVELS[level.toUpperCase()];
|
|
884
|
-
log(LOG_LEVELS.INFO, 'Log level updated', { newLevel: level });
|
|
885
|
-
}
|
|
886
|
-
response = {
|
|
887
|
-
jsonrpc: '2.0',
|
|
888
|
-
id: request.id,
|
|
889
|
-
result: {}
|
|
890
|
-
};
|
|
891
|
-
break;
|
|
892
|
-
|
|
893
|
-
case 'sampling/createMessage':
|
|
894
|
-
response = await handleSampling(request);
|
|
895
|
-
break;
|
|
896
|
-
|
|
897
|
-
default:
|
|
898
|
-
log(LOG_LEVELS.WARN, 'Unknown method', { method: request.method });
|
|
899
|
-
throw new Error(`Method "${request.method}" not found`);
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
903
|
-
res.end(JSON.stringify(response));
|
|
904
|
-
|
|
905
|
-
} catch (error) {
|
|
906
|
-
log(LOG_LEVELS.ERROR, 'Request processing failed', { error: error.message });
|
|
907
|
-
|
|
908
|
-
const errorResponse = {
|
|
909
|
-
jsonrpc: '2.0',
|
|
910
|
-
id: request?.id || null,
|
|
911
|
-
error: {
|
|
912
|
-
code: -32000,
|
|
913
|
-
message: error.message || 'Internal server error'
|
|
914
|
-
}
|
|
915
|
-
};
|
|
916
|
-
|
|
917
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
918
|
-
res.end(JSON.stringify(errorResponse));
|
|
919
|
-
}
|
|
920
|
-
});
|
|
921
|
-
return;
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
// Default 404
|
|
925
|
-
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
926
|
-
res.end(JSON.stringify({ error: 'Not Found' }));
|
|
927
|
-
});
|
|
928
|
-
|
|
929
|
-
// Tool handlers
|
|
930
|
-
async function handleToolCall(request) {
|
|
931
|
-
const toolName = request.params.name;
|
|
932
|
-
const toolParams = request.params.arguments || {};
|
|
933
|
-
|
|
934
|
-
try {
|
|
935
|
-
let result;
|
|
936
|
-
let responseText;
|
|
937
|
-
|
|
938
|
-
switch (toolName) {
|
|
939
|
-
case 'list_tables':
|
|
940
|
-
const includeSchema = toolParams.include_schema || false;
|
|
941
|
-
result = await callAirtableAPI(`meta/bases/${baseId}/tables`);
|
|
942
|
-
const tables = result.tables || [];
|
|
943
|
-
|
|
944
|
-
responseText = tables.length > 0
|
|
945
|
-
? `Found ${tables.length} table(s): ` +
|
|
946
|
-
tables.map((table, i) =>
|
|
947
|
-
`${table.name} (ID: ${table.id}, Fields: ${table.fields?.length || 0})`
|
|
948
|
-
).join(', ')
|
|
949
|
-
: 'No tables found in this base.';
|
|
950
|
-
break;
|
|
951
|
-
|
|
952
|
-
case 'list_records':
|
|
953
|
-
const { table, maxRecords, view, filterByFormula } = toolParams;
|
|
954
|
-
|
|
955
|
-
const queryParams = {};
|
|
956
|
-
if (maxRecords) queryParams.maxRecords = maxRecords;
|
|
957
|
-
if (view) queryParams.view = view;
|
|
958
|
-
if (filterByFormula) queryParams.filterByFormula = filterByFormula;
|
|
959
|
-
|
|
960
|
-
result = await callAirtableAPI(table, 'GET', null, queryParams);
|
|
961
|
-
const records = result.records || [];
|
|
962
|
-
|
|
963
|
-
responseText = records.length > 0
|
|
964
|
-
? `Found ${records.length} record(s) in table "${table}"`
|
|
965
|
-
: `No records found in table "${table}".`;
|
|
966
|
-
break;
|
|
967
|
-
|
|
968
|
-
case 'get_record':
|
|
969
|
-
const { table: getTable, recordId } = toolParams;
|
|
970
|
-
result = await callAirtableAPI(`${getTable}/${recordId}`);
|
|
971
|
-
responseText = `Retrieved record ${recordId} from table "${getTable}"`;
|
|
972
|
-
break;
|
|
973
|
-
|
|
974
|
-
case 'create_record':
|
|
975
|
-
const { table: createTable, fields } = toolParams;
|
|
976
|
-
const body = { fields: fields };
|
|
977
|
-
result = await callAirtableAPI(createTable, 'POST', body);
|
|
978
|
-
responseText = `Successfully created record in table "${createTable}" with ID: ${result.id}`;
|
|
979
|
-
break;
|
|
980
|
-
|
|
981
|
-
case 'update_record':
|
|
982
|
-
const { table: updateTable, recordId: updateRecordId, fields: updateFields } = toolParams;
|
|
983
|
-
const updateBody = { fields: updateFields };
|
|
984
|
-
result = await callAirtableAPI(`${updateTable}/${updateRecordId}`, 'PATCH', updateBody);
|
|
985
|
-
responseText = `Successfully updated record ${updateRecordId} in table "${updateTable}"`;
|
|
986
|
-
break;
|
|
987
|
-
|
|
988
|
-
case 'delete_record':
|
|
989
|
-
const { table: deleteTable, recordId: deleteRecordId } = toolParams;
|
|
990
|
-
result = await callAirtableAPI(`${deleteTable}/${deleteRecordId}`, 'DELETE');
|
|
991
|
-
responseText = `Successfully deleted record ${deleteRecordId} from table "${deleteTable}"`;
|
|
992
|
-
break;
|
|
993
|
-
|
|
994
|
-
default:
|
|
995
|
-
throw new Error(`Unknown tool: ${toolName}`);
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
return {
|
|
999
|
-
jsonrpc: '2.0',
|
|
1000
|
-
id: request.id,
|
|
1001
|
-
result: {
|
|
1002
|
-
content: [
|
|
1003
|
-
{
|
|
1004
|
-
type: 'text',
|
|
1005
|
-
text: responseText
|
|
1006
|
-
}
|
|
1007
|
-
]
|
|
1008
|
-
}
|
|
1009
|
-
};
|
|
1010
|
-
|
|
1011
|
-
} catch (error) {
|
|
1012
|
-
log(LOG_LEVELS.ERROR, `Tool ${toolName} failed`, { error: error.message });
|
|
1013
|
-
|
|
1014
|
-
return {
|
|
1015
|
-
jsonrpc: '2.0',
|
|
1016
|
-
id: request.id,
|
|
1017
|
-
result: {
|
|
1018
|
-
content: [
|
|
1019
|
-
{
|
|
1020
|
-
type: 'text',
|
|
1021
|
-
text: `Error executing ${toolName}: ${error.message}`
|
|
1022
|
-
}
|
|
1023
|
-
]
|
|
1024
|
-
}
|
|
1025
|
-
};
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
// Enhanced AI-powered prompt handlers
|
|
1030
|
-
async function handlePromptGet(request) {
|
|
1031
|
-
const promptName = request.params.name;
|
|
1032
|
-
const promptArgs = request.params.arguments || {};
|
|
1033
|
-
|
|
1034
|
-
try {
|
|
1035
|
-
const prompt = PROMPTS_SCHEMA.find(p => p.name === promptName);
|
|
1036
|
-
if (!prompt) {
|
|
1037
|
-
throw new Error(`Prompt "${promptName}" not found`);
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
let messages = [];
|
|
1041
|
-
|
|
1042
|
-
switch (promptName) {
|
|
1043
|
-
case 'analyze_data':
|
|
1044
|
-
const { table, analysis_type = 'statistical', field_focus, time_dimension, confidence_level = '0.95' } = promptArgs;
|
|
1045
|
-
messages = [
|
|
1046
|
-
{
|
|
1047
|
-
role: 'user',
|
|
1048
|
-
content: {
|
|
1049
|
-
type: 'text',
|
|
1050
|
-
text: `🤖 ADVANCED DATA ANALYSIS REQUEST
|
|
1051
|
-
|
|
1052
|
-
**Table**: ${table}
|
|
1053
|
-
**Analysis Type**: ${analysis_type}
|
|
1054
|
-
**Confidence Level**: ${confidence_level}
|
|
1055
|
-
${field_focus ? `**Focus Fields**: ${field_focus}` : ''}
|
|
1056
|
-
${time_dimension ? `**Time Dimension**: ${time_dimension}` : ''}
|
|
1057
|
-
|
|
1058
|
-
**Instructions**:
|
|
1059
|
-
1. First, examine the table schema and structure using list_tables with include_schema=true
|
|
1060
|
-
2. Retrieve representative sample data using list_records with appropriate filters
|
|
1061
|
-
3. Perform ${analysis_type} analysis with statistical rigor
|
|
1062
|
-
4. Generate insights with confidence intervals and significance testing
|
|
1063
|
-
5. Provide actionable recommendations based on findings
|
|
1064
|
-
|
|
1065
|
-
**Expected Deliverables**:
|
|
1066
|
-
- Statistical summary with key metrics
|
|
1067
|
-
- Pattern identification and trend analysis
|
|
1068
|
-
- Anomaly detection if applicable
|
|
1069
|
-
- Predictive insights where relevant
|
|
1070
|
-
- Visualization recommendations
|
|
1071
|
-
- Business impact assessment
|
|
1072
|
-
|
|
1073
|
-
Please use the available Airtable tools to gather data and provide comprehensive ${analysis_type} analysis.`
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
];
|
|
1077
|
-
break;
|
|
1078
|
-
|
|
1079
|
-
case 'create_report':
|
|
1080
|
-
const { table: reportTable, report_type = 'executive_summary', time_period = 'last_30_days', stakeholder_level = 'manager', include_recommendations = 'true' } = promptArgs;
|
|
1081
|
-
messages = [
|
|
1082
|
-
{
|
|
1083
|
-
role: 'user',
|
|
1084
|
-
content: {
|
|
1085
|
-
type: 'text',
|
|
1086
|
-
text: `📊 INTELLIGENT REPORT GENERATION
|
|
1087
|
-
|
|
1088
|
-
**Target Table**: ${reportTable}
|
|
1089
|
-
**Report Type**: ${report_type}
|
|
1090
|
-
**Time Period**: ${time_period}
|
|
1091
|
-
**Stakeholder Level**: ${stakeholder_level}
|
|
1092
|
-
**Include Recommendations**: ${include_recommendations}
|
|
1093
|
-
|
|
1094
|
-
**Report Generation Process**:
|
|
1095
|
-
1. Analyze table structure and data types
|
|
1096
|
-
2. Extract relevant data for specified time period
|
|
1097
|
-
3. Calculate key performance indicators
|
|
1098
|
-
4. Identify trends and patterns
|
|
1099
|
-
5. Generate visualizations suggestions
|
|
1100
|
-
6. Create ${stakeholder_level}-appropriate narrative
|
|
1101
|
-
|
|
1102
|
-
**Report Sections**:
|
|
1103
|
-
- Executive Summary (key findings)
|
|
1104
|
-
- Data Overview and Quality Assessment
|
|
1105
|
-
- Trend Analysis and Patterns
|
|
1106
|
-
- Performance Metrics and KPIs
|
|
1107
|
-
- Risk Assessment and Opportunities
|
|
1108
|
-
${include_recommendations === 'true' ? '- AI-Generated Recommendations' : ''}
|
|
1109
|
-
- Next Steps and Action Items
|
|
1110
|
-
|
|
1111
|
-
Please gather the necessary data and create a comprehensive ${report_type} tailored for ${stakeholder_level} level stakeholders.`
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1114
|
-
];
|
|
1115
|
-
break;
|
|
1116
|
-
|
|
1117
|
-
case 'data_insights':
|
|
1118
|
-
const { tables, insight_type = 'correlations', business_context = 'general', insight_depth = 'moderate' } = promptArgs;
|
|
1119
|
-
messages = [
|
|
1120
|
-
{
|
|
1121
|
-
role: 'user',
|
|
1122
|
-
content: {
|
|
1123
|
-
type: 'text',
|
|
1124
|
-
text: `🔍 ADVANCED DATA INSIGHTS DISCOVERY
|
|
1125
|
-
|
|
1126
|
-
**Target Tables**: ${tables}
|
|
1127
|
-
**Insight Type**: ${insight_type}
|
|
1128
|
-
**Business Context**: ${business_context}
|
|
1129
|
-
**Analysis Depth**: ${insight_depth}
|
|
1130
|
-
|
|
1131
|
-
**Discovery Framework**:
|
|
1132
|
-
1. Multi-table schema analysis and relationship mapping
|
|
1133
|
-
2. Cross-table data correlation analysis
|
|
1134
|
-
3. Pattern recognition using ${business_context} domain knowledge
|
|
1135
|
-
4. Statistical significance testing
|
|
1136
|
-
5. Business impact quantification
|
|
1137
|
-
|
|
1138
|
-
**Insight Categories**:
|
|
1139
|
-
- ${insight_type} analysis with statistical validation
|
|
1140
|
-
- Hidden patterns and unexpected relationships
|
|
1141
|
-
- Segmentation opportunities
|
|
1142
|
-
- Predictive indicators
|
|
1143
|
-
- Data quality insights
|
|
1144
|
-
- Business optimization opportunities
|
|
1145
|
-
|
|
1146
|
-
**${business_context.toUpperCase()} CONTEXT ANALYSIS**:
|
|
1147
|
-
${business_context === 'sales' ? '- Revenue drivers and conversion patterns\n- Customer lifetime value indicators\n- Sales cycle optimization opportunities' : ''}
|
|
1148
|
-
${business_context === 'marketing' ? '- Campaign effectiveness and attribution\n- Customer segmentation insights\n- Channel performance analysis' : ''}
|
|
1149
|
-
${business_context === 'operations' ? '- Process efficiency metrics\n- Resource utilization patterns\n- Bottleneck identification' : ''}
|
|
1150
|
-
|
|
1151
|
-
Please conduct ${insight_depth} analysis across the specified tables and provide actionable business insights.`
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
];
|
|
1155
|
-
break;
|
|
1156
|
-
|
|
1157
|
-
case 'optimize_workflow':
|
|
1158
|
-
const { base_overview, optimization_focus = 'automation', current_pain_points, team_size } = promptArgs;
|
|
1159
|
-
messages = [
|
|
1160
|
-
{
|
|
1161
|
-
role: 'user',
|
|
1162
|
-
content: {
|
|
1163
|
-
type: 'text',
|
|
1164
|
-
text: `⚡ AI-POWERED WORKFLOW OPTIMIZATION
|
|
1165
|
-
|
|
1166
|
-
**Optimization Focus**: ${optimization_focus}
|
|
1167
|
-
**Team Size**: ${team_size || 'Not specified'}
|
|
1168
|
-
${base_overview ? `**Base Overview**: ${base_overview}` : ''}
|
|
1169
|
-
${current_pain_points ? `**Current Pain Points**: ${current_pain_points}` : ''}
|
|
1170
|
-
|
|
1171
|
-
**Optimization Analysis**:
|
|
1172
|
-
1. Workflow pattern analysis and bottleneck identification
|
|
1173
|
-
2. Automation opportunity assessment
|
|
1174
|
-
3. User experience and efficiency evaluation
|
|
1175
|
-
4. Integration and scaling considerations
|
|
1176
|
-
5. ROI analysis for proposed improvements
|
|
1177
|
-
|
|
1178
|
-
**${optimization_focus.toUpperCase()} OPTIMIZATION**:
|
|
1179
|
-
${optimization_focus === 'automation' ? '- Identify repetitive manual tasks\n- Suggest automation workflows\n- Estimate time savings and ROI' : ''}
|
|
1180
|
-
${optimization_focus === 'data_quality' ? '- Data validation and cleansing rules\n- Consistency and accuracy improvements\n- Quality monitoring systems' : ''}
|
|
1181
|
-
${optimization_focus === 'collaboration' ? '- Team workflow improvements\n- Permission and access optimization\n- Communication enhancement strategies' : ''}
|
|
1182
|
-
|
|
1183
|
-
**Deliverables**:
|
|
1184
|
-
- Workflow efficiency assessment
|
|
1185
|
-
- Prioritized improvement recommendations
|
|
1186
|
-
- Implementation roadmap with timelines
|
|
1187
|
-
- Cost-benefit analysis
|
|
1188
|
-
- Change management considerations
|
|
1189
|
-
|
|
1190
|
-
Please analyze the current setup and provide comprehensive ${optimization_focus} optimization recommendations.`
|
|
1191
|
-
}
|
|
1192
|
-
}
|
|
1193
|
-
];
|
|
1194
|
-
break;
|
|
1195
|
-
|
|
1196
|
-
case 'smart_schema_design':
|
|
1197
|
-
const { use_case, data_volume = 'medium', integration_needs, compliance_requirements = 'none' } = promptArgs;
|
|
1198
|
-
messages = [
|
|
1199
|
-
{
|
|
1200
|
-
role: 'user',
|
|
1201
|
-
content: {
|
|
1202
|
-
type: 'text',
|
|
1203
|
-
text: `🏗️ AI-ASSISTED SCHEMA OPTIMIZATION
|
|
1204
|
-
|
|
1205
|
-
**Use Case**: ${use_case}
|
|
1206
|
-
**Data Volume**: ${data_volume}
|
|
1207
|
-
**Compliance**: ${compliance_requirements}
|
|
1208
|
-
${integration_needs ? `**Integrations**: ${integration_needs}` : ''}
|
|
1209
|
-
|
|
1210
|
-
**Schema Design Analysis**:
|
|
1211
|
-
1. Current schema evaluation for ${use_case} best practices
|
|
1212
|
-
2. Field type and relationship optimization
|
|
1213
|
-
3. Performance and scalability assessment
|
|
1214
|
-
4. Compliance requirement implementation
|
|
1215
|
-
5. Integration compatibility review
|
|
1216
|
-
|
|
1217
|
-
**${use_case.toUpperCase()} OPTIMIZATION**:
|
|
1218
|
-
${use_case === 'crm' ? '- Customer lifecycle tracking\n- Sales pipeline optimization\n- Contact relationship mapping' : ''}
|
|
1219
|
-
${use_case === 'project_management' ? '- Task dependency modeling\n- Resource allocation tracking\n- Timeline and milestone management' : ''}
|
|
1220
|
-
${use_case === 'inventory' ? '- Stock level monitoring\n- Supplier relationship tracking\n- Cost and pricing optimization' : ''}
|
|
1221
|
-
|
|
1222
|
-
**Recommendations**:
|
|
1223
|
-
- Optimal field types and relationships
|
|
1224
|
-
- Indexing and performance suggestions
|
|
1225
|
-
- Data validation and integrity rules
|
|
1226
|
-
- Automation and workflow triggers
|
|
1227
|
-
- Scaling and maintenance considerations
|
|
1228
|
-
|
|
1229
|
-
Please analyze the current schema and provide ${use_case}-optimized recommendations.`
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
];
|
|
1233
|
-
break;
|
|
1234
|
-
|
|
1235
|
-
case 'data_quality_audit':
|
|
1236
|
-
const { tables: auditTables, quality_dimensions = 'completeness,accuracy,consistency', severity_threshold = 'medium', auto_fix_suggestions = 'true' } = promptArgs;
|
|
1237
|
-
messages = [
|
|
1238
|
-
{
|
|
1239
|
-
role: 'user',
|
|
1240
|
-
content: {
|
|
1241
|
-
type: 'text',
|
|
1242
|
-
text: `🔍 COMPREHENSIVE DATA QUALITY AUDIT
|
|
1243
|
-
|
|
1244
|
-
**Tables to Audit**: ${auditTables}
|
|
1245
|
-
**Quality Dimensions**: ${quality_dimensions}
|
|
1246
|
-
**Severity Threshold**: ${severity_threshold}
|
|
1247
|
-
**Auto-Fix Suggestions**: ${auto_fix_suggestions}
|
|
1248
|
-
|
|
1249
|
-
**Audit Framework**:
|
|
1250
|
-
1. Data completeness analysis (missing values, empty fields)
|
|
1251
|
-
2. Accuracy assessment (format validation, range checks)
|
|
1252
|
-
3. Consistency evaluation (cross-field validation, duplicates)
|
|
1253
|
-
4. Validity verification (data type compliance, constraints)
|
|
1254
|
-
5. Uniqueness analysis (duplicate detection, key integrity)
|
|
1255
|
-
6. Timeliness review (data freshness, update patterns)
|
|
1256
|
-
|
|
1257
|
-
**Quality Assessment Process**:
|
|
1258
|
-
- Statistical analysis of data distribution
|
|
1259
|
-
- Pattern recognition for anomalies
|
|
1260
|
-
- Cross-table consistency validation
|
|
1261
|
-
- Historical trend analysis
|
|
1262
|
-
- Business rule compliance checking
|
|
1263
|
-
|
|
1264
|
-
**Deliverables**:
|
|
1265
|
-
- Quality score by dimension and table
|
|
1266
|
-
- Detailed issue identification and classification
|
|
1267
|
-
- Impact assessment and prioritization
|
|
1268
|
-
${auto_fix_suggestions === 'true' ? '- Automated fix suggestions and scripts' : ''}
|
|
1269
|
-
- Data governance recommendations
|
|
1270
|
-
- Monitoring and maintenance strategies
|
|
1271
|
-
|
|
1272
|
-
Please conduct a thorough data quality audit focusing on ${quality_dimensions} dimensions.`
|
|
1273
|
-
}
|
|
1274
|
-
}
|
|
1275
|
-
];
|
|
1276
|
-
break;
|
|
1277
|
-
|
|
1278
|
-
case 'predictive_analytics':
|
|
1279
|
-
const { table: predTable, target_field, prediction_horizon = 'next_month', model_type = 'trend_analysis', feature_fields } = promptArgs;
|
|
1280
|
-
messages = [
|
|
1281
|
-
{
|
|
1282
|
-
role: 'user',
|
|
1283
|
-
content: {
|
|
1284
|
-
type: 'text',
|
|
1285
|
-
text: `🔮 ADVANCED PREDICTIVE ANALYTICS
|
|
1286
|
-
|
|
1287
|
-
**Source Table**: ${predTable}
|
|
1288
|
-
**Target Field**: ${target_field}
|
|
1289
|
-
**Prediction Horizon**: ${prediction_horizon}
|
|
1290
|
-
**Model Type**: ${model_type}
|
|
1291
|
-
${feature_fields ? `**Feature Fields**: ${feature_fields}` : ''}
|
|
1292
|
-
|
|
1293
|
-
**Predictive Modeling Process**:
|
|
1294
|
-
1. Historical data analysis and trend identification
|
|
1295
|
-
2. Feature engineering and variable selection
|
|
1296
|
-
3. Model development using ${model_type} approach
|
|
1297
|
-
4. Validation and accuracy assessment
|
|
1298
|
-
5. Forecast generation for ${prediction_horizon}
|
|
1299
|
-
6. Confidence intervals and uncertainty quantification
|
|
1300
|
-
|
|
1301
|
-
**${model_type.toUpperCase()} ANALYSIS**:
|
|
1302
|
-
${model_type === 'time_series' ? '- Seasonal pattern detection\n- Trend decomposition\n- Cyclical behavior analysis' : ''}
|
|
1303
|
-
${model_type === 'regression' ? '- Variable relationship modeling\n- Predictive factor identification\n- Statistical significance testing' : ''}
|
|
1304
|
-
${model_type === 'classification' ? '- Category prediction modeling\n- Feature importance analysis\n- Classification accuracy metrics' : ''}
|
|
1305
|
-
|
|
1306
|
-
**Outputs**:
|
|
1307
|
-
- Historical pattern analysis
|
|
1308
|
-
- Predictive model performance metrics
|
|
1309
|
-
- Forecast values with confidence intervals
|
|
1310
|
-
- Key influencing factors identification
|
|
1311
|
-
- Model limitations and assumptions
|
|
1312
|
-
- Actionable insights and recommendations
|
|
1313
|
-
|
|
1314
|
-
Please develop a ${model_type} model to predict ${target_field} over ${prediction_horizon}.`
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
];
|
|
1318
|
-
break;
|
|
1319
|
-
|
|
1320
|
-
case 'natural_language_query':
|
|
1321
|
-
const { question, context_tables, response_format = 'narrative', include_confidence = 'true' } = promptArgs;
|
|
1322
|
-
messages = [
|
|
1323
|
-
{
|
|
1324
|
-
role: 'user',
|
|
1325
|
-
content: {
|
|
1326
|
-
type: 'text',
|
|
1327
|
-
text: `🗣️ NATURAL LANGUAGE DATA QUERY
|
|
1328
|
-
|
|
1329
|
-
**Question**: "${question}"
|
|
1330
|
-
${context_tables ? `**Context Tables**: ${context_tables}` : ''}
|
|
1331
|
-
**Response Format**: ${response_format}
|
|
1332
|
-
**Include Confidence**: ${include_confidence}
|
|
1333
|
-
|
|
1334
|
-
**Query Processing Framework**:
|
|
1335
|
-
1. Question analysis and intent recognition
|
|
1336
|
-
2. Relevant table and field identification
|
|
1337
|
-
3. Data retrieval strategy formulation
|
|
1338
|
-
4. Analysis execution and result compilation
|
|
1339
|
-
5. Natural language response generation
|
|
1340
|
-
|
|
1341
|
-
**Analysis Approach**:
|
|
1342
|
-
- Semantic understanding of the question
|
|
1343
|
-
- Automatic table and field mapping
|
|
1344
|
-
- Intelligent data filtering and aggregation
|
|
1345
|
-
- Statistical analysis where appropriate
|
|
1346
|
-
- Context-aware interpretation
|
|
1347
|
-
|
|
1348
|
-
**Response Requirements**:
|
|
1349
|
-
${response_format === 'narrative' ? '- Conversational, easy-to-understand explanation\n- Supporting data and evidence\n- Contextual insights and implications' : ''}
|
|
1350
|
-
${response_format === 'data_summary' ? '- Structured data summary\n- Key metrics and statistics\n- Trend identification' : ''}
|
|
1351
|
-
${response_format === 'visualization_suggestion' ? '- Chart and graph recommendations\n- Data visualization best practices\n- Tool-specific guidance' : ''}
|
|
1352
|
-
${include_confidence === 'true' ? '\n- Confidence scores for answers\n- Data quality indicators\n- Uncertainty acknowledgment' : ''}
|
|
1353
|
-
|
|
1354
|
-
Please analyze the available data and provide a comprehensive answer to: "${question}"`
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
];
|
|
1358
|
-
break;
|
|
1359
|
-
|
|
1360
|
-
case 'smart_data_transformation':
|
|
1361
|
-
const { source_table, transformation_goal, target_format, quality_rules, preserve_history = 'true' } = promptArgs;
|
|
1362
|
-
messages = [
|
|
1363
|
-
{
|
|
1364
|
-
role: 'user',
|
|
1365
|
-
content: {
|
|
1366
|
-
type: 'text',
|
|
1367
|
-
text: `🔄 INTELLIGENT DATA TRANSFORMATION
|
|
1368
|
-
|
|
1369
|
-
**Source Table**: ${source_table}
|
|
1370
|
-
**Transformation Goal**: ${transformation_goal}
|
|
1371
|
-
${target_format ? `**Target Format**: ${target_format}` : ''}
|
|
1372
|
-
${quality_rules ? `**Quality Rules**: ${quality_rules}` : ''}
|
|
1373
|
-
**Preserve History**: ${preserve_history}
|
|
1374
|
-
|
|
1375
|
-
**Transformation Framework**:
|
|
1376
|
-
1. Source data analysis and quality assessment
|
|
1377
|
-
2. Transformation strategy development
|
|
1378
|
-
3. Data mapping and conversion rules
|
|
1379
|
-
4. Quality validation and error handling
|
|
1380
|
-
5. Output optimization and validation
|
|
1381
|
-
|
|
1382
|
-
**${transformation_goal.toUpperCase()} PROCESS**:
|
|
1383
|
-
${transformation_goal === 'normalize' ? '- Database normalization principles\n- Redundancy elimination\n- Relationship optimization' : ''}
|
|
1384
|
-
${transformation_goal === 'standardize' ? '- Format standardization\n- Value normalization\n- Consistency enforcement' : ''}
|
|
1385
|
-
${transformation_goal === 'enrich' ? '- Data augmentation strategies\n- External data integration\n- Value-added field creation' : ''}
|
|
1386
|
-
${transformation_goal === 'cleanse' ? '- Data validation and correction\n- Duplicate removal\n- Missing value handling' : ''}
|
|
1387
|
-
|
|
1388
|
-
**Deliverables**:
|
|
1389
|
-
- Transformation execution plan
|
|
1390
|
-
- Data mapping specifications
|
|
1391
|
-
- Quality validation results
|
|
1392
|
-
- Performance optimization recommendations
|
|
1393
|
-
${preserve_history === 'true' ? '- Change audit trail and versioning' : ''}
|
|
1394
|
-
- Post-transformation validation
|
|
1395
|
-
|
|
1396
|
-
Please analyze the source data and execute ${transformation_goal} transformation with intelligent optimization.`
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
];
|
|
1400
|
-
break;
|
|
1401
|
-
|
|
1402
|
-
case 'automation_recommendations':
|
|
1403
|
-
const { workflow_description, automation_scope = 'single_table', frequency_patterns, complexity_tolerance = 'moderate', integration_capabilities } = promptArgs;
|
|
1404
|
-
messages = [
|
|
1405
|
-
{
|
|
1406
|
-
role: 'user',
|
|
1407
|
-
content: {
|
|
1408
|
-
type: 'text',
|
|
1409
|
-
text: `🤖 INTELLIGENT AUTOMATION RECOMMENDATIONS
|
|
1410
|
-
|
|
1411
|
-
**Automation Scope**: ${automation_scope}
|
|
1412
|
-
**Complexity Tolerance**: ${complexity_tolerance}
|
|
1413
|
-
${workflow_description ? `**Current Workflow**: ${workflow_description}` : ''}
|
|
1414
|
-
${frequency_patterns ? `**Frequency Patterns**: ${frequency_patterns}` : ''}
|
|
1415
|
-
${integration_capabilities ? `**Integration Tools**: ${integration_capabilities}` : ''}
|
|
1416
|
-
|
|
1417
|
-
**Automation Analysis Framework**:
|
|
1418
|
-
1. Workflow pattern analysis and task identification
|
|
1419
|
-
2. Automation opportunity assessment and prioritization
|
|
1420
|
-
3. Technical feasibility and complexity evaluation
|
|
1421
|
-
4. ROI calculation and benefit quantification
|
|
1422
|
-
5. Implementation roadmap development
|
|
1423
|
-
|
|
1424
|
-
**${automation_scope.toUpperCase()} AUTOMATION**:
|
|
1425
|
-
${automation_scope === 'single_table' ? '- Field auto-population rules\n- Data validation automation\n- Notification triggers' : ''}
|
|
1426
|
-
${automation_scope === 'multi_table' ? '- Cross-table data synchronization\n- Workflow orchestration\n- Complex business logic automation' : ''}
|
|
1427
|
-
${automation_scope === 'external_integration' ? '- API integration strategies\n- Data pipeline automation\n- Third-party tool connectivity' : ''}
|
|
1428
|
-
|
|
1429
|
-
**Recommendations**:
|
|
1430
|
-
- High-impact automation opportunities
|
|
1431
|
-
- Implementation complexity assessment
|
|
1432
|
-
- Cost-benefit analysis with ROI projections
|
|
1433
|
-
- Technical requirements and dependencies
|
|
1434
|
-
- Risk assessment and mitigation strategies
|
|
1435
|
-
- Success metrics and monitoring approach
|
|
1436
|
-
|
|
1437
|
-
Please analyze the workflow patterns and provide ${complexity_tolerance}-level automation recommendations for ${automation_scope} scope.`
|
|
1438
|
-
}
|
|
1439
|
-
}
|
|
1440
|
-
];
|
|
1441
|
-
break;
|
|
1442
|
-
|
|
1443
|
-
default:
|
|
1444
|
-
throw new Error(`Unsupported prompt: ${promptName}`);
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1447
|
-
return {
|
|
1448
|
-
jsonrpc: '2.0',
|
|
1449
|
-
id: request.id,
|
|
1450
|
-
result: {
|
|
1451
|
-
description: prompt.description,
|
|
1452
|
-
messages: messages
|
|
1453
|
-
}
|
|
1454
|
-
};
|
|
1455
|
-
|
|
1456
|
-
} catch (error) {
|
|
1457
|
-
log(LOG_LEVELS.ERROR, `Prompt ${promptName} failed`, { error: error.message });
|
|
1458
|
-
|
|
1459
|
-
return {
|
|
1460
|
-
jsonrpc: '2.0',
|
|
1461
|
-
id: request.id,
|
|
1462
|
-
error: {
|
|
1463
|
-
code: -32000,
|
|
1464
|
-
message: `Error getting prompt ${promptName}: ${error.message}`
|
|
1465
|
-
}
|
|
1466
|
-
};
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
|
|
1470
|
-
// Sampling handler
|
|
1471
|
-
async function handleSampling(request) {
|
|
1472
|
-
const { messages, modelPreferences } = request.params;
|
|
1473
|
-
|
|
1474
|
-
try {
|
|
1475
|
-
// Note: In a real implementation, this would integrate with an LLM API
|
|
1476
|
-
// For now, we'll return a structured response indicating sampling capability
|
|
1477
|
-
|
|
1478
|
-
log(LOG_LEVELS.INFO, 'Sampling request received', {
|
|
1479
|
-
messageCount: messages?.length,
|
|
1480
|
-
model: modelPreferences?.model
|
|
1481
|
-
});
|
|
1482
|
-
|
|
1483
|
-
return {
|
|
1484
|
-
jsonrpc: '2.0',
|
|
1485
|
-
id: request.id,
|
|
1486
|
-
result: {
|
|
1487
|
-
model: modelPreferences?.model || 'claude-3-sonnet',
|
|
1488
|
-
role: 'assistant',
|
|
1489
|
-
content: {
|
|
1490
|
-
type: 'text',
|
|
1491
|
-
text: 'Sampling capability is available. This MCP server can request AI assistance for complex data analysis and insights generation. In a full implementation, this would connect to your preferred LLM for intelligent Airtable operations.'
|
|
1492
|
-
},
|
|
1493
|
-
stopReason: 'end_turn'
|
|
1494
|
-
}
|
|
1495
|
-
};
|
|
1496
|
-
|
|
1497
|
-
} catch (error) {
|
|
1498
|
-
log(LOG_LEVELS.ERROR, 'Sampling failed', { error: error.message });
|
|
1499
|
-
|
|
1500
|
-
return {
|
|
1501
|
-
jsonrpc: '2.0',
|
|
1502
|
-
id: request.id,
|
|
1503
|
-
error: {
|
|
1504
|
-
code: -32000,
|
|
1505
|
-
message: `Sampling error: ${error.message}`
|
|
1506
|
-
}
|
|
1507
|
-
};
|
|
1508
|
-
}
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
|
-
// Server startup
|
|
1512
|
-
const PORT = CONFIG.PORT;
|
|
1513
|
-
const HOST = CONFIG.HOST;
|
|
1514
|
-
|
|
1515
|
-
server.listen(PORT, HOST, () => {
|
|
1516
|
-
log(LOG_LEVELS.INFO, `Airtable MCP Server started`, {
|
|
1517
|
-
host: HOST,
|
|
1518
|
-
port: PORT,
|
|
1519
|
-
version: '2.1.0'
|
|
1520
|
-
});
|
|
1521
|
-
|
|
1522
|
-
console.log(`
|
|
1523
|
-
╔═══════════════════════════════════════════════════════════════╗
|
|
1524
|
-
║ Airtable MCP Server v2.1 ║
|
|
1525
|
-
║ Model Context Protocol Implementation ║
|
|
1526
|
-
╠═══════════════════════════════════════════════════════════════╣
|
|
1527
|
-
║ 🌐 MCP Endpoint: http://${HOST}:${PORT}/mcp ║
|
|
1528
|
-
║ 📊 Health Check: http://${HOST}:${PORT}/health ║
|
|
1529
|
-
║ 🔒 Security: Rate limiting, input validation ║
|
|
1530
|
-
║ 📋 Tools: ${TOOLS_SCHEMA.length} available operations ║
|
|
1531
|
-
╠═══════════════════════════════════════════════════════════════╣
|
|
1532
|
-
║ 🔗 Connected to Airtable Base: ${baseId.slice(0, 8)}... ║
|
|
1533
|
-
║ 🚀 Ready for MCP client connections ║
|
|
1534
|
-
╚═══════════════════════════════════════════════════════════════╝
|
|
1535
|
-
`);
|
|
1536
|
-
});
|
|
1537
|
-
|
|
1538
|
-
// Graceful shutdown
|
|
1539
|
-
function gracefulShutdown(signal) {
|
|
1540
|
-
log(LOG_LEVELS.INFO, 'Graceful shutdown initiated', { signal });
|
|
1541
|
-
|
|
1542
|
-
server.close(() => {
|
|
1543
|
-
log(LOG_LEVELS.INFO, 'Server stopped');
|
|
1544
|
-
process.exit(0);
|
|
1545
|
-
});
|
|
1546
|
-
|
|
1547
|
-
setTimeout(() => {
|
|
1548
|
-
log(LOG_LEVELS.ERROR, 'Force shutdown - server did not close in time');
|
|
1549
|
-
process.exit(1);
|
|
1550
|
-
}, 10000);
|
|
1551
|
-
}
|
|
1552
|
-
|
|
1553
|
-
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
|
|
1554
|
-
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|
|
1555
|
-
|
|
1556
|
-
process.on('uncaughtException', (error) => {
|
|
1557
|
-
log(LOG_LEVELS.ERROR, 'Uncaught exception', { error: error.message });
|
|
1558
|
-
gracefulShutdown('uncaughtException');
|
|
1559
|
-
});
|
|
1560
|
-
|
|
1561
|
-
process.on('unhandledRejection', (reason) => {
|
|
1562
|
-
log(LOG_LEVELS.ERROR, 'Unhandled promise rejection', { reason: reason?.toString() });
|
|
1563
|
-
gracefulShutdown('unhandledRejection');
|
|
1564
|
-
});
|