mendix-mcp-server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mendix-mcp-serverAdd an entity called Customer to the module MyFirstModule."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Mendix MCP Server
An MCP (Model Context Protocol) server that exposes the Mendix Model SDK, Mendix Platform API, Deploy API, and a running app's runtime OQL endpoint as a suite of tools an AI agent (e.g. Claude Code) can call.
In short: it lets an LLM read and modify a Mendix application model — create modules, entities, attributes, associations, pages, microflows, REST services, security rules, navigation, and enumerations — and then commit, deploy, or query the result, all through plain tool calls over HTTP.
Table of contents
Related MCP server: CodeGraph
How it works
Mendix apps are not edited as loose files. The model lives on Mendix's Team Server, and
the canonical way to change it programmatically is the Mendix Model SDK (mendixmodelsdk)
driven through the Platform SDK (mendixplatformsdk). The pattern is always:
Open a temporary online working copy of an app from a branch.
Open its model (a live, typed, in-memory object graph of the whole app).
Read or mutate model elements (entities, pages, microflows, …).
Flush pending changes and commit the working copy back to the branch.
This server wraps that pattern in ~60 discrete MCP tools. Each tool is a thin, focused operation ("add an attribute to an entity", "add a widget to a page", "create a REST operation") that:
takes an
app_id(and usually abranch, defaulting tomain),opens a fresh working copy + model,
performs one well-scoped change,
commits with a generated message,
and returns a human/JSON result.
The AI agent orchestrates these small tools into larger changes. The server itself stays stateless — it holds no session between calls.
Architecture
┌───────────────────┐ JSON-RPC over HTTP (POST /mcp) ┌────────────────────────┐
│ MCP client │ ───────────────────────────────────────► │ Mendix MCP Server │
│ (Claude Code, etc.)│ ◄─────────────────────────────────────── │ (Node.js, port 3001) │
└───────────────────┘ tool results / streamed events └───────────┬────────────┘
│
┌──────────────────────────────────────────────────────┼───────────────────────────┐
│ │ │ │
▼ ▼ ▼ ▼
┌────────────────────┐ ┌──────────────────────────┐ ┌──────────────────────┐ ┌────────────────────┐
│ Platform SDK │ │ Deploy API (v2) │ │ Runtime OQL endpoint │ │ Local FS / Web │
│ + Model SDK │ │ deploy.mendix.com │ │ /rest/oql/v1/query │ │ (glob/read/write/ │
│ (Team Server model)│ │ │ │ on the running app │ │ fetch/docs search)│
└────────────────────┘ └──────────────────────────┘ └──────────────────────┘ └────────────────────┘
▲ ▲ ▲
MENDIX_PAT MENDIX_USERNAME + MENDIX_RUNTIME_TOKEN
MENDIX_API_KEYTwo source files form the spine:
src/server.ts— the HTTP + MCP transport layer. Builds anMcpServer, registers every tool group, and serves them over a Streamable HTTP transport atPOST /mcp.src/mendix-client.ts— the shared Mendix helper layer: authentication, working-copy/model lifecycle, module/document lookup, multi-language text handling, and result formatting.
Everything else lives under src/tools/, one file per capability area, each
exporting a registerXxxTools(server) function that server.ts calls.
The four Mendix surfaces it talks to
The server does not hit a single Mendix API. Different tools use different Mendix surfaces, each with its own credential:
Surface | Used by | Credential | What it does |
Model SDK / Platform SDK | Most tools — domain, pages, flows, security, navigation, enums, REST modeling, |
| Opens working copies and reads/mutates the app model on the Team Server. |
Deploy API v2 ( |
|
| Triggers cloud deployments and reports their status. |
Runtime OQL endpoint ( |
|
| Runs OQL against a live, running app instance and returns data. |
Local FS / public web |
| none | Local file ops, doc search, and pure string generation — no Mendix auth needed. |
The working-copy lifecycle (the core pattern)
Almost every model-mutating tool follows the same shape, implemented via helpers in
src/mendix-client.ts:
// 1. Open a fresh working copy for the app/branch and open its model.
const wc = await getWorkingCopy(app_id, branch); // createTemporaryWorkingCopy(branch)
const model = await wc.openModel();
// 2. Locate the target element.
const mod = findModule(model, moduleName); // by name
const doc = findDocument(model, moduleName, docName); // recursive folder search
// 3. Mutate the in-memory model graph (create/update/delete SDK objects).
// ...
// 4. Flush pending changes and commit the working copy back to the branch.
await commitWC(wc, model, "descriptive commit message", branch);Read-only tools skip step 4 and just call getModel(app_id, branch) to open a throwaway
working copy for inspection.
Key helpers in mendix-client.ts:
mendix— the singletonMendixPlatformClient. Its PAT is bridged fromMENDIX_PATinto the SDK's expectedMENDIX_TOKENmechanism viasetPlatformConfig(...).getWorkingCopy(appId, branch)/getModel(appId, branch)— open a working copy / model.commitWC(wc, model, message, branch)—flushChanges()thencommitToRepository(...).findModule/findDocument/splitQualifiedName— resolveModule.Elementnames, searching recursively through folders.setText/readText/getProjectLanguageCodes— Mendix user-visible text is never a plain string; it's aTextholding oneTranslationper configured language.setTextwrites a translation for every project language (avoiding consistency errors) and caches the language list per model.ok(msg)/json(data)/errorResult(err)— normalize tool return payloads.safe(handler)— wraps every tool handler so a thrown error becomes an MCP error result (isError: true) instead of crashing the server.
Request lifecycle
The HTTP layer in src/server.ts runs in stateless mode:
A client POSTs a JSON-RPC MCP message to
http://localhost:3001/mcp.The body is read and parsed.
A fresh
McpServer+StreamableHTTPServerTransportpair is built per request. (An MCP server/transport pair can only beconnect()-ed once — reusing it throws on the second call — so the server builds a new pair each time rather than holding a session.)All tool groups are registered on that fresh server, it connects to the transport, and the transport handles the request/response.
On connection close, both transport and server are closed.
Any non-/mcp path returns 404. Errors are returned as JSON-RPC error objects
(code: -32603).
Setup
Prerequisites
Node.js (with support for ES modules /
NodeNext; Node 18+ recommended for globalfetch).A Mendix account with:
a Personal Access Token (PAT) with
mx:modelrepositoryscopes (for model editing),optionally an API key + username (for deployments),
optionally a runtime token (for live OQL queries).
The Mendix app's App ID (found in the Mendix Portal / Developer Portal).
Install
npm installConfiguration
Copy .env.example to .env and fill in your credentials:
MENDIX_PAT=your_personal_access_token # Model/Platform SDK — model editing
MENDIX_USERNAME=your@email.com # Deploy API — deployments
MENDIX_API_KEY=your_deploy_api_key # Deploy API — deployments
MENDIX_RUNTIME_TOKEN=your_runtime_token # Runtime OQL — live data queries
PORT=3001 # HTTP port (default 3001).env is loaded automatically at startup via dotenv/config. Each credential is only
required for the tools that use it — you can run model-editing tools with just MENDIX_PAT.
Running the server
# Type-check + compile TypeScript → dist/
npm run build
# Run the compiled server
npm start
# → Mendix MCP -> http://localhost:3001/mcp
# Or run directly from source during development (ts-node loader):
npm run dev
# Auto-restart on file changes:
npm run watchConnecting an MCP client
Point any MCP client at the HTTP endpoint. For Claude Code, add an HTTP MCP server:
claude mcp add --transport http mendix http://localhost:3001/mcpOr via a client config that supports Streamable HTTP transports, use the URL
http://localhost:3001/mcp. Once connected, the client discovers all tools below and the
agent can call them by name.
Tool catalog
All tools that touch the model accept app_id and (usually) an optional branch (default
main). Grouped by source file:
Filesystem & knowledge — filesystem.ts, knowledge.ts
Tool | Description |
| Find files matching a glob pattern. |
| Read a file's contents. |
| Write or overwrite a file. |
| Read a skill/snippet from the skills library. |
| Fetch content from a URL. |
| Search Mendix docs / knowledge base (docs.mendix.com). |
Platform / element document ops (ped_*) — ped.ts
Generic, low-level building blocks used by the higher-level tools.
Tool | Description |
| Read a document's full JSON representation. |
| Summarize the SDK class + common properties for a document type. |
| Create a Page, Microflow, Nanoflow, Enumeration, or Snippet. |
| Create a new module. |
| Apply key-value property updates to a document. |
| Run consistency checks on the model. |
| Search documents by name substring / module / type. |
| List documents directly inside a module (or subfolder). |
Domain model — domain.ts
Tool | Description |
| Create an entity (persistence via generalization; see note below). |
| Add an attribute (optional default value + required rule). |
| Apply property updates to an attribute. |
| Delete an attribute. |
| List an entity's attributes with names + types. |
| Set entity access rules. |
| Copy an entity (including attributes). |
| Delete an entity. |
| Create an association between two entities (cross-module OK). |
| Apply property updates to an association. |
| Export a curated summary of a module's domain model. |
Supported attribute types: String, Integer, Long, Decimal, Boolean, DateTime, Enum, AutoNumber, Binary, HashString.
Enumerations, constants & snippets — enums.ts
Tool | Description |
| Manage enumeration values. |
| Create/set a Constant document. |
| Create a reusable snippet and place it on a page. |
Pages & widgets — pages.ts
Tool | Description |
| Add/remove/reposition widgets. |
| Set a single widget property (dynamic key-value). |
| Wire a widget's data source. |
| Set a visibility expression on a widget. |
| Change the page's layout. |
| Add a ListView wired to an entity. |
| Add a DataGrid wired to an entity, one column per attribute. |
| Set a widget's CSS class. |
| Duplicate a page. |
| Make an ActionButton navigate to another page. |
| Set a button's caption. |
Microflows / nanoflows — flows.ts
Tool | Description |
| Add an activity node. |
| Add an exclusive split with an expression condition. |
| Connect nodes with flows. |
| Configure an activity's properties. |
| Add a create-variable activity. |
| Add a database retrieve (list by entity). |
| Add a commit-object activity. |
| Add a loop over a list variable (empty body). |
| Add an error handler. |
| Call another microflow with argument mappings. |
| Add a call-REST-service activity. |
| List all nodes (id, type, position). |
| Run a microflow. |
REST services — rest.ts
Tool | Description |
| Model a consumed REST service + operations. |
| Model a published REST service at a base path. |
| Import an OpenAPI/Swagger spec (pragmatic, non- |
| List all consumed + published services. |
| Configure a mapping. |
| Invoke an operation for testing. |
Security — security.ts
Tool | Description |
| Manage project user roles. |
| Set module roles allowed on a page. |
| Set module roles allowed on a microflow. |
| Set entity access rules. |
| Summarize access configuration. |
Navigation — navigation.ts
Tool | Description |
| Read a navigation profile's menu. |
| Add/remove menu items. |
| Reorder menu items. |
| Set the profile's home page. |
OQL — oql.ts
Tool | Description | Auth |
| Build an OQL string from parameters (local templating). | none |
| Run OQL against a live running app ( |
|
Deployment & project — deployment.ts
Tool | Description | Auth |
| Open a working copy and commit (checkpoint history). |
|
| Create a branch. |
|
| Get a branch's commit history (Team Server API). |
|
| Deploy to a cloud environment (Sandbox/Test/Acceptance/Production). |
|
| Get a deployment's status. |
|
| Export the model as a local |
|
| Get the app's project settings document. |
|
Project layout
mendix-mcp-server/
├── src/
│ ├── server.ts # HTTP + MCP transport; registers all tool groups
│ ├── mendix-client.ts # Auth, working-copy/model lifecycle, helpers
│ └── tools/
│ ├── filesystem.ts # glob / read / write / fetch / read_skill
│ ├── knowledge.ts # Mendix docs search
│ ├── ped.ts # generic document/module ops (create/read/update/errors)
│ ├── domain.ts # entities, attributes, associations
│ ├── enums.ts # enumerations, constants, snippets
│ ├── pages.ts # pages & widgets
│ ├── flows.ts # microflows / nanoflows
│ ├── rest.ts # consumed & published REST services, OpenAPI import
│ ├── security.ts # user roles, page/microflow/entity access
│ ├── navigation.ts # navigation menus
│ ├── oql.ts # OQL generate + live read
│ └── deployment.ts # commit, branch, deploy, export, settings
├── dist/ # compiled output (npm run build)
├── package.json
├── tsconfig.json
├── .env / .env.example # credentials & port
└── README.mdHow a typical task flows end-to-end
Say the agent is asked: "Add a Customer entity to the Sales module with a Name field,
put it on a data grid, and deploy to Sandbox."
entity_create→ opens a working copy of the app, creates theCustomerentity inSales, commits.entity_add_attribute→ opens a fresh working copy, addsName(String), commits.ped_create_document→ creates aCustomerOverviewPage.page_add_datagrid→ wires a DataGrid toSales.Customerwith a column per attribute, commits.navigation_add_menu_item→ links the page into the navigation menu.ped_check_errors→ runs consistency checks to confirm the model is valid.project_deploy→ hits the Deploy API to push to the Sandbox environment.project_get_deploy_status→ polls until the deployment reports success.
Each step is a separate stateless HTTP call; the agent decides the order and reacts to each tool's result.
Notes, limitations & gotchas
Stateless by design. No sessions are kept; each request builds and tears down its own MCP server/transport pair. This is intentional — the MCP SDK forbids reusing a connected pair.
Every mutating call re-opens a working copy. Because tools are independent, a multi-step change is a series of commits, not one atomic transaction. Use
project_committo checkpoint andped_check_errorsto validate along the way.Text is multi-language. Any caption/label/title is a
Textwith oneTranslationper project language. Always use thesetText/readTexthelpers (the higher-level tools do this for you) — don't assume a plain string.Entity persistence is expressed through the entity's generalization, not a standalone flag: a
NoGeneralizationwithpersistable=true/false, or aGeneralizationpointing at a parent entity (which then determines persistence).rest_import_openapiis pragmatic, not complete. It readsinfo.title, the server URL, andpaths.*.<method>.operationId, but does not resolve$refs or import parameter/response schemas.Credential scoping. Model tools need only
MENDIX_PAT; deploy tools additionally needMENDIX_USERNAME+MENDIX_API_KEY;oql_readneedsMENDIX_RUNTIME_TOKEN. Missing credentials produce a clear error only when the relevant tool is called.Errors are non-fatal. The
safe()wrapper converts thrown errors into MCP error results, so a failing tool call returns an error payload rather than taking the server down.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/dhanavel10/mendix-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server