make-mcp-server 1.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/.env.example +10 -0
- package/LICENSE +21 -0
- package/README.md +334 -0
- package/bin/make-mcp.js +78 -0
- package/bin/postinstall.js +33 -0
- package/data/make-modules.db +0 -0
- package/dist/database/db.d.ts +15 -0
- package/dist/database/db.d.ts.map +1 -0
- package/dist/database/db.js +135 -0
- package/dist/database/db.js.map +1 -0
- package/dist/database/schema.sql +42 -0
- package/dist/mcp/server.d.ts +16 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +551 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/scrapers/scrape-modules.d.ts +18 -0
- package/dist/scrapers/scrape-modules.d.ts.map +1 -0
- package/dist/scrapers/scrape-modules.js +407 -0
- package/dist/scrapers/scrape-modules.js.map +1 -0
- package/dist/utils/logger.d.ts +17 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +55 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +71 -0
- package/scripts/build.js +41 -0
- package/scripts/prepublish.js +42 -0
- package/src/database/schema.sql +42 -0
package/.env.example
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Make.com API credentials (optional โ only needed for deployment)
|
|
2
|
+
MAKE_API_KEY=your_api_key_here
|
|
3
|
+
MAKE_API_URL=https://eu1.make.com/api/v2
|
|
4
|
+
MAKE_TEAM_ID=your_team_id
|
|
5
|
+
|
|
6
|
+
# Database (defaults to <package>/data/make-modules.db โ usually not needed)
|
|
7
|
+
# DATABASE_PATH=./data/make-modules.db
|
|
8
|
+
|
|
9
|
+
# Logging (debug, info, warn, error, silent)
|
|
10
|
+
LOG_LEVEL=info
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Daniel Shashko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
# make-mcp-server
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/make-mcp-server)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
A Model Context Protocol (MCP) server that provides AI assistants with comprehensive access to Make.com module documentation, scenario building, and deployment. Deploy in minutes to give Claude, Copilot, and other AI assistants deep knowledge about Make.com's 200+ automation modules across 40+ apps.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **๐ 200+ Modules** โ Full-text search across 200+ Make.com modules (Slack, Gmail, Google Sheets, Notion, OpenAI, and 35+ more apps)
|
|
11
|
+
- **๐ Module Details** โ Retrieve parameters, types, descriptions, and usage docs for any module
|
|
12
|
+
- **โ
Blueprint Validation** โ Check scenarios for missing parameters, unknown modules, and structural issues before deploying
|
|
13
|
+
- **๐ Deploy to Make.com** โ Push validated blueprints directly to Make.com via API
|
|
14
|
+
- **๐ Scenario Templates** โ Browse reusable scenario templates for common workflows
|
|
15
|
+
- **๐ Guided Prompts** โ MCP prompts for guided scenario building and module exploration
|
|
16
|
+
- **๐ Resource Catalog** โ MCP resources for browsing available apps
|
|
17
|
+
- **๐งช 42 Tests** โ Unit + integration test suite with Vitest
|
|
18
|
+
- **โก Fast Response** โ Optimized SQLite with FTS5 full-text search
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## ๐ Quick Start โ Self-Hosting Options
|
|
23
|
+
|
|
24
|
+
### Option A: npx (No Installation Needed!) ๐
|
|
25
|
+
|
|
26
|
+
The fastest way to get started โ no cloning, no building:
|
|
27
|
+
|
|
28
|
+
**Prerequisites:** [Node.js](https://nodejs.org/) installed on your system
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Run directly โ no installation needed!
|
|
32
|
+
npx make-mcp-server
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The package includes a pre-built database with all 200+ Make.com modules. Just add it to your MCP client config and go.
|
|
36
|
+
|
|
37
|
+
**Claude Desktop config** (`claude_desktop_config.json`):
|
|
38
|
+
|
|
39
|
+
Basic configuration (documentation tools only):
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"make-mcp-server": {
|
|
45
|
+
"command": "npx",
|
|
46
|
+
"args": ["make-mcp-server"],
|
|
47
|
+
"env": {
|
|
48
|
+
"LOG_LEVEL": "error"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Full configuration (with Make.com deployment):
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"mcpServers": {
|
|
60
|
+
"make-mcp-server": {
|
|
61
|
+
"command": "npx",
|
|
62
|
+
"args": ["make-mcp-server"],
|
|
63
|
+
"env": {
|
|
64
|
+
"LOG_LEVEL": "error",
|
|
65
|
+
"MAKE_API_KEY": "your_api_key_here",
|
|
66
|
+
"MAKE_TEAM_ID": "your_team_id",
|
|
67
|
+
"MAKE_API_URL": "https://eu1.make.com/api/v2"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
> **Note:** npx will download and cache the latest version automatically. The package includes a pre-built database with all Make.com module information โ no setup required.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### Option B: Docker (Isolated & Reproducible) ๐ณ
|
|
79
|
+
|
|
80
|
+
**Prerequisites:** Docker installed on your system
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Build the Docker image
|
|
84
|
+
docker build -t make-mcp-server .
|
|
85
|
+
|
|
86
|
+
# Test it works
|
|
87
|
+
echo '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1"}},"id":1}' | docker run -i --rm make-mcp-server
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Claude Desktop config:**
|
|
91
|
+
|
|
92
|
+
Basic configuration (documentation tools only):
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"mcpServers": {
|
|
97
|
+
"make-mcp-server": {
|
|
98
|
+
"command": "docker",
|
|
99
|
+
"args": [
|
|
100
|
+
"run", "-i", "--rm", "--init",
|
|
101
|
+
"-e", "LOG_LEVEL=error",
|
|
102
|
+
"make-mcp-server"
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Full configuration (with Make.com deployment):
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"mcpServers": {
|
|
114
|
+
"make-mcp-server": {
|
|
115
|
+
"command": "docker",
|
|
116
|
+
"args": [
|
|
117
|
+
"run", "-i", "--rm", "--init",
|
|
118
|
+
"-e", "LOG_LEVEL=error",
|
|
119
|
+
"-e", "MAKE_API_KEY=your_api_key_here",
|
|
120
|
+
"-e", "MAKE_TEAM_ID=your_team_id",
|
|
121
|
+
"-e", "MAKE_API_URL=https://eu1.make.com/api/v2",
|
|
122
|
+
"make-mcp-server"
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
> **Important:** The `-i` flag is required for MCP stdio communication.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### Option C: Local Installation (For Development) ๐ ๏ธ
|
|
134
|
+
|
|
135
|
+
**Prerequisites:** [Node.js](https://nodejs.org/) and Git
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# 1. Clone and install
|
|
139
|
+
git clone https://github.com/danishashko/make-mcp.git
|
|
140
|
+
cd make-mcp
|
|
141
|
+
npm install
|
|
142
|
+
|
|
143
|
+
# 2. Build
|
|
144
|
+
npm run build
|
|
145
|
+
|
|
146
|
+
# 3. Populate the module database (already done if using npm package)
|
|
147
|
+
npm run scrape:prod
|
|
148
|
+
|
|
149
|
+
# 4. Test it works
|
|
150
|
+
npm start
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Claude Desktop config:**
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"mcpServers": {
|
|
158
|
+
"make-mcp-server": {
|
|
159
|
+
"command": "node",
|
|
160
|
+
"args": ["/absolute/path/to/make-mcp/dist/mcp/server.js"],
|
|
161
|
+
"env": {
|
|
162
|
+
"LOG_LEVEL": "error",
|
|
163
|
+
"MAKE_API_KEY": "your_api_key_here",
|
|
164
|
+
"MAKE_TEAM_ID": "your_team_id"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
> **Note:** The Make.com API credentials are optional. Without them, you'll have access to all documentation, search, and validation tools. With them, you'll additionally get scenario deployment capabilities.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### Configuration File Locations
|
|
176
|
+
|
|
177
|
+
| Platform | Path |
|
|
178
|
+
|----------|------|
|
|
179
|
+
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
|
|
180
|
+
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
|
|
181
|
+
| Linux | `~/.config/Claude/claude_desktop_config.json` |
|
|
182
|
+
|
|
183
|
+
**Restart Claude Desktop after updating configuration.**
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
### ๐ป Connect Your IDE
|
|
188
|
+
|
|
189
|
+
make-mcp-server works with any MCP-compatible client:
|
|
190
|
+
|
|
191
|
+
- **Claude Desktop** โ See configurations above
|
|
192
|
+
- **VS Code (GitHub Copilot)** โ Add to `.vscode/mcp.json`
|
|
193
|
+
- **Cursor** โ Add to MCP settings
|
|
194
|
+
- **Claude Code** โ Use `claude mcp add` command
|
|
195
|
+
- **Windsurf** โ Add to MCP configuration
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Usage
|
|
200
|
+
|
|
201
|
+
Then ask your AI assistant things like:
|
|
202
|
+
|
|
203
|
+
> "Create a Make scenario that watches a Slack channel for new messages and logs them to a Google Sheet"
|
|
204
|
+
|
|
205
|
+
> "What modules does Make have for sending emails?"
|
|
206
|
+
|
|
207
|
+
> "Validate this scenario blueprint..."
|
|
208
|
+
|
|
209
|
+
**Tip:** The AI will automatically call `tools_documentation` first to understand how to use the server effectively.
|
|
210
|
+
|
|
211
|
+
## Available Tools
|
|
212
|
+
|
|
213
|
+
| Tool | Description |
|
|
214
|
+
|------|-------------|
|
|
215
|
+
| `tools_documentation` | **START HERE** โ Returns comprehensive documentation for all tools, prompts, and resources |
|
|
216
|
+
| `search_modules` | Full-text search across 200+ Make.com modules |
|
|
217
|
+
| `get_module` | Get detailed module info with parameters and docs |
|
|
218
|
+
| `validate_scenario` | Validate a scenario blueprint before deployment |
|
|
219
|
+
| `create_scenario` | Deploy a scenario to Make.com via API |
|
|
220
|
+
| `search_templates` | Search reusable scenario templates |
|
|
221
|
+
| `list_apps` | List all apps with module counts |
|
|
222
|
+
|
|
223
|
+
## MCP Prompts
|
|
224
|
+
|
|
225
|
+
| Prompt | Description |
|
|
226
|
+
|--------|-------------|
|
|
227
|
+
| `build_scenario` | Guided workflow for creating a Make.com scenario from a natural language description |
|
|
228
|
+
| `explain_module` | Get a detailed explanation of any Make.com module with usage examples |
|
|
229
|
+
|
|
230
|
+
## MCP Resources
|
|
231
|
+
|
|
232
|
+
| Resource URI | Description |
|
|
233
|
+
|-------------|-------------|
|
|
234
|
+
| `make://apps` | List of all available apps with module counts |
|
|
235
|
+
|
|
236
|
+
## CLI Usage
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
make-mcp-server # Start the MCP server (stdio transport)
|
|
240
|
+
make-mcp-server --scrape # Populate/refresh the module database
|
|
241
|
+
make-mcp-server --version # Print version
|
|
242
|
+
make-mcp-server --help # Show help
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Environment Variables
|
|
246
|
+
|
|
247
|
+
| Variable | Required | Default | Description |
|
|
248
|
+
|----------|----------|---------|-------------|
|
|
249
|
+
| `MAKE_API_KEY` | For deployment | โ | Make.com API key |
|
|
250
|
+
| `MAKE_API_URL` | No | `https://eu1.make.com/api/v2` | Make.com API base URL |
|
|
251
|
+
| `MAKE_TEAM_ID` | For deployment | โ | Default team ID for scenario deployment |
|
|
252
|
+
| `DATABASE_PATH` | No | `<package>/data/make-modules.db` | SQLite database file path |
|
|
253
|
+
| `LOG_LEVEL` | No | `info` | Logging level: `debug`, `info`, `warn`, `error`, `silent` |
|
|
254
|
+
|
|
255
|
+
## Development
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
npm run build # Compile TypeScript + copy schema + add shebang
|
|
259
|
+
npm run build:tsc # TypeScript only (no packaging)
|
|
260
|
+
npm run start:dev # Start with tsx (no build needed)
|
|
261
|
+
npm run dev # Start with file watching
|
|
262
|
+
npm run scrape # Populate DB with tsx (dev)
|
|
263
|
+
npm run scrape:prod # Populate DB from compiled JS
|
|
264
|
+
npm test # Run all 42 tests
|
|
265
|
+
npm run test:watch # Run tests in watch mode
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Publishing to npm
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
npm run prepublishOnly # Build + populate DB + verify (runs automatically on npm publish)
|
|
272
|
+
npm publish # Publish to npm registry
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Testing
|
|
276
|
+
|
|
277
|
+
The test suite includes 42 tests across 3 files:
|
|
278
|
+
|
|
279
|
+
- **Database tests** (14 tests) โ Insert, search, template operations, FTS5 queries
|
|
280
|
+
- **Logger tests** (7 tests) โ Stderr-only output, log levels, data serialization
|
|
281
|
+
- **Server integration tests** (21 tests) โ Full MCP protocol compliance via SDK client
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
npm test
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Architecture
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
src/
|
|
291
|
+
โโโ mcp/
|
|
292
|
+
โ โโโ server.ts # MCP server with tools, prompts, resources
|
|
293
|
+
โโโ database/
|
|
294
|
+
โ โโโ schema.sql # SQLite + FTS5 schema
|
|
295
|
+
โ โโโ db.ts # Database access layer (npx-safe path resolution)
|
|
296
|
+
โโโ scrapers/
|
|
297
|
+
โ โโโ scrape-modules.ts # Module data population (224 modules)
|
|
298
|
+
โโโ utils/
|
|
299
|
+
โโโ logger.ts # Structured stderr-only logger
|
|
300
|
+
bin/
|
|
301
|
+
โโโ make-mcp.js # CLI entry point (npx, --help, --version, --scrape)
|
|
302
|
+
โโโ postinstall.js # Post-install verification
|
|
303
|
+
scripts/
|
|
304
|
+
โโโ build.js # Build: tsc + copy schema + add shebang
|
|
305
|
+
โโโ prepublish.js # Publish prep: build + populate DB + verify
|
|
306
|
+
data/
|
|
307
|
+
โโโ make-modules.db # Pre-built SQLite database (bundled in npm package)
|
|
308
|
+
tests/
|
|
309
|
+
โโโ database.test.ts # Database unit tests (14)
|
|
310
|
+
โโโ logger.test.ts # Logger unit tests (7)
|
|
311
|
+
โโโ server.test.ts # MCP integration tests (21)
|
|
312
|
+
Dockerfile # Multi-stage Docker image
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Tech Stack
|
|
316
|
+
|
|
317
|
+
- **TypeScript** + **Node.js** (ESM)
|
|
318
|
+
- **@modelcontextprotocol/sdk** v1.26.0 โ MCP protocol implementation
|
|
319
|
+
- **better-sqlite3** โ Synchronous SQLite with FTS5 full-text search
|
|
320
|
+
- **zod** โ Schema validation for tool parameters
|
|
321
|
+
- **axios** โ HTTP client for Make.com API
|
|
322
|
+
- **vitest** โ Test framework
|
|
323
|
+
|
|
324
|
+
## Supported Apps (40+)
|
|
325
|
+
|
|
326
|
+
Google Sheets, Slack, OpenAI, Google Drive, Notion, Telegram Bot, HubSpot CRM, Gmail, Airtable, Tools, Flow Control, Google Calendar, Jira, Trello, Shopify, Google Docs, Microsoft Teams, Microsoft Outlook, Discord, Asana, monday.com, Salesforce, Stripe, GitHub, HTTP, Mailchimp, WordPress, Dropbox, Data Store, JSON, Twilio, Google Gemini AI, WhatsApp Business, Text Parser, Webhooks, Anthropic Claude, CSV, RSS, Email, Schedule
|
|
327
|
+
|
|
328
|
+
## Author
|
|
329
|
+
|
|
330
|
+
Built by **[Daniel Shashko](https://www.linkedin.com/in/daniel-shashko/)**
|
|
331
|
+
|
|
332
|
+
## License
|
|
333
|
+
|
|
334
|
+
MIT License โ see [LICENSE](LICENSE) for details.
|
package/bin/make-mcp.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* make-mcp-server CLI entry point
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx make-mcp-server โ Start MCP server on stdio
|
|
8
|
+
* npx make-mcp-server --scrape โ Populate/refresh the module database
|
|
9
|
+
* npx make-mcp-server --version โ Print version
|
|
10
|
+
* npx make-mcp-server --help โ Show help
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
import fs from 'fs';
|
|
16
|
+
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname = path.dirname(__filename);
|
|
19
|
+
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
|
|
22
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
23
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
24
|
+
process.stderr.write(`make-mcp-server v${pkg.version}\n`);
|
|
25
|
+
process.exit(0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
29
|
+
process.stderr.write(`
|
|
30
|
+
make-mcp-server โ MCP server for Make.com automation scenarios
|
|
31
|
+
|
|
32
|
+
Usage:
|
|
33
|
+
make-mcp-server Start the MCP server (stdio transport)
|
|
34
|
+
make-mcp-server --scrape Populate/refresh the module database
|
|
35
|
+
make-mcp-server --version Print version
|
|
36
|
+
make-mcp-server --help Show this help
|
|
37
|
+
|
|
38
|
+
Environment Variables:
|
|
39
|
+
MAKE_API_KEY Make.com API key (required for deployment)
|
|
40
|
+
MAKE_API_URL Make.com API base URL (default: https://eu1.make.com/api/v2)
|
|
41
|
+
MAKE_TEAM_ID Default team ID for scenario deployment
|
|
42
|
+
DATABASE_PATH SQLite database path (default: ./data/make-modules.db)
|
|
43
|
+
LOG_LEVEL Logging level: debug, info, warn, error, silent (default: info)
|
|
44
|
+
|
|
45
|
+
Claude Desktop Config:
|
|
46
|
+
{
|
|
47
|
+
"mcpServers": {
|
|
48
|
+
"make-mcp-server": {
|
|
49
|
+
"command": "npx",
|
|
50
|
+
"args": ["make-mcp-server"],
|
|
51
|
+
"env": {
|
|
52
|
+
"MAKE_API_KEY": "your_api_key_here",
|
|
53
|
+
"MAKE_TEAM_ID": "your_team_id"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
`);
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (args.includes('--scrape')) {
|
|
63
|
+
// Dynamic import of scraper
|
|
64
|
+
const scraperPath = path.join(__dirname, '..', 'dist', 'scrapers', 'scrape-modules.js');
|
|
65
|
+
if (!fs.existsSync(scraperPath)) {
|
|
66
|
+
process.stderr.write('Error: Build the project first with `npm run build`\n');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
await import(pathToFileURL(scraperPath).href);
|
|
70
|
+
} else {
|
|
71
|
+
// Start MCP server
|
|
72
|
+
const serverPath = path.join(__dirname, '..', 'dist', 'mcp', 'server.js');
|
|
73
|
+
if (!fs.existsSync(serverPath)) {
|
|
74
|
+
process.stderr.write('Error: Build the project first with `npm run build`\n');
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
await import(pathToFileURL(serverPath).href);
|
|
78
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postinstall script โ verifies database exists.
|
|
3
|
+
*
|
|
4
|
+
* When installed from npm, the pre-built database is bundled in data/make-modules.db.
|
|
5
|
+
* This script just ensures the data directory and DB file are present.
|
|
6
|
+
* If missing (dev/clone scenario), it tells the user how to populate it.
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
15
|
+
|
|
16
|
+
const dataDir = path.join(ROOT, 'data');
|
|
17
|
+
const dbPath = path.join(dataDir, 'make-modules.db');
|
|
18
|
+
|
|
19
|
+
// Ensure data directory exists
|
|
20
|
+
if (!fs.existsSync(dataDir)) {
|
|
21
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (fs.existsSync(dbPath)) {
|
|
25
|
+
const stats = fs.statSync(dbPath);
|
|
26
|
+
process.stderr.write(`[make-mcp-server] โ
Database ready (${(stats.size / 1024).toFixed(0)} KB)\n`);
|
|
27
|
+
} else {
|
|
28
|
+
process.stderr.write(
|
|
29
|
+
'[make-mcp-server] โ ๏ธ Database not found. If you cloned from source, run:\n' +
|
|
30
|
+
' npm run build && npm run scrape:prod\n' +
|
|
31
|
+
' to populate the module database.\n'
|
|
32
|
+
);
|
|
33
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class MakeDatabase {
|
|
2
|
+
private db;
|
|
3
|
+
constructor(dbPath?: string);
|
|
4
|
+
private initializeSchema;
|
|
5
|
+
searchModules(query: string, app?: string): any[];
|
|
6
|
+
getModule(moduleId: string): any;
|
|
7
|
+
getModuleExamples(moduleId: string, limit?: number): any[];
|
|
8
|
+
insertModule(module: any): void;
|
|
9
|
+
insertModules(modules: any[]): void;
|
|
10
|
+
searchTemplates(query?: string, category?: string): any[];
|
|
11
|
+
getTemplate(templateId: string): any;
|
|
12
|
+
insertTemplate(template: any): void;
|
|
13
|
+
close(): void;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/database/db.ts"],"names":[],"mappings":"AAuCA,qBAAa,YAAY;IACrB,OAAO,CAAC,EAAE,CAAoB;gBAElB,MAAM,CAAC,EAAE,MAAM;IAY3B,OAAO,CAAC,gBAAgB;IAMxB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE;IA+BjD,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG;IAIhC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,GAAG,EAAE;IAS7D,YAAY,CAAC,MAAM,EAAE,GAAG;IA4BxB,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE;IAS5B,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE;IAkBzD,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG;IAIpC,cAAc,CAAC,QAAQ,EAAE,GAAG;IAe5B,KAAK;CAGR"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
// Resolve paths relative to the package root (works with npx, global install, local)
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
// From src/database/ or dist/database/ โ package root
|
|
9
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..', '..');
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the database path.
|
|
12
|
+
* - Explicit path โ use as-is
|
|
13
|
+
* - Default โ <packageRoot>/data/make-modules.db
|
|
14
|
+
*/
|
|
15
|
+
function resolveDbPath(dbPath) {
|
|
16
|
+
if (dbPath && dbPath !== './data/make-modules.db') {
|
|
17
|
+
return path.resolve(dbPath);
|
|
18
|
+
}
|
|
19
|
+
return path.join(PACKAGE_ROOT, 'data', 'make-modules.db');
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Locate schema.sql โ check src/ first (dev), then fall back to dist/ (npm package).
|
|
23
|
+
*/
|
|
24
|
+
function resolveSchemaPath() {
|
|
25
|
+
const srcPath = path.join(PACKAGE_ROOT, 'src', 'database', 'schema.sql');
|
|
26
|
+
if (fs.existsSync(srcPath))
|
|
27
|
+
return srcPath;
|
|
28
|
+
// Bundled fallback: schema.sql shipped alongside compiled JS
|
|
29
|
+
const distPath = path.join(__dirname, 'schema.sql');
|
|
30
|
+
if (fs.existsSync(distPath))
|
|
31
|
+
return distPath;
|
|
32
|
+
throw new Error(`schema.sql not found. Searched:\n - ${srcPath}\n - ${distPath}`);
|
|
33
|
+
}
|
|
34
|
+
export class MakeDatabase {
|
|
35
|
+
db;
|
|
36
|
+
constructor(dbPath) {
|
|
37
|
+
const resolved = resolveDbPath(dbPath);
|
|
38
|
+
const dir = path.dirname(resolved);
|
|
39
|
+
if (!fs.existsSync(dir)) {
|
|
40
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
this.db = new Database(resolved);
|
|
43
|
+
this.db.pragma('journal_mode = WAL');
|
|
44
|
+
this.initializeSchema();
|
|
45
|
+
}
|
|
46
|
+
initializeSchema() {
|
|
47
|
+
const schemaPath = resolveSchemaPath();
|
|
48
|
+
const schema = fs.readFileSync(schemaPath, 'utf-8');
|
|
49
|
+
this.db.exec(schema);
|
|
50
|
+
}
|
|
51
|
+
searchModules(query, app) {
|
|
52
|
+
// Handle "list all" wildcard case
|
|
53
|
+
if (query === '*') {
|
|
54
|
+
let sql = 'SELECT * FROM modules';
|
|
55
|
+
const params = [];
|
|
56
|
+
if (app) {
|
|
57
|
+
sql += ' WHERE app = ?';
|
|
58
|
+
params.push(app);
|
|
59
|
+
}
|
|
60
|
+
sql += ' ORDER BY app, name LIMIT 500';
|
|
61
|
+
return this.db.prepare(sql).all(...params);
|
|
62
|
+
}
|
|
63
|
+
// Use FTS5 search with the standalone FTS table
|
|
64
|
+
let sql = `
|
|
65
|
+
SELECT m.* FROM modules m
|
|
66
|
+
WHERE m.id IN (
|
|
67
|
+
SELECT module_id FROM modules_fts WHERE modules_fts MATCH ?
|
|
68
|
+
)
|
|
69
|
+
`;
|
|
70
|
+
const params = [query];
|
|
71
|
+
if (app) {
|
|
72
|
+
sql += ' AND m.app = ?';
|
|
73
|
+
params.push(app);
|
|
74
|
+
}
|
|
75
|
+
sql += ' LIMIT 20';
|
|
76
|
+
return this.db.prepare(sql).all(...params);
|
|
77
|
+
}
|
|
78
|
+
getModule(moduleId) {
|
|
79
|
+
return this.db.prepare('SELECT * FROM modules WHERE id = ?').get(moduleId);
|
|
80
|
+
}
|
|
81
|
+
getModuleExamples(moduleId, limit = 5) {
|
|
82
|
+
return this.db.prepare(`
|
|
83
|
+
SELECT * FROM examples
|
|
84
|
+
WHERE module_id = ?
|
|
85
|
+
ORDER BY id DESC
|
|
86
|
+
LIMIT ?
|
|
87
|
+
`).all(moduleId, limit);
|
|
88
|
+
}
|
|
89
|
+
insertModule(module) {
|
|
90
|
+
// Use INSERT OR REPLACE so re-runs don't fail
|
|
91
|
+
const stmt = this.db.prepare(`
|
|
92
|
+
INSERT OR REPLACE INTO modules (id, name, app, type, description, parameters, examples, documentation)
|
|
93
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
94
|
+
`);
|
|
95
|
+
stmt.run(module.id, module.name, module.app, module.type, module.description, JSON.stringify(module.parameters), JSON.stringify(module.examples || []), module.documentation || '');
|
|
96
|
+
// Delete old FTS entry if exists, then insert new one
|
|
97
|
+
this.db.prepare('DELETE FROM modules_fts WHERE module_id = ?').run(module.id);
|
|
98
|
+
this.db.prepare('INSERT INTO modules_fts(module_id, name, app, description) VALUES (?, ?, ?, ?)').run(module.id, module.name, module.app, module.description);
|
|
99
|
+
}
|
|
100
|
+
insertModules(modules) {
|
|
101
|
+
const insertMany = this.db.transaction((mods) => {
|
|
102
|
+
for (const mod of mods) {
|
|
103
|
+
this.insertModule(mod);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
insertMany(modules);
|
|
107
|
+
}
|
|
108
|
+
searchTemplates(query, category) {
|
|
109
|
+
let sql = 'SELECT * FROM templates WHERE 1=1';
|
|
110
|
+
const params = [];
|
|
111
|
+
if (query) {
|
|
112
|
+
sql += ' AND (name LIKE ? OR description LIKE ?)';
|
|
113
|
+
params.push(`%${query}%`, `%${query}%`);
|
|
114
|
+
}
|
|
115
|
+
if (category) {
|
|
116
|
+
sql += ' AND category = ?';
|
|
117
|
+
params.push(category);
|
|
118
|
+
}
|
|
119
|
+
sql += ' LIMIT 50';
|
|
120
|
+
return this.db.prepare(sql).all(...params);
|
|
121
|
+
}
|
|
122
|
+
getTemplate(templateId) {
|
|
123
|
+
return this.db.prepare('SELECT * FROM templates WHERE id = ?').get(templateId);
|
|
124
|
+
}
|
|
125
|
+
insertTemplate(template) {
|
|
126
|
+
this.db.prepare(`
|
|
127
|
+
INSERT OR REPLACE INTO templates (id, name, description, blueprint, modules_used, category, difficulty)
|
|
128
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
129
|
+
`).run(template.id, template.name, template.description, JSON.stringify(template.blueprint), JSON.stringify(template.modules_used || []), template.category || 'general', template.difficulty || 'beginner');
|
|
130
|
+
}
|
|
131
|
+
close() {
|
|
132
|
+
this.db.close();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/database/db.ts"],"names":[],"mappings":"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"}
|