Skip to main content
Glama
index_20250401204237.ts11.9 kB
// MCP Server for Make.com with full tool implementations import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, ToolSchema, } from "@modelcontextprotocol/sdk/types.js"; import { z } from "zod"; import { zodToJsonSchema } from "zod-to-json-schema"; const MAKE_API_KEY = process.env.MAKE_DOT_COM_API_KEY!; const MAKE_BASE_URL = process.env.MAKE_DOT_COM_BASE_URL || "eu2.make.com"; const MAKE_TEAM_ID = process.env.MAKE_DOT_COM_TEAM_ID; if (!MAKE_API_KEY || !MAKE_TEAM_ID) { throw new Error("Missing Make.com credentials or team ID"); } function makeHeaders() { return { Authorization: `Token ${MAKE_API_KEY}`, "Content-Type": "application/json", Accept: "application/json", }; } // ========== Zod Schemas ========== const ScenarioIdSchema = z.object({ scenario_id: z.number(), draft: z.boolean().optional().default(false), }); const CreateScenarioSchema = z.object({ name: z.string(), folderId: z.number().optional(), description: z.string().optional(), }); const UpdateScenarioSchema = z.object({ scenario_id: z.number(), name: z.string().optional(), description: z.string().optional(), }); const DescribeModuleSchema = z.object({ scenario_id: z.number(), module_id: z.number(), draft: z.boolean().optional().default(false), }); const UpdateScenarioInterfaceArgsSchema = z.object({ scenario_id: z.number(), inputs: z.array( z.object({ name: z.string(), type: z.string(), label: z.string().optional(), required: z.boolean().optional(), multiline: z.boolean().optional(), default: z.union([z.string(), z.number(), z.boolean(), z.null()]).optional(), }) ), }); const CheckModuleSchema = z.object({ scenario_id: z.number(), module_id: z.number(), draft: z.boolean().optional().default(false), }); // Add PatchModuleInBlueprintSchema const PatchModuleInBlueprintSchema = z.object({ scenario_id: z.number().describe("ID of the Make.com scenario to patch"), module_id: z.number().describe("ID of the module in the blueprint to update"), draft: z.boolean().optional().default(false).describe("Update the draft version if true"), updates: z.object({ parameters: z.record(z.unknown()).optional().describe("Parameters to merge into existing ones"), mapper: z.record(z.unknown()).optional().describe("Mapper to merge into existing ones"), metadata: z.record(z.unknown()).optional().describe("Metadata to merge into existing ones") }).describe("Patch object with parameters, mapper or metadata") }); // ========== Server ========== const server = new Server( { name: "mcp-server-make-dot-com", version: "1.0.0" }, { capabilities: { tools: {} } } ); // ========== Tool List ========== const tools = [ { name: "read_make_dot_com_scenario_blueprint", description: "Retrieve blueprint for a scenario", inputSchema: zodToJsonSchema(ScenarioIdSchema), }, { name: "create_make_dot_com_scenario", description: "Create a new Make.com scenario", inputSchema: zodToJsonSchema(CreateScenarioSchema), }, { name: "update_make_dot_com_scenario", description: "Update an existing Make.com scenario", inputSchema: zodToJsonSchema(UpdateScenarioSchema), }, { name: "describe_make_dot_com_module", description: "Describe module parameters from blueprint", inputSchema: zodToJsonSchema(DescribeModuleSchema), }, { name: "update_make_dot_com_scenario_interface", description: "Updates the input interface (form fields) for a scenario using Make's on-demand input feature.", inputSchema: zodToJsonSchema(UpdateScenarioInterfaceArgsSchema), }, { name: "check_make_dot_com_module_data", description: "Check if module required fields are filled", inputSchema: zodToJsonSchema(CheckModuleSchema), }, { name: "list_make_dot_com_scenarios", description: "List available Make.com scenarios", inputSchema: { type: "object", properties: {}, required: [] }, }, { name: "list_make_dot_com_connections", description: "List Make.com connections and their validity", inputSchema: { type: "object", properties: {}, required: [] }, }, // Add new tool definition { name: "patch_make_dot_com_module_in_blueprint", description: "Patches a module's configuration inside a Make.com scenario blueprint. Supports parameters, mapper, and metadata updates.", inputSchema: zodToJsonSchema(PatchModuleInBlueprintSchema) as any, }, ]; // Add patchModuleInBlueprint function async function patchModuleInBlueprint(args: z.infer<typeof PatchModuleInBlueprintSchema>, apiKey: string, baseUrl: string, teamId: string): Promise<string> { const { scenario_id, module_id, updates, draft } = args; const blueprintUrl = `https://${baseUrl}/api/v2/scenarios/${scenario_id}/blueprint?includeDraft=${draft}&teamId=${teamId}`; const res = await fetch(blueprintUrl, { headers: { Authorization: `Token ${apiKey}`, "Content-Type": "application/json", Accept: "application/json" } }); if (!res.ok) { throw new Error(`Failed to fetch blueprint: ${res.status} ${res.statusText}\n${await res.text()}`); } const data = await res.json(); const blueprint = data.response.blueprint; const mod = blueprint.flow.find((m: any) => m.id === module_id); if (!mod) throw new Error(`Module ${module_id} not found in scenario.`); if (updates.parameters) { mod.parameters = { ...mod.parameters, ...updates.parameters }; } if (updates.mapper) { mod.mapper = { ...mod.mapper, ...updates.mapper }; } if (updates.metadata) { mod.metadata = { ...mod.metadata, ...updates.metadata }; } const patchRes = await fetch(blueprintUrl, { method: "PATCH", headers: { Authorization: `Token ${apiKey}`, "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify({ blueprint }) }); if (!patchRes.ok) { throw new Error(`Failed to update blueprint: ${patchRes.status} ${patchRes.statusText}\n${await patchRes.text()}`); } return `✅ Module ${module_id} in scenario ${scenario_id} updated successfully.`; } server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools })); server.setRequestHandler(CallToolRequestSchema, async ({ params: { name, arguments: args } }) => { switch (name) { case "read_make_dot_com_scenario_blueprint": { const { scenario_id, draft } = ScenarioIdSchema.parse(args); const url = `https://${MAKE_BASE_URL}/api/v2/scenarios/${scenario_id}/blueprint?includeDraft=${draft}&teamId=${MAKE_TEAM_ID}`; const res = await fetch(url, { headers: makeHeaders() }); return { content: [{ type: "text", text: await res.text() }] }; } case "create_make_dot_com_scenario": { const { name, folderId, description } = CreateScenarioSchema.parse(args); const res = await fetch(`https://${MAKE_BASE_URL}/api/v2/scenarios`, { method: "POST", headers: makeHeaders(), body: JSON.stringify({ name, folderId, description, teamId: MAKE_TEAM_ID }) }); return { content: [{ type: "text", text: await res.text() }] }; } case "update_make_dot_com_scenario": { const { scenario_id, name, description } = UpdateScenarioSchema.parse(args); const url = `https://${MAKE_BASE_URL}/api/v2/scenarios/${scenario_id}?teamId=${MAKE_TEAM_ID}`; const res = await fetch(url, { method: "PATCH", headers: makeHeaders(), body: JSON.stringify({ name, description }) }); return { content: [{ type: "text", text: await res.text() }] }; } case "describe_make_dot_com_module": { const { scenario_id, module_id, draft } = DescribeModuleSchema.parse(args); const url = `https://${MAKE_BASE_URL}/api/v2/scenarios/${scenario_id}/blueprint?includeDraft=${draft}&teamId=${MAKE_TEAM_ID}`; const res = await fetch(url, { headers: makeHeaders() }); const blueprint = await res.json(); const mod = blueprint.response?.blueprint?.flow?.find((m: any) => m.id === module_id); if (!mod) throw new Error("Module not found"); return { content: [{ type: "text", text: JSON.stringify(mod, null, 2) }] }; } case "update_module_parameters": { const parsed = UpdateScenarioInterfaceArgsSchema.safeParse(args); if (!parsed.success) { throw new Error( `Invalid arguments for update_make_dot_com_scenario_interface: ${parsed.error}` ); } const { scenario_id, inputs } = parsed.data; const response = await fetch( `https://${MAKE_BASE_URL}/api/v2/scenarios/${scenario_id}/interface?teamId=${MAKE_TEAM_ID}`, { method: "PATCH", headers: { Authorization: `Token ${MAKE_API_KEY}`, "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify({ interface: { input: inputs, }, }), } ); if (!response.ok) { throw new Error( `Make.com API error: ${response.status} ${response.statusText}\n${await response.text()}` ); } const data = await response.json(); return { content: [ { type: "text", text: `✅ Scenario interface updated successfully. Inputs: ${data.interface?.input?.length ?? 0}`, }, ], }; } case "check_make_dot_com_module_data": { const { scenario_id, module_id, draft } = CheckModuleSchema.parse(args); const url = `https://${MAKE_BASE_URL}/api/v2/scenarios/${scenario_id}/blueprint?includeDraft=${draft}&teamId=${MAKE_TEAM_ID}`; const res = await fetch(url, { headers: makeHeaders() }); const blueprint = await res.json(); const mod = blueprint.response?.blueprint?.flow?.find((m: any) => m.id === module_id); if (!mod) throw new Error("Module not found"); const required = mod.metadata?.interface?.filter((f: any) => f.required)?.map((f: any) => f.name) || []; const filled = required.filter((name: string) => mod.parameters?.[name] !== undefined); return { content: [{ type: "text", text: `${filled.length}/${required.length} required fields filled.` }] }; } case "list_make_dot_com_scenarios": { const url = `https://${MAKE_BASE_URL}/api/v2/scenarios?teamId=${MAKE_TEAM_ID}`; const res = await fetch(url, { headers: makeHeaders() }); const data = await res.json(); const result = data?.scenarios?.map((s: any) => `• ${s.name} (ID: ${s.id})`)?.join("\n") || "No scenarios found."; return { content: [{ type: "text", text: result }] }; } case "list_make_dot_com_connections": { const url = `https://${MAKE_BASE_URL}/api/v2/connections?teamId=${MAKE_TEAM_ID}`; const res = await fetch(url, { headers: makeHeaders() }); const data = await res.json(); const result = data.map((c: any) => `• ${c.label || c.name} (${c.id}) ${c.valid ? "✅" : "❌"}`).join("\n"); return { content: [{ type: "text", text: result }] }; } case "patch_make_dot_com_module_in_blueprint": { const parsedArgs = PatchModuleInBlueprintSchema.parse(args); const result = await patchModuleInBlueprint(parsedArgs, MAKE_API_KEY, MAKE_BASE_URL, MAKE_TEAM_ID); return { content: [{ type: "text", text: result }] }; } default: throw new Error(`Unknown tool: ${name}`); } }); // Start the server (async () => { const transport = new StdioServerTransport(); await server.connect(transport); console.error("✅ Make.com MCP Server running..."); })();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sparxHub/mcp-makesync'

If you have feedback or need assistance with the MCP directory API, please join our Discord server