@rashidazarang/airtable-mcp 1.2.4 → 1.4.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/.claude/settings.local.json +4 -1
- package/CAPABILITY_REPORT.md +118 -0
- package/DEVELOPMENT.md +1 -0
- package/IMPROVEMENT_PROPOSAL.md +371 -0
- package/MCP_REVIEW_SUMMARY.md +1 -0
- package/RELEASE_NOTES_v1.2.3.md +1 -0
- package/RELEASE_NOTES_v1.4.0.md +104 -0
- package/airtable_enhanced.js +499 -0
- package/airtable_simple.js +459 -83
- package/airtable_simple_v1.2.4_backup.js +277 -0
- package/airtable_v1.4.0.js +654 -0
- package/cleanup.sh +1 -0
- package/package.json +1 -1
- package/quick_test.sh +1 -0
- package/test_all_features.sh +146 -0
- package/test_all_operations.sh +120 -0
- package/test_enhanced_features.js +389 -0
- package/test_mcp_comprehensive.js +1 -0
- package/test_mock_server.js +180 -0
- package/test_v1.4.0_final.sh +131 -0
- package/test_webhooks.sh +105 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mock Airtable API Server for Testing
|
|
5
|
+
* Simulates Airtable API responses for testing the MCP
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const http = require('http');
|
|
9
|
+
const https = require('https');
|
|
10
|
+
|
|
11
|
+
// Mock data store
|
|
12
|
+
let mockTables = {
|
|
13
|
+
'tblTest123': {
|
|
14
|
+
id: 'tblTest123',
|
|
15
|
+
name: 'Tasks',
|
|
16
|
+
fields: [
|
|
17
|
+
{ id: 'fld1', name: 'Name', type: 'singleLineText' },
|
|
18
|
+
{ id: 'fld2', name: 'Status', type: 'singleSelect' },
|
|
19
|
+
{ id: 'fld3', name: 'Notes', type: 'multilineText' }
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
'tblTest456': {
|
|
23
|
+
id: 'tblTest456',
|
|
24
|
+
name: 'Projects',
|
|
25
|
+
fields: [
|
|
26
|
+
{ id: 'fld4', name: 'Title', type: 'singleLineText' },
|
|
27
|
+
{ id: 'fld5', name: 'Description', type: 'multilineText' }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
let mockRecords = {
|
|
33
|
+
'tblTest123': [
|
|
34
|
+
{
|
|
35
|
+
id: 'recABC123',
|
|
36
|
+
fields: { Name: 'Test Task 1', Status: 'Todo', Notes: 'First test task' },
|
|
37
|
+
createdTime: '2025-08-14T10:00:00.000Z'
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 'recDEF456',
|
|
41
|
+
fields: { Name: 'Test Task 2', Status: 'In Progress', Notes: 'Second test task' },
|
|
42
|
+
createdTime: '2025-08-14T11:00:00.000Z'
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
'tblTest456': []
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
let recordIdCounter = 1000;
|
|
49
|
+
|
|
50
|
+
// Create mock server
|
|
51
|
+
const server = http.createServer((req, res) => {
|
|
52
|
+
console.log(`Mock API: ${req.method} ${req.url}`);
|
|
53
|
+
|
|
54
|
+
// Parse URL
|
|
55
|
+
const url = req.url;
|
|
56
|
+
|
|
57
|
+
// Enable CORS
|
|
58
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
59
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE, OPTIONS');
|
|
60
|
+
res.setHeader('Access-Control-Allow-Headers', 'Authorization, Content-Type');
|
|
61
|
+
|
|
62
|
+
// Check authorization
|
|
63
|
+
if (!req.headers.authorization || !req.headers.authorization.includes('Bearer')) {
|
|
64
|
+
res.writeHead(401, { 'Content-Type': 'application/json' });
|
|
65
|
+
res.end(JSON.stringify({ error: { type: 'UNAUTHORIZED', message: 'Missing authorization' } }));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Handle preflight
|
|
70
|
+
if (req.method === 'OPTIONS') {
|
|
71
|
+
res.writeHead(200);
|
|
72
|
+
res.end();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Route handlers
|
|
77
|
+
if (url.includes('/v0/meta/bases/') && url.includes('/tables')) {
|
|
78
|
+
// List tables
|
|
79
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
80
|
+
res.end(JSON.stringify({ tables: Object.values(mockTables) }));
|
|
81
|
+
|
|
82
|
+
} else if (req.method === 'GET' && url.match(/\/v0\/test_base\/(tbl\w+)$/)) {
|
|
83
|
+
// List records
|
|
84
|
+
const tableId = url.match(/\/(tbl\w+)$/)[1];
|
|
85
|
+
const records = mockRecords[tableId] || [];
|
|
86
|
+
|
|
87
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
88
|
+
res.end(JSON.stringify({ records }));
|
|
89
|
+
|
|
90
|
+
} else if (req.method === 'GET' && url.match(/\/v0\/test_base\/(tbl\w+)\/(rec\w+)$/)) {
|
|
91
|
+
// Get single record
|
|
92
|
+
const matches = url.match(/\/(tbl\w+)\/(rec\w+)$/);
|
|
93
|
+
const tableId = matches[1];
|
|
94
|
+
const recordId = matches[2];
|
|
95
|
+
|
|
96
|
+
const records = mockRecords[tableId] || [];
|
|
97
|
+
const record = records.find(r => r.id === recordId);
|
|
98
|
+
|
|
99
|
+
if (record) {
|
|
100
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
101
|
+
res.end(JSON.stringify(record));
|
|
102
|
+
} else {
|
|
103
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
104
|
+
res.end(JSON.stringify({ error: { type: 'NOT_FOUND', message: 'Record not found' } }));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
} else if (req.method === 'POST' && url.match(/\/v0\/test_base\/(tbl\w+)$/)) {
|
|
108
|
+
// Create record
|
|
109
|
+
const tableId = url.match(/\/(tbl\w+)$/)[1];
|
|
110
|
+
|
|
111
|
+
let body = '';
|
|
112
|
+
req.on('data', chunk => body += chunk);
|
|
113
|
+
req.on('end', () => {
|
|
114
|
+
const data = JSON.parse(body);
|
|
115
|
+
const newRecord = {
|
|
116
|
+
id: `recNEW${recordIdCounter++}`,
|
|
117
|
+
fields: data.fields,
|
|
118
|
+
createdTime: new Date().toISOString()
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
if (!mockRecords[tableId]) mockRecords[tableId] = [];
|
|
122
|
+
mockRecords[tableId].push(newRecord);
|
|
123
|
+
|
|
124
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
125
|
+
res.end(JSON.stringify(newRecord));
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
} else if (req.method === 'PATCH' && url.match(/\/v0\/test_base\/(tbl\w+)\/(rec\w+)$/)) {
|
|
129
|
+
// Update record
|
|
130
|
+
const matches = url.match(/\/(tbl\w+)\/(rec\w+)$/);
|
|
131
|
+
const tableId = matches[1];
|
|
132
|
+
const recordId = matches[2];
|
|
133
|
+
|
|
134
|
+
let body = '';
|
|
135
|
+
req.on('data', chunk => body += chunk);
|
|
136
|
+
req.on('end', () => {
|
|
137
|
+
const data = JSON.parse(body);
|
|
138
|
+
const records = mockRecords[tableId] || [];
|
|
139
|
+
const record = records.find(r => r.id === recordId);
|
|
140
|
+
|
|
141
|
+
if (record) {
|
|
142
|
+
Object.assign(record.fields, data.fields);
|
|
143
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
144
|
+
res.end(JSON.stringify(record));
|
|
145
|
+
} else {
|
|
146
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
147
|
+
res.end(JSON.stringify({ error: { type: 'NOT_FOUND', message: 'Record not found' } }));
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
} else if (req.method === 'DELETE' && url.match(/\/v0\/test_base\/(tbl\w+)\/(rec\w+)$/)) {
|
|
152
|
+
// Delete record
|
|
153
|
+
const matches = url.match(/\/(tbl\w+)\/(rec\w+)$/);
|
|
154
|
+
const tableId = matches[1];
|
|
155
|
+
const recordId = matches[2];
|
|
156
|
+
|
|
157
|
+
const records = mockRecords[tableId] || [];
|
|
158
|
+
const index = records.findIndex(r => r.id === recordId);
|
|
159
|
+
|
|
160
|
+
if (index !== -1) {
|
|
161
|
+
records.splice(index, 1);
|
|
162
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
163
|
+
res.end(JSON.stringify({ id: recordId, deleted: true }));
|
|
164
|
+
} else {
|
|
165
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
166
|
+
res.end(JSON.stringify({ error: { type: 'NOT_FOUND', message: 'Record not found' } }));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
} else {
|
|
170
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
171
|
+
res.end(JSON.stringify({ error: { type: 'NOT_FOUND', message: 'Endpoint not found' } }));
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Start mock server on port 8888
|
|
176
|
+
server.listen(8888, () => {
|
|
177
|
+
console.log('🎭 Mock Airtable API server running on http://localhost:8888');
|
|
178
|
+
console.log('📋 Mock tables: Tasks (tblTest123), Projects (tblTest456)');
|
|
179
|
+
console.log('📝 Mock records: 2 in Tasks, 0 in Projects');
|
|
180
|
+
});
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
echo "🚀 FINAL TEST SUITE FOR AIRTABLE MCP v1.4.0"
|
|
4
|
+
echo "==========================================="
|
|
5
|
+
echo ""
|
|
6
|
+
|
|
7
|
+
PASSED=0
|
|
8
|
+
FAILED=0
|
|
9
|
+
|
|
10
|
+
# Helper function to test a tool
|
|
11
|
+
test_tool() {
|
|
12
|
+
local tool_name=$1
|
|
13
|
+
local args=$2
|
|
14
|
+
local expected=$3
|
|
15
|
+
|
|
16
|
+
result=$(curl -s -X POST http://localhost:8010/mcp \
|
|
17
|
+
-H "Content-Type: application/json" \
|
|
18
|
+
-d "{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"tools/call\", \"params\": {\"name\": \"$tool_name\", \"arguments\": $args}}")
|
|
19
|
+
|
|
20
|
+
if echo "$result" | grep -q "$expected"; then
|
|
21
|
+
echo "✅ $tool_name: PASSED"
|
|
22
|
+
((PASSED++))
|
|
23
|
+
return 0
|
|
24
|
+
else
|
|
25
|
+
echo "❌ $tool_name: FAILED"
|
|
26
|
+
echo " Response: $(echo "$result" | python3 -c "import sys, json; r=json.load(sys.stdin); print(r.get('result', {}).get('content', [{}])[0].get('text', 'ERROR')[:100])")"
|
|
27
|
+
((FAILED++))
|
|
28
|
+
return 1
|
|
29
|
+
fi
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
echo "📋 Testing 12 Tools"
|
|
33
|
+
echo "==================="
|
|
34
|
+
echo ""
|
|
35
|
+
|
|
36
|
+
# 1. List tools
|
|
37
|
+
echo -n "1. Tools available: "
|
|
38
|
+
tools_count=$(curl -s -X POST http://localhost:8010/mcp \
|
|
39
|
+
-H "Content-Type: application/json" \
|
|
40
|
+
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' \
|
|
41
|
+
| python3 -c "import sys, json; print(len(json.load(sys.stdin)['result']['tools']))")
|
|
42
|
+
echo "$tools_count tools"
|
|
43
|
+
|
|
44
|
+
# 2. List tables
|
|
45
|
+
test_tool "list_tables" "{}" "table"
|
|
46
|
+
|
|
47
|
+
# 3. Create record
|
|
48
|
+
RECORD_JSON=$(curl -s -X POST http://localhost:8010/mcp \
|
|
49
|
+
-H "Content-Type: application/json" \
|
|
50
|
+
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "create_record", "arguments": {"table": "tblH7TnJxYpNqhQYK", "fields": {"Name": "Test v1.4.0", "Status": "Testing"}}}}')
|
|
51
|
+
|
|
52
|
+
if echo "$RECORD_JSON" | grep -q "Successfully created"; then
|
|
53
|
+
echo "✅ create_record: PASSED"
|
|
54
|
+
((PASSED++))
|
|
55
|
+
RECORD_ID=$(echo "$RECORD_JSON" | grep -o 'rec[a-zA-Z0-9]\+' | head -1)
|
|
56
|
+
else
|
|
57
|
+
echo "❌ create_record: FAILED"
|
|
58
|
+
((FAILED++))
|
|
59
|
+
RECORD_ID=""
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# 4. Get record
|
|
63
|
+
if [ ! -z "$RECORD_ID" ]; then
|
|
64
|
+
test_tool "get_record" "{\"table\": \"tblH7TnJxYpNqhQYK\", \"recordId\": \"$RECORD_ID\"}" "Record $RECORD_ID"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# 5. Update record
|
|
68
|
+
if [ ! -z "$RECORD_ID" ]; then
|
|
69
|
+
test_tool "update_record" "{\"table\": \"tblH7TnJxYpNqhQYK\", \"recordId\": \"$RECORD_ID\", \"fields\": {\"Status\": \"Updated\"}}" "Successfully updated"
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# 6. List records
|
|
73
|
+
test_tool "list_records" "{\"table\": \"tblH7TnJxYpNqhQYK\", \"maxRecords\": 2}" "record"
|
|
74
|
+
|
|
75
|
+
# 7. Search records
|
|
76
|
+
test_tool "search_records" "{\"table\": \"tblH7TnJxYpNqhQYK\", \"maxRecords\": 2}" "record"
|
|
77
|
+
|
|
78
|
+
# 8. List webhooks
|
|
79
|
+
test_tool "list_webhooks" "{}" "webhook"
|
|
80
|
+
|
|
81
|
+
# 9. Create webhook
|
|
82
|
+
WEBHOOK_JSON=$(curl -s -X POST http://localhost:8010/mcp \
|
|
83
|
+
-H "Content-Type: application/json" \
|
|
84
|
+
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "create_webhook", "arguments": {"notificationUrl": "https://webhook.site/unique-test-id"}}}')
|
|
85
|
+
|
|
86
|
+
if echo "$WEBHOOK_JSON" | grep -q "Successfully created"; then
|
|
87
|
+
echo "✅ create_webhook: PASSED"
|
|
88
|
+
((PASSED++))
|
|
89
|
+
WEBHOOK_ID=$(echo "$WEBHOOK_JSON" | grep -o 'ach[a-zA-Z0-9]\+' | head -1)
|
|
90
|
+
else
|
|
91
|
+
echo "❌ create_webhook: FAILED"
|
|
92
|
+
((FAILED++))
|
|
93
|
+
WEBHOOK_ID=""
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
# 10. Get webhook payloads
|
|
97
|
+
if [ ! -z "$WEBHOOK_ID" ]; then
|
|
98
|
+
test_tool "get_webhook_payloads" "{\"webhookId\": \"$WEBHOOK_ID\"}" "payload"
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# 11. Refresh webhook
|
|
102
|
+
if [ ! -z "$WEBHOOK_ID" ]; then
|
|
103
|
+
test_tool "refresh_webhook" "{\"webhookId\": \"$WEBHOOK_ID\"}" "refreshed"
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# 12. Delete webhook
|
|
107
|
+
if [ ! -z "$WEBHOOK_ID" ]; then
|
|
108
|
+
test_tool "delete_webhook" "{\"webhookId\": \"$WEBHOOK_ID\"}" "deleted"
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# 13. Delete record (cleanup)
|
|
112
|
+
if [ ! -z "$RECORD_ID" ]; then
|
|
113
|
+
test_tool "delete_record" "{\"table\": \"tblH7TnJxYpNqhQYK\", \"recordId\": \"$RECORD_ID\"}" "Successfully deleted"
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
echo ""
|
|
117
|
+
echo "📊 TEST RESULTS"
|
|
118
|
+
echo "=============="
|
|
119
|
+
echo "✅ Passed: $PASSED"
|
|
120
|
+
echo "❌ Failed: $FAILED"
|
|
121
|
+
echo "📈 Success Rate: $(( PASSED * 100 / (PASSED + FAILED) ))%"
|
|
122
|
+
|
|
123
|
+
if [ $FAILED -eq 0 ]; then
|
|
124
|
+
echo ""
|
|
125
|
+
echo "🎉 ALL TESTS PASSED! Ready for production!"
|
|
126
|
+
exit 0
|
|
127
|
+
else
|
|
128
|
+
echo ""
|
|
129
|
+
echo "⚠️ Some tests failed. Please review before publishing."
|
|
130
|
+
exit 1
|
|
131
|
+
fi
|
package/test_webhooks.sh
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
echo "🪝 TESTING WEBHOOK FUNCTIONALITY"
|
|
4
|
+
echo "================================"
|
|
5
|
+
echo ""
|
|
6
|
+
|
|
7
|
+
# Test 1: List webhooks
|
|
8
|
+
echo "1️⃣ LIST WEBHOOKS"
|
|
9
|
+
echo "-----------------"
|
|
10
|
+
result=$(curl -s -X POST http://localhost:8010/mcp \
|
|
11
|
+
-H "Content-Type: application/json" \
|
|
12
|
+
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": "list_webhooks"}}')
|
|
13
|
+
|
|
14
|
+
if echo "$result" | grep -q "webhook\\|No webhooks"; then
|
|
15
|
+
echo "✅ PASSED: list_webhooks working"
|
|
16
|
+
echo "$result" | python3 -c "import sys, json; print(json.load(sys.stdin)['result']['content'][0]['text'])"
|
|
17
|
+
else
|
|
18
|
+
echo "❌ FAILED: list_webhooks error"
|
|
19
|
+
echo "$result" | python3 -m json.tool
|
|
20
|
+
fi
|
|
21
|
+
echo ""
|
|
22
|
+
|
|
23
|
+
# Test 2: Create webhook
|
|
24
|
+
echo "2️⃣ CREATE WEBHOOK"
|
|
25
|
+
echo "------------------"
|
|
26
|
+
result=$(curl -s -X POST http://localhost:8010/mcp \
|
|
27
|
+
-H "Content-Type: application/json" \
|
|
28
|
+
-d '{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "create_webhook", "arguments": {"notificationUrl": "https://webhook.site/test-webhook"}}}')
|
|
29
|
+
|
|
30
|
+
if echo "$result" | grep -q "Successfully created webhook"; then
|
|
31
|
+
echo "✅ PASSED: create_webhook working"
|
|
32
|
+
# Extract webhook ID
|
|
33
|
+
WEBHOOK_ID=$(echo "$result" | grep -o 'ach[a-zA-Z0-9]*' | head -1)
|
|
34
|
+
echo "Created webhook ID: $WEBHOOK_ID"
|
|
35
|
+
echo "$result" | python3 -c "import sys, json; t=json.load(sys.stdin)['result']['content'][0]['text']; print(t[:300])"
|
|
36
|
+
else
|
|
37
|
+
echo "❌ FAILED: create_webhook error"
|
|
38
|
+
echo "$result" | python3 -m json.tool | head -20
|
|
39
|
+
fi
|
|
40
|
+
echo ""
|
|
41
|
+
|
|
42
|
+
# Test 3: List webhooks again
|
|
43
|
+
echo "3️⃣ VERIFY WEBHOOK CREATED"
|
|
44
|
+
echo "--------------------------"
|
|
45
|
+
result=$(curl -s -X POST http://localhost:8010/mcp \
|
|
46
|
+
-H "Content-Type: application/json" \
|
|
47
|
+
-d '{"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "list_webhooks"}}')
|
|
48
|
+
|
|
49
|
+
if echo "$result" | grep -q "Found.*webhook"; then
|
|
50
|
+
echo "✅ PASSED: Webhook appears in list"
|
|
51
|
+
count=$(echo "$result" | grep -o "ID: ach" | wc -l)
|
|
52
|
+
echo "Total webhooks: $count"
|
|
53
|
+
else
|
|
54
|
+
echo "⚠️ WARNING: No webhooks found"
|
|
55
|
+
fi
|
|
56
|
+
echo ""
|
|
57
|
+
|
|
58
|
+
# Test 4: Get webhook payloads (if webhook exists)
|
|
59
|
+
if [ ! -z "$WEBHOOK_ID" ]; then
|
|
60
|
+
echo "4️⃣ GET WEBHOOK PAYLOADS"
|
|
61
|
+
echo "------------------------"
|
|
62
|
+
result=$(curl -s -X POST http://localhost:8010/mcp \
|
|
63
|
+
-H "Content-Type: application/json" \
|
|
64
|
+
-d "{\"jsonrpc\": \"2.0\", \"id\": 4, \"method\": \"tools/call\", \"params\": {\"name\": \"get_webhook_payloads\", \"arguments\": {\"webhookId\": \"$WEBHOOK_ID\"}}}")
|
|
65
|
+
|
|
66
|
+
if echo "$result" | grep -q "payload\\|No payloads"; then
|
|
67
|
+
echo "✅ PASSED: get_webhook_payloads working"
|
|
68
|
+
else
|
|
69
|
+
echo "❌ FAILED: get_webhook_payloads error"
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# Test 5: Refresh webhook
|
|
73
|
+
echo ""
|
|
74
|
+
echo "5️⃣ REFRESH WEBHOOK"
|
|
75
|
+
echo "-------------------"
|
|
76
|
+
result=$(curl -s -X POST http://localhost:8010/mcp \
|
|
77
|
+
-H "Content-Type: application/json" \
|
|
78
|
+
-d "{\"jsonrpc\": \"2.0\", \"id\": 5, \"method\": \"tools/call\", \"params\": {\"name\": \"refresh_webhook\", \"arguments\": {\"webhookId\": \"$WEBHOOK_ID\"}}}")
|
|
79
|
+
|
|
80
|
+
if echo "$result" | grep -q "Successfully refreshed"; then
|
|
81
|
+
echo "✅ PASSED: refresh_webhook working"
|
|
82
|
+
else
|
|
83
|
+
echo "❌ FAILED: refresh_webhook error"
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# Test 6: Delete webhook
|
|
87
|
+
echo ""
|
|
88
|
+
echo "6️⃣ DELETE WEBHOOK"
|
|
89
|
+
echo "------------------"
|
|
90
|
+
result=$(curl -s -X POST http://localhost:8010/mcp \
|
|
91
|
+
-H "Content-Type: application/json" \
|
|
92
|
+
-d "{\"jsonrpc\": \"2.0\", \"id\": 6, \"method\": \"tools/call\", \"params\": {\"name\": \"delete_webhook\", \"arguments\": {\"webhookId\": \"$WEBHOOK_ID\"}}}")
|
|
93
|
+
|
|
94
|
+
if echo "$result" | grep -q "Successfully deleted"; then
|
|
95
|
+
echo "✅ PASSED: delete_webhook working"
|
|
96
|
+
else
|
|
97
|
+
echo "❌ FAILED: delete_webhook error"
|
|
98
|
+
echo "$result" | python3 -m json.tool | head -20
|
|
99
|
+
fi
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
echo ""
|
|
103
|
+
echo "📊 WEBHOOK TEST SUMMARY"
|
|
104
|
+
echo "======================"
|
|
105
|
+
echo "Webhook operations tested with Airtable API"
|