Skip to main content
Glama
dhanavel10

mendix-mcp-server

by dhanavel10

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:

  1. Open a temporary online working copy of an app from a branch.

  2. Open its model (a live, typed, in-memory object graph of the whole app).

  3. Read or mutate model elements (entities, pages, microflows, …).

  4. 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 a branch, defaulting to main),

  • 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_KEY

Two source files form the spine:

  • src/server.ts — the HTTP + MCP transport layer. Builds an McpServer, registers every tool group, and serves them over a Streamable HTTP transport at POST /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, ped_*, project_commit/branch/export/settings

MENDIX_PAT

Opens working copies and reads/mutates the app model on the Team Server.

Deploy API v2 (deploy.mendix.com)

project_deploy, project_get_deploy_status

MENDIX_USERNAME + MENDIX_API_KEY

Triggers cloud deployments and reports their status.

Runtime OQL endpoint (/rest/oql/v1/query)

oql_read

MENDIX_RUNTIME_TOKEN

Runs OQL against a live, running app instance and returns data.

Local FS / public web

glob, read_file, write_file, read_skill, web_fetch, search_mendix_knowledge_base, oql_generate

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 singleton MendixPlatformClient. Its PAT is bridged from MENDIX_PAT into the SDK's expected MENDIX_TOKEN mechanism via setPlatformConfig(...).

  • getWorkingCopy(appId, branch) / getModel(appId, branch) — open a working copy / model.

  • commitWC(wc, model, message, branch)flushChanges() then commitToRepository(...).

  • findModule / findDocument / splitQualifiedName — resolve Module.Element names, searching recursively through folders.

  • setText / readText / getProjectLanguageCodes — Mendix user-visible text is never a plain string; it's a Text holding one Translation per configured language. setText writes 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:

  1. A client POSTs a JSON-RPC MCP message to http://localhost:3001/mcp.

  2. The body is read and parsed.

  3. A fresh McpServer + StreamableHTTPServerTransport pair is built per request. (An MCP server/transport pair can only be connect()-ed once — reusing it throws on the second call — so the server builds a new pair each time rather than holding a session.)

  4. All tool groups are registered on that fresh server, it connects to the transport, and the transport handles the request/response.

  5. 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 global fetch).

  • A Mendix account with:

    • a Personal Access Token (PAT) with mx:modelrepository scopes (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 install

Configuration

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 watch

Connecting 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/mcp

Or 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

glob

Find files matching a glob pattern.

read_file

Read a file's contents.

write_file

Write or overwrite a file.

read_skill

Read a skill/snippet from the skills library.

web_fetch

Fetch content from a URL.

search_mendix_knowledge_base

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

ped_read_document

Read a document's full JSON representation.

ped_get_schema

Summarize the SDK class + common properties for a document type.

ped_create_document

Create a Page, Microflow, Nanoflow, Enumeration, or Snippet.

ped_create_module

Create a new module.

ped_update_document

Apply key-value property updates to a document.

ped_check_errors

Run consistency checks on the model.

ped_find_document

Search documents by name substring / module / type.

ped_list_folder

List documents directly inside a module (or subfolder).

Domain model — domain.ts

Tool

Description

entity_create

Create an entity (persistence via generalization; see note below).

entity_add_attribute

Add an attribute (optional default value + required rule).

entity_update_attribute

Apply property updates to an attribute.

entity_delete_attribute

Delete an attribute.

entity_list_attributes

List an entity's attributes with names + types.

entity_set_access_rules

Set entity access rules.

entity_copy

Copy an entity (including attributes).

entity_delete

Delete an entity.

association_create

Create an association between two entities (cross-module OK).

association_set_properties

Apply property updates to an association.

domain_model_export

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

enum_add_value / enum_update_value / enum_list_values

Manage enumeration values.

constant_create / constant_set_value

Create/set a Constant document.

snippet_create / snippet_add_to_page

Create a reusable snippet and place it on a page.

Pages & widgets — pages.ts

Tool

Description

page_add_widget / page_remove_widget / page_move_widget

Add/remove/reposition widgets.

page_set_widget_property

Set a single widget property (dynamic key-value).

page_set_data_source

Wire a widget's data source.

page_set_conditional_visibility

Set a visibility expression on a widget.

page_set_layout

Change the page's layout.

page_add_listview

Add a ListView wired to an entity.

page_add_datagrid

Add a DataGrid wired to an entity, one column per attribute.

page_set_class

Set a widget's CSS class.

page_duplicate

Duplicate a page.

page_set_navigation_target

Make an ActionButton navigate to another page.

page_set_button_caption

Set a button's caption.

Microflows / nanoflows — flows.ts

Tool

Description

flow_add_activity

Add an activity node.

flow_add_decision

Add an exclusive split with an expression condition.

flow_connect_activities

Connect nodes with flows.

flow_configure_activity

Configure an activity's properties.

flow_add_variable

Add a create-variable activity.

flow_add_retrieve

Add a database retrieve (list by entity).

flow_add_commit

Add a commit-object activity.

flow_add_loop

Add a loop over a list variable (empty body).

flow_add_error_handler

Add an error handler.

flow_call_microflow

Call another microflow with argument mappings.

flow_call_rest_service

Add a call-REST-service activity.

flow_get_activities

List all nodes (id, type, position).

flow_run_microflow

Run a microflow.

REST services — rest.ts

Tool

Description

rest_create_consumed_service / rest_add_operation

Model a consumed REST service + operations.

rest_create_published_service / rest_add_published_resource

Model a published REST service at a base path.

rest_import_openapi

Import an OpenAPI/Swagger spec (pragmatic, non-$ref parser) into a consumed service.

rest_list_services

List all consumed + published services.

rest_set_mapping

Configure a mapping.

rest_test_operation

Invoke an operation for testing.

Security — security.ts

Tool

Description

security_create_userrole / security_list_roles

Manage project user roles.

security_set_page_access

Set module roles allowed on a page.

security_set_microflow_access

Set module roles allowed on a microflow.

security_set_entity_access

Set entity access rules.

security_get_access_summary

Summarize access configuration.

Navigation — navigation.ts

Tool

Description

navigation_get_menu

Read a navigation profile's menu.

navigation_add_menu_item / navigation_remove_menu_item

Add/remove menu items.

navigation_reorder_items

Reorder menu items.

navigation_set_home_page

Set the profile's home page.

OQL — oql.ts

Tool

Description

Auth

oql_generate

Build an OQL string from parameters (local templating).

none

oql_read

Run OQL against a live running app (POST /rest/oql/v1/query).

MENDIX_RUNTIME_TOKEN

Deployment & project — deployment.ts

Tool

Description

Auth

project_commit

Open a working copy and commit (checkpoint history).

MENDIX_PAT

project_create_branch

Create a branch.

MENDIX_PAT

project_get_revisions

Get a branch's commit history (Team Server API).

MENDIX_PAT

project_deploy

Deploy to a cloud environment (Sandbox/Test/Acceptance/Production).

MENDIX_USERNAME + MENDIX_API_KEY

project_get_deploy_status

Get a deployment's status.

MENDIX_USERNAME + MENDIX_API_KEY

project_export_mpk

Export the model as a local .mpk.

MENDIX_PAT

project_get_settings

Get the app's project settings document.

MENDIX_PAT


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.md

How 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."

  1. entity_create → opens a working copy of the app, creates the Customer entity in Sales, commits.

  2. entity_add_attribute → opens a fresh working copy, adds Name (String), commits.

  3. ped_create_document → creates a CustomerOverview Page.

  4. page_add_datagrid → wires a DataGrid to Sales.Customer with a column per attribute, commits.

  5. navigation_add_menu_item → links the page into the navigation menu.

  6. ped_check_errors → runs consistency checks to confirm the model is valid.

  7. project_deploy → hits the Deploy API to push to the Sandbox environment.

  8. 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_commit to checkpoint and ped_check_errors to validate along the way.

  • Text is multi-language. Any caption/label/title is a Text with one Translation per project language. Always use the setText/readText helpers (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 NoGeneralization with persistable=true/false, or a Generalization pointing at a parent entity (which then determines persistence).

  • rest_import_openapi is pragmatic, not complete. It reads info.title, the server URL, and paths.*.<method>.operationId, but does not resolve $refs or import parameter/response schemas.

  • Credential scoping. Model tools need only MENDIX_PAT; deploy tools additionally need MENDIX_USERNAME + MENDIX_API_KEY; oql_read needs MENDIX_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.

F
license - not found
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

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