@rashidazarang/airtable-mcp 2.1.0 → 2.2.0
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 +1 -1
- package/airtable_simple_production.js +387 -5
- package/examples/claude_simple_config.json +0 -9
- package/package.json +10 -1
- package/.github/ISSUE_TEMPLATE/bug-report.yml +0 -173
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
- package/.github/ISSUE_TEMPLATE/custom.md +0 -10
- package/.github/ISSUE_TEMPLATE/feature-request.yml +0 -209
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/.github/ISSUE_TEMPLATE/security-report.yml +0 -216
- package/.github/pull_request_template.md +0 -245
- package/.github/workflows/ci-cd.yml +0 -408
- package/.github/workflows/security-audit.yml +0 -316
- package/API_DOCUMENTATION.md +0 -897
- package/CAPABILITY_REPORT.md +0 -118
- package/CLAUDE_INTEGRATION.md +0 -96
- package/CODE_OF_CONDUCT.md +0 -181
- package/CONTRIBUTING.md +0 -81
- package/DEVELOPMENT.md +0 -190
- package/Dockerfile +0 -39
- package/Dockerfile.node +0 -20
- package/Dockerfile.production +0 -127
- package/IMPROVEMENT_PROPOSAL.md +0 -371
- package/INSTALLATION.md +0 -183
- package/ISSUE_RESPONSES.md +0 -171
- package/MCP_REVIEW_SUMMARY.md +0 -142
- package/QUICK_START.md +0 -60
- package/RELEASE_NOTES_v1.2.0.md +0 -50
- package/RELEASE_NOTES_v1.2.1.md +0 -40
- package/RELEASE_NOTES_v1.2.2.md +0 -48
- package/RELEASE_NOTES_v1.2.3.md +0 -105
- package/RELEASE_NOTES_v1.2.4.md +0 -60
- package/RELEASE_NOTES_v1.4.0.md +0 -104
- package/RELEASE_NOTES_v1.5.0.md +0 -185
- package/RELEASE_NOTES_v1.6.0.md +0 -248
- package/SECURITY_NOTICE.md +0 -40
- package/airtable-clipper/CHANGELOG.md +0 -198
- package/airtable-clipper/CHROME_STORE_SUBMISSION.md +0 -343
- package/airtable-clipper/LAUNCH_STRATEGY.md +0 -495
- package/airtable-clipper/LICENSE +0 -21
- package/airtable-clipper/OAUTH_SETUP.md +0 -51
- package/airtable-clipper/PRIVACY_POLICY.md +0 -187
- package/airtable-clipper/README.md +0 -575
- package/airtable-clipper/SUBMIT_TO_CHROME_STORE.md +0 -273
- package/airtable-clipper/build.sh +0 -85
- package/airtable-clipper/docs/QUICK_START.md +0 -99
- package/airtable-clipper/docs/SETUP.md +0 -291
- package/airtable-clipper/extension/background.js +0 -337
- package/airtable-clipper/extension/base-setup.html +0 -324
- package/airtable-clipper/extension/base-setup.js +0 -471
- package/airtable-clipper/extension/content.js +0 -771
- package/airtable-clipper/extension/icons/README.md +0 -69
- package/airtable-clipper/extension/icons/icon-16.png +0 -3
- package/airtable-clipper/extension/manifest.json +0 -73
- package/airtable-clipper/extension/popup.html +0 -144
- package/airtable-clipper/extension/popup.js +0 -475
- package/airtable-clipper/extension/styles/content.css +0 -229
- package/airtable-clipper/extension/styles/popup.css +0 -477
- package/airtable-clipper/privacy-policy.md +0 -63
- package/airtable-clipper/releases/v1.0.0/background.js +0 -337
- package/airtable-clipper/releases/v1.0.0/base-setup.html +0 -324
- package/airtable-clipper/releases/v1.0.0/base-setup.js +0 -471
- package/airtable-clipper/releases/v1.0.0/content.js +0 -771
- package/airtable-clipper/releases/v1.0.0/icons/README.md +0 -69
- package/airtable-clipper/releases/v1.0.0/icons/icon-128.png +0 -2
- package/airtable-clipper/releases/v1.0.0/icons/icon-16.png +0 -3
- package/airtable-clipper/releases/v1.0.0/icons/icon-32.png +0 -2
- package/airtable-clipper/releases/v1.0.0/icons/icon-48.png +0 -2
- package/airtable-clipper/releases/v1.0.0/manifest.json +0 -73
- package/airtable-clipper/releases/v1.0.0/popup.html +0 -144
- package/airtable-clipper/releases/v1.0.0/popup.js +0 -475
- package/airtable-clipper/releases/v1.0.0/sidepanel.html +0 -25
- package/airtable-clipper/releases/v1.0.0/styles/content.css +0 -229
- package/airtable-clipper/releases/v1.0.0/styles/popup.css +0 -477
- package/airtable-clipper/releases/v1.0.1/background.js +0 -337
- package/airtable-clipper/releases/v1.0.1/base-setup.html +0 -324
- package/airtable-clipper/releases/v1.0.1/base-setup.js +0 -471
- package/airtable-clipper/releases/v1.0.1/content.js +0 -771
- package/airtable-clipper/releases/v1.0.1/icons/README.md +0 -69
- package/airtable-clipper/releases/v1.0.1/icons/icon-128.png +0 -2
- package/airtable-clipper/releases/v1.0.1/icons/icon-16.png +0 -3
- package/airtable-clipper/releases/v1.0.1/icons/icon-32.png +0 -2
- package/airtable-clipper/releases/v1.0.1/icons/icon-48.png +0 -2
- package/airtable-clipper/releases/v1.0.1/manifest.json +0 -70
- package/airtable-clipper/releases/v1.0.1/popup.html +0 -157
- package/airtable-clipper/releases/v1.0.1/popup.js +0 -562
- package/airtable-clipper/releases/v1.0.1/sidepanel.html +0 -25
- package/airtable-clipper/releases/v1.0.1/styles/content.css +0 -229
- package/airtable-clipper/releases/v1.0.1/styles/popup.css +0 -647
- package/airtable-clipper/releases/v1.0.2/background.js +0 -337
- package/airtable-clipper/releases/v1.0.2/base-setup.html +0 -324
- package/airtable-clipper/releases/v1.0.2/base-setup.js +0 -471
- package/airtable-clipper/releases/v1.0.2/content.js +0 -771
- package/airtable-clipper/releases/v1.0.2/icons/README.md +0 -69
- package/airtable-clipper/releases/v1.0.2/icons/icon-128.png +0 -2
- package/airtable-clipper/releases/v1.0.2/icons/icon-16.png +0 -3
- package/airtable-clipper/releases/v1.0.2/icons/icon-32.png +0 -2
- package/airtable-clipper/releases/v1.0.2/icons/icon-48.png +0 -2
- package/airtable-clipper/releases/v1.0.2/manifest.json +0 -62
- package/airtable-clipper/releases/v1.0.2/popup.html +0 -157
- package/airtable-clipper/releases/v1.0.2/popup.js +0 -567
- package/airtable-clipper/releases/v1.0.2/sidepanel.html +0 -25
- package/airtable-clipper/releases/v1.0.2/styles/content.css +0 -229
- package/airtable-clipper/releases/v1.0.2/styles/popup.css +0 -647
- package/airtable-clipper/terms-of-service.md +0 -124
- package/airtable-clipper/test-credentials.md +0 -61
- package/airtable-clipper/test-extension/background.js +0 -337
- package/airtable-clipper/test-extension/base-setup.html +0 -324
- package/airtable-clipper/test-extension/base-setup.js +0 -471
- package/airtable-clipper/test-extension/content.js +0 -873
- package/airtable-clipper/test-extension/icons/README.md +0 -69
- package/airtable-clipper/test-extension/icons/icon-128.png +0 -2
- package/airtable-clipper/test-extension/icons/icon-16.png +0 -3
- package/airtable-clipper/test-extension/icons/icon-32.png +0 -2
- package/airtable-clipper/test-extension/icons/icon-48.png +0 -2
- package/airtable-clipper/test-extension/manifest.json +0 -72
- package/airtable-clipper/test-extension/popup.html +0 -274
- package/airtable-clipper/test-extension/popup.js +0 -729
- package/airtable-clipper/test-extension/sidepanel.html +0 -25
- package/airtable-clipper/test-extension/styles/content.css +0 -229
- package/airtable-clipper/test-extension/styles/popup.css +0 -794
- package/airtable_mcp/__init__.py +0 -5
- package/airtable_mcp/src/server.py +0 -329
- package/airtable_mcp_v2.js +0 -1505
- package/airtable_mcp_v2_oauth.js +0 -1048
- package/airtable_mcp_v3_advanced.js +0 -1161
- package/cleanup.sh +0 -71
- package/docker-compose.production.yml +0 -366
- package/helm/airtable-mcp/Chart.yaml +0 -122
- package/helm/airtable-mcp/values.yaml +0 -538
- package/index.js +0 -179
- package/inspector.py +0 -148
- package/inspector_server.py +0 -337
- package/k8s/deployment.yaml +0 -402
- package/k8s/namespace.yaml +0 -108
- package/k8s/service.yaml +0 -194
- package/monitoring/alerts.yml +0 -289
- package/monitoring/prometheus.yml +0 -224
- package/publish-steps.txt +0 -27
- package/quick_test.sh +0 -30
- package/requirements.txt +0 -10
- package/setup.py +0 -29
- package/simple_airtable_server.py +0 -151
- package/smithery.yaml +0 -45
- package/test_all_features.sh +0 -146
- package/test_all_operations.sh +0 -120
- package/test_client.py +0 -70
- package/test_enhanced_features.js +0 -389
- package/test_mcp_comprehensive.js +0 -163
- package/test_mock_server.js +0 -180
- package/test_v1.4.0_final.sh +0 -131
- package/test_v1.5.0_comprehensive.sh +0 -96
- package/test_v1.5.0_final.sh +0 -224
- package/test_v1.6.0_comprehensive.sh +0 -187
- package/test_webhooks.sh +0 -105
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Airtable MCP Server
|
|
2
2
|
|
|
3
|
+
[](https://archestra.ai/mcp-catalog/rashidazarang__airtable-mcp)
|
|
3
4
|
[](https://smithery.ai/server/@rashidazarang/airtable-mcp)
|
|
4
|
-
[](https://archestra.ai/mcp-catalog/rashidazarang__airtable-mcp)
|
|
5
5
|

|
|
6
6
|
[](https://github.com/rashidazarang/airtable-mcp)
|
|
7
7
|
|
|
@@ -56,7 +56,7 @@ const CONFIG = {
|
|
|
56
56
|
|
|
57
57
|
// Logging
|
|
58
58
|
const LOG_LEVELS = { ERROR: 0, WARN: 1, INFO: 2, DEBUG: 3, TRACE: 4 };
|
|
59
|
-
|
|
59
|
+
let currentLogLevel = LOG_LEVELS[CONFIG.LOG_LEVEL] || LOG_LEVELS.INFO;
|
|
60
60
|
|
|
61
61
|
function log(level, message, metadata = {}) {
|
|
62
62
|
if (level <= currentLogLevel) {
|
|
@@ -236,6 +236,98 @@ const TOOLS_SCHEMA = [
|
|
|
236
236
|
}
|
|
237
237
|
];
|
|
238
238
|
|
|
239
|
+
// Prompts schema - AI-powered templates for common Airtable operations
|
|
240
|
+
const PROMPTS_SCHEMA = [
|
|
241
|
+
{
|
|
242
|
+
name: 'analyze_data',
|
|
243
|
+
description: 'Analyze data patterns and provide insights from Airtable records',
|
|
244
|
+
arguments: [
|
|
245
|
+
{
|
|
246
|
+
name: 'table',
|
|
247
|
+
description: 'Table name or ID to analyze',
|
|
248
|
+
required: true
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
name: 'analysis_type',
|
|
252
|
+
description: 'Type of analysis (trends, summary, patterns, insights)',
|
|
253
|
+
required: false
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
name: 'field_focus',
|
|
257
|
+
description: 'Specific fields to focus the analysis on',
|
|
258
|
+
required: false
|
|
259
|
+
}
|
|
260
|
+
]
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: 'create_report',
|
|
264
|
+
description: 'Generate a comprehensive report based on Airtable data',
|
|
265
|
+
arguments: [
|
|
266
|
+
{
|
|
267
|
+
name: 'table',
|
|
268
|
+
description: 'Table name or ID for the report',
|
|
269
|
+
required: true
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
name: 'report_type',
|
|
273
|
+
description: 'Type of report (summary, detailed, dashboard, metrics)',
|
|
274
|
+
required: false
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
name: 'time_period',
|
|
278
|
+
description: 'Time period for the report (if applicable)',
|
|
279
|
+
required: false
|
|
280
|
+
}
|
|
281
|
+
]
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
name: 'data_insights',
|
|
285
|
+
description: 'Discover hidden insights and correlations in your Airtable data',
|
|
286
|
+
arguments: [
|
|
287
|
+
{
|
|
288
|
+
name: 'tables',
|
|
289
|
+
description: 'Comma-separated list of table names to analyze',
|
|
290
|
+
required: true
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
name: 'insight_type',
|
|
294
|
+
description: 'Type of insights to find (correlations, outliers, trends, predictions)',
|
|
295
|
+
required: false
|
|
296
|
+
}
|
|
297
|
+
]
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: 'optimize_workflow',
|
|
301
|
+
description: 'Suggest workflow optimizations based on your Airtable usage patterns',
|
|
302
|
+
arguments: [
|
|
303
|
+
{
|
|
304
|
+
name: 'base_overview',
|
|
305
|
+
description: 'Overview of the base structure and usage',
|
|
306
|
+
required: false
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
name: 'optimization_focus',
|
|
310
|
+
description: 'Focus area (automation, fields, views, collaboration)',
|
|
311
|
+
required: false
|
|
312
|
+
}
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
];
|
|
316
|
+
|
|
317
|
+
// Roots configuration for filesystem access
|
|
318
|
+
const ROOTS_CONFIG = [
|
|
319
|
+
{
|
|
320
|
+
uri: 'file:///airtable-exports',
|
|
321
|
+
name: 'Airtable Exports'
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
uri: 'file:///airtable-attachments',
|
|
325
|
+
name: 'Airtable Attachments'
|
|
326
|
+
}
|
|
327
|
+
];
|
|
328
|
+
|
|
329
|
+
// Logging configuration (currentLogLevel is already declared above)
|
|
330
|
+
|
|
239
331
|
// HTTP server
|
|
240
332
|
const server = http.createServer(async (req, res) => {
|
|
241
333
|
// Security headers
|
|
@@ -261,13 +353,106 @@ const server = http.createServer(async (req, res) => {
|
|
|
261
353
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
262
354
|
res.end(JSON.stringify({
|
|
263
355
|
status: 'healthy',
|
|
264
|
-
version: '2.
|
|
356
|
+
version: '2.2.0',
|
|
265
357
|
timestamp: new Date().toISOString(),
|
|
266
358
|
uptime: process.uptime()
|
|
267
359
|
}));
|
|
268
360
|
return;
|
|
269
361
|
}
|
|
270
362
|
|
|
363
|
+
// OAuth2 authorization endpoint
|
|
364
|
+
if (pathname === '/oauth/authorize' && req.method === 'GET') {
|
|
365
|
+
const params = parsedUrl.query;
|
|
366
|
+
const clientId = params.client_id;
|
|
367
|
+
const redirectUri = params.redirect_uri;
|
|
368
|
+
const state = params.state;
|
|
369
|
+
const codeChallenge = params.code_challenge;
|
|
370
|
+
const codeChallengeMethod = params.code_challenge_method;
|
|
371
|
+
|
|
372
|
+
// Generate authorization code
|
|
373
|
+
const authCode = crypto.randomBytes(32).toString('hex');
|
|
374
|
+
|
|
375
|
+
// In a real implementation, store the auth code with expiration
|
|
376
|
+
// and associate it with the client and PKCE challenge
|
|
377
|
+
|
|
378
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
379
|
+
res.end(`
|
|
380
|
+
<!DOCTYPE html>
|
|
381
|
+
<html>
|
|
382
|
+
<head><title>OAuth2 Authorization</title></head>
|
|
383
|
+
<body>
|
|
384
|
+
<h2>Airtable MCP Server - OAuth2 Authorization</h2>
|
|
385
|
+
<p>Client ID: ${clientId}</p>
|
|
386
|
+
<p>Redirect URI: ${redirectUri}</p>
|
|
387
|
+
<div style="margin: 20px 0;">
|
|
388
|
+
<button onclick="authorize()" style="background: #18BFFF; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer;">
|
|
389
|
+
Authorize Application
|
|
390
|
+
</button>
|
|
391
|
+
<button onclick="deny()" style="background: #ff4444; color: white; padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; margin-left: 10px;">
|
|
392
|
+
Deny Access
|
|
393
|
+
</button>
|
|
394
|
+
</div>
|
|
395
|
+
<script>
|
|
396
|
+
function authorize() {
|
|
397
|
+
const url = '${redirectUri}?code=${authCode}&state=${state || ''}';
|
|
398
|
+
window.location.href = url;
|
|
399
|
+
}
|
|
400
|
+
function deny() {
|
|
401
|
+
const url = '${redirectUri}?error=access_denied&state=${state || ''}';
|
|
402
|
+
window.location.href = url;
|
|
403
|
+
}
|
|
404
|
+
</script>
|
|
405
|
+
</body>
|
|
406
|
+
</html>
|
|
407
|
+
`);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// OAuth2 token endpoint
|
|
412
|
+
if (pathname === '/oauth/token' && req.method === 'POST') {
|
|
413
|
+
let body = '';
|
|
414
|
+
req.on('data', chunk => body += chunk.toString());
|
|
415
|
+
|
|
416
|
+
req.on('end', () => {
|
|
417
|
+
try {
|
|
418
|
+
const params = querystring.parse(body);
|
|
419
|
+
const grantType = params.grant_type;
|
|
420
|
+
const code = params.code;
|
|
421
|
+
const codeVerifier = params.code_verifier;
|
|
422
|
+
const clientId = params.client_id;
|
|
423
|
+
|
|
424
|
+
// In a real implementation, verify the authorization code and PKCE
|
|
425
|
+
if (grantType === 'authorization_code' && code) {
|
|
426
|
+
// Generate access token
|
|
427
|
+
const accessToken = crypto.randomBytes(32).toString('hex');
|
|
428
|
+
const refreshToken = crypto.randomBytes(32).toString('hex');
|
|
429
|
+
|
|
430
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
431
|
+
res.end(JSON.stringify({
|
|
432
|
+
access_token: accessToken,
|
|
433
|
+
token_type: 'Bearer',
|
|
434
|
+
expires_in: 3600,
|
|
435
|
+
refresh_token: refreshToken,
|
|
436
|
+
scope: 'data.records:read data.records:write schema.bases:read'
|
|
437
|
+
}));
|
|
438
|
+
} else {
|
|
439
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
440
|
+
res.end(JSON.stringify({
|
|
441
|
+
error: 'invalid_request',
|
|
442
|
+
error_description: 'Invalid grant type or authorization code'
|
|
443
|
+
}));
|
|
444
|
+
}
|
|
445
|
+
} catch (error) {
|
|
446
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
447
|
+
res.end(JSON.stringify({
|
|
448
|
+
error: 'invalid_request',
|
|
449
|
+
error_description: 'Malformed request body'
|
|
450
|
+
}));
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
|
|
271
456
|
// MCP endpoint
|
|
272
457
|
if (pathname === '/mcp' && req.method === 'POST') {
|
|
273
458
|
// Rate limiting
|
|
@@ -321,9 +506,9 @@ const server = http.createServer(async (req, res) => {
|
|
|
321
506
|
logging: {}
|
|
322
507
|
},
|
|
323
508
|
serverInfo: {
|
|
324
|
-
name: 'Airtable MCP Server',
|
|
325
|
-
version: '2.
|
|
326
|
-
description: '
|
|
509
|
+
name: 'Airtable MCP Server Enhanced',
|
|
510
|
+
version: '2.2.0',
|
|
511
|
+
description: 'Complete MCP 2024-11-05 server with Prompts, Sampling, Roots, Logging, and OAuth2'
|
|
327
512
|
}
|
|
328
513
|
}
|
|
329
514
|
};
|
|
@@ -344,6 +529,47 @@ const server = http.createServer(async (req, res) => {
|
|
|
344
529
|
response = await handleToolCall(request);
|
|
345
530
|
break;
|
|
346
531
|
|
|
532
|
+
case 'prompts/list':
|
|
533
|
+
response = {
|
|
534
|
+
jsonrpc: '2.0',
|
|
535
|
+
id: request.id,
|
|
536
|
+
result: {
|
|
537
|
+
prompts: PROMPTS_SCHEMA
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
break;
|
|
541
|
+
|
|
542
|
+
case 'prompts/get':
|
|
543
|
+
response = await handlePromptGet(request);
|
|
544
|
+
break;
|
|
545
|
+
|
|
546
|
+
case 'roots/list':
|
|
547
|
+
response = {
|
|
548
|
+
jsonrpc: '2.0',
|
|
549
|
+
id: request.id,
|
|
550
|
+
result: {
|
|
551
|
+
roots: ROOTS_CONFIG
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
break;
|
|
555
|
+
|
|
556
|
+
case 'logging/setLevel':
|
|
557
|
+
const level = request.params?.level;
|
|
558
|
+
if (level && LOG_LEVELS[level.toUpperCase()] !== undefined) {
|
|
559
|
+
currentLogLevel = LOG_LEVELS[level.toUpperCase()];
|
|
560
|
+
log(LOG_LEVELS.INFO, 'Log level updated', { newLevel: level });
|
|
561
|
+
}
|
|
562
|
+
response = {
|
|
563
|
+
jsonrpc: '2.0',
|
|
564
|
+
id: request.id,
|
|
565
|
+
result: {}
|
|
566
|
+
};
|
|
567
|
+
break;
|
|
568
|
+
|
|
569
|
+
case 'sampling/createMessage':
|
|
570
|
+
response = await handleSampling(request);
|
|
571
|
+
break;
|
|
572
|
+
|
|
347
573
|
default:
|
|
348
574
|
log(LOG_LEVELS.WARN, 'Unknown method', { method: request.method });
|
|
349
575
|
throw new Error(`Method "${request.method}" not found`);
|
|
@@ -476,6 +702,162 @@ async function handleToolCall(request) {
|
|
|
476
702
|
}
|
|
477
703
|
}
|
|
478
704
|
|
|
705
|
+
// Prompt handlers
|
|
706
|
+
async function handlePromptGet(request) {
|
|
707
|
+
const promptName = request.params.name;
|
|
708
|
+
const promptArgs = request.params.arguments || {};
|
|
709
|
+
|
|
710
|
+
try {
|
|
711
|
+
const prompt = PROMPTS_SCHEMA.find(p => p.name === promptName);
|
|
712
|
+
if (!prompt) {
|
|
713
|
+
throw new Error(`Prompt "${promptName}" not found`);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
let messages = [];
|
|
717
|
+
|
|
718
|
+
switch (promptName) {
|
|
719
|
+
case 'analyze_data':
|
|
720
|
+
const { table, analysis_type = 'summary', field_focus } = promptArgs;
|
|
721
|
+
messages = [
|
|
722
|
+
{
|
|
723
|
+
role: 'user',
|
|
724
|
+
content: {
|
|
725
|
+
type: 'text',
|
|
726
|
+
text: `Please analyze the data in table "${table}".
|
|
727
|
+
Analysis type: ${analysis_type}
|
|
728
|
+
${field_focus ? `Focus on fields: ${field_focus}` : ''}
|
|
729
|
+
|
|
730
|
+
First, list the tables and their schemas, then retrieve sample records from "${table}"
|
|
731
|
+
and provide insights based on the ${analysis_type} analysis type.`
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
];
|
|
735
|
+
break;
|
|
736
|
+
|
|
737
|
+
case 'create_report':
|
|
738
|
+
const { table: reportTable, report_type = 'summary', time_period } = promptArgs;
|
|
739
|
+
messages = [
|
|
740
|
+
{
|
|
741
|
+
role: 'user',
|
|
742
|
+
content: {
|
|
743
|
+
type: 'text',
|
|
744
|
+
text: `Create a ${report_type} report for table "${reportTable}".
|
|
745
|
+
${time_period ? `Time period: ${time_period}` : ''}
|
|
746
|
+
|
|
747
|
+
Please gather the table schema and recent records, then generate a comprehensive
|
|
748
|
+
${report_type} report with key metrics, trends, and actionable insights.`
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
];
|
|
752
|
+
break;
|
|
753
|
+
|
|
754
|
+
case 'data_insights':
|
|
755
|
+
const { tables, insight_type = 'correlations' } = promptArgs;
|
|
756
|
+
messages = [
|
|
757
|
+
{
|
|
758
|
+
role: 'user',
|
|
759
|
+
content: {
|
|
760
|
+
type: 'text',
|
|
761
|
+
text: `Discover ${insight_type} insights across these tables: ${tables}
|
|
762
|
+
|
|
763
|
+
Please examine the data structures and content to identify:
|
|
764
|
+
- ${insight_type} patterns
|
|
765
|
+
- Unexpected relationships
|
|
766
|
+
- Optimization opportunities
|
|
767
|
+
- Data quality insights`
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
];
|
|
771
|
+
break;
|
|
772
|
+
|
|
773
|
+
case 'optimize_workflow':
|
|
774
|
+
const { base_overview, optimization_focus = 'automation' } = promptArgs;
|
|
775
|
+
messages = [
|
|
776
|
+
{
|
|
777
|
+
role: 'user',
|
|
778
|
+
content: {
|
|
779
|
+
type: 'text',
|
|
780
|
+
text: `Analyze the current Airtable setup and suggest ${optimization_focus} optimizations.
|
|
781
|
+
${base_overview ? `Base overview: ${base_overview}` : ''}
|
|
782
|
+
|
|
783
|
+
Please review the table structures, field types, and relationships to recommend:
|
|
784
|
+
- ${optimization_focus} improvements
|
|
785
|
+
- Best practice implementations
|
|
786
|
+
- Performance enhancements
|
|
787
|
+
- Workflow streamlining opportunities`
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
];
|
|
791
|
+
break;
|
|
792
|
+
|
|
793
|
+
default:
|
|
794
|
+
throw new Error(`Unsupported prompt: ${promptName}`);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
return {
|
|
798
|
+
jsonrpc: '2.0',
|
|
799
|
+
id: request.id,
|
|
800
|
+
result: {
|
|
801
|
+
description: prompt.description,
|
|
802
|
+
messages: messages
|
|
803
|
+
}
|
|
804
|
+
};
|
|
805
|
+
|
|
806
|
+
} catch (error) {
|
|
807
|
+
log(LOG_LEVELS.ERROR, `Prompt ${promptName} failed`, { error: error.message });
|
|
808
|
+
|
|
809
|
+
return {
|
|
810
|
+
jsonrpc: '2.0',
|
|
811
|
+
id: request.id,
|
|
812
|
+
error: {
|
|
813
|
+
code: -32000,
|
|
814
|
+
message: `Error getting prompt ${promptName}: ${error.message}`
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// Sampling handler
|
|
821
|
+
async function handleSampling(request) {
|
|
822
|
+
const { messages, modelPreferences } = request.params;
|
|
823
|
+
|
|
824
|
+
try {
|
|
825
|
+
// Note: In a real implementation, this would integrate with an LLM API
|
|
826
|
+
// For now, we'll return a structured response indicating sampling capability
|
|
827
|
+
|
|
828
|
+
log(LOG_LEVELS.INFO, 'Sampling request received', {
|
|
829
|
+
messageCount: messages?.length,
|
|
830
|
+
model: modelPreferences?.model
|
|
831
|
+
});
|
|
832
|
+
|
|
833
|
+
return {
|
|
834
|
+
jsonrpc: '2.0',
|
|
835
|
+
id: request.id,
|
|
836
|
+
result: {
|
|
837
|
+
model: modelPreferences?.model || 'claude-3-sonnet',
|
|
838
|
+
role: 'assistant',
|
|
839
|
+
content: {
|
|
840
|
+
type: 'text',
|
|
841
|
+
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.'
|
|
842
|
+
},
|
|
843
|
+
stopReason: 'end_turn'
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
|
|
847
|
+
} catch (error) {
|
|
848
|
+
log(LOG_LEVELS.ERROR, 'Sampling failed', { error: error.message });
|
|
849
|
+
|
|
850
|
+
return {
|
|
851
|
+
jsonrpc: '2.0',
|
|
852
|
+
id: request.id,
|
|
853
|
+
error: {
|
|
854
|
+
code: -32000,
|
|
855
|
+
message: `Sampling error: ${error.message}`
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
|
|
479
861
|
// Server startup
|
|
480
862
|
const PORT = CONFIG.PORT;
|
|
481
863
|
const HOST = CONFIG.HOST;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rashidazarang/airtable-mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Airtable MCP server for Claude Desktop - Connect directly to Airtable using natural language",
|
|
5
5
|
"main": "airtable_simple_production.js",
|
|
6
6
|
"bin": {
|
|
@@ -22,6 +22,15 @@
|
|
|
22
22
|
"ai",
|
|
23
23
|
"database"
|
|
24
24
|
],
|
|
25
|
+
"files": [
|
|
26
|
+
"airtable_simple.js",
|
|
27
|
+
"airtable_simple_production.js",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE",
|
|
30
|
+
"package.json",
|
|
31
|
+
"examples/",
|
|
32
|
+
"bin/"
|
|
33
|
+
],
|
|
25
34
|
"author": "Rashid Azarang",
|
|
26
35
|
"license": "MIT",
|
|
27
36
|
"dependencies": {
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
name: 🐛 Bug Report
|
|
2
|
-
description: Create a comprehensive bug report to help us improve
|
|
3
|
-
title: "[BUG] "
|
|
4
|
-
labels: ["bug", "triage"]
|
|
5
|
-
assignees: []
|
|
6
|
-
|
|
7
|
-
body:
|
|
8
|
-
- type: markdown
|
|
9
|
-
attributes:
|
|
10
|
-
value: |
|
|
11
|
-
## 🐛 Bug Report for Airtable MCP Server
|
|
12
|
-
|
|
13
|
-
Thank you for taking the time to report a bug! This helps us improve the quality and reliability of the Airtable MCP Server.
|
|
14
|
-
|
|
15
|
-
**🎯 Our Goal**: Achieve 100/100 Trust Score with your help!
|
|
16
|
-
|
|
17
|
-
- type: checkboxes
|
|
18
|
-
id: preflight
|
|
19
|
-
attributes:
|
|
20
|
-
label: 🔍 Pre-flight Checklist
|
|
21
|
-
description: Please verify you've completed these steps before submitting
|
|
22
|
-
options:
|
|
23
|
-
- label: I've searched existing issues and this hasn't been reported yet
|
|
24
|
-
required: true
|
|
25
|
-
- label: I've read the documentation and troubleshooting guide
|
|
26
|
-
required: true
|
|
27
|
-
- label: I'm using the latest version of the MCP server
|
|
28
|
-
required: true
|
|
29
|
-
- label: I've tested with the minimal reproduction case
|
|
30
|
-
required: true
|
|
31
|
-
|
|
32
|
-
- type: dropdown
|
|
33
|
-
id: severity
|
|
34
|
-
attributes:
|
|
35
|
-
label: 🚨 Severity Level
|
|
36
|
-
description: How critical is this bug?
|
|
37
|
-
options:
|
|
38
|
-
- Critical - Server crashes or data loss
|
|
39
|
-
- High - Major functionality broken
|
|
40
|
-
- Medium - Minor functionality issues
|
|
41
|
-
- Low - Cosmetic or documentation issues
|
|
42
|
-
default: 1
|
|
43
|
-
validations:
|
|
44
|
-
required: true
|
|
45
|
-
|
|
46
|
-
- type: dropdown
|
|
47
|
-
id: component
|
|
48
|
-
attributes:
|
|
49
|
-
label: 🎯 Component Affected
|
|
50
|
-
description: Which component has the issue?
|
|
51
|
-
options:
|
|
52
|
-
- MCP Protocol Implementation
|
|
53
|
-
- OAuth2 Authentication
|
|
54
|
-
- Airtable API Integration
|
|
55
|
-
- Security Features
|
|
56
|
-
- Rate Limiting
|
|
57
|
-
- Logging System
|
|
58
|
-
- Docker Container
|
|
59
|
-
- Documentation
|
|
60
|
-
- CI/CD Pipeline
|
|
61
|
-
- Other
|
|
62
|
-
default: 0
|
|
63
|
-
validations:
|
|
64
|
-
required: true
|
|
65
|
-
|
|
66
|
-
- type: textarea
|
|
67
|
-
id: description
|
|
68
|
-
attributes:
|
|
69
|
-
label: 📝 Bug Description
|
|
70
|
-
description: A clear and concise description of what the bug is
|
|
71
|
-
placeholder: Describe what happened and what you expected to happen...
|
|
72
|
-
validations:
|
|
73
|
-
required: true
|
|
74
|
-
|
|
75
|
-
- type: textarea
|
|
76
|
-
id: reproduction
|
|
77
|
-
attributes:
|
|
78
|
-
label: 🔄 Steps to Reproduce
|
|
79
|
-
description: Detailed steps to reproduce the behavior
|
|
80
|
-
placeholder: |
|
|
81
|
-
1. Start the MCP server with...
|
|
82
|
-
2. Send a request to...
|
|
83
|
-
3. Observe the error...
|
|
84
|
-
validations:
|
|
85
|
-
required: true
|
|
86
|
-
|
|
87
|
-
- type: textarea
|
|
88
|
-
id: expected
|
|
89
|
-
attributes:
|
|
90
|
-
label: ✅ Expected Behavior
|
|
91
|
-
description: What should have happened instead?
|
|
92
|
-
placeholder: Describe the expected behavior...
|
|
93
|
-
validations:
|
|
94
|
-
required: true
|
|
95
|
-
|
|
96
|
-
- type: textarea
|
|
97
|
-
id: actual
|
|
98
|
-
attributes:
|
|
99
|
-
label: ❌ Actual Behavior
|
|
100
|
-
description: What actually happened?
|
|
101
|
-
placeholder: Describe what actually occurred...
|
|
102
|
-
validations:
|
|
103
|
-
required: true
|
|
104
|
-
|
|
105
|
-
- type: textarea
|
|
106
|
-
id: environment
|
|
107
|
-
attributes:
|
|
108
|
-
label: 🖥️ Environment Information
|
|
109
|
-
description: Your environment details
|
|
110
|
-
value: |
|
|
111
|
-
**Server Version**:
|
|
112
|
-
**Node.js Version**:
|
|
113
|
-
**Operating System**:
|
|
114
|
-
**MCP Client**:
|
|
115
|
-
**Airtable API Version**:
|
|
116
|
-
**Authentication Method**:
|
|
117
|
-
render: markdown
|
|
118
|
-
validations:
|
|
119
|
-
required: true
|
|
120
|
-
|
|
121
|
-
- type: textarea
|
|
122
|
-
id: logs
|
|
123
|
-
attributes:
|
|
124
|
-
label: 📋 Relevant Logs
|
|
125
|
-
description: Any relevant log output (please redact sensitive information)
|
|
126
|
-
placeholder: Paste relevant logs here...
|
|
127
|
-
render: shell
|
|
128
|
-
|
|
129
|
-
- type: textarea
|
|
130
|
-
id: config
|
|
131
|
-
attributes:
|
|
132
|
-
label: ⚙️ Configuration
|
|
133
|
-
description: Relevant configuration (please redact sensitive values)
|
|
134
|
-
placeholder: |
|
|
135
|
-
Environment variables, config files, or command line arguments used...
|
|
136
|
-
render: yaml
|
|
137
|
-
|
|
138
|
-
- type: textarea
|
|
139
|
-
id: additional
|
|
140
|
-
attributes:
|
|
141
|
-
label: ➕ Additional Context
|
|
142
|
-
description: Add any other context about the problem here
|
|
143
|
-
placeholder: |
|
|
144
|
-
- Screenshots
|
|
145
|
-
- Related issues
|
|
146
|
-
- Workarounds tried
|
|
147
|
-
- Network configuration
|
|
148
|
-
- Browser/client details
|
|
149
|
-
|
|
150
|
-
- type: checkboxes
|
|
151
|
-
id: contribution
|
|
152
|
-
attributes:
|
|
153
|
-
label: 🤝 Contribution
|
|
154
|
-
description: Are you willing to help fix this issue?
|
|
155
|
-
options:
|
|
156
|
-
- label: I'm willing to submit a pull request to fix this bug
|
|
157
|
-
- label: I can provide additional testing for the fix
|
|
158
|
-
- label: I can help with documentation updates
|
|
159
|
-
|
|
160
|
-
- type: markdown
|
|
161
|
-
attributes:
|
|
162
|
-
value: |
|
|
163
|
-
## 🙏 Thank You!
|
|
164
|
-
|
|
165
|
-
Your bug report helps us improve the Airtable MCP Server and work towards our **100/100 Trust Score** goal.
|
|
166
|
-
|
|
167
|
-
**What happens next?**
|
|
168
|
-
1. Our team will triage this issue within 24 hours
|
|
169
|
-
2. We'll add appropriate labels and assign it to a maintainer
|
|
170
|
-
3. We'll provide updates on progress and estimated timeline
|
|
171
|
-
4. Once fixed, we'll include it in the next release
|
|
172
|
-
|
|
173
|
-
**Need immediate help?** Check out our [troubleshooting guide](./TROUBLESHOOTING.md) or start a [discussion](https://github.com/rashidazarang/airtable-mcp/discussions).
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Bug report
|
|
3
|
-
about: Create a report to help us improve
|
|
4
|
-
title: ''
|
|
5
|
-
labels: ''
|
|
6
|
-
assignees: ''
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
**Describe the bug**
|
|
11
|
-
A clear and concise description of what the bug is.
|
|
12
|
-
|
|
13
|
-
**To Reproduce**
|
|
14
|
-
Steps to reproduce the behavior:
|
|
15
|
-
1. Go to '...'
|
|
16
|
-
2. Click on '....'
|
|
17
|
-
3. Scroll down to '....'
|
|
18
|
-
4. See error
|
|
19
|
-
|
|
20
|
-
**Expected behavior**
|
|
21
|
-
A clear and concise description of what you expected to happen.
|
|
22
|
-
|
|
23
|
-
**Screenshots**
|
|
24
|
-
If applicable, add screenshots to help explain your problem.
|
|
25
|
-
|
|
26
|
-
**Desktop (please complete the following information):**
|
|
27
|
-
- OS: [e.g. iOS]
|
|
28
|
-
- Browser [e.g. chrome, safari]
|
|
29
|
-
- Version [e.g. 22]
|
|
30
|
-
|
|
31
|
-
**Smartphone (please complete the following information):**
|
|
32
|
-
- Device: [e.g. iPhone6]
|
|
33
|
-
- OS: [e.g. iOS8.1]
|
|
34
|
-
- Browser [e.g. stock browser, safari]
|
|
35
|
-
- Version [e.g. 22]
|
|
36
|
-
|
|
37
|
-
**Additional context**
|
|
38
|
-
Add any other context about the problem here.
|