Build and debug Make.com scenarios with Claude Code or Claude Desktop. Covers blueprint structure, MCP tool safety (context overflow prevention), IML expressions, and working module patterns for HubSpot, Brevo, Discord, and OpenAI. Use when creating automations, debugging "successful" scenarios that produce wrong output, or integrating services through Make.com.
Resources
4Install
npx skillscat add striketheviol/make-com-mastery Install via the SkillsCat registry.
Make.com Mastery
A battle-tested skill for building and debugging Make.com scenarios with AI assistance.
Why This Skill Exists
Make.com's MCP integration is powerful but has hidden gotchas:
scenarios_getcan return 200KB+ blueprints that overflow context windows- Scenarios report "success" while modules silently fail behind error handlers
- IML syntax has unintuitive rules (1-based arrays,
emptyarrayrequirement)
This skill documents patterns learned the hard way so you don't have to.
Quick Start
"Debug my scenario that says success but doesn't work"
→ Remove Ignore error handlers, check actual module errors
"Create a webhook that adds contacts to HubSpot and Brevo"
→ Use upsertAContact (not updateContact), build listIds with emptyarray + add()
"Update my scenario blueprint"
→ Fetch via API to file, modify with Python, PATCH back
Direct API vs MCP Decision Matrix
Default to the Direct API for blueprint modifications. The MCP is great for discovery but risky for complex updates.
| Task | Approach | Why |
|---|---|---|
| Modify blueprints | Direct API | MCP can overflow context; API writes to disk |
| Bulk operations | Direct API | Data stays out of context window |
| Debug failed scenarios | Direct API | Full control over payloads |
| Fetch blueprints | Direct API | Save to file, parse with Python |
| Inspect a scenario | MCP scenarios_get |
OK if used early in conversation only |
| List scenarios/connections | MCP | Quick, low-risk |
| Get module schemas | MCP app-module_get |
Use format=instructions |
| Check execution status | MCP executions_list |
Simple query |
| Discover module names | MCP app-modules_list |
Fastest way |
| Validate module config | MCP validate_module_configuration |
Pre-flight check |
Context Overflow Warning
scenarios_get — Use Early or Use API
scenarios_get returns the full blueprint which can be 200KB+. It works via MCP, but only early in a conversation when context window headroom is large.
Rule of thumb:
- First few messages? MCP
scenarios_getis fine. - Long conversation with many tool calls? Fetch via Direct API and save to disk instead.
MCP Tool Risk Levels
| Tool | Risk | Notes |
|---|---|---|
scenarios_list, connections_list, executions_list |
✅ LOW | Always safe |
app-modules_list, scenarios_interface |
✅ LOW | Always safe |
app-module_get (format=instructions) |
✅ LOW | Always safe |
validate_module_configuration |
✅ LOW | Pre-flight check |
scenarios_get |
⚠️ CONDITIONAL | Safe early; use API later |
executions_get_detail |
⚠️ HIGH | Prefer executions_list |
app-module_get (format=json) |
⚠️ MEDIUM | Use format=instructions |
Blueprint Modification Workflow
1. Fetch blueprint → Direct API: curl ... -o blueprint.json (SAVE TO FILE)
OR early in conversation: MCP scenarios_get
2. Parse with Python → Modify in memory/disk (NOT in context)
3. Validate → MCP validate_module_configuration
4. Deactivate → MCP scenarios_deactivate (or API /stop)
5. Update → MCP scenarios_update (or API PATCH)
6. Activate → MCP scenarios_activate (or API /start)
7. Test → Trigger webhook / run scenario
8. Check executions → MCP executions_listBlueprint Structure Essentials
{
"flow": [
{
"id": 1,
"mapper": {},
"module": "app:ModuleName",
"version": 1,
"metadata": {"designer": {"x": 0, "y": 0}},
"parameters": {"__IMTCONN__": YOUR_CONNECTION_ID}
}
],
"name": "Scenario Name",
"metadata": {
"instant": false, "version": 1,
"designer": {"orphans": []},
"scenario": {"dlq": false, "dataloss": false, "maxErrors": 3, "autoCommit": true, "sequential": false}
}
}Key rules:
- parameters: Static config (connection IDs). No IML expressions allowed.
- mapper: Dynamic values. IML expressions go here.
- Scenario inputs: Use
{{var.input.fieldname}}— never{{1.fieldname}}. - Interface spec: Only
nameandtypeproperties allowed.
Debugging "Successful" Scenarios
The Golden Rule: Ignore Handlers Mask Errors
A scenario can show status: 1 (SUCCESS) while modules silently fail. Error handlers like builtin:Ignore hide actual problems.
Debugging Workflow
1. Check execution status → executions_list(scenarioId)
2. If status=1 but wrong output → Error handlers are hiding failures
3. Remove Ignore handlers → Update blueprint with onerror:[] removed
4. Trigger test data → Run the scenario
5. Check execution again → Now status=3 with actual error
6. Read the error message → [405], [400], validation errors, etc.
7. Fix root cause → See Common Error Patterns
8. Re-add Ignore handlers → Restore error handling once fixedCommon Error Patterns
| Error | Likely Cause | Fix |
|---|---|---|
[405] on HubSpot update |
updateContact is finicky |
Use upsertAContact instead |
[400] Property values not valid |
Enum value mismatch | Check contains() transforms |
| JSON blob in text field | Wrong array access syntax | Use [1] indexing, not first().nested |
listIds/0 should be type number |
split() for numeric array |
Use add(emptyarray; N) pattern |
'6' is not a valid array |
add() without emptyarray |
Start with add(emptyarray; 6) |
BlueprintValidationError |
Wrong input variable syntax | Use {{var.input.x}} |
Common Pitfalls (Quick Reference)
- Array indexing is 1-based:
[1]for first element, not[0] - Nested access: Use
{{6.choices[1].message.content}}notfirst().nested - Ignore handlers hide errors: Remove them to debug
- updateContact is unreliable: Use
upsertAContact - Module names are case-sensitive: Verify with
app-modules_list - No IML in parameters: Never use
{{...}}in parameters block - Scenario input syntax:
{{var.input.fieldname}} - Interface spec: Only
nameandtypeproperties - Numeric arrays need emptyarray:
add(emptyarray; N)pattern - split() returns strings: Use
emptyarray + add()for numbers
Reference Files
Load these as needed based on the task:
- references/api-reference.md: Direct API commands, auth, Python patterns
- references/iml-reference.md: IML functions, array building, indexing
- references/module-patterns.md: Working configs for Brevo, HubSpot, OpenAI, Discord
Examples
Example 1: Webhook → HubSpot + Brevo
User: "Create a webhook that captures form data, adds to HubSpot, and subscribes to Brevo list 6"
Claude: I'll create this scenario. Key patterns:
- Webhook trigger (builtin:BasicWebhook)
- HubSpot upsertAContact (not updateContact)
- Brevo CreateContact with listIds: {{add(emptyarray; 6)}}Example 2: Debug Silent Failure
User: "My scenario shows success but the HubSpot contact isn't updating"
Claude: This is usually an Ignore handler masking errors. Let me:
1. Fetch the blueprint via API
2. Find modules with onerror: [{"handler": "builtin:Ignore"}]
3. Temporarily remove them
4. Re-run to see the actual errorExample 3: AI Research Bot
User: "Build a scenario that takes a company name and enriches the contact with research"
Claude: I'll use:
- Scenario inputs (interface) for company name
- OpenAI/Perplexity module for research
- Access response with {{3.choices[1].message.content}} (1-based!)
- HubSpot upsertAContact to save findingsLicense
MIT — Use freely, attribution appreciated.