@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.
Files changed (155) hide show
  1. package/README.md +1 -1
  2. package/airtable_simple_production.js +387 -5
  3. package/examples/claude_simple_config.json +0 -9
  4. package/package.json +10 -1
  5. package/.github/ISSUE_TEMPLATE/bug-report.yml +0 -173
  6. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
  7. package/.github/ISSUE_TEMPLATE/custom.md +0 -10
  8. package/.github/ISSUE_TEMPLATE/feature-request.yml +0 -209
  9. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  10. package/.github/ISSUE_TEMPLATE/security-report.yml +0 -216
  11. package/.github/pull_request_template.md +0 -245
  12. package/.github/workflows/ci-cd.yml +0 -408
  13. package/.github/workflows/security-audit.yml +0 -316
  14. package/API_DOCUMENTATION.md +0 -897
  15. package/CAPABILITY_REPORT.md +0 -118
  16. package/CLAUDE_INTEGRATION.md +0 -96
  17. package/CODE_OF_CONDUCT.md +0 -181
  18. package/CONTRIBUTING.md +0 -81
  19. package/DEVELOPMENT.md +0 -190
  20. package/Dockerfile +0 -39
  21. package/Dockerfile.node +0 -20
  22. package/Dockerfile.production +0 -127
  23. package/IMPROVEMENT_PROPOSAL.md +0 -371
  24. package/INSTALLATION.md +0 -183
  25. package/ISSUE_RESPONSES.md +0 -171
  26. package/MCP_REVIEW_SUMMARY.md +0 -142
  27. package/QUICK_START.md +0 -60
  28. package/RELEASE_NOTES_v1.2.0.md +0 -50
  29. package/RELEASE_NOTES_v1.2.1.md +0 -40
  30. package/RELEASE_NOTES_v1.2.2.md +0 -48
  31. package/RELEASE_NOTES_v1.2.3.md +0 -105
  32. package/RELEASE_NOTES_v1.2.4.md +0 -60
  33. package/RELEASE_NOTES_v1.4.0.md +0 -104
  34. package/RELEASE_NOTES_v1.5.0.md +0 -185
  35. package/RELEASE_NOTES_v1.6.0.md +0 -248
  36. package/SECURITY_NOTICE.md +0 -40
  37. package/airtable-clipper/CHANGELOG.md +0 -198
  38. package/airtable-clipper/CHROME_STORE_SUBMISSION.md +0 -343
  39. package/airtable-clipper/LAUNCH_STRATEGY.md +0 -495
  40. package/airtable-clipper/LICENSE +0 -21
  41. package/airtable-clipper/OAUTH_SETUP.md +0 -51
  42. package/airtable-clipper/PRIVACY_POLICY.md +0 -187
  43. package/airtable-clipper/README.md +0 -575
  44. package/airtable-clipper/SUBMIT_TO_CHROME_STORE.md +0 -273
  45. package/airtable-clipper/build.sh +0 -85
  46. package/airtable-clipper/docs/QUICK_START.md +0 -99
  47. package/airtable-clipper/docs/SETUP.md +0 -291
  48. package/airtable-clipper/extension/background.js +0 -337
  49. package/airtable-clipper/extension/base-setup.html +0 -324
  50. package/airtable-clipper/extension/base-setup.js +0 -471
  51. package/airtable-clipper/extension/content.js +0 -771
  52. package/airtable-clipper/extension/icons/README.md +0 -69
  53. package/airtable-clipper/extension/icons/icon-16.png +0 -3
  54. package/airtable-clipper/extension/manifest.json +0 -73
  55. package/airtable-clipper/extension/popup.html +0 -144
  56. package/airtable-clipper/extension/popup.js +0 -475
  57. package/airtable-clipper/extension/styles/content.css +0 -229
  58. package/airtable-clipper/extension/styles/popup.css +0 -477
  59. package/airtable-clipper/privacy-policy.md +0 -63
  60. package/airtable-clipper/releases/v1.0.0/background.js +0 -337
  61. package/airtable-clipper/releases/v1.0.0/base-setup.html +0 -324
  62. package/airtable-clipper/releases/v1.0.0/base-setup.js +0 -471
  63. package/airtable-clipper/releases/v1.0.0/content.js +0 -771
  64. package/airtable-clipper/releases/v1.0.0/icons/README.md +0 -69
  65. package/airtable-clipper/releases/v1.0.0/icons/icon-128.png +0 -2
  66. package/airtable-clipper/releases/v1.0.0/icons/icon-16.png +0 -3
  67. package/airtable-clipper/releases/v1.0.0/icons/icon-32.png +0 -2
  68. package/airtable-clipper/releases/v1.0.0/icons/icon-48.png +0 -2
  69. package/airtable-clipper/releases/v1.0.0/manifest.json +0 -73
  70. package/airtable-clipper/releases/v1.0.0/popup.html +0 -144
  71. package/airtable-clipper/releases/v1.0.0/popup.js +0 -475
  72. package/airtable-clipper/releases/v1.0.0/sidepanel.html +0 -25
  73. package/airtable-clipper/releases/v1.0.0/styles/content.css +0 -229
  74. package/airtable-clipper/releases/v1.0.0/styles/popup.css +0 -477
  75. package/airtable-clipper/releases/v1.0.1/background.js +0 -337
  76. package/airtable-clipper/releases/v1.0.1/base-setup.html +0 -324
  77. package/airtable-clipper/releases/v1.0.1/base-setup.js +0 -471
  78. package/airtable-clipper/releases/v1.0.1/content.js +0 -771
  79. package/airtable-clipper/releases/v1.0.1/icons/README.md +0 -69
  80. package/airtable-clipper/releases/v1.0.1/icons/icon-128.png +0 -2
  81. package/airtable-clipper/releases/v1.0.1/icons/icon-16.png +0 -3
  82. package/airtable-clipper/releases/v1.0.1/icons/icon-32.png +0 -2
  83. package/airtable-clipper/releases/v1.0.1/icons/icon-48.png +0 -2
  84. package/airtable-clipper/releases/v1.0.1/manifest.json +0 -70
  85. package/airtable-clipper/releases/v1.0.1/popup.html +0 -157
  86. package/airtable-clipper/releases/v1.0.1/popup.js +0 -562
  87. package/airtable-clipper/releases/v1.0.1/sidepanel.html +0 -25
  88. package/airtable-clipper/releases/v1.0.1/styles/content.css +0 -229
  89. package/airtable-clipper/releases/v1.0.1/styles/popup.css +0 -647
  90. package/airtable-clipper/releases/v1.0.2/background.js +0 -337
  91. package/airtable-clipper/releases/v1.0.2/base-setup.html +0 -324
  92. package/airtable-clipper/releases/v1.0.2/base-setup.js +0 -471
  93. package/airtable-clipper/releases/v1.0.2/content.js +0 -771
  94. package/airtable-clipper/releases/v1.0.2/icons/README.md +0 -69
  95. package/airtable-clipper/releases/v1.0.2/icons/icon-128.png +0 -2
  96. package/airtable-clipper/releases/v1.0.2/icons/icon-16.png +0 -3
  97. package/airtable-clipper/releases/v1.0.2/icons/icon-32.png +0 -2
  98. package/airtable-clipper/releases/v1.0.2/icons/icon-48.png +0 -2
  99. package/airtable-clipper/releases/v1.0.2/manifest.json +0 -62
  100. package/airtable-clipper/releases/v1.0.2/popup.html +0 -157
  101. package/airtable-clipper/releases/v1.0.2/popup.js +0 -567
  102. package/airtable-clipper/releases/v1.0.2/sidepanel.html +0 -25
  103. package/airtable-clipper/releases/v1.0.2/styles/content.css +0 -229
  104. package/airtable-clipper/releases/v1.0.2/styles/popup.css +0 -647
  105. package/airtable-clipper/terms-of-service.md +0 -124
  106. package/airtable-clipper/test-credentials.md +0 -61
  107. package/airtable-clipper/test-extension/background.js +0 -337
  108. package/airtable-clipper/test-extension/base-setup.html +0 -324
  109. package/airtable-clipper/test-extension/base-setup.js +0 -471
  110. package/airtable-clipper/test-extension/content.js +0 -873
  111. package/airtable-clipper/test-extension/icons/README.md +0 -69
  112. package/airtable-clipper/test-extension/icons/icon-128.png +0 -2
  113. package/airtable-clipper/test-extension/icons/icon-16.png +0 -3
  114. package/airtable-clipper/test-extension/icons/icon-32.png +0 -2
  115. package/airtable-clipper/test-extension/icons/icon-48.png +0 -2
  116. package/airtable-clipper/test-extension/manifest.json +0 -72
  117. package/airtable-clipper/test-extension/popup.html +0 -274
  118. package/airtable-clipper/test-extension/popup.js +0 -729
  119. package/airtable-clipper/test-extension/sidepanel.html +0 -25
  120. package/airtable-clipper/test-extension/styles/content.css +0 -229
  121. package/airtable-clipper/test-extension/styles/popup.css +0 -794
  122. package/airtable_mcp/__init__.py +0 -5
  123. package/airtable_mcp/src/server.py +0 -329
  124. package/airtable_mcp_v2.js +0 -1505
  125. package/airtable_mcp_v2_oauth.js +0 -1048
  126. package/airtable_mcp_v3_advanced.js +0 -1161
  127. package/cleanup.sh +0 -71
  128. package/docker-compose.production.yml +0 -366
  129. package/helm/airtable-mcp/Chart.yaml +0 -122
  130. package/helm/airtable-mcp/values.yaml +0 -538
  131. package/index.js +0 -179
  132. package/inspector.py +0 -148
  133. package/inspector_server.py +0 -337
  134. package/k8s/deployment.yaml +0 -402
  135. package/k8s/namespace.yaml +0 -108
  136. package/k8s/service.yaml +0 -194
  137. package/monitoring/alerts.yml +0 -289
  138. package/monitoring/prometheus.yml +0 -224
  139. package/publish-steps.txt +0 -27
  140. package/quick_test.sh +0 -30
  141. package/requirements.txt +0 -10
  142. package/setup.py +0 -29
  143. package/simple_airtable_server.py +0 -151
  144. package/smithery.yaml +0 -45
  145. package/test_all_features.sh +0 -146
  146. package/test_all_operations.sh +0 -120
  147. package/test_client.py +0 -70
  148. package/test_enhanced_features.js +0 -389
  149. package/test_mcp_comprehensive.js +0 -163
  150. package/test_mock_server.js +0 -180
  151. package/test_v1.4.0_final.sh +0 -131
  152. package/test_v1.5.0_comprehensive.sh +0 -96
  153. package/test_v1.5.0_final.sh +0 -224
  154. package/test_v1.6.0_comprehensive.sh +0 -187
  155. package/test_webhooks.sh +0 -105
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Airtable MCP Server
2
2
 
3
+ [![Trust Score](https://archestra.ai/mcp-catalog/api/badge/quality/rashidazarang/airtable-mcp)](https://archestra.ai/mcp-catalog/rashidazarang__airtable-mcp)
3
4
  [![smithery badge](https://smithery.ai/badge/@rashidazarang/airtable-mcp)](https://smithery.ai/server/@rashidazarang/airtable-mcp)
4
- [![Trust Score](https://archestra.ai/badge/@rashidazarang/airtable-mcp)](https://archestra.ai/mcp-catalog/rashidazarang__airtable-mcp)
5
5
  ![Airtable](https://img.shields.io/badge/Airtable-18BFFF?style=for-the-badge&logo=Airtable&logoColor=white)
6
6
  [![MCP](https://img.shields.io/badge/MCP-1.6.0-green)](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
- const currentLogLevel = LOG_LEVELS[CONFIG.LOG_LEVEL] || LOG_LEVELS.INFO;
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.1.0',
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.1.0',
326
- description: 'Model Context Protocol server for Airtable integration'
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;
@@ -1,15 +1,6 @@
1
1
  {
2
2
  "mcpServers": {
3
3
  "airtable": {
4
- "command": "curl",
5
- "args": [
6
- "-s",
7
- "-X",
8
- "POST",
9
- "-H",
10
- "Content-Type: application/json",
11
- "http://localhost:8010/mcp"
12
- ],
13
4
  "url": "http://localhost:8010/mcp"
14
5
  }
15
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rashidazarang/airtable-mcp",
3
- "version": "2.1.0",
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.