Skip to content

Commit 69f9865

Browse files
committed
Fix compatibility issues with Claude and Windsurf. Add AbortController polyfill and improve JSON parsing.
1 parent 07b8818 commit 69f9865

File tree

7 files changed

+232
-91
lines changed

7 files changed

+232
-91
lines changed

CLAUDE_INTEGRATION.md

Lines changed: 73 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,109 @@
1-
# Using Airtable MCP with Claude
1+
# Claude/Windsurf Integration Guide
22

3-
This guide explains how to integrate the Airtable MCP with various Claude MCP clients.
3+
This guide explains how to set up the Airtable MCP for use with Claude (including Anthropic's tools and in VSCode extensions like Windsurf).
44

5-
## Compatible Claude MCP Clients
5+
## Setup for Claude
66

7-
This MCP works with any client that supports Anthropic's Model Context Protocol (MCP), including:
7+
### Requirements
88

9-
- [Claude Desktop](https://claude.ai/desktop)
10-
- [Cursor](https://cursor.sh/)
11-
- [Cline](https://github.com/lpw/cline)
12-
- [Zed](https://zed.dev/)
13-
- Any other MCP-compatible client
9+
- Node.js v14 or higher
10+
- An Airtable account with Personal Access Token
11+
- An Airtable base you want to connect to
1412

15-
## Recommended: Using Smithery (Easiest Method)
13+
### Configuration
1614

17-
The recommended way to use this MCP is through Smithery, which handles all dependencies and configuration automatically:
15+
Claude requires the configuration to be specified in JSON format. Here's how to set up the configuration for Claude:
1816

19-
1. **Configure your MCP client**:
20-
- Edit your client's MCP configuration file (e.g., `~/.cursor/mcp.json`)
21-
- Add the following configuration:
17+
1. In Claude settings, add a new MCP server with these settings:
18+
- Name: `airtable-mcp`
19+
- Command: `npx`
20+
- Arguments:
21+
```
22+
-y @smithery/cli@latest run @rashidazarang/airtable-mcp --config {"airtable_token":"your_token_here","base_id":"your_base_id_here"}
23+
```
2224
25+
2. **IMPORTANT: JSON Format**
26+
Make sure the JSON in the `--config` parameter is properly formatted:
27+
- No line breaks
28+
- No extra backslashes
29+
- No surrounding quotes
30+
31+
### Troubleshooting JSON Issues
32+
33+
If you encounter the error `Unexpected token 'F', "Found & ig"... is not valid JSON`, try these fixes:
34+
35+
1. **Method 1: Simplify JSON** - Remove any complex characters from your token and try again.
36+
37+
2. **Method 2: Escape Properly** - Make sure you format the command with proper escaping:
38+
```
39+
-y @smithery/cli@latest run @rashidazarang/airtable-mcp --config {\"airtable_token\":\"your_token_here\",\"base_id\":\"your_base_id_here\"}
40+
```
41+
42+
3. **Method 3: Use Separate Parameters** - Instead of using --config, use individual parameters:
43+
```
44+
-y @smithery/cli@latest run @rashidazarang/airtable-mcp --token your_token_here --base your_base_id_here
45+
```
46+
47+
## Setup for Windsurf
48+
49+
Windsurf users should use a dedicated config file to avoid JSON parsing issues:
50+
51+
1. Create a file called `mcp_config.json` with:
2352
```json
2453
{
2554
"mcpServers": {
26-
"airtable-mcp": {
55+
"AIRTABLE": {
2756
"command": "npx",
2857
"args": [
2958
"-y",
3059
"@smithery/cli@latest",
3160
"run",
3261
"@rashidazarang/airtable-mcp",
33-
"--config",
34-
"{\"airtable_token\":\"YOUR_AIRTABLE_TOKEN\\\"\",\"base_id\":\"YOUR_BASE_ID\"}"
62+
"--token",
63+
"your_token_here",
64+
"--base",
65+
"your_base_id_here"
3566
]
3667
}
3768
}
3869
}
3970
```
4071

41-
2. **Replace tokens**:
42-
- Replace `YOUR_AIRTABLE_TOKEN\"` with your Airtable Personal Access Token (maintaining the backslash and quote)
43-
- Replace `YOUR_BASE_ID` with your Airtable base ID
72+
2. In Windsurf settings, configure it to use this file.
4473

45-
3. **Restart your client** to load the new tools
74+
## Common Issues
4675

47-
## Setting Up with Claude Desktop
76+
### AbortController Error
4877

49-
1. **Install the Airtable MCP**:
50-
```bash
51-
npm install -g airtable-mcp
52-
```
53-
54-
2. **Start the MCP server**:
55-
```bash
56-
airtable-mcp --token "your_airtable_token" --base "your_base_id"
57-
```
58-
59-
3. **Configure Claude Desktop**:
60-
- Open Claude Desktop
61-
- Go to Settings > Tools > Add Tool
62-
- For the tool URL, use: `http://localhost:8010/mcp` (default port)
63-
- Click "Add Tool"
64-
- You'll now see the Airtable tools in Claude's tool palette
65-
66-
## Setting Up with Cursor
67-
68-
1. **Edit your Cursor MCP configuration**:
69-
- Open or create the file: `~/.cursor/mcp.json`
70-
- Add the Smithery configuration as described in the "Recommended" section above
71-
72-
2. **Restart Cursor** to load the new tools
73-
74-
## Setting Up with Cline
75-
76-
1. **Start the MCP server**:
77-
```bash
78-
npx airtable-mcp --token "your_airtable_token" --base "your_base_id"
79-
```
80-
81-
2. **Run Cline with MCP support**:
82-
```bash
83-
cline --mcp-urls http://localhost:8010/mcp
84-
```
78+
If you see an error like `ReferenceError: AbortController is not defined`, this is because you're using an older version of Node.js that doesn't include this feature. Options to fix:
8579

86-
## Using the MCP in Claude
80+
1. **Update Node.js** (recommended) - Install Node.js v15+ which includes AbortController natively.
8781

88-
Once configured, you can use natural language to work with Airtable data. Here are some examples:
82+
2. **Use Polyfill** - New versions of our MCP (1.1.0+) automatically add a polyfill for older Node versions.
8983

90-
- "Can you list all the tables in our Airtable base?"
91-
- "Get all records from the Projects table where Status is Complete"
92-
- "Create a new record in the Contacts table with name John Smith and email [email protected]"
93-
- "Update the Budget field for the Marketing project to $15,000"
84+
### Server Disconnected or Timeout Errors
9485

95-
## Testing Your Setup
86+
1. Check that your Airtable token is valid and has the necessary permissions
87+
2. Ensure you have proper internet connectivity
88+
3. Try restarting the MCP server
89+
4. Check the logs for any specific error messages
9690

97-
To confirm your MCP setup is working correctly:
91+
## Using the MCP with Claude
9892

99-
1. Restart your MCP client after making configuration changes
100-
2. Start a conversation with Claude
101-
3. Ask a simple question like "Can you list all the tables in my Airtable base?"
102-
4. Claude should respond with a list of tables from your Airtable base
93+
Once connected, you can use the following tools:
10394

104-
If you see tables listed, congratulations! Your Airtable MCP is working correctly.
95+
- `list_bases` - Show available Airtable bases
96+
- `list_tables` - List tables in the current base
97+
- `list_records` - Get records from a specific table
98+
- `create_records` - Add new records to a table
99+
- `update_records` - Modify existing records
105100

106-
## Troubleshooting
101+
For example, in Claude, you might ask:
102+
"Please list all tables in my Airtable base and then show me records from the 'Contacts' table."
107103

108-
- **Tool not appearing**: Make sure the MCP server is running and the client is properly configured
109-
- **Authentication errors**: Verify your Airtable token has the necessary permissions
110-
- **Connection issues**: Confirm the MCP server is running on the expected port (default is 8010)
111-
- **JSON escaping issues**: Make sure the backslash characters in the configuration are preserved
112-
- **Smithery not found**: Try installing the Smithery CLI globally with `npm install -g @smithery/cli`
104+
## Support
113105

114-
For more detailed troubleshooting, check the server logs where you started the Airtable MCP.
106+
If you continue to experience issues, please report them on GitHub with:
107+
- Error messages
108+
- Node.js version (`node -v`)
109+
- Operating system details

README.md

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,44 @@ This MCP has been updated to work with the latest MCP SDK version. The new imple
5151
- Airtable API token
5252
- A compatible MCP client (Cursor, Claude Desktop, etc.)
5353

54-
### Smithery Installation (Recommended)
54+
### Recommended: Using Smithery via NPX (Easiest Method)
5555

56-
The easiest way to install:
56+
The simplest way to use this MCP is through Smithery via NPX. This handles all dependencies and configuration automatically.
57+
58+
1. Configure your MCP client by adding the following to your MCP configuration file (e.g., `~/.cursor/mcp.json`):
59+
60+
```json
61+
{
62+
"mcpServers": {
63+
"airtable-mcp": {
64+
"command": "npx",
65+
"args": [
66+
"-y",
67+
"@smithery/cli@latest",
68+
"run",
69+
"@rashidazarang/airtable-mcp",
70+
"--config",
71+
"{\"airtable_token\":\"YOUR_AIRTABLE_TOKEN\\\"\",\"base_id\":\"YOUR_BASE_ID\"}"
72+
]
73+
}
74+
}
75+
}
76+
```
77+
78+
2. Replace `YOUR_AIRTABLE_TOKEN\"` with your Airtable API token (maintaining the backslash and quote), and `YOUR_BASE_ID` with your Airtable base ID.
79+
3. Restart your MCP client to load the new tools.
80+
81+
### Smithery Web Installation (Alternative)
82+
83+
Another easy installation method:
5784

5885
1. Visit [Smithery](https://smithery.ai)
5986
2. Search for "@rashidazarang/airtable-mcp"
6087
3. Click "Install" and follow the prompts
6188

62-
### Quick Setup with NPX (Alternative)
89+
### Traditional NPX Installation (Advanced)
6390

64-
Another fast way to get started:
91+
If you prefer a more traditional approach:
6592

6693
```bash
6794
# Install globally
@@ -147,4 +174,36 @@ MIT
147174

148175
## Contributing
149176

150-
Contributions are welcome! Please feel free to submit a Pull Request.
177+
Contributions are welcome! Please feel free to submit a Pull Request.
178+
179+
## Using with Claude and Windsurf
180+
181+
### Version 1.2.0 Update: Improved Compatibility
182+
183+
The latest version includes important fixes to address common issues:
184+
185+
1. **AbortController Compatibility**: Added polyfill for Node.js versions < 15.0.0
186+
2. **JSON Parsing Improvements**: Enhanced handling of malformed JSON configurations
187+
3. **Windsurf Support**: Special configuration templates for Windsurf users
188+
189+
### Common Issues and Solutions
190+
191+
#### JSON Format Errors
192+
193+
If you see errors like `Unexpected token 'F', "Found & ig"... is not valid JSON`, try:
194+
195+
1. **Use Individual Parameters**:
196+
```
197+
npx -y @smithery/cli@latest run @rashidazarang/airtable-mcp --token YOUR_TOKEN --base YOUR_BASE_ID
198+
```
199+
200+
2. **For Windsurf Users**: Use the template in `examples/windsurf_mcp_config.json`
201+
202+
#### AbortController Not Defined
203+
204+
This typically happens on older Node.js versions. The current version includes an automatic polyfill, but you can also:
205+
206+
1. **Update Node.js**: Install Node.js v15+ for native AbortController support
207+
2. **Update This Package**: Make sure you're using version 1.2.0 or higher
208+
209+
See [CLAUDE_INTEGRATION.md](./CLAUDE_INTEGRATION.md) for detailed setup instructions.

examples/claude_config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"airtable_token": "YOUR_AIRTABLE_TOKEN",
3+
"base_id": "YOUR_BASE_ID"
4+
}

examples/windsurf_mcp_config.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"mcpServers": {
3+
"AIRTABLE": {
4+
"command": "npx",
5+
"args": [
6+
"-y",
7+
"@smithery/cli@latest",
8+
"run",
9+
"@rashidazarang/airtable-mcp",
10+
"--token",
11+
"YOUR_AIRTABLE_TOKEN",
12+
"--base",
13+
"YOUR_BASE_ID"
14+
]
15+
}
16+
}
17+
}

index.js

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@ const path = require('path');
44
const { execSync } = require('child_process');
55
const { spawn } = require('child_process');
66

7+
// Polyfill for AbortController in older Node.js versions
8+
if (typeof globalThis.AbortController === 'undefined') {
9+
globalThis.AbortController = class AbortController {
10+
constructor() {
11+
this.signal = {
12+
aborted: false,
13+
addEventListener: () => {},
14+
removeEventListener: () => {},
15+
dispatchEvent: () => true
16+
};
17+
}
18+
abort() {
19+
this.signal.aborted = true;
20+
}
21+
};
22+
console.log('ℹ️ Added AbortController polyfill for compatibility with older Node.js versions');
23+
}
24+
725
// Parse command-line arguments
826
const args = process.argv.slice(2);
927
let tokenIndex = args.indexOf('--token');
@@ -91,7 +109,36 @@ if (config) {
91109
console.log(`✅ Using base ID from config: ${configObj.base_id}`);
92110
}
93111
} catch (e) {
94-
console.warn('⚠️ Could not parse config JSON, passing it directly to Python script');
112+
console.warn('⚠️ Could not parse config JSON, attempting to sanitize...');
113+
114+
// Sanitize config JSON - fix common formatting issues
115+
try {
116+
// Remove any unexpected line breaks, extra quotes, and escape characters
117+
const sanitizedConfig = config
118+
.replace(/[\r\n]+/g, '')
119+
.replace(/\\+"/g, '"')
120+
.replace(/^"/, '')
121+
.replace(/"$/, '')
122+
.replace(/\\/g, '');
123+
124+
// Try parsing it
125+
const configObj = JSON.parse(sanitizedConfig);
126+
if (configObj) {
127+
console.log('✅ Successfully sanitized config JSON');
128+
// Update config with sanitized version
129+
scriptArgs[scriptArgs.indexOf(config)] = sanitizedConfig;
130+
config = sanitizedConfig;
131+
132+
if (configObj.airtable_token) {
133+
console.log('✅ Using API token from sanitized config');
134+
}
135+
if (configObj.base_id) {
136+
console.log(`✅ Using base ID from sanitized config: ${configObj.base_id}`);
137+
}
138+
}
139+
} catch (sanitizeErr) {
140+
console.warn('⚠️ Could not sanitize config JSON, passing it directly to Python script');
141+
}
95142
}
96143
} else {
97144
if (token) {

inspector_server.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,31 @@ def parse_args():
3939
try:
4040
# Strip any trailing quotes or backslashes that might be present
4141
config_str = args.config_json.rstrip('\\"')
42-
logger.info(f"Parsing config: {config_str}")
42+
# Additional sanitization for JSON format
43+
config_str = config_str.strip()
44+
# Handle escaped quotes
45+
if config_str.startswith('"') and config_str.endswith('"'):
46+
config_str = config_str[1:-1]
47+
# Fix escaped quotes within JSON
48+
config_str = config_str.replace('\\"', '"')
49+
# Replace escaped backslashes
50+
config_str = config_str.replace('\\\\', '\\')
51+
52+
logger.info(f"Parsing sanitized config: {config_str}")
4353
config = json.loads(config_str)
4454
logger.info(f"Successfully parsed config: {config}")
4555
except json.JSONDecodeError as e:
4656
logger.error(f"Failed to parse config JSON: {e}")
4757
logger.error(f"Raw config string: {args.config_json}")
58+
# Try one more approach - sometimes config is double-quoted JSON
59+
try:
60+
# Try to interpret as Python string literal
61+
import ast
62+
literal_str = ast.literal_eval(f"'''{args.config_json}'''")
63+
config = json.loads(literal_str)
64+
logger.info(f"Successfully parsed config using ast: {config}")
65+
except Exception as ast_error:
66+
logger.error(f"Failed alternate parsing method: {ast_error}")
4867

4968
# Create MCP server
5069
app = FastMCP("Airtable Tools")

0 commit comments

Comments
 (0)