{"id":50474829,"url":"https://github.com/jmpijll/make-code-mode-mcp","last_synced_at":"2026-06-01T12:31:10.082Z","repository":{"id":358127178,"uuid":"1240080525","full_name":"jmpijll/make-code-mode-mcp","owner":"jmpijll","description":"Code-mode MCP server for the Make.com Web API v2 — two tools (search + execute), QuickJS WASM sandbox, ~467 operations behind one flat make.* namespace, scope-aware 401/403 errors, stdio + Streamable HTTP transports.","archived":false,"fork":false,"pushed_at":"2026-05-15T21:35:38.000Z","size":650,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-15T23:10:49.580Z","etag":null,"topics":["cloudflare-workers","code-mode","integromat","llm-tools","make-com","mcp","model-context-protocol","openapi","quickjs","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jmpijll.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-15T18:43:04.000Z","updated_at":"2026-05-15T21:33:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jmpijll/make-code-mode-mcp","commit_stats":null,"previous_names":["jmpijll/make-code-mode-mcp"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/jmpijll/make-code-mode-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmpijll%2Fmake-code-mode-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmpijll%2Fmake-code-mode-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmpijll%2Fmake-code-mode-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmpijll%2Fmake-code-mode-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jmpijll","download_url":"https://codeload.github.com/jmpijll/make-code-mode-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jmpijll%2Fmake-code-mode-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33775856,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloudflare-workers","code-mode","integromat","llm-tools","make-com","mcp","model-context-protocol","openapi","quickjs","typescript"],"created_at":"2026-06-01T12:31:09.970Z","updated_at":"2026-06-01T12:31:10.073Z","avatar_url":"https://github.com/jmpijll.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Make.com Code-Mode MCP\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Status: beta](https://img.shields.io/badge/status-beta-orange.svg)](#project-status)\n[![Version: v0.1.0-beta.1](https://img.shields.io/badge/version-v0.1.0--beta.1-blue.svg)](CHANGELOG.md)\n\n\u003e ## Project status\n\u003e\n\u003e **Public beta. Install from source. Not on npm yet.**\n\u003e\n\u003e One sandbox surface (`make.*`) covers the entire Make.com Web API v2\n\u003e (~467 operations on the EU1 zone). 85/85 unit + integration tests\n\u003e green, end-to-end LLM-mediated invocation verified through MCP\n\u003e Inspector CLI, opencode (DeepSeek v4 Flash), and OpenAI Codex (CLI\n\u003e 0.131.0-alpha.9 + Codex desktop app, both driving `gpt-5.5`) against a\n\u003e real Make.com Core-tier account (all-scope token, 12 sandbox host calls\n\u003e per discovery sweep). Read-only sweeps of `/users/me`,\n\u003e `/users/me/current-authorization`, `/organizations`, `/teams`,\n\u003e `/scenarios`, `/connections`, `/data-stores`, `/hooks`, and `/sdk/apps`\n\u003e are live-verified. Mutations are wired but **not** verified by us\n\u003e (write ops would consume Make.com operation credits and need a\n\u003e non-production tenant). See [verification status](#verification-status)\n\u003e for what is actually proven.\n\nA Model Context Protocol (MCP) server for the **Make.com Web API v2**, built on the **Cloudflare \"Code Mode\" pattern**: instead of one MCP tool per endpoint, the server exposes **two tools** — `search` and `execute` — and the LLM writes JavaScript that runs in a QuickJS WASM sandbox. This keeps the LLM context small (~constant) regardless of how big the underlying API is.\n\n## Why Code Mode?\n\nThe Make.com Web API v2 has **~467 endpoints** across **83 tags** (scenarios, connections, data stores, hooks, organizations, teams, users, agents, SDK apps, admin/HQ, …). Exposing each as a separate MCP tool floods the LLM context with tens of thousands of tokens before the model has read the user's question. Code Mode collapses the entire API surface into two tools and lets the model search the OpenAPI spec, then execute calls programmatically — including loops, batching, and post-processing. See Cloudflare's [Code Mode for MCP](https://blog.cloudflare.com/code-mode-mcp/) blog post and the official `@cloudflare/codemode` package.\n\n## Highlights\n\n- **Cloudflare Code Mode compatible** — two-tool design (`search` + `execute`), QuickJS WASM sandbox semantics.\n- **One flat surface — `make.*`** — every Make.com Web API v2 operation, including admin/internal endpoints, exposed through the same sandbox namespace. No surface splits, no hidden filtering — 403s are self-documenting (and decorated with the scope hint from `operation.security`).\n- **Single-user (env) and multi-user (per-request HTTP headers)** — same server runs as a private workspace tool or a hosted multi-tenant gateway.\n- **Zone-aware** — `MAKE_BASE_URL` / `X-Make-Base-Url` selects the regional zone (defaults to `https://eu1.make.com/api/v2`). Unknown base URLs warn at startup but still work.\n- **Dynamic OpenAPI loading** — the spec is fetched live from `${MAKE_BASE_URL}/openapi.json` at boot, hash-cached on disk, and falls back to a bundled snapshot when the live fetch fails.\n- **Scope-aware 401/403 errors** — `[make.http] HTTP 403 on /scenarios: ... (operation requires scope ``scenarios:read``)` so the model can tell the user exactly which scope their token is missing.\n- **Hybrid deployment** — runs on Node.js (stdio + Streamable HTTP); a Cloudflare Workers scaffold ships in `cf-worker/` for parity-smoke verification.\n- **Plan-tier aware** — verified end-to-end against a Make.com **Core** account (all-scope token). Free-tier tokens still work for read-only `/users/me` / `/organizations` / `/teams` probes; tier-gated endpoints (e.g. audit logs need Pro/Teams) return upstream `402 Payment Required` and admin endpoints are VPN-gated `403`s — both surface verbatim with the operation path and Make.com error code.\n\n## For agents driving this server\n\nIf you're an LLM agent (or a human configuring one) connecting to a running instance, read [`SKILL.md`](SKILL.md) for the operating manual — the `search → execute` loop, the single `make.*` surface, the three call shapes, the error taxonomy, and ready-to-paste recipes. The example persona at [`examples/make-expert-agent/`](examples/make-expert-agent/) bundles a focused \"Make.com automation expert\" system prompt plus cross-platform install snippets.\n\n## Quickstart (single-user / stdio)\n\n```bash\ngit clone https://github.com/jmpijll/make-code-mode-mcp.git\ncd make-code-mode-mcp\nnpm install\ncp .env.example .env\n# Edit .env: MAKE_API_KEY=...  (defaults: MAKE_BASE_URL=https://eu1.make.com/api/v2)\nnpm run build\nnpm start                # MCP_TRANSPORT=stdio\n```\n\nThen point your MCP client at `node /path/to/make-code-mode-mcp/dist/index.js`.\n\n## Quickstart (multi-user / HTTP)\n\n```bash\nMCP_TRANSPORT=http npm start\n```\n\nEach MCP client request must include credentials as headers:\n\n```http\nPOST /mcp HTTP/1.1\nX-Make-Api-Key: \u003cyour make.com api token\u003e\nX-Make-Base-Url: https://eu1.make.com/api/v2\n```\n\nSee [`docs/multi-tenant.md`](docs/multi-tenant.md).\n\n## Example session\n\nThe model first searches the spec:\n\n```js\n// search tool\nfindOperationsByPath('/scenarios')\n  .filter((op) =\u003e op.method === 'GET')\n  .map((op) =\u003e ({ id: op.operationId, path: op.path, summary: op.summary }));\n```\n\nThen executes calls:\n\n```js\n// execute tool — list scenarios in the first team of the first org\n// (Make.com's pg[…] pagination is encoded automatically from nested objects)\n(async () =\u003e {\n  const orgs = await make.callOperation('getOrganizations', {});\n  const teams = await make.callOperation('getTeams', { organizationId: orgs.organizations[0].id });\n  const scenarios = await make.callOperation('listScenarios', {\n    teamId: teams.teams[0].id,\n    pg: { limit: 25, sortBy: 'name', sortDir: 'asc' },\n  });\n  return scenarios.scenarios.map((s) =\u003e ({ id: s.id, name: s.name, isActive: s.isActive }));\n})();\n```\n\n## Architecture\n\n```mermaid\nflowchart LR\n  Client[MCP client] --\u003e|search/execute| Server[make-mcp Node host]\n  Server --\u003e|prelude inject| Sandbox[QuickJS WASM sandbox]\n  Sandbox --\u003e|\"__makeCall(opId, args)\"| Server\n  Server --\u003e|\"Authorization: Token …\"| Make[Make.com /api/v2]\n  Server -.spec.-\u003e SpecLoader[spec loader]\n  SpecLoader --\u003e|\"GET /api/v2/openapi.json\"| Make\n  SpecLoader --\u003e|fallback| Fallback[bundled make-fallback.json]\n```\n\n## Status\n\nPre-1.0. The Make.com Web API v2 spec is loaded dynamically from `${MAKE_BASE_URL}/openapi.json`; the server adapts to spec mutations without code edits.\n\n### Verification status\n\nWhat we have **directly verified** so far:\n\n| Layer | How | Result |\n|---|---|---|\n| Unit tests | Vitest, 85 cases across config, tenant, spec loader, spec index, HTTP client (including `pg[limit]` bracket-notation query encoding), dispatcher, sandbox, integration scenarios | ✅ all green |\n| Integration tests (in-process MCP transport) | `InMemoryTransport` against `createMcpServer` + a mock Make.com Web API v2 | ✅ green |\n| Integration tests (real Streamable HTTP transport) | `StreamableHTTPClientTransport` over a real HTTP listener | ✅ green |\n| Live HTTP-client round-trip | In-process mock asserting `Authorization: Token …`, 429 retry, and scope-aware 403 error formatting | ✅ green |\n| **Live read-only sweep on a real Make.com tenant** | `npm run live-test` against `https://eu1.make.com/api/v2` with a 1Password-managed **Core-tier** API key (all 67 scopes including `admin:read`, `scenarios:run`, `mcp:use`); 3-call sandbox sweep through `/users/me`, `/organizations`, `/teams` | ✅ 3/3 calls returned real data in ~220 ms; transcript at `out/verification/make-live-smoke.txt` (PII redacted) |\n| **Broad read-only discovery sweep** | `npm run discover` — 12-call sandbox traversal through `/users/me`, `/users/me/current-authorization`, `/admin/owners`, `/sdk/apps`, `/organizations`, `/teams`, `/audit-logs/organization/{id}`, plus per-team `/scenarios`, `/connections`, `/data-stores`, `/hooks`, `/audit-logs/team/{id}` — uses Make.com's bracketed `pg[limit]=…` pagination syntax end-to-end | ✅ 12 calls; sdk/apps + connections + scenarios + data-stores + hooks succeed; audit-logs return `402 Payment Required` (need Teams/Enterprise plan); `/admin/owners` returns `403 VPN access only [IM121]` (IP-gated, not scope-gated); transcript at `out/verification/make-discover-core.txt` |\n| **MCP Inspector (CLI mode)** | `@modelcontextprotocol/inspector@0.20.0 --cli --transport stdio` against the live API; `tools/list`, credentialled `search` (`findOperationsByPath`), credentialled `execute` (`getUsersMe`), a credentialled 403 probe (`/admin/owners`), and a credentialled `pg[limit]` bracket-encoding probe | ✅ all five phases pass; transcripts in `out/verification/mcp-inspector-*.txt` |\n| **End-to-end LLM-mediated invocation via opencode** | DeepSeek v4 Flash via `opencode-go` provider, project-scoped `opencode.json`, opencode v1.14.30 — model called `make_search` with `spec.operations.length` then `make_execute` with the async-IIFE `getUsersMe` recipe | ✅ Model received MCP tools as `make_search` / `make_execute`, called them with the right code, server returned `467` (operation count) and the real user `{name, email}`; transcripts at `out/verification/opencode-make-mcp-*.txt` |\n| **End-to-end LLM-mediated invocation via OpenAI Codex (CLI + desktop app)** | `codex-cli 0.131.0-alpha.9` (bundled with `Codex.app`), `gpt-5.5`. Server registered once via `codex mcp add make -- node …/dist/index.js`; entry lives in `~/.codex/config.toml` and is shared by both the CLI and the Codex macOS desktop app. CLI ran the two-step `mcp__make__search` / `mcp__make__execute` recipe via `codex exec --json`; the Codex desktop app drove the same recipe interactively after approving the `make` server. | ✅ Tools surface as `mcp__make__search` / `mcp__make__execute` in both clients; CLI returned `opCount=467 userId=\u003cid\u003e` from a single `search → execute → reply` round-trip; desktop app produced the same result interactively. CLI transcript at `out/verification/codex-cli-make-mcp.txt`. |\n| **Cloudflare Workers — `wrangler dev` parity smoke** | `npm run cf:dev` (Miniflare) + curl probes against `/health`, `/mcp`, unknown paths | ✅ Worker boots; `/health` → `{\"status\":\"ok\"}`; `/mcp` without creds → 401 with documented missing-header message; `/mcp` with creds → 502 (spec-load failure for stub baseUrl, as expected); unknown path → 404. The 501 transport-adapter scaffold is documented and unreachable without real creds + a publicly-trusted controller. Transcript at `out/verification/cf-worker-parity-smoke.txt` |\n\nWhat is **not yet verified** (testers welcome):\n\n- Mutating operations (POST/PUT/PATCH/DELETE) — wired but unproven. Make.com bills \"operations\" for *scenario module executions*, not API calls, so listing/inspecting is free, but creating real scenarios still has side effects that we don't want to ship into a production tenant. Verification is gated on having a throwaway non-production tenant.\n- Admin/internal endpoints (`/admin/*`, `/hq/*`, `/debug/*`, `/mailhub/*`) — the token has `admin:read`/`admin:write` scopes, but `/admin/owners` cleanly returns `403 VPN access only [IM121]` from outside Make's office network. Behaviour from a VPN-allowlisted environment is unverified.\n- Audit logs (`/audit-logs/*`) — the token has the scope, but the endpoint requires Make's **Teams / Enterprise** tier and returns `402 Payment Required` on a Core plan.\n- Other regional zones (`eu2`, `us1`, `us2`, Celonis variants) — the loader trusts whatever `MAKE_BASE_URL` resolves to; only EU1 has been driven end-to-end.\n- Other agent / IDE clients beyond MCP Inspector CLI, opencode, Codex CLI, and the Codex desktop app (Cursor, Claude Desktop, Claude Code, Continue, Cline, Codeium, Aider, Zed, …) and the MCP Inspector UI / HTTP / SSE transports.\n- Hosted/multi-tenant deployment behind a reverse proxy.\n- Long-running soak / stability under sustained load.\n- The Cloudflare Workers transport adapter — the routing, auth-header validation, spec loader, and 404/401/502 paths all work; the `worker_loaders` `LOADER` binding is wired in (wrangler@4 ships in `devDependencies` and recognises the binding on `deploy --dry-run`), but the 501 transport-adapter scaffold bridging the MCP SDK's `node:http` transport to the Workers Fetch API is still TODO.\n\n## Plan tiers \u0026 scopes\n\nMake.com's [pricing page](https://www.make.com/en/pricing) gates *some* API surfaces by paid tier:\n\n- **Free plan** has \"Limited\" API access. Read-only `/users/me`, `/organizations`, and team-scoped listing typically work; admin/HQ paths and many write ops will 403.\n- **Core plan** (verified) unlocks the bulk of the API. Audit logs still require Teams/Enterprise (`402 Payment Required`). Admin endpoints are additionally IP-gated to Make's VPN (`403 VPN access only [IM121]`) regardless of plan.\n\nThe server's error messages quote Make.com's response verbatim — including the `[IM121]`, `[SC400]`, `[SC403]` error codes — so the model can tell the user whether the block is plan-tier, scope, or network, and stop guessing.\n\n## Documentation\n\n- [`docs/architecture.md`](docs/architecture.md) — How the server is built, request lifecycle, sandbox details.\n- [`docs/multi-tenant.md`](docs/multi-tenant.md) — Header protocol, deployment patterns, security model.\n- [`docs/security.md`](docs/security.md) — Threat model, credential handling, sandbox guarantees.\n- [`docs/deployment.md`](docs/deployment.md) — Docker, Cloudflare Workers, systemd.\n- [`docs/usage.md`](docs/usage.md) — Tool descriptions, common patterns, gotchas.\n\n## License\n\nMIT — see [`LICENSE`](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmpijll%2Fmake-code-mode-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjmpijll%2Fmake-code-mode-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjmpijll%2Fmake-code-mode-mcp/lists"}